docs(i18n): copy edits to internationalization cookbook (#2980)
* docs(i18n): copy edits * docs(i18n): copy edit to data.json * docs(i18n): Ward requested copy edits
This commit is contained in:
parent
9a3cbd611f
commit
41833ed08a
|
@ -48,7 +48,7 @@
|
|||
|
||||
"i18n": {
|
||||
"title": "Internationalization (i18n)",
|
||||
"intro": "Translate the app's template text into multiple languages"
|
||||
"intro": "Translate the app's template text into multiple languages."
|
||||
},
|
||||
|
||||
"set-document-title": {
|
||||
|
|
|
@ -2,7 +2,7 @@ include ../_util-fns
|
|||
|
||||
a#top
|
||||
: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
|
||||
|
||||
|
@ -11,11 +11,11 @@ a#top
|
|||
* [Add _i18n-..._ translation attributes](#translate-attributes)
|
||||
* [Handle singular and plural](#cardinality)
|
||||
* [Select among alternative texts](#select)
|
||||
* [Use the **_ng-xi18n_ extraction tool** to create a translation source file](#ng-xi18n)
|
||||
* [Translate](#translate)
|
||||
* [Create a translation source file with the **_ng-xi18n_ extraction tool**](#ng-xi18n)
|
||||
* [Translate text messages](#translate)
|
||||
* [Merge the completed translation file into the app](#merge)
|
||||
* [JIT configuration](#jit)
|
||||
* [AOT configuration](#aot)
|
||||
* [Merge with the JIT compiler](#jit)
|
||||
* [Internationalization with the AOT compiler](#aot)
|
||||
* [Translation file maintenance and _id_ changes](#maintenance)
|
||||
|
||||
:marked
|
||||
|
@ -32,7 +32,7 @@ a#angular-i18n
|
|||
takes dedication and enduring commitment.
|
||||
Angular's _i18n_ internationalization facilities can help.
|
||||
|
||||
This page describes the _i18n_ tools to assist translation of component template text
|
||||
This page describes the _i18n_ tools available to assist translation of component template text
|
||||
into multiple languages.
|
||||
|
||||
|
||||
|
@ -55,7 +55,7 @@ a#angular-i18n
|
|||
replaces the original messages with translated text, and generates a new version of the application
|
||||
in the target language.
|
||||
|
||||
You build and deploy a separate version of the application for each supported language.
|
||||
You need to build and deploy a separate version of the application for each supported language.
|
||||
|
||||
a#i18n-attribute
|
||||
.l-main-section
|
||||
|
@ -69,10 +69,11 @@ a#i18n-attribute
|
|||
:marked
|
||||
`i18n` is not an Angular _directive_.
|
||||
It's a custom _attribute_, recognized by Angular tools and compilers.
|
||||
It will be removed by the compiler _after_ translation.
|
||||
After translation, the compiler removes it.
|
||||
|
||||
:marked
|
||||
In the accompanying sample, an `<h1>` tag displays a simple English language greeting which you will translate to Spanish:
|
||||
In the accompanying sample, an `<h1>` tag displays a simple English language greeting
|
||||
that you translate into Spanish:
|
||||
+makeExample('cb-i18n/ts/app/app.component.1.html', 'greeting', 'app/app.component.html')(format=".")
|
||||
:marked
|
||||
Add the `i18n` attribute to the tag to mark it for translation.
|
||||
|
@ -82,30 +83,31 @@ a#i18n-attribute
|
|||
:marked
|
||||
### Help the translator with a _description_ and _intent_
|
||||
|
||||
The translator may need a description of the message to translate it accurately.
|
||||
In order to translate it accurately, the translator may
|
||||
need a description of the message.
|
||||
Assign a description to the i18n attribute:
|
||||
|
||||
+makeExample('cb-i18n/ts/app/app.component.1.html', 'i18n-attribute-desc', 'app/app.component.html')(format=".")
|
||||
|
||||
:marked
|
||||
The translator may need to know your _intent_ —
|
||||
the true _meaning_ of the text within _this particular_ application context —
|
||||
in order to deliver a correct translation.
|
||||
Add some contextual meaning to the assigned string, in front of the description,
|
||||
In order to deliver a correct translation, the translator may need to
|
||||
know your _intent_—the true _meaning_ of the text
|
||||
within _this particular_ application context.
|
||||
In front of the description, add some contextual meaning to the assigned string,
|
||||
separating it from the description with the `|` character (`<meaning>|<description>`):
|
||||
|
||||
+makeExample('cb-i18n/ts/app/app.component.html', 'i18n-attribute-meaning', 'app/app.component.html')(format=".")
|
||||
|
||||
:marked
|
||||
While all appearances of a message with the _same_ meaning have the _same_ translation,
|
||||
a message with *different 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
|
||||
to facilitiate contextually-specific translations.
|
||||
|
||||
### Translate text without creating an element
|
||||
|
||||
Suppose there is a stretch of text that you'd like to translate.
|
||||
You could wrap it in a `<span>` 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.
|
||||
|
||||
Here are two techniques to try.
|
||||
|
@ -123,7 +125,7 @@ a#i18n-attribute
|
|||
a#translate-attributes
|
||||
:marked
|
||||
## Add _i18n-..._ translation attributes
|
||||
You've added an image to your template. You care about accessibility too so you add a `title` tag:
|
||||
You've added an image to your template. You care about accessibility too so you add a `title` attribute:
|
||||
|
||||
+makeExample('cb-i18n/ts/app/app.component.1.html', 'i18n-title', 'app/app.component.html')(format=".")
|
||||
|
||||
|
@ -150,14 +152,16 @@ a#cardinality
|
|||
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.
|
||||
|
||||
Here's how you could markup 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/app/app.component.html', 'i18n-plural', 'app/app.component.html')(format=".")
|
||||
|
||||
:marked
|
||||
* The first parameter is the key. It will be bound to the component property (`wolves`) that determines the number of wolves.
|
||||
* The second parameter indentifies this as a `plural` translation type.
|
||||
* The third parameter defines a pluralization pattern consisting of pluralization categories and their matching values.
|
||||
* The first parameter is the key. It is bound to the component property (`wolves`)
|
||||
that determines the number of wolves.
|
||||
* The second parameter identifies this as a `plural` translation type.
|
||||
* The third parameter defines a pluralization pattern consisting of pluralization
|
||||
categories and their matching values.
|
||||
|
||||
Pluralization categories include:
|
||||
* =0
|
||||
|
@ -179,14 +183,14 @@ a#cardinality
|
|||
:marked
|
||||
This syntax conforms to the
|
||||
<a href="http://userguide.icu-project.org/formatparse/messages" target="_blank" title="ICU Message Format">ICU Message Format</a>
|
||||
which derives from the
|
||||
<a href="http://cldr.unicode.org/" target="_blank" title="CLDR">Common Locale Data Repository (CLDR)</a>
|
||||
that derives from the
|
||||
<a href="http://cldr.unicode.org/" target="_blank" title="CLDR">Common Locale Data Repository (CLDR),</a>
|
||||
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#select
|
||||
:marked
|
||||
## Select
|
||||
## Select among alternative texts
|
||||
The application displays different text depending upon whether the hero is male or female.
|
||||
These text alternatives require translation too.
|
||||
|
||||
|
@ -195,7 +199,8 @@ a#select
|
|||
<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.
|
||||
|
||||
The following format message in the component template binds to the component's `gender` property which outputs either an 'm' or an 'f'.
|
||||
The following format message in the component template binds to the component's `gender`
|
||||
property, which outputs either an "m" or an "f".
|
||||
The message maps those values to the appropriate translation:
|
||||
|
||||
+makeExample('cb-i18n/ts/app/app.component.html', 'i18n-select', 'app/app.component.html')(format=".")
|
||||
|
@ -222,10 +227,10 @@ code-example(language="sh" class="code-shell").
|
|||
|
||||
.l-sub-section
|
||||
:marked
|
||||
Windows users may have to quote the command: like this `"./node_modules/.bin/ng-xi18n"`
|
||||
Windows users may have to quote the command like this: `"./node_modules/.bin/ng-xi18n"`
|
||||
|
||||
:marked
|
||||
By default the tool generates a translation file named **`messages.xlf`** in the
|
||||
By default, the tool generates a translation file named **`messages.xlf`** in the
|
||||
<a href="https://en.wikipedia.org/wiki/XLIFF" target="_blank">XML Localisation Interchange File Format (XLIFF, version 1.2)</a>.
|
||||
|
||||
a#other-formats
|
||||
|
@ -246,7 +251,8 @@ a#ng-xi18n-options
|
|||
:marked
|
||||
### Other options
|
||||
You may have to specify additional options.
|
||||
For example, if the `tsconfig.json` TypeScript configuration file is located other than in the root folder,
|
||||
For example, if the `tsconfig.json` TypeScript configuration
|
||||
file is located somewhere other than in the root folder,
|
||||
you must identify the path to it with the `-p` option:
|
||||
code-example(language="sh" class="code-shell").
|
||||
./node_modules/.bin/ng-xi18n -p path/to/tsconfig.json
|
||||
|
@ -272,15 +278,17 @@ code-example(language="sh" class="code-shell").
|
|||
npm run i18n -- --i18nFormat=xmb -p path/to/tsconfig.json
|
||||
:marked
|
||||
Note the `--` flag before the options.
|
||||
It tells _npm_ that every flag thereafter should be passed through to `ng-xi18n`.
|
||||
It tells _npm_ to pass every flag thereafter to `ng-xi18n`.
|
||||
|
||||
a#translate
|
||||
.l-main-section
|
||||
:marked
|
||||
## Translate _los mensajes de texto_
|
||||
## Translate text messages
|
||||
|
||||
The `ng-xi18n` command generated a translation source file in the project root folder named `messages.xlf`.
|
||||
The next step is to translate the English language template text into the specific language translation
|
||||
The `ng-xi18n` command generates a translation source file
|
||||
in the project root folder named `messages.xlf`.
|
||||
The next step is to translate the English language template
|
||||
text into the specific language translation
|
||||
files. The cookbook sample creates a Spanish translation file.
|
||||
|
||||
a#localization-folder
|
||||
|
@ -291,13 +299,13 @@ a#localization-folder
|
|||
for the project structure to reflect your entire internationalization effort.
|
||||
|
||||
One approach is to dedicate a folder to localization and store related assets
|
||||
(e.g. internationalization files) there.
|
||||
(for example, internationalization files) there.
|
||||
.l-sub-section
|
||||
:marked
|
||||
Localization and internationalization are
|
||||
<a href="https://en.wikipedia.org/wiki/Internationalization_and_localization" target="_blank">different but closely related terms</a>.
|
||||
:marked
|
||||
This sample follows that suggestion. It has a `locale` folder under the project root.
|
||||
This cookbook follows that suggestion. It has a `locale` folder under the project root.
|
||||
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>.
|
||||
|
||||
|
@ -323,10 +331,10 @@ a#localization-folder
|
|||
|
||||
.alert.is-important
|
||||
:marked
|
||||
Note that the `id` is generated by the tool. **Don't touch it.**
|
||||
Note that the tool generates the `id`. **Don't touch it.**
|
||||
Its value depends on the content of the message and its assigned meaning.
|
||||
Change either factor and the `id` changes as well.
|
||||
See the **[translation file maintenance discussion](#maintenance)** below.
|
||||
See the **[translation file maintenance discussion](#maintenance)**.
|
||||
|
||||
:marked
|
||||
Translate the other text nodes the same way:
|
||||
|
@ -338,9 +346,10 @@ a#translate-plural-select
|
|||
## Translate _plural_ and _select_
|
||||
Translating _plural_ and _select_ messages is a little tricky.
|
||||
|
||||
The `<source>` tag is empty for `plural` and `select` translation units which makes them hard to correlate with the original template.
|
||||
The ICU rules are not yet supported in the `XLIFF` format; they soon will be.
|
||||
The ICU rules _are_ supported in the `XMB` format.
|
||||
The `<source>` tag is empty for `plural` and `select` translation
|
||||
units, which makes them hard to correlate with the original template.
|
||||
The `XLIFF` format doesn't yet support the ICU rules; it soon will.
|
||||
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.
|
||||
In this example, you know the translation unit for the `select` must be just below the translation unit for the logo.
|
||||
|
@ -378,13 +387,14 @@ a#translate-plural-select
|
|||
|
||||
.l-main-content
|
||||
:marked
|
||||
The entire template translation is complete. It's time to incorporate that translation in the application.
|
||||
The entire template translation is complete. It's
|
||||
time to incorporate that translation into the application.
|
||||
|
||||
#app-pre-translation
|
||||
:marked
|
||||
### The app before translation
|
||||
|
||||
After the previous steps, the sample app _and_ its translation file are as follows:
|
||||
When the previous steps finish, the sample app _and_ its translation file are as follows:
|
||||
|
||||
+makeTabs(`
|
||||
cb-i18n/ts/app/app.component.html,
|
||||
|
@ -403,12 +413,12 @@ a#translate-plural-select
|
|||
a#merge
|
||||
.l-main-section
|
||||
:marked
|
||||
## Merge the completed translation file
|
||||
## Merge the completed translation file into the app
|
||||
|
||||
To merge the translated text into component templates,
|
||||
you 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
|
||||
in one of the other formats (`.xlif` and `.xtb`) that Angular understands.
|
||||
in another format (`.xlif` and `.xtb`) that Angular understands.
|
||||
|
||||
You provide the Angular compiler with three new pieces of information:
|
||||
* the translation file
|
||||
|
@ -419,23 +429,23 @@ a#merge
|
|||
_How_ you provide this information depends upon whether you compile with
|
||||
the JIT (_Just-in-Time_) compiler or the AOT (_Ahead-of-Time_) compiler.
|
||||
|
||||
* with [JIT](#jit), you provide the information at bootstrap time.
|
||||
* with [AOT](#aot), you pass the information as `ngc` options.
|
||||
* With [JIT](#jit), you provide the information at bootstrap time.
|
||||
* With [AOT](#aot), you pass the information as `ngc` options.
|
||||
|
||||
a#jit
|
||||
.l-main-section
|
||||
:marked
|
||||
### Merge with the JIT compiler
|
||||
|
||||
The JIT (_Just-in-Time_) compiler compiles the application in the browser as the application loads.
|
||||
Translation with the JIT compiler is a dynamic process of ...
|
||||
The JIT compiler compiles the application in the browser as the application loads.
|
||||
Translation with the JIT compiler is a dynamic process of:
|
||||
|
||||
1. determining the language version for the current user,
|
||||
2. importing the appropriate language translation file as a string constant,
|
||||
3. creating corresponding translation providers to guide the JIT compiler,
|
||||
4. bootstrapping the application with those providers.
|
||||
1. Determining the language version for the current user.
|
||||
2. Importing the appropriate language translation file as a string constant.
|
||||
3. Creating corresponding translation providers to guide the JIT compiler.
|
||||
4. Bootstrapping the application with those providers.
|
||||
|
||||
Open `index.html` and revise the launch script as shown here:
|
||||
Open `index.html` and revise the launch script as follows:
|
||||
+makeExample('cb-i18n/ts/index.html', 'i18n', 'index.html (launch script)')(format='.')
|
||||
:marked
|
||||
In this sample, the user's language is hardcoded as a global `document.locale` variable
|
||||
|
@ -446,7 +456,7 @@ a#text-plugin
|
|||
### SystemJS Text plugin
|
||||
|
||||
Notice the SystemJS mapping of `text` to a `systemjs-text-plugin.js`.
|
||||
With the help of a text pluglin, 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
|
||||
return the contents as a string.
|
||||
You'll need it to import the language translation file.
|
||||
|
||||
|
@ -460,7 +470,7 @@ a#text-plugin
|
|||
while compiling the application:
|
||||
|
||||
* `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.
|
||||
|
||||
The `getTranslationProviders` function in the following `app/i18n-providers.ts`
|
||||
|
@ -468,21 +478,21 @@ a#text-plugin
|
|||
and the corresponding translation file:
|
||||
+makeExample('cb-i18n/ts/app/i18n-providers.ts', null, 'app/i18n-providers.ts')
|
||||
:marked
|
||||
* It gets the locale from the global `document.locale` variable that was set in `index.html`.
|
||||
1. It gets the locale from the global `document.locale` variable that was set in `index.html`.
|
||||
|
||||
* If there is no locale or the language is U.S. English (`en-US`), there is no need to translate.
|
||||
1. If there is no locale or the language is U.S. English (`en-US`), there is no need to translate.
|
||||
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 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).
|
||||
|
||||
* 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).
|
||||
|
||||
* The callback composes a providers array with the three translation providers.
|
||||
1. The callback composes a providers array with the three translation providers.
|
||||
|
||||
* Finally, `getTranslationProviders` returns the entire effort as a promise.
|
||||
1. Finally, `getTranslationProviders` returns the entire effort as a promise.
|
||||
|
||||
### Bootstrap the app with translation providers
|
||||
|
||||
|
@ -505,21 +515,27 @@ a#aot
|
|||
:marked
|
||||
### _Internationalize_ with the AOT compiler
|
||||
|
||||
The JIT compiler translates the application into the target language while compiling dynamically in the browser.
|
||||
The JIT compiler translates the application into the target language
|
||||
while compiling dynamically in the browser.
|
||||
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 produces a small, fast, ready-to-run application package.
|
||||
When you internationalize with the AOT compiler, you pre-build a separate application package for each
|
||||
language. Then in the host web page (`index.html`), you determine which language the user needs
|
||||
The AOT (_Ahead-of-Time_) compiler is part of a build process that
|
||||
produces a small, fast, ready-to-run application package.
|
||||
When you internationalize with the AOT compiler, you pre-build
|
||||
a separate application package for each
|
||||
language. Then in the host web page (`index.html`),
|
||||
you determine which language the user needs
|
||||
and serve the appropriate application package.
|
||||
|
||||
This cookbook doesn't cover how to build multiple application packages and
|
||||
serve them according to the user's language preference.
|
||||
It does explain the few steps necessary to tell the AOT 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 some setup specifically for AOT.
|
||||
Start with application project as shown [just before merging the translation file](#app-pre-translationStart)
|
||||
and refer to the [AOT cookbook](aot-compiler.html) to make it _AoT-ready_.
|
||||
Internationalization with the AOT compiler requires
|
||||
some setup specifically for AOT compilation.
|
||||
Start with the application project as shown
|
||||
[just before merging the translation file](#app-pre-translation)
|
||||
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).
|
||||
The result is a separate version of the application for each language.
|
||||
|
@ -543,13 +559,18 @@ a#maintenance
|
|||
:marked
|
||||
## Translation file maintenance and _id_ changes
|
||||
|
||||
As the application evolves, you will change the _i18n_ markup and re-run the `ng-xi18n` extraction tool many times.
|
||||
The _new_ markup that you add is not a problem.
|
||||
But _most_ changes to _existing_ markup will trigger generation of _new_ `id`s for the affected translation units.
|
||||
As the application evolves, you will change the _i18n_ markup
|
||||
and re-run the `ng-xi18n` extraction tool many times.
|
||||
The _new_ markup that you add is not a problem;
|
||||
but _most_ changes to _existing_ markup trigger
|
||||
generation of _new_ `id`s for the affected translation units.
|
||||
|
||||
After an `id` changes, the translation files are no longer in-sync.
|
||||
**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 they don't tell you what the new `id`s should be.
|
||||
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.
|
||||
|
||||
**Commit all translation message files to source control**, especially the English source `messages.xlf`.
|
||||
The difference between the old and the new `messages.xlf` file will help you find and update `id` changes across your translation files.
|
||||
**Commit all translation message files to source control**,
|
||||
especially the English source `messages.xlf`.
|
||||
The difference between the old and the new `messages.xlf` file
|
||||
help you find and update `id` changes across your translation files.
|
||||
|
|
Loading…
Reference in New Issue