docs(i18n): apply guidelines and update TOCs (#3535)

This commit is contained in:
Kapunahele Wong 2017-04-12 15:18:38 -04:00 committed by Ward Bell
parent 8554e38dd2
commit 9bb44197ec
1 changed files with 140 additions and 120 deletions

View File

@ -3,34 +3,46 @@ include ../_util-fns
a#top a#top
:marked :marked
Angular's _internationalization_ (_i18n_) tools help make your app available in multiple languages. Angular's _internationalization_ (_i18n_) tools help make your app available in multiple languages.
## Table of contents # Contents
* [Angular and i18n template translation](#angular-i18n) * [Angular and i18n template translation](#angular-i18n)
* [Mark text with the _i18n_ attribute](#i18n-attribute) * [Mark text with the _i18n_ attribute](#i18n-attribute)
* [Help the translator with a description and intent](#help-translator)
* [Translate text without creating an element](#no-element)
* [Add _i18n-..._ translation attributes](#translate-attributes) * [Add _i18n-..._ translation attributes](#translate-attributes)
* [Handle singular and plural](#cardinality) * [Handle singular and plural](#cardinality)
* [Select among alternative texts](#select) * [Select among alternative texts](#select)
* [Create a translation source file with the **_ng-xi18n_ extraction tool**](#ng-xi18n) * [Create a translation source file with the **_ng-xi18n_ extraction tool**](#ng-xi18n)
* [Other translation formats](#other-formats)
* [Other options](#ng-xi18n-options)
* [Add an `npm` script for convenience](#npm-i18n-script)
* [Translate text messages](#translate) * [Translate text messages](#translate)
* [Create a localization folder](#localization-folder)
* [Translate text nodes](#translate-text-nodes)
* [Translate `plural` and `select`](#translate-plural-select)
* [Translate `plural`](#translate-plural)
* [Translate `select`](#translate-select)
* [The app before translation](#app-pre-translation)
* [Merge the completed translation file into the app](#merge) * [Merge the completed translation file into the app](#merge)
* [Merge with the JIT compiler](#jit) * [Merge with the JIT compiler](#jit)
* [SystemJS text plugin](#text-plugin)
* [Create translation providers](#create-translation-providers)
* [Bootstrap the app with translation providers](#bootstrap-the-app)
* [Internationalization with the AOT compiler](#aot) * [Internationalization with the AOT compiler](#aot)
* [Translation file maintenance and _id_ changes](#maintenance) * [Translation file maintenance and _id_ changes](#maintenance)
:marked :marked
**Try this** <live-example name="cb-i18n" title="i18n Example in Spanish">live example</live-example> Try this <live-example name="cb-i18n" title="i18n Example in Spanish">live example</live-example>
of a JIT-compiled app, translated into Spanish. of a JIT-compiled app, translated into Spanish.
a#angular-i18n a#angular-i18n
.l-main-section .l-main-section
:marked :marked
## Angular and _i18n_ template translation ## Angular and _i18n_ template translation
Application internationalization is a challenging, many-faceted effort that Application internationalization is a challenging, many-faceted effort that
takes dedication and enduring commitment. takes dedication and enduring commitment.
Angular's _i18n_ internationalization facilities can help. Angular's _i18n_ internationalization facilities can help.
@ -42,18 +54,18 @@ a#angular-i18n
:marked :marked
Practitioners of _internationalization_ refer to a translatable text as a "_message_". Practitioners of _internationalization_ refer to a translatable text as a "_message_".
This page uses the words "_text_" and "_message_" interchangably and in the combination, "_text message_". This page uses the words "_text_" and "_message_" interchangably and in the combination, "_text message_".
:marked :marked
The _i18n_ template translation process has four phases: The _i18n_ template translation process has four phases:
1. Mark static text messages in your component templates for translation. 1. Mark static text messages in your component templates for translation.
1. An angular _i18n_ tool extracts the marked messages into an industry standard translation source file. 1. An angular _i18n_ tool extracts the marked messages into an industry standard translation source file.
1. A translator edits that file, translating the extracted text messages into the target language, 1. A translator edits that file, translating the extracted text messages into the target language,
and returns the file to you. and returns the file to you.
1. The Angular compiler imports the completed translation files, 1. The Angular compiler imports the completed translation files,
replaces the original messages with translated text, and generates a new version of the application replaces the original messages with translated text, and generates a new version of the application
in the target language. in the target language.
@ -63,18 +75,18 @@ a#i18n-attribute
.l-main-section .l-main-section
:marked :marked
## Mark text with the _i18n_ attribute ## Mark text with the _i18n_ attribute
The Angular `i18n` attribute is a marker for translatable content. The Angular `i18n` attribute is a marker for translatable content.
Place it on every element tag whose fixed text should be translated. Place it on every element tag whose fixed text should be translated.
.alert.is-helpful .alert.is-helpful
:marked :marked
`i18n` is not an Angular _directive_. `i18n` is not an Angular _directive_.
It's a custom _attribute_, recognized by Angular tools and compilers. It's a custom _attribute_, recognized by Angular tools and compilers.
After translation, the compiler removes it. After translation, the compiler removes it.
:marked :marked
In the accompanying sample, an `<h1>` tag displays a simple English language greeting In the accompanying sample, an `<h1>` tag displays a simple English language greeting
that you translate into Spanish: that you translate into Spanish:
+makeExample('cb-i18n/ts/src/app/app.component.1.html', 'greeting', 'src/app/app.component.html')(format=".") +makeExample('cb-i18n/ts/src/app/app.component.1.html', 'greeting', 'src/app/app.component.html')(format=".")
:marked :marked
@ -82,36 +94,39 @@ a#i18n-attribute
+makeExample('cb-i18n/ts/src/app/app.component.1.html', 'i18n-attribute', 'src/app/app.component.html')(format=".") +makeExample('cb-i18n/ts/src/app/app.component.1.html', 'i18n-attribute', 'src/app/app.component.html')(format=".")
a#help-translator
:marked :marked
### Help the translator with a _description_ and _intent_ ### Help the translator with a _description_ and _intent_
In order to translate it accurately, the translator may In order to translate it accurately, the translator may
need a description of the message. need a description of the message.
Assign a description to the i18n attribute: Assign a description to the i18n attribute:
+makeExample('cb-i18n/ts/src/app/app.component.1.html', 'i18n-attribute-desc', 'src/app/app.component.html')(format=".") +makeExample('cb-i18n/ts/src/app/app.component.1.html', 'i18n-attribute-desc', 'src/app/app.component.html')(format=".")
:marked :marked
In order to deliver a correct translation, the translator may need to In order to deliver a correct translation, the translator may need to
know your _intent_&mdash;the true _meaning_ of the text know your _intent_&mdash;the true _meaning_ of the text
within _this particular_ application context. within _this particular_ application context.
In front of the description, add some contextual meaning to the assigned string, In front of the description, add some contextual meaning to the assigned string,
separating it from the description with the `|` character (`<meaning>|<description>`): separating it from the description with the `|` character (`<meaning>|<description>`):
+makeExample('cb-i18n/ts/src/app/app.component.html', 'i18n-attribute-meaning', 'src/app/app.component.html')(format=".") +makeExample('cb-i18n/ts/src/app/app.component.html', 'i18n-attribute-meaning', 'src/app/app.component.html')(format=".")
:marked :marked
While all appearances of a message with the _same_ meaning have the _same_ translation, While all appearances of a message with the _same_ meaning have the _same_ translation,
a message with *a variety of possible meanings* could have different translations. a message with *a variety of possible meanings* could have different translations.
The Angular extraction tool preserves both the _meaning_ and the _description_ in the translation source file The Angular extraction tool preserves both the _meaning_ and the _description_ in the translation source file
to facilitiate contextually-specific translations. to facilitiate contextually-specific translations.
a#no-element
:marked
### Translate text without creating an element ### Translate text without creating an element
Suppose there is a stretch of text that you'd like to translate. Suppose there is a stretch of text that you'd like to translate.
You could wrap it in a `<span>` tag but for some reason (CSS comes to mind) You could wrap it in a `<span>` tag but for some reason (CSS comes to mind)
you don't want to create a new DOM element merely to facilitate translation. you don't want to create a new DOM element merely to facilitate translation.
Here are two techniques to try. Here are two techniques to try.
(1) Wrap the text in an `<ng-container>` element. The `<ng-container>` is never renderered: (1) Wrap the text in an `<ng-container>` element. The `<ng-container>` is never renderered:
@ -132,10 +147,10 @@ a#translate-attributes
+makeExample('cb-i18n/ts/src/app/app.component.1.html', 'i18n-title', 'src/app/app.component.html')(format=".") +makeExample('cb-i18n/ts/src/app/app.component.1.html', 'i18n-title', 'src/app/app.component.html')(format=".")
:marked :marked
The `title` attribute needs to be translated. The `title` attribute needs to be translated.
Angular i18n support has more translation attributes in the form,`i18n-x`, where `x` is the Angular i18n support has more translation attributes in the form,`i18n-x`, where `x` is the
name of the attribute to translate. name of the attribute to translate.
To translate the `title` on the `img` tag from the previous example, write: To translate the `title` on the `img` tag from the previous example, write:
+makeExample('cb-i18n/ts/src/app/app.component.html', 'i18n-title-translate', 'src/app/app.component.html')(format=".") +makeExample('cb-i18n/ts/src/app/app.component.html', 'i18n-title-translate', 'src/app/app.component.html')(format=".")
@ -147,22 +162,22 @@ a#translate-attributes
a#cardinality a#cardinality
:marked :marked
## Handle singular and plural ## Handle singular and plural
Different languages have different pluralization rules. Different languages have different pluralization rules.
Suppose your application says something about a collection of wolves. Suppose your application says something about a collection of wolves.
In English, depending upon the number of wolves, you could display "no wolves", "one wolf", "two wolves", or "a wolf pack". In English, depending upon the number of wolves, you could display "no wolves", "one wolf", "two wolves", or "a wolf pack".
Other languages might express the _cardinality_ differently. Other languages might express the _cardinality_ differently.
Here's how you could mark up the component template to display the phrase appropriate to the number of wolves: Here's how you could mark up the component template to display the phrase appropriate to the number of wolves:
+makeExample('cb-i18n/ts/src/app/app.component.html', 'i18n-plural', 'src/app/app.component.html')(format=".") +makeExample('cb-i18n/ts/src/app/app.component.html', 'i18n-plural', 'src/app/app.component.html')(format=".")
:marked :marked
* The first parameter is the key. It is bound to the component property (`wolves`) * The first parameter is the key. It is bound to the component property (`wolves`)
that determines the number of wolves. that determines the number of wolves.
* The second parameter identifies this as a `plural` translation type. * The second parameter identifies this as a `plural` translation type.
* The third parameter defines a pluralization pattern consisting of pluralization * The third parameter defines a pluralization pattern consisting of pluralization
categories and their matching values. categories and their matching values.
Pluralization categories include: Pluralization categories include:
@ -177,7 +192,7 @@ a#cardinality
* When you're talking about one wolf, you could write `=1 {one wolf}`. * When you're talking about one wolf, you could write `=1 {one wolf}`.
* For zero wolves, you could write `=0 {no wolves}`. * For zero wolves, you could write `=0 {no wolves}`.
* For two wolves, you could write `=2 {two wolves}`. * For two wolves, you could write `=2 {two wolves}`.
You could keep this up for three, four, and every other number of wolves. You could keep this up for three, four, and every other number of wolves.
Or you could specify the **`other`** category as a catch-all for any unmatched cardinality Or you could specify the **`other`** category as a catch-all for any unmatched cardinality
@ -187,8 +202,8 @@ a#cardinality
:marked :marked
This syntax conforms to the This syntax conforms to the
<a href="http://userguide.icu-project.org/formatparse/messages" target="_blank" title="ICU Message Format">ICU Message Format</a> <a href="http://userguide.icu-project.org/formatparse/messages" target="_blank" title="ICU Message Format">ICU Message Format</a>
that derives from the that derives from the
<a href="http://cldr.unicode.org/" target="_blank" title="CLDR">Common Locale Data Repository (CLDR),</a> <a href="http://cldr.unicode.org/" target="_blank" title="CLDR">Common Locale Data Repository (CLDR)</a>,
which specifies the which specifies the
<a href="http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules" target="_blank" title="Pluralization Rules">pluralization rules</a>. <a href="http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules" target="_blank" title="Pluralization Rules">pluralization rules</a>.
@ -198,12 +213,12 @@ a#select
The application displays different text depending upon whether the hero is male or female. The application displays different text depending upon whether the hero is male or female.
These text alternatives require translation too. These text alternatives require translation too.
You can handle this with a `select` translation. You can handle this with a `select` translation.
A `select` also follows the A `select` also follows the
<a href="http://userguide.icu-project.org/formatparse/messages" target="_blank" title="ICU Message Format">ICU message syntax</a>. <a href="http://userguide.icu-project.org/formatparse/messages" target="_blank" title="ICU Message Format">ICU message syntax</a>.
You choose among alternative translation based on a string value instead of a number. You choose among alternative translation based on a string value instead of a number.
The following format message in the component template binds to the component's `gender` The following format message in the component template binds to the component's `gender`
property, which outputs either an "m" or an "f". property, which outputs either an "m" or an "f".
The message maps those values to the appropriate translation: The message maps those values to the appropriate translation:
@ -213,19 +228,19 @@ a#ng-xi18n
.l-main-section .l-main-section
:marked :marked
## Create a translation source file with the _ng-xi18n_ tool ## Create a translation source file with the _ng-xi18n_ tool
Use the **_ng-xi18n_ extraction tool** to extract the `i18n`-marked texts Use the **_ng-xi18n_ extraction tool** to extract the `i18n`-marked texts
into a translation source file in an industry standard format. into a translation source file in an industry standard format.
This is an Angular CLI tool in the `@angular/compiler-cli` npm package. This is an Angular CLI tool in the `@angular/compiler-cli` npm package.
If you haven't already installed the CLI and its `platform-server` peer dependency, do so now: If you haven't already installed the CLI and its `platform-server` peer dependency, do so now:
code-example(language="sh" class="code-shell"). code-example(language="sh" class="code-shell").
npm install @angular/compiler-cli @angular/platform-server --save npm install @angular/compiler-cli @angular/platform-server --save
:marked :marked
Open a terminal window at the root of the application project and enter the `ng-xi18n` command: Open a terminal window at the root of the application project and enter the `ng-xi18n` command:
code-example(language="sh" class="code-shell"). code-example(language="sh" class="code-shell").
./node_modules/.bin/ng-xi18n ./node_modules/.bin/ng-xi18n
@ -241,7 +256,7 @@ a#other-formats
:marked :marked
### Other translation formats ### Other translation formats
You can generate a file named **`messages.xmb`** in the You can generate a file named **`messages.xmb`** in the
<a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" target="_blank">XML Message Bundle (XMB)</a> format <a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" target="_blank">XML Message Bundle (XMB)</a> format
by adding the `--i18nFormat=xmb` flag. by adding the `--i18nFormat=xmb` flag.
@ -254,8 +269,8 @@ code-example(language="sh" class="code-shell").
a#ng-xi18n-options a#ng-xi18n-options
:marked :marked
### Other options ### Other options
You may have to specify additional options. You may have to specify additional options.
For example, if the `tsconfig.json` TypeScript configuration For example, if the `tsconfig.json` TypeScript configuration
file is located somewhere other than in the root folder, file is located somewhere other than in the root folder,
you must identify the path to it with the `-p` option: you must identify the path to it with the `-p` option:
code-example(language="sh" class="code-shell"). code-example(language="sh" class="code-shell").
@ -266,12 +281,12 @@ code-example(language="sh" class="code-shell").
a#npm-i18n-script a#npm-i18n-script
:marked :marked
### Add an _npm_ script for convenience ### Add an _npm_ script for convenience
Consider adding a convenience shortcut to the `scripts` section of the `package.json` Consider adding a convenience shortcut to the `scripts` section of the `package.json`
to make the command easier to remember and run: to make the command easier to remember and run:
code-example(format='.' language='sh' ). code-example(format='.' language='sh' ).
"scripts": { "scripts": {
"i18n": "ng-xi18n", "i18n": "ng-xi18n",
... ...
} }
:marked :marked
@ -281,17 +296,17 @@ code-example(language="sh" class="code-shell").
npm run i18n -- -p path/to/tsconfig.json npm run i18n -- -p path/to/tsconfig.json
npm run i18n -- --i18nFormat=xmb -p path/to/tsconfig.json npm run i18n -- --i18nFormat=xmb -p path/to/tsconfig.json
:marked :marked
Note the `--` flag before the options. Note the `--` flag before the options.
It tells _npm_ to pass every flag thereafter to `ng-xi18n`. It tells _npm_ to pass every flag thereafter to `ng-xi18n`.
a#translate a#translate
.l-main-section .l-main-section
:marked :marked
## Translate text messages ## Translate text messages
The `ng-xi18n` command generates a translation source file The `ng-xi18n` command generates a translation source file
in the project root folder named `messages.xlf`. in the project root folder named `messages.xlf`.
The next step is to translate the English language template The next step is to translate the English language template
text into the specific language translation text into the specific language translation
files. The cookbook sample creates a Spanish translation file. files. The cookbook sample creates a Spanish translation file.
@ -301,22 +316,23 @@ a#localization-folder
You will probably translate into more than one other language so it's a good idea You will probably translate into more than one other language so it's a good idea
for the project structure to reflect your entire internationalization effort. for the project structure to reflect your entire internationalization effort.
One approach is to dedicate a folder to localization and store related assets One approach is to dedicate a folder to localization and store related assets,
(for example, internationalization files) there. such as internationalization files, there.
.l-sub-section .l-sub-section
:marked :marked
Localization and internationalization are Localization and internationalization are
<a href="https://en.wikipedia.org/wiki/Internationalization_and_localization" target="_blank">different but closely related terms</a>. <a href="https://en.wikipedia.org/wiki/Internationalization_and_localization" target="_blank">different but closely related terms</a>.
:marked :marked
This cookbook follows that suggestion. It has a `locale` folder under the `src/`. This cookbook follows that suggestion. It has a `locale` folder under the `src/`.
Assets within the folder carry a filename extension that matches a language-culture code from a Assets within the folder carry a filename extension that matches a language-culture code from a
<a href="https://msdn.microsoft.com/en-us/library/ee825488(v=cs.20).aspx" target="_blank">well-known codeset</a>. <a href="https://msdn.microsoft.com/en-us/library/ee825488(v=cs.20).aspx" target="_blank">well-known codeset</a>.
Make a copy of the `messages.xlf` file, put it in the `locale` folder and Make a copy of the `messages.xlf` file, put it in the `locale` folder and
rename it `messages.es.xlf`for the Spanish language translation. rename it `messages.es.xlf`for the Spanish language translation.
Do the same for each target language. Do the same for each target language.
a#translate-text-nodes
:marked
### Translate text nodes ### Translate text nodes
In the real world, you send the `messages.es.xlf` file to a Spanish translator who fills in the translations In the real world, you send the `messages.es.xlf` file to a Spanish translator who fills in the translations
using one of the using one of the
@ -327,8 +343,8 @@ a#localization-folder
+makeExample('cb-i18n/ts/src/locale/messages.es.xlf.html', 'translated-hello', 'src/locale/messages.es.xlf (<trans-unit>)')(format=".") +makeExample('cb-i18n/ts/src/locale/messages.es.xlf.html', 'translated-hello', 'src/locale/messages.es.xlf (<trans-unit>)')(format=".")
:marked :marked
This XML element represents the translation of the `<h1>` greeting tag you marked with the `i18n` attribute. This XML element represents the translation of the `<h1>` greeting tag you marked with the `i18n` attribute.
Using the _source_, _description_, and _meaning_ elements to guide your translation, Using the _source_, _description_, and _meaning_ elements to guide your translation,
replace the `<target/>` tag with the Spanish greeting: replace the `<target/>` tag with the Spanish greeting:
+makeExample('cb-i18n/ts/src/locale/messages.es.xlf.html', 'translated-hello', 'src/locale/messages.es.xlf (<trans-unit>, after translation)')(format=".") +makeExample('cb-i18n/ts/src/locale/messages.es.xlf.html', 'translated-hello', 'src/locale/messages.es.xlf (<trans-unit>, after translation)')(format=".")
@ -350,31 +366,33 @@ a#translate-plural-select
## Translate _plural_ and _select_ ## Translate _plural_ and _select_
Translating _plural_ and _select_ messages is a little tricky. Translating _plural_ and _select_ messages is a little tricky.
The `<source>` tag is empty for `plural` and `select` translation The `<source>` tag is empty for `plural` and `select` translation
units, which makes them hard to correlate with the original template. units, which makes them hard to correlate with the original template.
The `XLIFF` format doesn't yet support the ICU rules; it soon will. The `XLIFF` format doesn't yet support the ICU rules.
However, the `XMB` format does support the ICU rules. However, the `XMB` format does support the ICU rules.
You'll just have to look for them in relation to other translation units that you recognize from elsewhere in the source template. You'll just have to look for them in relation to other translation units that you recognize from elsewhere in the source template.
In this example, you know the translation unit for the `select` must be just below the translation unit for the logo. In this example, you know the translation unit for the `select` must be just below the translation unit for the logo.
a#translate-plural
:marked :marked
### Translate _plural_ ### Translate _plural_
To translate a `plural`, translate its ICU format match values: To translate a `plural`, translate its ICU format match values:
+makeExample('cb-i18n/ts/src/locale/messages.es.xlf.html', 'translated-plural', 'src/locale/messages.es.xlf (<trans-unit>)')(format=".") +makeExample('cb-i18n/ts/src/locale/messages.es.xlf.html', 'translated-plural', 'src/locale/messages.es.xlf (<trans-unit>)')(format=".")
a#translate-select
:marked :marked
### Translate _select_ ### Translate _select_
The `select` behaves a little differently. Here again is the ICU format message in the component template: The `select` behaves a little differently. Here again is the ICU format message in the component template:
+makeExample('cb-i18n/ts/src/app/app.component.html', 'i18n-select', 'src/app/app.component.html')(format=".") +makeExample('cb-i18n/ts/src/app/app.component.html', 'i18n-select', 'src/app/app.component.html')(format=".")
:marked :marked
The extraction tool broke that into _two_ translation units. The extraction tool broke that into _two_ translation units.
The first unit contains the text that was _outside_ the `select`. The first unit contains the text that was _outside_ the `select`.
In place of the `select` is a placeholder, `<x id="ICU">`, that represents the `select` message. In place of the `select` is a placeholder, `<x id="ICU">`, that represents the `select` message.
Translate the text and leave the placeholder where it is. Translate the text and leave the placeholder where it is.
+makeExample('cb-i18n/ts/src/locale/messages.es.xlf.html', 'translate-select-1', 'src/locale/messages.es.xlf (<trans-unit>)')(format=".") +makeExample('cb-i18n/ts/src/locale/messages.es.xlf.html', 'translate-select-1', 'src/locale/messages.es.xlf (<trans-unit>)')(format=".")
@ -391,7 +409,7 @@ a#translate-plural-select
.l-main-content .l-main-content
:marked :marked
The entire template translation is complete. It's The entire template translation is complete. It's
time to incorporate that translation into the application. time to incorporate that translation into the application.
#app-pre-translation #app-pre-translation
@ -421,27 +439,27 @@ a#merge
To merge the translated text into component templates, To merge the translated text into component templates,
compile the application with the completed translation file. compile the application with the completed translation file.
The process is the same whether the file is in `.xlf` format or The process is the same whether the file is in `.xlf` format or
in another format (`.xlif` and `.xtb`) that Angular understands. in another format that Angular understands, such as `.xlif` or `.xtb`.
You provide the Angular compiler with three new pieces of information: You provide the Angular compiler with three new pieces of information:
* the translation file * The translation file.
* the translation file format * The translation file format.
* the <a href="https://en.wikipedia.org/wiki/XLIFF" target="_blank">_Locale ID_</a> * The <a href="https://en.wikipedia.org/wiki/XLIFF" target="_blank">_Locale ID_</a>
(`es` or `en-US` for instance) (`es` or `en-US` for instance).
_How_ you provide this information depends upon whether you compile with _How_ you provide this information depends upon whether you compile with
the JIT (_Just-in-Time_) compiler or the AOT (_Ahead-of-Time_) compiler. the JIT (_Just-in-Time_) compiler or the AOT (_Ahead-of-Time_) compiler.
* With [JIT](#jit), you provide the information at bootstrap time. * With [JIT](#jit), you provide the information at bootstrap time.
* With [AOT](#aot), you pass the information as `ngc` options. * With [AOT](#aot), you pass the information as `ngc` options.
a#jit a#jit
.l-main-section .l-main-section
:marked :marked
### Merge with the JIT compiler ### Merge with the JIT compiler
The JIT compiler compiles the application in the browser as the application loads. The JIT compiler compiles the application in the browser as the application loads.
Translation with the JIT compiler is a dynamic process of: Translation with the JIT compiler is a dynamic process of:
@ -458,7 +476,7 @@ a#jit
a#text-plugin a#text-plugin
:marked :marked
### SystemJS Text plugin ### SystemJS text plugin
Notice the SystemJS mapping of `text` to a `systemjs-text-plugin.js`. Notice the SystemJS mapping of `text` to a `systemjs-text-plugin.js`.
With the help of a text plugin, SystemJS can read any file as raw text and With the help of a text plugin, SystemJS can read any file as raw text and
@ -468,6 +486,7 @@ a#text-plugin
SystemJS doesn't ship with a raw text plugin but it's easy to add. SystemJS doesn't ship with a raw text plugin but it's easy to add.
Create the following `systemjs-text-plugin.js` in the `src/` folder: Create the following `systemjs-text-plugin.js` in the `src/` folder:
+makeExample('cb-i18n/ts/src/systemjs-text-plugin.js', null, 'src/systemjs-text-plugin.js')(format='.') +makeExample('cb-i18n/ts/src/systemjs-text-plugin.js', null, 'src/systemjs-text-plugin.js')(format='.')
a#create-translation-providers
:marked :marked
### Create translation providers ### Create translation providers
@ -475,10 +494,10 @@ a#text-plugin
while compiling the application: while compiling the application:
* `TRANSLATIONS` is a string containing the content of the translation file. * `TRANSLATIONS` is a string containing the content of the translation file.
* `TRANSLATIONS_FORMAT` is the format of the file: `xlf`, `xlif` or `xtb`. * `TRANSLATIONS_FORMAT` is the format of the file: `xlf`, `xlif`, or `xtb`.
* `LOCALE_ID` is the locale of the target language. * `LOCALE_ID` is the locale of the target language.
The `getTranslationProviders` function in the following `src/app/i18n-providers.ts` The `getTranslationProviders()` function in the following `src/app/i18n-providers.ts`
creates those providers based on the user's _locale_ creates those providers based on the user's _locale_
and the corresponding translation file: and the corresponding translation file:
+makeExample('cb-i18n/ts/src/app/i18n-providers.ts', null, 'src/app/i18n-providers.ts') +makeExample('cb-i18n/ts/src/app/i18n-providers.ts', null, 'src/app/i18n-providers.ts')
@ -490,27 +509,28 @@ a#text-plugin
The function returns an empty `noProviders` array as a `Promise`. The function returns an empty `noProviders` array as a `Promise`.
It must return a `Promise` because this function could read a translation file asynchronously from the server. It must return a `Promise` because this function could read a translation file asynchronously from the server.
1. It creates a transaction filename from the locale according to the name and location convention 1. It creates a transaction filename from the locale according to the name and location convention
[described earlier](#localization-folder). [described earlier](#localization-folder).
1. The `getTranslationsWithSystemJs` method reads the translation and returns the contents as a string. 1. The `getTranslationsWithSystemJs()` method reads the translation and returns the contents as a string.
Notice that it appends `!text` to the filename, telling SystemJS to use the [text plugin](#text-plugin). Notice that it appends `!text` to the filename, telling SystemJS to use the [text plugin](#text-plugin).
1. The callback composes a providers array with the three translation providers. 1. The callback composes a providers array with the three translation providers.
1. Finally, `getTranslationProviders` returns the entire effort as a promise. 1. Finally, `getTranslationProviders()` returns the entire effort as a promise.
a#bootstrap-the-app
:marked
### Bootstrap the app with translation providers ### Bootstrap the app with translation providers
The Angular `bootstrapModule` method has a second, _options_ parameter The Angular `bootstrapModule()` method has a second _options_ parameter
that can influence the behavior of the compiler. that can influence the behavior of the compiler.
You'll create an _options_ object with the translation providers from `getTranslationProviders` You'll create an _options_ object with the translation providers from `getTranslationProviders()`
and pass it to `bootstrapModule`. and pass it to `bootstrapModule`.
Open the `src/main.ts` and modify the bootstrap code as follows: Open the `src/main.ts` and modify the bootstrap code as follows:
+makeExample('cb-i18n/ts/src/main.ts', null, 'src/main.ts')(format=".") +makeExample('cb-i18n/ts/src/main.ts', null, 'src/main.ts')(format=".")
:marked :marked
Notice that it waits for the `getTranslationProviders` promise to resolve before Notice that it waits for the `getTranslationProviders()` promise to resolve before
bootstrapping the app. bootstrapping the app.
The app is now _internationalized_ for English and Spanish and there is a clear path for adding The app is now _internationalized_ for English and Spanish and there is a clear path for adding
@ -519,40 +539,40 @@ a#text-plugin
a#aot a#aot
.l-main-section .l-main-section
:marked :marked
### _Internationalize_ with the AOT compiler ### _Internationalization_ with the AOT compiler
The JIT compiler translates the application into the target language The JIT compiler translates the application into the target language
while compiling dynamically in the browser. while compiling dynamically in the browser.
That's flexible but may not be fast enough for your users. That's flexible but may not be fast enough for your users.
The AOT (_Ahead-of-Time_) compiler is part of a build process that The AOT (_Ahead-of-Time_) compiler is part of a build process that
produces a small, fast, ready-to-run application package. produces a small, fast, ready-to-run application package.
When you internationalize with the AOT compiler, you pre-build When you internationalize with the AOT compiler, you pre-build
a separate application package for each a separate application package for each
language. Then in the host web page (`index.html`), language. Then in the host web page, in this case `index.html`,
you determine which language the user needs you determine which language the user needs
and serve the appropriate application package. and serve the appropriate application package.
This cookbook doesn't cover how to build multiple application packages and This cookbook doesn't cover how to build multiple application packages and
serve them according to the user's language preference. serve them according to the user's language preference.
It does explain the few steps necessary to tell the AOT compiler to apply a translations file. It does explain the few steps necessary to tell the AOT compiler to apply a translations file.
Internationalization with the AOT compiler requires Internationalization with the AOT compiler requires
some setup specifically for AOT compilation. some setup specifically for AOT compilation.
Start with the application project as shown Start with the application project as shown
[just before merging the translation file](#app-pre-translation) [just before merging the translation file](#app-pre-translation)
and refer to the [AOT cookbook](aot-compiler.html) to make it _AOT-ready_. and refer to the [AOT cookbook](aot-compiler.html) to make it _AOT-ready_.
Next, issue an `ngc` compile command for each supported language (including English). Next, issue an `ngc` compile command for each supported language, including English.
The result is a separate version of the application for each language. The result is a separate version of the application for each language.
Tell AOT how to translate by adding three options to the `ngc` command: Tell AOT how to translate by adding three options to the `ngc` command:
* `--i18nFile`: the path to the translation file * `--i18nFile`: the path to the translation file.
* `--locale`: the name of the locale * `--locale`: the name of the locale.
* `--i18nFormat`: the format of the localization file * `--i18nFormat`: the format of the localization file.
For this sample, the Spanish language command would be For this sample, the Spanish language command would be:
code-example(language="sh" class="code-shell"). code-example(language="sh" class="code-shell").
./node_modules/.bin/ngc --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf ./node_modules/.bin/ngc --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf
@ -565,19 +585,19 @@ code-example(language="sh" class="code-shell").
a#maintenance a#maintenance
:marked :marked
## Translation file maintenance and _id_ changes ## Translation file maintenance and _id_ changes
As the application evolves, you will change the _i18n_ markup As the application evolves, you will change the _i18n_ markup
and re-run the `ng-xi18n` extraction tool many times. and re-run the `ng-xi18n` extraction tool many times.
The _new_ markup that you add is not a problem; The _new_ markup that you add is not a problem;
but _most_ changes to _existing_ markup trigger but _most_ changes to existing markup trigger
generation of _new_ `id`s for the affected translation units. generation of new `id`s for the affected translation units.
After an `id` changes, the translation files are no longer in-sync. After an `id` changes, the translation files are no longer in sync.
**All translated versions of the application will fail** during re-compilation. **All translated versions of the application will fail** during re-compilation.
The error messages identify the old `id`s that are no longer valid but The error messages identify the old `id`s that are no longer valid but
they don't tell you what the new `id`s should be. they don't tell you what the new `id`s should be.
**Commit all translation message files to source control**, **Commit all translation message files to source control**,
especially the English source `messages.xlf`. especially the English source `messages.xlf`.
The difference between the old and the new `messages.xlf` file The difference between the old and the new `messages.xlf` file
help you find and update `id` changes across your translation files. help you find and update `id` changes across your translation files.