diff --git a/integration/ivy-i18n/e2e/de/app.e2e-spec.ts b/integration/ivy-i18n/e2e/de/app.e2e-spec.ts index 0bc71b5b29..e147aa8348 100644 --- a/integration/ivy-i18n/e2e/de/app.e2e-spec.ts +++ b/integration/ivy-i18n/e2e/de/app.e2e-spec.ts @@ -15,7 +15,13 @@ describe('cli-hello-world-ivy App', () => { expect(page.getParagraph('message')).toEqual('Willkommen in der i18n App. (inline)'); }); - it('should display the locale', () => { expect(page.getParagraph('locale')).toEqual('de'); }); + it('should display extra message', () => { + expect(page.getParagraph('extra')).toEqual('Zusätzliche Nachricht'); + }); + + it('should display the locale', () => { + expect(page.getParagraph('locale')).toEqual('de'); + }); // TODO : Re-enable when CLI translation inlining supports locale inlining (and so we can use it // to load the correct locale data) diff --git a/integration/ivy-i18n/e2e/en/app.e2e-spec.ts b/integration/ivy-i18n/e2e/en/app.e2e-spec.ts index b7935f18cb..66d2d1b7f9 100644 --- a/integration/ivy-i18n/e2e/en/app.e2e-spec.ts +++ b/integration/ivy-i18n/e2e/en/app.e2e-spec.ts @@ -7,13 +7,21 @@ describe('cli-hello-world-ivy App', () => { page.navigateTo(); }); - it('should display title', - () => { expect(page.getHeading()).toEqual('Hello cli-hello-world-ivy-compat!'); }); + it('should display title', () => { + expect(page.getHeading()).toEqual('Hello cli-hello-world-ivy-compat!'); + }); - it('should display welcome message', - () => { expect(page.getParagraph('message')).toEqual('Welcome to the i18n app.'); }); + it('should display welcome message', () => { + expect(page.getParagraph('message')).toEqual('Welcome to the i18n app.'); + }); - it('should display the locale', () => { expect(page.getParagraph('locale')).toEqual('en-US'); }); + it('should display extra message', () => { + expect(page.getParagraph('extra')).toEqual('Extra message'); + }); + + it('should display the locale', () => { + expect(page.getParagraph('locale')).toEqual('en-US'); + }); it('the date pipe should show the localized month', () => { page.navigateTo(); diff --git a/integration/ivy-i18n/e2e/fr/app.e2e-spec.ts b/integration/ivy-i18n/e2e/fr/app.e2e-spec.ts index 795b80e169..93876089bb 100644 --- a/integration/ivy-i18n/e2e/fr/app.e2e-spec.ts +++ b/integration/ivy-i18n/e2e/fr/app.e2e-spec.ts @@ -7,14 +7,21 @@ describe('cli-hello-world-ivy App', () => { page.navigateTo(); }); - it('should display title', - () => { expect(page.getHeading()).toEqual('Bonjour, cli-hello-world-ivy-compat! (inline)'); }); + it('should display title', () => { + expect(page.getHeading()).toEqual('Bonjour, cli-hello-world-ivy-compat! (inline)'); + }); it('should display welcome message', () => { expect(page.getParagraph('message')).toEqual('Bienvenue sur l\'application i18n. (inline)'); }); - it('should display the locale', () => { expect(page.getParagraph('locale')).toEqual('fr'); }); + it('should display extra message', () => { + expect(page.getParagraph('extra')).toEqual('Message supplémentaire'); + }); + + it('should display the locale', () => { + expect(page.getParagraph('locale')).toEqual('fr'); + }); it('the date pipe should show the localized month', () => { page.navigateTo(); diff --git a/integration/ivy-i18n/package.json b/integration/ivy-i18n/package.json index c3ecf05c23..1d8cf1a87c 100644 --- a/integration/ivy-i18n/package.json +++ b/integration/ivy-i18n/package.json @@ -11,7 +11,7 @@ "start": "ng serve", "pretest": "ng version", "test": "ng test && yarn e2e --configuration=ci && yarn e2e --configuration=ci-production && yarn translated:test && yarn translated:legacy-xlf:test && yarn translated:legacy-xmb:test", - "translate": "localize-translate -r \"dist/\" -s \"**/*\" -l \"en-US\" -t \"src/locales/messages.de.json\" \"src/locales/messages.fr.json\" -o \"../tmp/translations/{{LOCALE}}\"", + "translate": "localize-translate -r \"dist/\" -s \"**/*\" -l \"en-US\" -t \"[src/locales/messages.de.json, src/locales/extra.de.json]\" [src/locales/messages.fr.json,src/locales/extra.fr.json] -o \"../tmp/translations/{{LOCALE}}\"", "runtime:test": "yarn e2e --configuration=runtime-translations", "translated:test": "yarn build && yarn translate && yarn translated:fr:e2e && yarn translated:de:e2e && yarn translated:en:e2e", "translated:fr:serve": "serve ../tmp/translations/fr --listen 4200", @@ -72,4 +72,4 @@ "resolutions": { "**/webdriver-manager": "file:../../node_modules/webdriver-manager" } -} +} \ No newline at end of file diff --git a/integration/ivy-i18n/src/app/app.component.html b/integration/ivy-i18n/src/app/app.component.html index eb7616861d..819c20e303 100644 --- a/integration/ivy-i18n/src/app/app.component.html +++ b/integration/ivy-i18n/src/app/app.component.html @@ -1,25 +1,10 @@ - -
{{ message }}
-{{extra}}
{{ locale }}
{{ 1 | percent }} awesome
-{{ jan | date : 'LLLL' }}
-{{ jan | date : 'LLLL' }}
\ No newline at end of file diff --git a/integration/ivy-i18n/src/app/app.component.ts b/integration/ivy-i18n/src/app/app.component.ts index c6aafcce33..ddf6cb97d0 100644 --- a/integration/ivy-i18n/src/app/app.component.ts +++ b/integration/ivy-i18n/src/app/app.component.ts @@ -5,6 +5,7 @@ import {Component, Inject, LOCALE_ID} from '@angular/core'; export class AppComponent { constructor(@Inject(LOCALE_ID) public locale: string) {} title = `cli-hello-world-ivy-compat`; - message = $localize `Welcome to the i18n app.`; + message = $localize`Welcome to the i18n app.`; jan = new Date(2000, 0, 1); + extra = $localize`:@@custom:Extra message`; } diff --git a/integration/ivy-i18n/src/locales/extra.de.json b/integration/ivy-i18n/src/locales/extra.de.json new file mode 100644 index 0000000000..ce3cbf509c --- /dev/null +++ b/integration/ivy-i18n/src/locales/extra.de.json @@ -0,0 +1,6 @@ +{ + "locale": "de", + "translations": { + "custom": "Zusätzliche Nachricht" + } +} \ No newline at end of file diff --git a/integration/ivy-i18n/src/locales/extra.fr.json b/integration/ivy-i18n/src/locales/extra.fr.json new file mode 100644 index 0000000000..10c9704f7c --- /dev/null +++ b/integration/ivy-i18n/src/locales/extra.fr.json @@ -0,0 +1,6 @@ +{ + "locale": "fr", + "translations": { + "custom": "Message supplémentaire" + } +} \ No newline at end of file diff --git a/integration/ivy-i18n/yarn.lock b/integration/ivy-i18n/yarn.lock index db8afee3a5..45fd3a3efa 100644 --- a/integration/ivy-i18n/yarn.lock +++ b/integration/ivy-i18n/yarn.lock @@ -2,25 +2,25 @@ # yarn lockfile v1 -"@angular-devkit/architect@0.900.0-rc.11": - version "0.900.0-rc.11" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.900.0-rc.11.tgz#e9f3e5e372d467a220027cf53231b88e8e857fbc" - integrity sha512-rRbq4ipppnY4FvVo89Cv+yC7rlt1/VFE/jaB77Ra2tI6zVlFWCTjnMzuc9TYz/3jK1ssThzgEA2sebPDmjH47w== +"@angular-devkit/architect@0.900.3": + version "0.900.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.900.3.tgz#9c396733abd12fbb1d5bbc4542b2ee52418adb02" + integrity sha512-4UHc58Dlc5XHY3eiYSX9gytLyPNYixGSRwLcc/LRwuPgrmUFKPzCN3nwgB+9kc03/HN89CsJ1rS1scid6N6vxQ== dependencies: - "@angular-devkit/core" "9.0.0-rc.11" + "@angular-devkit/core" "9.0.3" rxjs "6.5.3" "@angular-devkit/build-angular@file:../../node_modules/@angular-devkit/build-angular": - version "0.900.0-rc.11" + version "0.900.3" dependencies: - "@angular-devkit/architect" "0.900.0-rc.11" - "@angular-devkit/build-optimizer" "0.900.0-rc.11" - "@angular-devkit/build-webpack" "0.900.0-rc.11" - "@angular-devkit/core" "9.0.0-rc.11" + "@angular-devkit/architect" "0.900.3" + "@angular-devkit/build-optimizer" "0.900.3" + "@angular-devkit/build-webpack" "0.900.3" + "@angular-devkit/core" "9.0.3" "@babel/core" "7.7.7" "@babel/generator" "7.7.7" "@babel/preset-env" "7.7.7" - "@ngtools/webpack" "9.0.0-rc.11" + "@ngtools/webpack" "9.0.3" ajv "6.10.2" autoprefixer "9.7.1" babel-loader "8.0.6" @@ -75,10 +75,10 @@ webpack-subresource-integrity "1.3.4" worker-plugin "3.2.0" -"@angular-devkit/build-optimizer@0.900.0-rc.11": - version "0.900.0-rc.11" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.900.0-rc.11.tgz#96c2446fa9cd2e90700ab8a68312b28b3907f6d9" - integrity sha512-GJC+7H7ER6bxDC2UdAGwW357EYHpv8ISKKmS19wdJV5gZPMPANcpbg9FIpl27SDhUyZX9C2DOrcATvYYFoYgDQ== +"@angular-devkit/build-optimizer@0.900.3": + version "0.900.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.900.3.tgz#91f90c56affb0be9f7910dfc1d414f16c21c2c3f" + integrity sha512-VLAWtAXpOzOoYUJrN6sT90UdIdvrVIipkzGz7nfI1kscDvxUFwVZnsNNHtFinaY2SfZAunHhYQOA/B9FJ8WPdQ== dependencies: loader-utils "1.2.3" source-map "0.7.3" @@ -86,19 +86,19 @@ typescript "3.6.4" webpack-sources "1.4.3" -"@angular-devkit/build-webpack@0.900.0-rc.11": - version "0.900.0-rc.11" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.900.0-rc.11.tgz#d9a91c2b67a629f6adfe87980d26e495f2e30e0a" - integrity sha512-utBAnkO6WLi323Rto1s7TJpaDRqDNR8jkD0C0PG5Zm3y1U9ARbAjTkugkrB/7bc4gEIqWZD+1dLYaaJCidye2Q== +"@angular-devkit/build-webpack@0.900.3": + version "0.900.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.900.3.tgz#4a2fd13cebe190c091606e18397a1f7cccfab6bb" + integrity sha512-9gSTLWf7yq/XBOec0CtZcjNMsC7L8IuVDProBQHps2SvTfr982DtHfEge95J2lc9BjRbqidv+phImFsQ1J3mFA== dependencies: - "@angular-devkit/architect" "0.900.0-rc.11" - "@angular-devkit/core" "9.0.0-rc.11" + "@angular-devkit/architect" "0.900.3" + "@angular-devkit/core" "9.0.3" rxjs "6.5.3" -"@angular-devkit/core@9.0.0-rc.11": - version "9.0.0-rc.11" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.0.0-rc.11.tgz#9e69545eb21284a573ad78e4c33003f2ea25afd5" - integrity sha512-ki7Sln+mQdCctJNBalzy70tiFn2hOCY2Yyte8B0xKWVHnofZySvG+ANzoLgodnKFOBH18AQy35FhgzZM++N9tQ== +"@angular-devkit/core@9.0.3": + version "9.0.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.0.3.tgz#a027862d2edd981afcc6245176e9f27768c631c9" + integrity sha512-3+abmv9K9d+BVgUAolYgoOqlGAA2Jb1pWo2biapSDG6KjUZHUCJdnsKigLtLorCdv0SrjTp56FFplkcqKsFQgA== dependencies: ajv "6.10.2" fast-json-stable-stringify "2.0.0" @@ -106,26 +106,26 @@ rxjs "6.5.3" source-map "0.7.3" -"@angular-devkit/schematics@9.0.0-rc.11": - version "9.0.0-rc.11" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.0.0-rc.11.tgz#e0d4d271d8d783ebf05eced576262f20e6c3562c" - integrity sha512-aJqOLzsoAkVj3AVTf1ehH2hA9wHHz1+7TTtfqI+Yx+S3jFyvGmnKrNBCKtMuIV5JdEHiXmhhuGbNBHwRFWpOow== +"@angular-devkit/schematics@9.0.3": + version "9.0.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.0.3.tgz#e65fa1ce08a3d5ef0af594b623024439c1110a0d" + integrity sha512-BQnZtFQPLZZOijhuEndtzL6cOnhaE8nNxupkRHavWohOMStnLsRyvVJj6JVDkf37wvT5koqTNjHhbdMxcCRc6A== dependencies: - "@angular-devkit/core" "9.0.0-rc.11" + "@angular-devkit/core" "9.0.3" ora "4.0.2" rxjs "6.5.3" "@angular/animations@file:../../dist/packages-dist/animations": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@angular/cli@file:../../node_modules/@angular/cli": - version "9.0.0-rc.11" + version "9.0.3" dependencies: - "@angular-devkit/architect" "0.900.0-rc.11" - "@angular-devkit/core" "9.0.0-rc.11" - "@angular-devkit/schematics" "9.0.0-rc.11" - "@schematics/angular" "9.0.0-rc.11" - "@schematics/update" "0.900.0-rc.11" + "@angular-devkit/architect" "0.900.3" + "@angular-devkit/core" "9.0.3" + "@angular-devkit/schematics" "9.0.3" + "@schematics/angular" "9.0.3" + "@schematics/update" "0.900.3" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "^4.1.1" @@ -143,10 +143,10 @@ uuid "^3.3.2" "@angular/common@file:../../dist/packages-dist/common": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@angular/compiler-cli@file:../../dist/packages-dist/compiler-cli": - version "9.0.0-rc.1" + version "10.0.0-next.2" dependencies: canonical-path "1.0.0" chokidar "^3.0.0" @@ -158,35 +158,36 @@ reflect-metadata "^0.1.2" semver "^6.3.0" source-map "^0.6.1" - yargs "13.1.0" + sourcemap-codec "^1.4.8" + yargs "15.3.0" "@angular/compiler@file:../../dist/packages-dist/compiler": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@angular/core@file:../../dist/packages-dist/core": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@angular/forms@file:../../dist/packages-dist/forms": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@angular/language-service@file:../../dist/packages-dist/language-service": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@angular/localize@file:../../dist/packages-dist/localize": - version "9.0.0-rc.1" + version "10.0.0-next.2" dependencies: "@babel/core" "7.8.3" glob "7.1.2" - yargs "13.1.0" + yargs "15.3.0" "@angular/platform-browser-dynamic@file:../../dist/packages-dist/platform-browser-dynamic": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@angular/platform-browser@file:../../dist/packages-dist/platform-browser": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@angular/router@file:../../dist/packages-dist/router": - version "9.0.0-rc.1" + version "10.0.0-next.2" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": version "7.5.5" @@ -1057,31 +1058,31 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@ngtools/webpack@9.0.0-rc.11": - version "9.0.0-rc.11" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.0.0-rc.11.tgz#10b5997bec7cf48d1b144c8b4d46ffd0039c522a" - integrity sha512-qeW81ISiO8GVEndOaCYv0k6fzRIxzZs6jrXGl1pcLH1H6qv2mxhA5DA0vC/9TN6wenrS43RGjDIQpp+RvkiLwA== +"@ngtools/webpack@9.0.3": + version "9.0.3" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.0.3.tgz#d05b5a15584909262a4db027919f03ccb074dc11" + integrity sha512-pMIXfq1IJLbvwmkPonGs7nrpuBCXrlZTf9A4OYsMBZcfU8JMn0pRdx7G2+bC9Q/f+uSw2uvPSv76xJXLBOntmA== dependencies: - "@angular-devkit/core" "9.0.0-rc.11" + "@angular-devkit/core" "9.0.3" enhanced-resolve "4.1.1" rxjs "6.5.3" webpack-sources "1.4.3" -"@schematics/angular@9.0.0-rc.11": - version "9.0.0-rc.11" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.0.0-rc.11.tgz#d544c0d4e7b3dd59ed56be5183e038ebe06a165e" - integrity sha512-9InC+F71KiPXE0jl7Ow4iPFJ2AZZDbfTM6yWZoYLk3hzTCohAZZciBl00Tfyu2uerGshx8akbJMLySjXtf+q0g== +"@schematics/angular@9.0.3": + version "9.0.3" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.0.3.tgz#8b0fb91fa18dd909001ac0d888479a96810aa640" + integrity sha512-6XSnPW4G7aoKXccg0FTpZ02y/yi9y/bj7swnSL9Z4RRPIvPVapDjB7uJPg8sm8+PTIpcMhEFQrchIqM3LXW4zA== dependencies: - "@angular-devkit/core" "9.0.0-rc.11" - "@angular-devkit/schematics" "9.0.0-rc.11" + "@angular-devkit/core" "9.0.3" + "@angular-devkit/schematics" "9.0.3" -"@schematics/update@0.900.0-rc.11": - version "0.900.0-rc.11" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.900.0-rc.11.tgz#d22df30f13a6f38970b759db61ad84d3f9b03a78" - integrity sha512-nV0oCPzzd0vi2Exo1910rWXwz/RnMc4zF9FxSOCZzsIv+AkwIehhL815OKyjUSCzU9+IM0/o1LKkPPrSWK7QEA== +"@schematics/update@0.900.3": + version "0.900.3" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.900.3.tgz#9141ee2e1b6356e66f6269b92c284c86e4faf065" + integrity sha512-mlRsm3/HM1f/10Wdz4xMYA+mpW3EDCB+whlV5cJ7PGMhjUMaxA9DuWvoP06h05le6XmgnjIEoxL6NJ7CgesHcA== dependencies: - "@angular-devkit/core" "9.0.0-rc.11" - "@angular-devkit/schematics" "9.0.0-rc.11" + "@angular-devkit/core" "9.0.3" + "@angular-devkit/schematics" "9.0.3" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" npm-package-arg "^7.0.0" @@ -1090,6 +1091,11 @@ semver "6.3.0" semver-intersect "1.4.0" +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + "@types/estree@*": version "0.0.39" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" @@ -1114,15 +1120,11 @@ resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.4.2.tgz#49f672de24043b3c1fb919901fd3cd36f027bc93" integrity sha512-SaSSGOzwUnBEn64c+HTyVTJhRf8F1CXZLnxYx2ww3UrgGBmEEw38RSux2l3fYiT9brVLP67DU5omWA6V9OHI5Q== -"@types/jasmine@3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.4.4.tgz#be3fbd73e72725edb44e6f7f509cd52912d1550c" - integrity sha512-+/sHcTPyDS1JQacDRRRWb+vNrjBwnD+cKvTaWlxlJ/uOOFvzCkjOwNaqVjYMLfsjzNi0WtDH9RyReDXPG1Cdug== +"@types/jasmine@file:../../node_modules/@types/jasmine": + version "3.5.10" -"@types/jasminewd2@2.0.8": +"@types/jasminewd2@file:../../node_modules/@types/jasminewd2": version "2.0.8" - resolved "https://registry.yarnpkg.com/@types/jasminewd2/-/jasminewd2-2.0.8.tgz#67afe5098d5ef2386073a7b7384b69a840dfe93b" - integrity sha512-d9p31r7Nxk0ZH0U39PTH0hiDlJ+qNVGjlt1ucOoTUptxb2v+Y5VMnsxfwN+i3hK4yQnqBi3FMmoMFcd1JHDxdg== dependencies: "@types/jasmine" "*" @@ -1142,7 +1144,7 @@ integrity sha512-Otxmr2rrZLKRYIybtdG/sgeO+tHY20GxeDjcGmUnmmlCWyEnv2a2x1ZXBo3BTec4OiTXMQCiazB8NMBf0iRlFw== "@types/node@file:../../node_modules/@types/node": - version "12.11.1" + version "12.12.34" "@types/q@^0.0.32": version "0.0.32" @@ -1493,6 +1495,11 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -1505,6 +1512,14 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -2392,6 +2407,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -2455,12 +2479,19 @@ color-convert@^1.9.0, color-convert@^1.9.1: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== @@ -2723,7 +2754,7 @@ core-js@^3.1.3: integrity sha512-0xmD4vUJRY8nfLyV9zcpC17FtSie5STXzw+HyYw2t8IIvmDnbq7RJUULECCo+NstpJtwK9kx8S+898iyqgeUow== "core-js@file:../../node_modules/core-js": - version "2.5.7" + version "2.6.11" core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -3353,11 +3384,6 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -3889,7 +3915,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -6323,7 +6349,7 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-locale@^3.0.0, os-locale@^3.1.0: +os-locale@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== @@ -7145,7 +7171,7 @@ punycode@^2.1.0: integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== "puppeteer@file:../../node_modules/puppeteer": - version "2.1.0" + version "2.1.1" dependencies: "@types/mime-types" "^2.1.0" debug "^4.1.0" @@ -7623,15 +7649,15 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@6.5.3, "rxjs@file:../../node_modules/rxjs": +rxjs@6.5.3: version "6.5.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== dependencies: tslib "^1.9.0" -rxjs@^6.4.0: +rxjs@^6.4.0, "rxjs@file:../../node_modules/rxjs": version "6.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" - integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== dependencies: tslib "^1.9.0" @@ -8124,6 +8150,11 @@ sourcemap-codec@^1.4.4: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz#e30a74f0402bad09807640d39e971090a08ce1e9" integrity sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg== +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" @@ -8310,15 +8341,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff" @@ -8328,6 +8350,15 @@ string-width@^4.1.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^5.2.0" +string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string.prototype.padend@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0" @@ -8404,6 +8435,13 @@ strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -8717,7 +8755,7 @@ tslib@1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== "tslib@file:../../node_modules/tslib": - version "1.10.0" + version "1.11.1" tslint@5.18.0: version "5.18.0" @@ -8786,7 +8824,7 @@ typescript@3.6.4: integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg== "typescript@file:../../node_modules/typescript": - version "3.7.4" + version "3.8.3" uglify-js@^3.1.4: version "3.6.1" @@ -9259,6 +9297,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -9332,10 +9379,10 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.0.0: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== +yargs-parser@^18.1.0: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -9358,22 +9405,22 @@ yargs@12.0.5: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.1.0.tgz#b2729ce4bfc0c584939719514099d8a916ad2301" - integrity sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg== +yargs@15.3.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.0.tgz#403af6edc75b3ae04bf66c94202228ba119f0976" + integrity sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA== dependencies: - cliui "^4.0.0" - find-up "^3.0.0" + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" get-caller-file "^2.0.1" - os-locale "^3.1.0" require-directory "^2.1.1" require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^3.0.0" + string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.0.0" + yargs-parser "^18.1.0" yauzl@2.4.1: version "2.4.1" diff --git a/packages/localize/src/tools/src/translate/main.ts b/packages/localize/src/tools/src/translate/main.ts index 55fa300e62..9178ed810d 100644 --- a/packages/localize/src/tools/src/translate/main.ts +++ b/packages/localize/src/tools/src/translate/main.ts @@ -10,8 +10,7 @@ import * as glob from 'glob'; import {resolve} from 'path'; import * as yargs from 'yargs'; -import {Diagnostics} from '../diagnostics'; -import {MissingTranslationStrategy} from '../source_file_utils'; +import {DiagnosticHandlingStrategy, Diagnostics} from '../diagnostics'; import {AssetTranslationHandler} from './asset_files/asset_translation_handler'; import {getOutputPathFn, OutputPathFn} from './output_path'; import {SourceFileTranslationHandler} from './source_files/source_file_translation_handler'; @@ -51,7 +50,10 @@ if (require.main === module) { array: true, describe: 'A list of paths to the translation files to load, either absolute or relative to the current working directory.\n' + - 'E.g. "-t src/locale/messages.en.xlf src/locale/messages.fr.xlf src/locale/messages.de.xlf".', + 'E.g. `-t src/locale/messages.en.xlf src/locale/messages.fr.xlf src/locale/messages.de.xlf`.\n' + + 'If you want to merge multiple translation files for each locale, then provide the list of files in an array.\n' + + 'Note that the arrays must be in double quotes if you include any whitespace within the array.\n' + + 'E.g. `-t "[src/locale/messages.en.xlf, src/locale/messages-2.en.xlf]" [src/locale/messages.fr.xlf,src/locale/messages-2.fr.xlf]`', }) .option('target-locales', { @@ -74,6 +76,14 @@ if (require.main === module) { choices: ['error', 'warning', 'ignore'], default: 'warning', }) + + .option('d', { + alias: 'duplicateTranslation', + describe: 'How to handle duplicate translations.', + choices: ['error', 'warning', 'ignore'], + default: 'warning', + }) + .strict() .help() .parse(args); @@ -81,10 +91,11 @@ if (require.main === module) { const sourceRootPath = options['r']; const sourceFilePaths = glob.sync(options['s'], {absolute: true, cwd: sourceRootPath, nodir: true}); - const translationFilePaths: string[] = options['t']; + const translationFilePaths: (string|string[])[] = convertArraysFromArgs(options['t']); const outputPathFn = getOutputPathFn(options['o']); const diagnostics = new Diagnostics(); const missingTranslation: DiagnosticHandlingStrategy = options['m']; + const duplicateTranslation: DiagnosticHandlingStrategy = options['d']; const sourceLocale: string|undefined = options['l']; const translationFileLocales: string[] = options['target-locales'] || []; @@ -96,6 +107,7 @@ if (require.main === module) { outputPathFn, diagnostics, missingTranslation, + duplicateTranslation, sourceLocale }); @@ -116,10 +128,29 @@ export interface TranslateFilesOptions { /** * An array of paths to the translation files to load, either absolute or relative to the current * working directory. + * + * For each locale to be translated, there should be an element in `translationFilePaths`. + * Each element is either an absolute path to the translation file, or an array of absolute paths + * to translation files, for that locale. + * + * If the element contains more than one translation file, then the translations are merged. + * + * If allowed by the `duplicateTranslation` property, when more than one translation has the same + * message id, the message from the earlier translation file in the array is used. + * + * For example, if the files are `[app.xlf, lib-1.xlf, lib-2.xlif]` then a message that appears in + * `app.xlf` will override the same message in `lib-1.xlf` or `lib-2.xlf`. */ - translationFilePaths: string[]; + translationFilePaths: (string|string[])[]; /** * A collection of the target locales for the translation files. + * + * If there is a locale provided in `translationFileLocales` then this is used rather than a + * locale extracted from the file itself. + * If there is neither a provided locale nor a locale parsed from the file, then an error is + * thrown. + * If there are both a provided locale and a locale parsed from the file, and they are not the + * same, then a warning is reported. */ translationFileLocales: (string|undefined)[]; /** @@ -135,6 +166,10 @@ export interface TranslateFilesOptions { * How to handle missing translations. */ missingTranslation: DiagnosticHandlingStrategy; + /** + * How to handle duplicate translations. + */ + duplicateTranslation: DiagnosticHandlingStrategy; /** * The locale of the source files. * If this is provided then a copy of the application will be created with no translation but just @@ -151,6 +186,7 @@ export function translateFiles({ outputPathFn, diagnostics, missingTranslation, + duplicateTranslation, sourceLocale }: TranslateFilesOptions) { const translationLoader = new TranslationLoader( @@ -160,7 +196,7 @@ export function translateFiles({ new XtbTranslationParser(), new SimpleJsonTranslationParser(), ], - diagnostics); + duplicateTranslation, diagnostics); const resourceProcessor = new Translator( [ @@ -169,8 +205,25 @@ export function translateFiles({ ], diagnostics); - const translations = translationLoader.loadBundles(translationFilePaths, translationFileLocales); + // Convert all the `translationFilePaths` elements to arrays. + const translationFilePathsArrays = + translationFilePaths.map(filePaths => Array.isArray(filePaths) ? filePaths : [filePaths]); + + const translations = + translationLoader.loadBundles(translationFilePathsArrays, translationFileLocales); sourceRootPath = resolve(sourceRootPath); resourceProcessor.translateFiles( sourceFilePaths, sourceRootPath, outputPathFn, translations, sourceLocale); } + +/** + * Parse each of the given string `args` and convert it to an array if it is of the form + * `[abc, def, ghi]`, i.e. it is enclosed in square brackets with comma delimited items. + * @param args The string to potentially convert to arrays. + */ +function convertArraysFromArgs(args: string[]): (string|string[])[] { + return args.map( + arg => (arg.startsWith('[') && arg.endsWith(']')) ? + arg.slice(1, -1).split(',').map(arg => arg.trim()) : + arg); +} \ No newline at end of file diff --git a/packages/localize/src/tools/src/translate/translation_files/translation_loader.ts b/packages/localize/src/tools/src/translate/translation_files/translation_loader.ts index 58e51b7c47..a7cf016f82 100644 --- a/packages/localize/src/tools/src/translate/translation_files/translation_loader.ts +++ b/packages/localize/src/tools/src/translate/translation_files/translation_loader.ts @@ -5,9 +5,10 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -import {Diagnostics} from '../../diagnostics'; +import {DiagnosticHandlingStrategy, Diagnostics} from '../../diagnostics'; import {FileUtils} from '../../file_utils'; import {TranslationBundle} from '../translator'; + import {TranslationParser} from './translation_parsers/translation_parser'; /** @@ -16,61 +17,108 @@ import {TranslationParser} from './translation_parsers/translation_parser'; export class TranslationLoader { constructor( private translationParsers: TranslationParser