Skip to content

Commit ebccd78

Browse files
rockument69kapunahelewong
authored andcommitted
docs: Refactor-i18n
Rewrite headings to focus on tasks and separate reference info and best practices from tasks. Add missing steps or procedures, and links to important information. Make the example open in StackBlitz. See i18n Documentation Plan at https://docs.google.com/document/d/1aV2TKsIqry7JnNiHEfhmheu5rNAbNl1IRYVhYErc7Ks/edit?usp=sharing
1 parent 1197965 commit ebccd78

8 files changed

Lines changed: 848 additions & 502 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"description": "i18n",
3+
"files":[
4+
"!**/*.d.ts",
5+
"!**/*.js",
6+
"!**/*.[0-9].*"
7+
],
8+
"file": "src/app/app.component.ts",
9+
"tags": ["Angular", "i18n", "internationalization"]
10+
}

aio/content/guide/i18n.md

Lines changed: 557 additions & 427 deletions
Large diffs are not rendered by default.

aio/tools/examples/run-example-e2e.js

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ const DEFAULT_CLI_EXAMPLE_PORT = 4200;
2323
const DEFAULT_CLI_SPECS_CONCURRENCY = 1;
2424
const IGNORED_EXAMPLES = [];
2525

26-
const fixmeIvyExamples = [
27-
// fixmeIvy('unknown') app fails at runtime due to missing external service (goog is undefined)
28-
'i18n',
29-
];
26+
const fixmeIvyExamples = [];
3027

3128
if (!argv.viewengine) {
3229
IGNORED_EXAMPLES.push(...fixmeIvyExamples);
@@ -72,8 +69,10 @@ function runE2e() {
7269
const outputFile = path.join(AIO_PATH, './protractor-results.txt');
7370

7471
return Promise.resolve()
75-
.then(() => findAndRunE2eTests(argv.filter, outputFile, argv.shard,
76-
argv.cliSpecsConcurrency || DEFAULT_CLI_SPECS_CONCURRENCY, argv.retry || 1))
72+
.then(
73+
() => findAndRunE2eTests(
74+
argv.filter, outputFile, argv.shard,
75+
argv.cliSpecsConcurrency || DEFAULT_CLI_SPECS_CONCURRENCY, argv.retry || 1))
7776
.then((status) => {
7877
reportStatus(status, outputFile);
7978
if (status.failed.length > 0) {
@@ -226,8 +225,12 @@ function runProtractorSystemJS(prepPromise, appDir, appRunSpawnInfo, outputFile)
226225
});
227226
})
228227
.then(
229-
function() { return finish(appRunSpawnInfo.proc.pid, true); },
230-
function() { return finish(appRunSpawnInfo.proc.pid, false); });
228+
function() {
229+
return finish(appRunSpawnInfo.proc.pid, true);
230+
},
231+
function() {
232+
return finish(appRunSpawnInfo.proc.pid, false);
233+
});
231234
}
232235

233236
function finish(spawnProcId, ok) {
@@ -263,15 +266,15 @@ function runE2eTestsCLI(appDir, outputFile, bufferOutput, port) {
263266
// `--no-webdriver-update` is needed to preserve the ChromeDriver version already installed.
264267
const config = loadExampleConfig(appDir);
265268
const testCommands = config.tests || [{
266-
cmd: 'yarn',
267-
args: [
268-
'e2e',
269-
'--prod',
270-
'--protractor-config=e2e/protractor-puppeteer.conf.js',
271-
'--no-webdriver-update',
272-
'--port={PORT}',
273-
],
274-
}];
269+
cmd: 'yarn',
270+
args: [
271+
'e2e',
272+
'--prod',
273+
'--protractor-config=e2e/protractor-puppeteer.conf.js',
274+
'--no-webdriver-update',
275+
'--port={PORT}',
276+
],
277+
}];
275278
let bufferedOutput = `\n\n============== AIO example output for: ${appDir}\n\n`;
276279

