docs(i18n): apply guidelines and update TOCs (#3535)
This commit is contained in:
parent
8554e38dd2
commit
9bb44197ec
|
@ -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_—the true _meaning_ of the text
|
know your _intent_—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.
|
||||||
|
|
Loading…
Reference in New Issue