test(ivy): i18n - add compile time translation to integration test (#32881)
PR Close #32881
This commit is contained in:
		
							parent
							
								
									90855f331f
								
							
						
					
					
						commit
						009cab8dce
					
				
							
								
								
									
										1
									
								
								integration/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								integration/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,6 +1,7 @@ | |||||||
| built/ | built/ | ||||||
| dist/ | dist/ | ||||||
| vendor/ | vendor/ | ||||||
|  | tmp/ | ||||||
| */src/*.d.ts | */src/*.d.ts | ||||||
| */src/*.js | */src/*.js | ||||||
| !karma.conf.js | !karma.conf.js | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ | |||||||
|         "build": { |         "build": { | ||||||
|           "builder": "@angular-devkit/build-angular:browser", |           "builder": "@angular-devkit/build-angular:browser", | ||||||
|           "options": { |           "options": { | ||||||
|  |             "progress": false, | ||||||
|             "outputPath": "dist", |             "outputPath": "dist", | ||||||
|             "index": "src/index.html", |             "index": "src/index.html", | ||||||
|             "main": "src/main.ts", |             "main": "src/main.ts", | ||||||
| @ -31,6 +32,9 @@ | |||||||
|             "scripts": [] |             "scripts": [] | ||||||
|           }, |           }, | ||||||
|           "configurations": { |           "configurations": { | ||||||
|  |             "view-engine": { | ||||||
|  |               "tsConfig": "src/tsconfig.view-engine.json" | ||||||
|  |             }, | ||||||
|             "production": { |             "production": { | ||||||
|               "fileReplacements": [ |               "fileReplacements": [ | ||||||
|                 { |                 { | ||||||
| @ -55,9 +59,8 @@ | |||||||
|                 } |                 } | ||||||
|               ] |               ] | ||||||
|             }, |             }, | ||||||
|             "legacy-id-mode": { |             "translated-legacy": { | ||||||
|               "tsConfig": "src/tsconfig.legacy-id-mode.json", |               "tsConfig": "src/tsconfig.legacy.json", | ||||||
|               "polyfills": "src/polyfills.legacy-id-mode.ts", |  | ||||||
|               "optimization": true, |               "optimization": true, | ||||||
|               "outputHashing": "all", |               "outputHashing": "all", | ||||||
|               "sourceMap": false, |               "sourceMap": false, | ||||||
| @ -66,7 +69,7 @@ | |||||||
|               "aot": true, |               "aot": true, | ||||||
|               "extractLicenses": true, |               "extractLicenses": true, | ||||||
|               "vendorChunk": false, |               "vendorChunk": false, | ||||||
|               "buildOptimizer": true, |               "buildOptimizer": true | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
| @ -85,17 +88,15 @@ | |||||||
|             "ci-production": { |             "ci-production": { | ||||||
|               "browserTarget": "cli-hello-world-ivy-compat:build:production", |               "browserTarget": "cli-hello-world-ivy-compat:build:production", | ||||||
|               "progress": false |               "progress": false | ||||||
|             }, |  | ||||||
|             "legacy-id-mode": { |  | ||||||
|               "browserTarget": "cli-hello-world-ivy-compat:build:legacy-id-mode", |  | ||||||
|               "progress": false |  | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|         "extract-i18n": { |         "extract-i18n": { | ||||||
|           "builder": "@angular-devkit/build-angular:extract-i18n", |           "builder": "@angular-devkit/build-angular:extract-i18n", | ||||||
|           "options": { |           "options": { | ||||||
|             "browserTarget": "cli-hello-world-ivy-compat:build" |             "browserTarget": "cli-hello-world-ivy-compat:build:view-engine", | ||||||
|  |             "outputPath": "../tmp/legacy-locales/", | ||||||
|  |             "outFile": "messages.legacy.xlf" | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|         "test": { |         "test": { | ||||||
| @ -137,8 +138,9 @@ | |||||||
|         "e2e": { |         "e2e": { | ||||||
|           "builder": "@angular-devkit/build-angular:protractor", |           "builder": "@angular-devkit/build-angular:protractor", | ||||||
|           "options": { |           "options": { | ||||||
|             "protractorConfig": "e2e/protractor.conf.js", |             "protractorConfig": "e2e/runtime/protractor.conf.js", | ||||||
|             "devServerTarget": "cli-hello-world-ivy-compat:serve" |             "devServerTarget": "cli-hello-world-ivy-compat:serve", | ||||||
|  |             "webdriverUpdate": true | ||||||
|           }, |           }, | ||||||
|           "configurations": { |           "configurations": { | ||||||
|             "production": { |             "production": { | ||||||
| @ -150,8 +152,17 @@ | |||||||
|             "ci-production": { |             "ci-production": { | ||||||
|               "devServerTarget": "cli-hello-world-ivy-compat:serve:ci-production" |               "devServerTarget": "cli-hello-world-ivy-compat:serve:ci-production" | ||||||
|             }, |             }, | ||||||
|             "legacy-id-mode": { |             "translated-legacy": { | ||||||
|               "devServerTarget": "cli-hello-world-ivy-compat:serve:legacy-id-mode" |               "devServerTarget": "", | ||||||
|  |               "protractorConfig": "e2e/legacy/protractor.conf.js" | ||||||
|  |             }, | ||||||
|  |             "translated-fr": { | ||||||
|  |               "devServerTarget": "", | ||||||
|  |               "protractorConfig": "e2e/fr/protractor.conf.js" | ||||||
|  |             }, | ||||||
|  |             "translated-de": { | ||||||
|  |               "devServerTarget": "", | ||||||
|  |               "protractorConfig": "e2e/de/protractor.conf.js" | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|  | |||||||
							
								
								
									
										38
									
								
								integration/cli-hello-world-ivy-i18n/e2e/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								integration/cli-hello-world-ivy-i18n/e2e/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | ## E2E tests | ||||||
|  | 
 | ||||||
|  | There are four different sets of e2e tests in this folder. They are all testing different | ||||||
|  | translation scenarios, but they are all built with IVY enabled. | ||||||
|  | 
 | ||||||
|  | ### runtime | ||||||
|  | 
 | ||||||
|  | Translations are provided at runtime by calling `loadTranslations()` in the polyfill.ts | ||||||
|  | 
 | ||||||
|  | ### de and fr | ||||||
|  | 
 | ||||||
|  | The application is built (into the `dist` folder) and then two sets of translations | ||||||
|  | (`src/locales/messages.(de|fr).json`) are used to generate two copies of the app, which have | ||||||
|  | been translated (compile-time inlined). | ||||||
|  | 
 | ||||||
|  | These translated apps are stored in `tmp/translations/(de|fr)`. | ||||||
|  | 
 | ||||||
|  | ### legacy | ||||||
|  | 
 | ||||||
|  | The legacy `ng xi18n` tool extracts the messages from the Angular templates, into the XLIFF 1.2 | ||||||
|  | format with legacy message ids (`tmp/legacy-locales/messages.legacy.xlf`). | ||||||
|  | 
 | ||||||
|  | The translation file is modified to apply a simple translation. | ||||||
|  | 
 | ||||||
|  | The app must be compiled using the `i18nLegacyMessageIdFormat` option set to ensure that the correct | ||||||
|  | message ids are used to match those in the translation files. | ||||||
|  | 
 | ||||||
|  | The app is translated using the compile-time inlining tool to generate a copy that has the | ||||||
|  | translated message in it. | ||||||
|  | 
 | ||||||
|  | ## Hosting | ||||||
|  | 
 | ||||||
|  | Since the CLI hosts from and in-memory file-system the compile-time inliner is not able to | ||||||
|  | translate the output files. So the `de`, `fr` and `legacy` apps must be statically built to | ||||||
|  | disk and translated there. | ||||||
|  | 
 | ||||||
|  | Since the translated app is now on disk, we cannot use the CLI to serve it. Instead we use | ||||||
|  | a simple static HTTP server instead. | ||||||
							
								
								
									
										17
									
								
								integration/cli-hello-world-ivy-i18n/e2e/de/app.e2e-spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								integration/cli-hello-world-ivy-i18n/e2e/de/app.e2e-spec.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | import {AppPage} from '../app.po'; | ||||||
|  | 
 | ||||||
|  | describe('cli-hello-world-ivy App', () => { | ||||||
|  |   let page: AppPage; | ||||||
|  |   beforeEach(() => { | ||||||
|  |     page = new AppPage(); | ||||||
|  |     page.navigateTo(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should display title', () => { | ||||||
|  |     expect(page.getHeading()).toEqual('Guten Tag, cli-hello-world-ivy-compat! (inline)'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should display welcome message', () => { | ||||||
|  |     expect(page.getParagraph('message')).toEqual('Willkommen in der i18n App. (inline)'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | const {config} = require('../protractor.conf'); | ||||||
|  | exports.config = { | ||||||
|  |   ...config, | ||||||
|  |   specs: ['./app.e2e-spec.ts'], | ||||||
|  | }; | ||||||
							
								
								
									
										16
									
								
								integration/cli-hello-world-ivy-i18n/e2e/fr/app.e2e-spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								integration/cli-hello-world-ivy-i18n/e2e/fr/app.e2e-spec.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | import {AppPage} from '../app.po'; | ||||||
|  | 
 | ||||||
|  | describe('cli-hello-world-ivy App', () => { | ||||||
|  |   let page: AppPage; | ||||||
|  |   beforeEach(() => { | ||||||
|  |     page = new AppPage(); | ||||||
|  |     page.navigateTo(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   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)'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | const {config} = require('../protractor.conf'); | ||||||
|  | exports.config = { | ||||||
|  |   ...config, | ||||||
|  |   specs: ['./app.e2e-spec.ts'], | ||||||
|  | }; | ||||||
| @ -0,0 +1,18 @@ | |||||||
|  | import {AppPage} from '../app.po'; | ||||||
|  | 
 | ||||||
|  | describe('cli-hello-world-ivy App', () => { | ||||||
|  |   let page: AppPage; | ||||||
|  |   beforeEach(() => { | ||||||
|  |     page = new AppPage(); | ||||||
|  |     page.navigateTo(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should display translated title', | ||||||
|  |      () => { expect(page.getHeading()).toEqual('Bonjour cli-hello-world-ivy-compat!'); }); | ||||||
|  | 
 | ||||||
|  |   it('should display untranslated welcome message', () => { | ||||||
|  |     // This message does not get translated because we did not provide a translation for it
 | ||||||
|  |     // See "translated:legacy:extract-and-update" in package.json.
 | ||||||
|  |     expect(page.getParagraph('message')).toEqual('Welcome to the i18n app.'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | const {config} = require('../protractor.conf'); | ||||||
|  | exports.config = { | ||||||
|  |   ...config, | ||||||
|  |   specs: ['./app.e2e-spec.ts'], | ||||||
|  | }; | ||||||
| @ -1,4 +1,4 @@ | |||||||
| import {AppPage} from './app.po'; | import {AppPage} from '../app.po'; | ||||||
| 
 | 
 | ||||||
| describe('cli-hello-world-ivy App', () => { | describe('cli-hello-world-ivy App', () => { | ||||||
|   let page: AppPage; |   let page: AppPage; | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | const {config} = require('../protractor.conf'); | ||||||
|  | exports.config = { | ||||||
|  |   ...config, | ||||||
|  |   specs: ['./app.e2e-spec.ts'], | ||||||
|  | }; | ||||||
| @ -10,7 +10,22 @@ | |||||||
|     "postinstall": "webdriver-manager update --gecko=false --standalone=false $CI_CHROMEDRIVER_VERSION_ARG", |     "postinstall": "webdriver-manager update --gecko=false --standalone=false $CI_CHROMEDRIVER_VERSION_ARG", | ||||||
|     "start": "ng serve", |     "start": "ng serve", | ||||||
|     "pretest": "ng version", |     "pretest": "ng version", | ||||||
|     "test": "ng test --progress=false --watch=false && yarn e2e --configuration=ci && yarn e2e --configuration=ci-production && yarn e2e --configuration=legacy-id-mode" |     "test": "ng test --progress=false --watch=false && yarn e2e --configuration=ci && yarn e2e --configuration=ci-production && yarn translated:test && yarn translated:legacy:test", | ||||||
|  |     "translate": "localize-translate -r \"dist/\" -s \"**/*\" -t \"src/locales/messages.*\" -o \"tmp/translations/{{LOCALE}}\"", | ||||||
|  |      | ||||||
|  |     "translated:test": "yarn build && yarn translate && yarn translated:fr:e2e && yarn translated:de:e2e", | ||||||
|  |      | ||||||
|  |     "translated:fr:serve": "serve tmp/translations/fr --listen 4200", | ||||||
|  |     "translated:fr:e2e": "npm-run-all -p -r translated:fr:serve \"ng e2e --configuration=translated-fr --webdriver-update=false\"", | ||||||
|  |      | ||||||
|  |     "translated:de:serve": "serve tmp/translations/de --listen 4200", | ||||||
|  |     "translated:de:e2e": "npm-run-all -p -r translated:de:serve \"ng e2e --configuration=translated-de --webdriver-update=false\"", | ||||||
|  |      | ||||||
|  |     "translated:legacy:test": "yarn translated:legacy:extract-and-update && ng build --configuration=translated-legacy && yarn translated:legacy:translate && yarn translated:legacy:e2e", | ||||||
|  |     "translated:legacy:extract-and-update": "ng xi18n && sed -i.bak -e 's/source>/target>'/ -e 's/Hello/Bonjour/' -e 's/source-language=\"en\"/source-language=\"en\" target-language=\"legacy\"/' tmp/legacy-locales/messages.legacy.xlf", | ||||||
|  |     "translated:legacy:translate": "localize-translate -r \"dist/\" -s \"**/*\" -t \"tmp/legacy-locales/messages.legacy.xlf\" -o \"tmp/translations/{{LOCALE}}\"", | ||||||
|  |     "translated:legacy:serve": "serve tmp/translations/legacy --listen 4200", | ||||||
|  |     "translated:legacy:e2e": "npm-run-all -p -r translated:legacy:serve \"ng e2e --configuration=translated-legacy --webdriver-update=false\"" | ||||||
|   }, |   }, | ||||||
|   "private": true, |   "private": true, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
| @ -24,13 +39,15 @@ | |||||||
|     "@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic", |     "@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic", | ||||||
|     "@angular/router": "file:../../dist/packages-dist/router", |     "@angular/router": "file:../../dist/packages-dist/router", | ||||||
|     "core-js": "file:../../node_modules/core-js", |     "core-js": "file:../../node_modules/core-js", | ||||||
|  |     "npm-run-all": "^4.1.5", | ||||||
|     "rxjs": "file:../../node_modules/rxjs", |     "rxjs": "file:../../node_modules/rxjs", | ||||||
|  |     "serve": "^11.2.0", | ||||||
|     "tslib": "^1.9.3", |     "tslib": "^1.9.3", | ||||||
|     "zone.js": "file:../../node_modules/zone.js" |     "zone.js": "file:../../node_modules/zone.js" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@angular-devkit/build-angular": "^0.803.0-next.1", |     "@angular-devkit/build-angular": "^0.900.0-next.8", | ||||||
|     "@angular/cli": "^8.3.0-next.1", |     "@angular/cli": "9.0.0-next.8", | ||||||
|     "@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli", |     "@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli", | ||||||
|     "@angular/language-service": "file:../../dist/packages-dist/language-service", |     "@angular/language-service": "file:../../dist/packages-dist/language-service", | ||||||
|     "@types/jasmine": "~2.8.8", |     "@types/jasmine": "~2.8.8", | ||||||
|  | |||||||
| @ -0,0 +1,7 @@ | |||||||
|  | { | ||||||
|  |   "locale": "de", | ||||||
|  |   "translations": { | ||||||
|  |     "1638894134994447485": " Guten Tag, {$INTERPOLATION}! (inline)", | ||||||
|  |     "6762263703087737643": "Willkommen in der i18n App. (inline)" | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | { | ||||||
|  |   "locale": "fr", | ||||||
|  |   "translations": { | ||||||
|  |     "1638894134994447485": " Bonjour, {$INTERPOLATION}! (inline)", | ||||||
|  |     "6762263703087737643": "Bienvenue sur l'application i18n. (inline)" | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,104 +0,0 @@ | |||||||
| /** |  | ||||||
|  * This file includes polyfills needed by Angular and is loaded before the app. |  | ||||||
|  * You can add your own extra polyfills to this file. |  | ||||||
|  * |  | ||||||
|  * This file is divided into 2 sections: |  | ||||||
|  *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. |  | ||||||
|  *   2. Application imports. Files imported after ZoneJS that should be loaded before your main |  | ||||||
|  *      file. |  | ||||||
|  * |  | ||||||
|  * The current setup is for so-called "evergreen" browsers; the last versions of browsers that |  | ||||||
|  * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), |  | ||||||
|  * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. |  | ||||||
|  * |  | ||||||
|  * Learn more in https://angular.io/guide/browser-support
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| /*************************************************************************************************** |  | ||||||
|  * BROWSER POLYFILLS |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| /** IE9, IE10, IE11, and Chrome <55 requires all of the following polyfills. |  | ||||||
|  *  This also includes Android Emulators with older versions of Chrome and Google Search/Googlebot |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| // import 'core-js/es6/symbol';
 |  | ||||||
| // import 'core-js/es6/object';
 |  | ||||||
| // import 'core-js/es6/function';
 |  | ||||||
| // import 'core-js/es6/parse-int';
 |  | ||||||
| // import 'core-js/es6/parse-float';
 |  | ||||||
| // import 'core-js/es6/number';
 |  | ||||||
| // import 'core-js/es6/math';
 |  | ||||||
| // import 'core-js/es6/string';
 |  | ||||||
| // import 'core-js/es6/date';
 |  | ||||||
| // import 'core-js/es6/array';
 |  | ||||||
| // import 'core-js/es6/regexp';
 |  | ||||||
| // import 'core-js/es6/map';
 |  | ||||||
| // import 'core-js/es6/weak-map';
 |  | ||||||
| // import 'core-js/es6/set';
 |  | ||||||
| 
 |  | ||||||
| /** IE10 and IE11 requires the following for NgClass support on SVG elements */ |  | ||||||
| // import 'classlist.js';  // Run `npm install --save classlist.js`.
 |  | ||||||
| 
 |  | ||||||
| /** IE10 and IE11 requires the following for the Reflect API. */ |  | ||||||
| // import 'core-js/es6/reflect';
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Web Animations `@angular/platform-browser/animations` |  | ||||||
|  * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. |  | ||||||
|  * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). |  | ||||||
|  */ |  | ||||||
| // import 'web-animations-js';  // Run `npm install --save web-animations-js`.
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * By default, zone.js will patch all possible macroTask and DomEvents |  | ||||||
|  * user can disable parts of macroTask/DomEvents patch by setting following flags |  | ||||||
|  * because those flags need to be set before `zone.js` being loaded, and webpack |  | ||||||
|  * will put import in the top of bundle, so user need to create a separate file |  | ||||||
|  * in this directory (for example: zone-flags.ts), and put the following flags |  | ||||||
|  * into that file, and then add the following code before importing zone.js. |  | ||||||
|  * import './zone-flags.ts'; |  | ||||||
|  * |  | ||||||
|  * The flags allowed in zone-flags.ts are listed here. |  | ||||||
|  * |  | ||||||
|  * The following flags will work for all browsers. |  | ||||||
|  * |  | ||||||
|  * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch
 |  | ||||||
|  * requestAnimationFrame |  | ||||||
|  * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
 |  | ||||||
|  * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch
 |  | ||||||
|  * specified eventNames |  | ||||||
|  * |  | ||||||
|  *  in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js |  | ||||||
|  *  with the following flag, it will bypass `zone.js` patch for IE/Edge |  | ||||||
|  * |  | ||||||
|  *  (window as any).__Zone_enable_cross_context_check = true; |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| /*************************************************************************************************** |  | ||||||
|  * Zone JS is required by default for Angular itself. |  | ||||||
|  */ |  | ||||||
| import 'zone.js/dist/zone'; // Included with Angular CLI.
 |  | ||||||
| 
 |  | ||||||
| /*************************************************************************************************** |  | ||||||
|  * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates. |  | ||||||
|  */ |  | ||||||
| import '@angular/localize/init'; |  | ||||||
| 
 |  | ||||||
| // Note that `computeMsgId` is a private API at this stage. It will probably be exported directly
 |  | ||||||
| // from `@angular/localize` at some point.
 |  | ||||||
| import {computeMsgId} from '@angular/compiler'; |  | ||||||
| import {loadTranslations} from '@angular/localize'; |  | ||||||
| 
 |  | ||||||
| // Load some runtime translations
 |  | ||||||
| loadTranslations({ |  | ||||||
|   // This message is in a template so it uses the legacy message id
 |  | ||||||
|   ['2f8d6ae7ef7b0a53392bc23d0968d074ae02a318']: 'Bonjour {$INTERPOLATION}!', |  | ||||||
|   // This message is in application code so it uses the normal message id
 |  | ||||||
|   [computeMsgId('Welcome to the i18n app.')]: 'Bienvenue sur l\'application i18n.', |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| /*************************************************************************************************** |  | ||||||
|  * APPLICATION IMPORTS |  | ||||||
|  */ |  | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | { | ||||||
|  |   "extends": "./tsconfig.app.json", | ||||||
|  |   "angularCompilerOptions": { | ||||||
|  |     "enableIvy": false | ||||||
|  |   } | ||||||
|  | } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user