277280
const e2eSpawnPromise = testCommands.reduce((prevSpawnPromise, {cmd, args}) => {
@@ -281,26 +284,30 @@ function runE2eTestsCLI(appDir, outputFile, bufferOutput, port) {
281284
args = args.map(a => a.replace('{PORT}', port || DEFAULT_CLI_EXAMPLE_PORT));
282285

283286
return prevSpawnPromise.then(() => {
284-
const currSpawn = spawnExt(cmd, args, {cwd: appDir}, false,
285-
bufferOutput ? msg => bufferedOutput += msg : undefined);
287+
const currSpawn = spawnExt(
288+
cmd, args, {cwd: appDir}, false, bufferOutput ? msg => bufferedOutput += msg : undefined);
286289
return currSpawn.promise.then(
287290
() => Promise.resolve(finish(currSpawn.proc.pid, true)),
288291
() => Promise.reject(finish(currSpawn.proc.pid, false)));
289292
});
290293
}, Promise.resolve());
291294

292-
return e2eSpawnPromise.then(() => {
293-
fs.appendFileSync(outputFile, `Passed: ${appDir}\n\n`);
294-
return true;
295-
}, () => {
296-
fs.appendFileSync(outputFile, `Failed: ${appDir}\n\n`);
297-
return false;
298-
}).then(passed => {
299-
if (bufferOutput) {
300-
process.stdout.write(bufferedOutput);
301-
}
302-
return passed;
303-
});
295+
return e2eSpawnPromise
296+
.then(
297+
() => {
298+
fs.appendFileSync(outputFile, `Passed: ${appDir}\n\n`);
299+
return true;
300+
},
301+
() => {
302+
fs.appendFileSync(outputFile, `Failed: ${appDir}\n\n`);
303+
return false;
304+
})
305+
.then(passed => {
306+
if (bufferOutput) {
307+
process.stdout.write(bufferedOutput);
308+
}
309+
return passed;
310+
});
304311
}
305312

306313
// Report final status.
@@ -309,23 +316,31 @@ function reportStatus(status, outputFile) {
309316

310317
log.push('Suites ignored due to legacy guides:');
311318
IGNORED_EXAMPLES.filter(example => !fixmeIvyExamples.find(ex => ex.startsWith(example)))
312-
.forEach(function(val) { log.push(' ' + val); });
319+
.forEach(function(val) {
320+
log.push(' ' + val);
321+
});
313322

314323
if (!argv.viewengine) {
315324
log.push('');
316325
log.push('Suites ignored due to breakage with Ivy:');
317-
fixmeIvyExamples.forEach(function(val) { log.push(' ' + val); });
326+
fixmeIvyExamples.forEach(function(val) {
327+
log.push(' ' + val);
328+
});
318329
}
319330

320331
log.push('');
321332
log.push('Suites passed:');
322-
status.passed.forEach(function(val) { log.push(' ' + val); });
333+
status.passed.forEach(function(val) {
334+
log.push(' ' + val);
335+
});
323336

324337
if (status.failed.length == 0) {
325338
log.push('All tests passed');
326339
} else {
327340
log.push('Suites failed:');
328-
status.failed.forEach(function(val) { log.push(' ' + val); });
341+
status.failed.forEach(function(val) {
342+
log.push(' ' + val);
343+
});
329344
}
330345
log.push('\nElapsed time: ' + status.elapsedTime + ' seconds');
331346
log = log.join('\n');
@@ -334,8 +349,8 @@ function reportStatus(status, outputFile) {
334349
}
335350

336351
// Returns both a promise and the spawned process so that it can be killed if needed.
337-
function spawnExt(command, args, options, ignoreClose = false,
338-
printMessage = msg => process.stdout.write(msg)) {
352+
function spawnExt(
353+
command, args, options, ignoreClose = false, printMessage = msg => process.stdout.write(msg)) {
339354
let proc;
340355
const promise = new Promise((resolve, reject) => {
341356
let descr = command + ' ' + args.join(' ');
@@ -370,13 +385,19 @@ function getE2eSpecs(basePath, filter) {
370385
let specs = {};
371386

372387
return getE2eSpecsFor(basePath, SJS_SPEC_FILENAME, filter)
373-
.then(sjsPaths => { specs.systemjs = sjsPaths; })
388+
.then(sjsPaths => {
389+
specs.systemjs = sjsPaths;
390+
})
374391
.then(() => {
375392
return getE2eSpecsFor(basePath, CLI_SPEC_FILENAME, filter).then(cliPaths => {
376-
return cliPaths.map(p => { return p.replace(`${CLI_SPEC_FILENAME}`, ''); });
393+
return cliPaths.map(p => {
394+
return p.replace(`${CLI_SPEC_FILENAME}`, '');
395+
});
377396
});
378397
})
379-
.then(cliPaths => { specs.cli = cliPaths; })
398+
.then(cliPaths => {
399+
specs.cli = cliPaths;
400+
})
380401
.then(() => specs);
381402
}
382403

aio/tools/examples/shared/boilerplate/i18n/angular.json

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,18 @@
99
"root": "",
1010
"sourceRoot": "src",
1111
"prefix": "app",
12+
"i18n": {
13+
"sourceLocale": "en-US",
14+
"locales": {
15+
"fr": "src/locale/messages.fr.xlf"
16+
}
17+
},
1218
"architect": {
1319
"build": {
1420
"builder": "@angular-devkit/build-angular:browser",
1521
"options": {
22+
"localize": true,
23+
"aot": true,
1624
"outputPath": "dist",
1725
"index": "src/index.html",
1826
"main": "src/main.ts",
@@ -57,35 +65,10 @@
5765
}
5866
]
5967
},
60-
"production-fr": {
61-
"fileReplacements": [
62-
{
63-
"replace": "src/environments/environment.ts",
64-
"with": "src/environments/environment.prod.ts"
65-
}
66-
],
67-
"optimization": true,
68-
"outputHashing": "all",
69-
"sourceMap": false,
70-
"extractCss": true,
71-
"namedChunks": false,
72-
"aot": true,
73-
"extractLicenses": true,
74-
"vendorChunk": false,
75-
"buildOptimizer": true,
76-
"outputPath": "dist/my-project-fr/",
77-
"i18nFile": "src/locale/messages.fr.xlf",
78-
"i18nFormat": "xlf",
79-
"i18nLocale": "fr",
80-
"i18nMissingTranslation": "error"
81-
},
8268
"fr": {
83-
"aot": true,
84-
"outputPath": "dist/my-project-fr/",
85-
"i18nFile": "src/locale/messages.fr.xlf",
86-
"i18nFormat": "xlf",
87-
"i18nLocale": "fr",
88-
"i18nMissingTranslation": "error"
69+
"localize": [
70+
"fr"
71+
]
8972
}
9073
}
9174
},

aio/tools/examples/shared/boilerplate/i18n/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@angular/compiler": "~9.1.4",
2121
"@angular/core": "~9.1.4",
2222
"@angular/forms": "~9.1.4",
23+
"@angular/localize": "^9.1.4",
2324
"@angular/platform-browser": "~9.1.4",
2425
"@angular/platform-browser-dynamic": "~9.1.4",
2526
"@angular/router": "~9.1.4",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/***************************************************************************************************
2+
* Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
3+
*/
4+
import '@angular/localize/init';
5+
/**
6+
* This file includes polyfills needed by Angular and is loaded before the app.
7+
* You can add your own extra polyfills to this file.
8+
*
9+
* This file is divided into 2 sections:
10+
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
11+
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
12+
* file.
13+
*
14+
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
15+
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
16+
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
17+
*
18+
* Learn more in https://angular.io/guide/browser-support
19+
*/
20+
21+
/***************************************************************************************************
22+
* BROWSER POLYFILLS
23+
*/
24+
25+
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
26+
// import 'classlist.js'; // Run `npm install --save classlist.js`.
27+
28+
/**
29+
* Web Animations `@angular/platform-browser/animations`
30+
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
31+
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
32+
*/
33+
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
34+
35+
/**
36+
* By default, zone.js will patch all possible macroTask and DomEvents
37+
* user can disable parts of macroTask/DomEvents patch by setting following flags
38+
* because those flags need to be set before `zone.js` being loaded, and webpack
39+
* will put import in the top of bundle, so user need to create a separate file
40+
* in this directory (for example: zone-flags.ts), and put the following flags
41+
* into that file, and then add the following code before importing zone.js.
42+
* import './zone-flags';
43+
*
44+
* The flags allowed in zone-flags.ts are listed here.
45+
*
46+
* The following flags will work for all browsers.
47+
*
48+
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch
49+
* requestAnimationFrame
50+
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
51+
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch
52+
* specified eventNames
53+
*
54+
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
55+
* with the following flag, it will bypass `zone.js` patch for IE/Edge
56+
*
57+
* (window as any).__Zone_enable_cross_context_check = true;
58+
*
59+
*/
60+
61+
/***************************************************************************************************
62+
* Zone JS is required by default for Angular itself.
63+
*/
64+
import 'zone.js/dist/zone'; // Included with Angular CLI.
65+
66+
/***************************************************************************************************
67+
* APPLICATION IMPORTS
68+
*/

aio/tools/examples/shared/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@angular/core": "~9.1.4",
2727
"@angular/elements": "~9.1.4",
2828
"@angular/forms": "~9.1.4",
29+
"@angular/localize": "~9.1.4",
2930
"@angular/platform-browser": "~9.1.4",
3031
"@angular/platform-browser-dynamic": "~9.1.4",
3132
"@angular/platform-server": "~9.1.4",

0 commit comments

Comments
 (0)