841 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			841 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Internationalization (i18n)
 | |
| 
 | |
| Application internationalization is a many-faceted area of development, focused on making
 | |
| applications available and user-friendly to a worldwide audience. This page describes Angular's
 | |
| internationalization (i18n) tools, which can help you make your app available in multiple languages.
 | |
| 
 | |
| See the <live-example downloadOnly name="i18n">i18n Example</live-example> for a simple example of
 | |
| an AOT-compiled app, translated into French.
 | |
| 
 | |
| {@a angular-i18n}
 | |
| ## Angular and i18n
 | |
| 
 | |
| *Internationalization* is the process of designing and preparing your app to be usable in different languages. 
 | |
| *Localization* is the process of translating your internationalized app into specific languages for particular locales. 
 | |
| 
 | |
| Angular simplifies the following aspects of internationalization:
 | |
| * Displaying dates, number, percentages, and currencies in a local format.
 | |
| * Preparing text in component templates for translation.
 | |
| * Handling plural forms of words.
 | |
| * Handling alternative text.
 | |
| 
 | |
| For localization, you can use the [Angular CLI](cli) to generate most of the boilerplate necessary to create files for translators, and to publish your app in multiple languages. 
 | |
| After you have set up your app to use i18n, the CLI can help you with the following steps:
 | |
| * Extracting localizable text into a file that you can send out to be translated.
 | |
| * Building and serving the app for a given locale, using the translated text.
 | |
| * Creating multiple language versions of your app.
 | |
| 
 | |
| 
 | |
| {@a setting-up-locale}
 | |
| ## Setting up the locale of your app
 | |
| 
 | |
| A locale is an identifier (id) that refers to a set of user preferences that tend to be shared
 | |
| within a region of the world, such as country. This document refers to a locale identifier as a
 | |
| "locale" or "locale id".
 | |
| 
 | |
| A Unicode locale identifier is composed of a Unicode language identifier and (optionally) the
 | |
| character `-` followed by a locale extension. (For historical reasons the character `_` is supported
 | |
| as an alternative to `-`.)  For example, in the locale id `fr-CA` the `fr` refers to the French
 | |
| language identifier, and the `CA` refers to the locale extension Canada.
 | |
| 
 | |
| <div class="alert is-critical">
 | |
| 
 | |
| Angular follows the Unicode LDML convention that uses stable identifiers (Unicode locale identifiers)
 | |
| based on the norm [BCP47](http://www.rfc-editor.org/rfc/bcp/bcp47.txt). It is very important that
 | |
| you follow this convention when you define your locale, because the Angular i18n tools use this
 | |
| locale id to find the correct corresponding locale data.
 | |
| 
 | |
| </div>
 | |
| 
 | |
| By default, Angular uses the locale `en-US`, which is English as spoken in the United States of America.
 | |
| 
 | |
| For more information about Unicode locale identifiers, see the
 | |
| [CLDR core spec](http://cldr.unicode.org/core-spec#Unicode_Language_and_Locale_Identifiers).
 | |
| 
 | |
| For a complete list of locales supported by Angular, see
 | |
| [the Angular repository](https://github.com/angular/angular/tree/master/packages/common/locales).
 | |
| 
 | |
| The locale identifiers used by CLDR and Angular are based on [BCP47](http://www.rfc-editor.org/rfc/bcp/bcp47.txt).
 | |
| These specifications change over time; the following table maps previous identifiers to current ones at
 | |
| time of writing:
 | |
| 
 | |
| | Locale name                   | Old locale id     | New locale id |
 | |
| |-------------------------------|-------------------|---------------|
 | |
| | Indonesian                    | in                | id            |
 | |
| | Hebrew                        | iw                | he            |
 | |
| | Romanian Moldova              | mo                | ro-MD         |
 | |
| | Norwegian Bokmål              | no, no-NO         | nb            |
 | |
| | Serbian Latin                 | sh                | sr-Latn       |
 | |
| | Filipino                      | tl                | fil           |
 | |
| | Portuguese Brazil             | pt-BR             | pt            |
 | |
| | Chinese Simplified            | zh-cn, zh-Hans-CN | zh-Hans       |
 | |
| | Chinese Traditional           | zh-tw, zh-Hant-TW | zh-Hant       |
 | |
| | Chinese Traditional Hong Kong | zh-hk             | zh-Hant-HK    |
 | |
| 
 | |
| 
 | |
| ## i18n pipes
 | |
| 
 | |
| Angular pipes can help you with internationalization: the `DatePipe`, `CurrencyPipe`, `DecimalPipe`
 | |
| and `PercentPipe` use locale data to format data based on the `LOCALE_ID`.
 | |
| 
 | |
| By default, Angular only contains locale data for `en-US`. If you set the value of
 | |
| `LOCALE_ID` to another locale, you must import locale data for that new locale.
 | |
| The CLI imports the locale data for you when you use the parameter `--configuration` with `ng serve` and
 | |
| `ng build`.
 | |
| 
 | |
| If you want to import locale data for other languages, you can do it manually:
 | |
| 
 | |
| <code-example path="i18n/doc-files/app.locale_data.ts" region="import-locale" header="src/app/app.module.ts" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| The first parameter is an object containing the locale data imported from `@angular/common/locales`.
 | |
| By default, the imported locale data is registered with the locale id that is defined in the Angular
 | |
| locale data itself.
 | |
| If you want to register the imported locale data with another locale id, use the second parameter to
 | |
| specify a custom locale id. For example, Angular's locale data defines the locale id for French as
 | |
| "fr". You can use the second parameter to associate the imported French locale data with the custom
 | |
| locale id "fr-FR" instead of "fr".
 | |
| 
 | |
| The files in `@angular/common/locales` contain most of the locale data that you
 | |
| need, but some advanced formatting options might only be available in the extra dataset that you can
 | |
| import from `@angular/common/locales/extra`. An error message informs you when this is the case.
 | |
| 
 | |
|   <code-example path="i18n/doc-files/app.locale_data_extra.ts" region="import-locale-extra" header="src/app/app.module.ts" linenums="false">
 | |
|   </code-example>
 | |
| 
 | |
| <div class="alert is-helpful">
 | |
| 
 | |
|   All locale data used by Angular are extracted from the Unicode Consortium's
 | |
|   <a href="http://cldr.unicode.org/" title="CLDR">Common Locale Data Repository (CLDR)</a>.
 | |
| 
 | |
| </div>
 | |
| 
 | |
| 
 | |
| ## Template translations
 | |
| 
 | |
| <div class="alert is-helpful">
 | |
| 
 | |
|   This document refers to a unit of translatable text as "text," a "message", or a
 | |
|   "text message."
 | |
| 
 | |
| </div>
 | |
| 
 | |
| The i18n template translation process has four phases:
 | |
| 
 | |
| 1. Mark static text messages in your component templates for translation.
 | |
| 
 | |
| 2. Create a translation file: Use the Angular CLI `xi18n` command to extract the marked text into an industry-standard translation source file.
 | |
| 
 | |
| 3. Edit the generated translation file: Translate the extracted text into the target language.
 | |
| 
 | |
| 4. Merge the completed translation file into the app. To do this, use the Angular CLI `build` command to compile the app, choosing a [locale-specific configuration](#merge-aot), or specifying the following command options.
 | |
| 
 | |
|     * `--i18nFile`=*path to the translation file*
 | |
|     * `--i18nFormat`=*format of the translation file*
 | |
|     * `--i18nLocale`= *locale id* 
 | |
| 
 | |
| The command replaces the original messages with translated text, and generates a new version of the app in the target language. 
 | |
| 
 | |
| You need to build and deploy a separate version of the app for each supported language.
 | |
| 
 | |
| {@a i18n-attribute}
 | |
| ### Mark text with the i18n attribute
 | |
| 
 | |
| The Angular `i18n` attribute marks translatable content. Place it on every element tag whose fixed
 | |
| text is to be translated.
 | |
| 
 | |
| In the example below, an `<h1>` tag displays a simple English language greeting, "Hello i18n!"
 | |
| 
 | |
| <code-example path="i18n/doc-files/app.component.html" region="greeting" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| To mark the greeting for translation, add the `i18n` attribute to the `<h1>` tag.
 | |
| 
 | |
| <code-example path="i18n/doc-files/app.component.html" region="i18n-attribute" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| 
 | |
| <div class="alert is-helpful">
 | |
| 
 | |
|   `i18n` is a custom attribute, recognized by Angular tools and compilers.
 | |
|   After translation, the compiler removes it. It is not an Angular directive.
 | |
| 
 | |
| </div>
 | |
| 
 | |
| 
 | |
| {@a help-translator}
 | |
| ### Help the translator with a description and meaning
 | |
| 
 | |
| To translate a text message accurately, the translator may need additional information or context.
 | |
| 
 | |
| You can add a description of the text message as the value of the `i18n` attribute, as shown in the
 | |
| example below:
 | |
| 
 | |
| <code-example path="i18n/doc-files/app.component.html" region="i18n-attribute-desc" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| The translator may also need to know the meaning or intent of the text message within this particular
 | |
| app context.
 | |
| 
 | |
| You add context by beginning the `i18n` attribute value with the _meaning_ and
 | |
| separating it from the _description_ with the `|` character: `<meaning>|<description>`
 | |
| 
 | |
| <code-example path="i18n/doc-files/app.component.html" region="i18n-attribute-meaning" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| All occurrences of a text message that have the same meaning will have the same translation.
 | |
| A text message that is associated with different meanings can have different translations.
 | |
| 
 | |
| The Angular extraction tool preserves both the meaning and the description in the translation
 | |
| source file to facilitate contextually-specific translations, but only the combination of meaning
 | |
| and text message are used to generate the specific id of a translation. If you have two
 | |
| similar text messages with different meanings, they are extracted separately. If you have two similar
 | |
| text messages with different descriptions (not different meanings), then they are extracted only once.
 | |
| 
 | |
| 
 | |
| {@a custom-id}
 | |
| ### Set a custom id for persistence and maintenance
 | |
| 
 | |
| The angular i18n extractor tool generates a file with a translation unit entry for each `i18n`
 | |
| attribute in a template. By default, it assigns each translation unit a unique id such as this one:
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="generated-id" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| When you change the translatable text, the extractor tool generates a new id for that translation unit.
 | |
| You must then update the translation file with the new id.
 | |
| 
 | |
| Alternatively, you can specify a custom id in the `i18n` attribute by using the prefix `@@`.
 | |
| The example below defines the custom id `introductionHeader`:
 | |
| 
 | |
| <code-example path='i18n/doc-files/app.component.html' region='i18n-attribute-solo-id' header='app/app.component.html' linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| When you specify a custom id, the extractor tool and compiler generate a translation unit with that
 | |
| custom id.
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="custom-id" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| The custom id is persistent. The extractor tool does not change it when the translatable text changes.
 | |
| Therefore, you do not need to update the translation. This approach makes maintenance easier.
 | |
| 
 | |
| #### Use a custom id with a description
 | |
| 
 | |
| You can use a custom id in combination with a description by including both in the value of the
 | |
| `i18n` attribute. In the example below, the `i18n` attribute value includes a description, followed
 | |
| by the custom `id`:
 | |
| 
 | |
| <code-example path='i18n/doc-files/app.component.html' region='i18n-attribute-id' header='app/app.component.html' linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| You also can add a meaning, as shown in this example:
 | |
| 
 | |
| <code-example path='i18n/doc-files/app.component.html' region='i18n-attribute-meaning-and-id' header='app/app.component.html' linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| #### Define unique custom ids
 | |
| 
 | |
| Be sure to define custom ids that are unique. If you use the same id for two different text messages,
 | |
| only the first one is extracted, and its translation is used in place of both original text messages.
 | |
| 
 | |
| In the example below the custom id `myId` is used for two different messages:
 | |
| 
 | |
|   ```html
 | |
|     <h3 i18n="@@myId">Hello</h3>
 | |
|     <!-- ... -->
 | |
|     <p i18n="@@myId">Good bye</p>
 | |
|   ```
 | |
| 
 | |
| Consider this translation to French:
 | |
| 
 | |
|   ```xml
 | |
|     <trans-unit id="myId" datatype="html">
 | |
|       <source>Hello</source>
 | |
|       <target state="new">Bonjour</target>
 | |
|     </trans-unit>
 | |
|   ```
 | |
| 
 | |
| Because the custom id is the same, both of the elements in the resulting translation contain
 | |
| the same text, `Bonjour`:
 | |
| 
 | |
|   ```html
 | |
|     <h3>Bonjour</h3>
 | |
|     <!-- ... -->
 | |
|     <p>Bonjour</p>
 | |
|   ```
 | |
| 
 | |
| 
 | |
| 
 | |
| {@a no-element}
 | |
| ### Translate text without creating an element
 | |
| 
 | |
| If there is a section of text that you would like to translate, you can wrap it in a `<span>` tag.
 | |
| However, if you don't want to create a new DOM element merely to facilitate translation,
 | |
| you can wrap the text in an `<ng-container>` element.
 | |
| The `<ng-container>` is transformed into an html comment:
 | |
| 
 | |
| <code-example path="i18n/src/app/app.component.html" region="i18n-ng-container" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| {@a translate-attributes}
 | |
| ### Translate attributes
 | |
| 
 | |
| Displayed text is sometimes supplied as the value of an attribute, rather than the content of tag.
 | |
| For example, if your template has an image with a `title` attribute, the text value of the `title` attribute needs to be translated.
 | |
| 
 | |
| <code-example path="i18n/doc-files/app.component.html" region="i18n-title" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| To mark an attribute for translation, add an attribute in the form of `i18n-x`,
 | |
| where `x` is the name of the attribute to translate. The following example shows how to mark the
 | |
| `title` attribute for translation by adding the `i18n-title` attribute on the `img` tag:
 | |
| 
 | |
| <code-example path="i18n/src/app/app.component.html" region="i18n-title-translate" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| This technique works for any attribute of any element.
 | |
| 
 | |
| You also can assign a meaning, description, and id with the `i18n-x="<meaning>|<description>@@<id>"`
 | |
| syntax.
 | |
| 
 | |
| ## Regular expressions for plurals and selections
 | |
| 
 | |
| Different languages have different pluralization rules and grammatical constructions that add 
 | |
| complexity to the translation task. 
 | |
| You can use regular expressions with the `plural` and `select` clauses to provide patterns that aid translation in these cases.
 | |
| 
 | |
| {@a plural-ICU}
 | |
| ### Pluralization
 | |
| 
 | |
| Suppose that you want to say that something was "updated x minutes ago".
 | |
| In English, depending upon the number of minutes, you could display "just now", "one minute ago",
 | |
| or "x minutes ago" (with x being the actual number).
 | |
| Other languages might express the cardinality differently.
 | |
| 
 | |
| The example below shows how to use a `plural` ICU expression to display one of those three options
 | |
| based on when the update occurred:
 | |
| 
 | |
| <code-example path="i18n/src/app/app.component.html" region="i18n-plural" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| * The first parameter is the key. It is bound to the component property (`minutes`), which determines
 | |
| the number of minutes.
 | |
| * 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.
 | |
| 
 | |
| 
 | |
| <div class="alert is-helpful">
 | |
| 
 | |
|   This syntax conforms to the
 | |
|   <a href="http://userguide.icu-project.org/formatparse/messages" title="ICU Message Format">ICU Message Format</a>
 | |
|   as specified in the
 | |
|   <a href="http://cldr.unicode.org/index/cldr-spec/plural-rules" title="Pluralization Rules">CLDR pluralization rules</a>.
 | |
| 
 | |
| </div>
 | |
| 
 | |
| Pluralization categories include (depending on the language):
 | |
| 
 | |
| * =0 (or any other number)
 | |
| * zero
 | |
| * one
 | |
| * two
 | |
| * few
 | |
| * many
 | |
| * other
 | |
| 
 | |
| After the pluralization category, put the default English text in braces (`{}`).
 | |
| 
 | |
| In the example above, the three options are specified according to that pluralization pattern. For
 | |
| talking about zero minutes, you use `=0 {just now}`. For one minute, you use `=1 {one minute}`.
 | |
| Any unmatched cardinality uses `other {{{minutes}} minutes ago}`. You could choose to add patterns
 | |
| for two, three, or any other number if the pluralization rules were different. For the example of
 | |
| "minute", only these three patterns are necessary in English.
 | |
| 
 | |
| <div class="alert is-helpful">
 | |
| 
 | |
|   You can use interpolations and html markup inside of your translations.
 | |
| 
 | |
| </div>
 | |
| 
 | |
| {@a select-ICU}
 | |
| ### Select among alternative text messages
 | |
| 
 | |
| If your template needs to display different text messages depending on the value of a variable, you
 | |
| need to translate all of those alternative text messages.
 | |
| 
 | |
| You can handle this with a `select` ICU expression. It is similar to the `plural` expressions
 | |
| except that you choose among alternative translations based on a string value instead of a number,
 | |
| and you define those string values.
 | |
| 
 | |
| The following format message in the component template binds to the component's `gender` property,
 | |
| which outputs one of the following string values: "male", "female" or "other".
 | |
| The message maps those values to the appropriate translations:
 | |
| 
 | |
| <code-example path="i18n/src/app/app.component.html" region="i18n-select" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| {@a nesting-ICUS}
 | |
| ### Nesting plural and select ICU expressions
 | |
| 
 | |
| You can also nest different ICU expressions together, as shown in this example:
 | |
| 
 | |
| <code-example path="i18n/src/app/app.component.html" region="i18n-nested" header="src/app/app.component.html">
 | |
| </code-example>
 | |
| 
 | |
| {@a ng-xi18n}
 | |
| {@a ng-xi18n-options}
 | |
| 
 | |
| ## Create a translation source file
 | |
| 
 | |
| When your app is ready, you can use the Angular CLI to extract the text messages marked with `i18n` and attributes marked with `i18n-x` into a translation source file.
 | |
| Open a terminal window at the root of the app project and run the CLI command `xi18n`.
 | |
| 
 | |
| <code-example language="sh" class="code-shell">
 | |
|   ng xi18n
 | |
| </code-example>
 | |
| 
 | |
| By default, the command creates a file named `messages.xlf` in your `src/` folder. 
 | |
| 
 | |
| <div class="alert is-helpful">
 | |
| 
 | |
| If you don't use the CLI, you have two options:
 | |
| * You can use the `ng-xi18n` tool directly from the `@angular/compiler-cli` package.
 | |
| For more information, see the [`ng xi18n` command documentation](cli/xi18n).
 | |
| * You can use the CLI Webpack plugin `AngularCompilerPlugin` from the `@ngtools/webpack` package.
 | |
| Set the parameters `i18nOutFile` and `i18nOutFormat` to trigger the extraction.
 | |
| For more information, see the [Angular Ahead-of-Time Webpack Plugin documentation](https://github.com/angular/angular-cli/tree/master/packages/%40ngtools/webpack).
 | |
| 
 | |
| </div>
 | |
| 
 | |
| {@a other-formats}
 | |
| ### Output options
 | |
| 
 | |
| You can supply command options to change the format, the name, the location, and the source locale of the extracted file. 
 | |
| For example, to create a file in the `src/locale` folder, specify the output path:
 | |
| 
 | |
| <code-example language="sh" class="code-shell">
 | |
|   ng xi18n --output-path src/locale
 | |
| </code-example>
 | |
| 
 | |
| By default, the `xi18n` command generates a translation file named `messages.xlf` in the
 | |
| <a href="https://en.wikipedia.org/wiki/XLIFF">XML Localization Interchange File Format
 | |
| (XLIFF, version 1.2)</a>.
 | |
| 
 | |
| The command can read and write files in three translation formats:
 | |
| * XLIFF 1.2 (default)
 | |
| * XLIFF 2
 | |
| * <a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" >XML Message
 | |
| Bundle (XMB)</a>
 | |
| 
 | |
| You can specify the translation format explicitly with the `--i18nFormat` command option, as illustrated in
 | |
| these example commands:
 | |
| 
 | |
| <code-example language="sh" class="code-shell">
 | |
| ng xi18n  --i18n-format=xlf
 | |
| ng xi18n  --i18n-format=xlf2
 | |
| ng xi18n  --i18n-format=xmb
 | |
| </code-example>
 | |
| 
 | |
| The sample in this guide uses the default XLIFF 1.2 format.
 | |
| 
 | |
| <div class="alert is-helpful">
 | |
| 
 | |
|   XLIFF files have the extension .xlf. The XMB format generates .xmb source files but uses
 | |
|   .xtb (XML Translation Bundle: XTB) translation files.
 | |
| 
 | |
| </div>
 | |
| 
 | |
| You can change the name of the translation source file that is generated by the extraction tool with
 | |
| the `--outFile` command option:
 | |
| 
 | |
| <code-example language="sh" class="code-shell">
 | |
| 
 | |
|   ng xi18n --out-file source.xlf
 | |
| 
 | |
| </code-example>
 | |
| 
 | |
| You can specify the base locale of your app with the`--i18n-locale` command option:
 | |
| 
 | |
| <code-example language="sh" class="code-shell">
 | |
| 
 | |
|   ng xi18n --i18n-locale fr
 | |
| 
 | |
| </code-example>
 | |
| 
 | |
| The extraction tool uses the locale to add the app locale information into your translation source
 | |
| file. This information is not used by Angular, but external translation tools may need it.
 | |
| 
 | |
| 
 | |
| {@a translate}
 | |
| ## Translate the source text
 | |
| 
 | |
| The `ng xi18n` command generates a translation source file named `messages.xlf` in the project `src`
 | |
| folder.
 | |
| The next step is to translate the display strings in this source file into language-specific 
 | |
| translation files. The example in this guide creates a French translation file.
 | |
| 
 | |
| {@a localization-folder}
 | |
| ### Create a localization folder
 | |
| 
 | |
| Most apps are translated into more than one other language. For this reason, it is standard practice
 | |
| for the project structure to reflect the entire internationalization effort.
 | |
| 
 | |
| One approach is to dedicate a folder to localization and store related assets, such as
 | |
| internationalization files, there.
 | |
| 
 | |
| <div class="alert is-helpful">
 | |
| 
 | |
|   Localization and internationalization are
 | |
|   <a href="https://en.wikipedia.org/wiki/Internationalization_and_localization">different but
 | |
|   closely related terms</a>.
 | |
| 
 | |
| </div>
 | |
| 
 | |
| This guide follows that approach. It has a `locale` folder under `src/`.
 | |
| Assets within that folder have a filename extension that matches their associated locale.
 | |
| 
 | |
| ### Create the translation files
 | |
| 
 | |
| For each translation source file, there must be at least one language translation file for the
 | |
| resulting translation.
 | |
| 
 | |
| For this example:
 | |
| 
 | |
| 1. Make a copy of the `messages.xlf` file.
 | |
| 2. Put the copy in the `locale` folder.
 | |
| 3. Rename the copy to `messages.fr.xlf` for the French language translation.
 | |
| 
 | |
| If you were translating to other languages, you would repeat these steps for each target language.
 | |
| 
 | |
| {@a translate-text-nodes}
 | |
| ### Translate text nodes
 | |
| 
 | |
| In a large translation project, you would send the `messages.fr.xlf` file to a French translator who
 | |
| would enter the translations using an XLIFF file editor.
 | |
| 
 | |
| This sample file is easy to translate without a special editor or knowledge of French.
 | |
| 
 | |
| 1. Open `messages.fr.xlf` and find the first `<trans-unit>` section:
 | |
| 
 | |
| > <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-hello-before" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| > This XML element represents the translation of the `<h1>` greeting tag that you marked with the
 | |
|   `i18n` attribute earlier in this guide.
 | |
| 
 | |
| > Note that the translation unit `id=introductionHeader` is derived from the
 | |
|   [custom `id`](#custom-id "Set a custom id") that you set earlier, but
 | |
|   without the `@@` prefix required in the source HTML.
 | |
| 
 | |
| 
 | |
| 2. Duplicate the `<source/>` tag, rename it `target`, and then replace its content with the French
 | |
|   greeting. If you were working with a more complex translation, you could use the information
 | |
|   and context provided by the source, description, and meaning elements to guide your selection of
 | |
|   the appropriate French translation.
 | |
| 
 | |
| > <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-hello" header="src/locale/messages.fr.xlf (<trans-unit>, after translation)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| 3. Translate the other text nodes the same way:
 | |
| 
 | |
| > <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-other-nodes" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| <div class="alert is-important">
 | |
| 
 | |
|   **The Angular i18n tools generated the ids for these translation units. Don't change them.**
 | |
|   Each `id` depends upon the content of the template text and its assigned meaning.
 | |
|   If you change either the text or the meaning, then the `id` changes.
 | |
|   For more information, see the **[translation file maintenance discussion](#custom-id)**.
 | |
| 
 | |
| </div>
 | |
| 
 | |
| {@a translate-plural-select}
 | |
| ## Translating plural and select expressions
 | |
| 
 | |
| The _plural_ and _select_ ICU expressions are extracted separately, so they require special attention
 | |
| when preparing for translation.
 | |
| 
 | |
| Look for these expressions 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.
 | |
| 
 | |
| {@a translate-plural}
 | |
| ### Translate _plural_
 | |
| 
 | |
| To translate a `plural`, translate its ICU format match values:
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-plural" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| You can add or remove plural cases, with each language having its own cardinality.  (See
 | |
| [CLDR plural rules](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html).)
 | |
| 
 | |
| {@a translate-select}
 | |
| ### Translate _select_
 | |
| 
 | |
| Below is the content of our example `select` ICU expression in the component template:
 | |
| 
 | |
| <code-example path="i18n/src/app/app.component.html" region="i18n-select" header="src/app/app.component.html" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| The extraction tool broke that into two translation units because ICU expressions are extracted
 | |
| separately.
 | |
| 
 | |
| The first unit contains the text that was outside of the `select`.
 | |
| In place of the `select` is a placeholder, `<x id="ICU">`, that represents the `select` message.
 | |
| Translate the text and move around the placeholder if necessary, but don't remove it. If you remove
 | |
| the placeholder, the ICU expression will not be present in your translated app.
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-select-1" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| The second translation unit, immediately below the first one, contains the `select` message.
 | |
| Translate that as well.
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-select-2" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| Here they are together, after translation:
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-select" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| {@a translate-nested}
 | |
| ### Translate a nested expression
 | |
| 
 | |
| A nested expression is similar to the previous examples. As in the previous example, there are
 | |
| two translation units. The first one contains the text outside of the nested expression:
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-nested-1" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| The second unit contains the complete nested expression:
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-nested-2" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| And both together:
 | |
| 
 | |
| <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-nested" header="src/locale/messages.fr.xlf (<trans-unit>)" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| The entire template translation is complete. The next section describes how to load that translation
 | |
| into the app.
 | |
| 
 | |
| {@a app-pre-translation}
 | |
| ### The app and its translation file
 | |
| 
 | |
| The sample app and its translation file are now as follows:
 | |
| 
 | |
| <code-tabs>
 | |
|   <code-pane header="src/app/app.component.html" path="i18n/src/app/app.component.html">
 | |
|   </code-pane>
 | |
|   <code-pane header="src/app/app.component.ts" path="i18n/src/app/app.component.ts">
 | |
|   </code-pane>
 | |
|   <code-pane header="src/app/app.module.ts" path="i18n/src/app/app.module.ts">
 | |
|   </code-pane>
 | |
|   <code-pane header="src/main.ts" path="i18n/doc-files/main.1.ts">
 | |
|   </code-pane>
 | |
|   <code-pane header="src/locale/messages.fr.xlf" path="i18n/doc-files/messages.fr.xlf.html">
 | |
|   </code-pane>
 | |
| </code-tabs>
 | |
| 
 | |
| {@a merge}
 | |
| ## Merge the completed translation file into the app
 | |
| 
 | |
| To merge the translated text into component templates, compile the app with the completed
 | |
| translation file.
 | |
| 
 | |
|  Provide the Angular compiler with three translation-specific pieces of information:
 | |
| 
 | |
|   * The translation file.
 | |
|   * The translation file format.
 | |
|   * The locale (`fr` or `en-US` for instance).
 | |
| 
 | |
| The compilation process is the same whether the translation file is in `.xlf` format or in another
 | |
| format that Angular understands, such as `.xtb`.
 | |
| 
 | |
| How you provide this information depends upon whether you compile with
 | |
| the JIT compiler or the AOT compiler.
 | |
| 
 | |
|   * With [AOT](guide/i18n#merge-aot), you pass the information as configuration settings.
 | |
|   * With [JIT](guide/i18n#merge-jit), you provide the information at bootstrap time.
 | |
| 
 | |
| 
 | |
| {@a merge-aot}
 | |
| ### Merge with the AOT compiler
 | |
| 
 | |
| The [AOT compiler](guide/glossary#aot) is part of a build process that produces a small, fast,
 | |
| ready-to-run application package, typically for production.
 | |
| 
 | |
| When you internationalize with the AOT compiler, you must pre-build a separate application
 | |
| package for each language and serve the appropriate package based on either server-side language
 | |
| detection or url parameters.
 | |
| 
 | |
| To instruct the AOT compiler to use your translation configuration, set the three "i18n" build configuration options in your `angular.json` file.
 | |
| 
 | |
| * `i18nFile`: the path to the translation file.
 | |
| * `i18nFormat`: the format of the translation file.
 | |
| * `i18nLocale`: the locale id.
 | |
| 
 | |
| You should also direct the output to a locale-specific folder to keep it separate from other locale versions of your app, by setting the `outputPath` configuration option.
 | |
| 
 | |
| ```
 | |
| "build": {
 | |
|   ...
 | |
|   "configurations": {
 | |
|     ...
 | |
|     "fr": {
 | |
|       "aot": true,
 | |
|       "outputPath": "dist/my-project-fr/",
 | |
|       "i18nFile": "src/locale/messages.fr.xlf",
 | |
|       "i18nFormat": "xlf",
 | |
|       "i18nLocale": "fr",
 | |
|       ...
 | |
|     }
 | |
|   }
 | |
| },
 | |
| "serve": {
 | |
|   ...
 | |
|   "configurations": {
 | |
|     ...
 | |
|     "fr": {
 | |
|       "browserTarget": "*project-name*:build:fr"
 | |
|     }
 | |
|   }
 | |
| }
 | |
| ```
 | |
| 
 | |
| You can then pass this configuration to the `ng serve` or `ng build` commands.
 | |
| The example below shows how to serve the French language file created in previous
 | |
| sections of this guide:
 | |
| 
 | |
| <code-example language="sh" class="code-shell">
 | |
|   ng serve --configuration=fr
 | |
| </code-example>
 | |
| 
 | |
| For production builds, you define a separate `production-fr` build configuration in
 | |
| the CLI configuration file, `angular.json`.
 | |
| 
 | |
| ```
 | |
| ...
 | |
| "architect": {
 | |
|   "build": {
 | |
|     "builder": "@angular-devkit/build-angular:browser",
 | |
|     "options": { ... },
 | |
|     "configurations": {
 | |
|       "fr": {
 | |
|         "aot": true,
 | |
|         "outputPath": "dist/my-project-fr/",
 | |
|         "i18nFile": "src/locale/messages.fr.xlf",
 | |
|         "i18nFormat": "xlf",
 | |
|         "i18nLocale": "fr",
 | |
|         "i18nMissingTranslation": "error",
 | |
|       }
 | |
| // ...
 | |
| "serve": {
 | |
|   "builder": "@angular-devkit/build-angular:dev-server",
 | |
|   "options": {
 | |
|     "browserTarget": "my-project:build"
 | |
|   },
 | |
|   "configurations": {
 | |
|     "production": {
 | |
|       "browserTarget": "my-project:build:production"
 | |
|     },
 | |
|     "fr": {
 | |
|       "browserTarget": "my-project:build:fr"
 | |
|     }
 | |
|   }
 | |
| },
 | |
| 
 | |
| ```
 | |
| 
 | |
| The same configuration options can also be provided through the CLI with your existing `production` configuration.
 | |
| 
 | |
| <code-example language="sh" class="code-shell">
 | |
|   ng build --prod --i18n-file src/locale/messages.fr.xlf --i18n-format xlf --i18n-locale fr
 | |
| </code-example>
 | |
| 
 | |
| {@a merge-jit}
 | |
| ### Merge with the JIT compiler
 | |
| 
 | |
| The [JITcompiler](guide/glossary#jit) compiles your app in the browser as the app loads.
 | |
| To support translation with the JIT compiler, you must do the following:
 | |
| 
 | |
| 1. Import the appropriate language translation file as a string constant.
 | |
| 2. Create corresponding translation providers for the JIT compiler.
 | |
| 3. Bootstrap the app with those providers.
 | |
| 
 | |
| Three providers tell the JIT compiler how to translate the template texts for a particular language
 | |
| while compiling the app:
 | |
| 
 | |
| * `TRANSLATIONS` is a string containing the content of the translation file.
 | |
| * `TRANSLATIONS_FORMAT` is the format of the file: `xlf`, `xlf2`, or `xtb`.
 | |
| * `LOCALE_ID` is the locale of the target language.
 | |
| 
 | |
| The Angular `bootstrapModule` method has a second `compilerOptions` parameter that can influence the
 | |
| behavior of the compiler. You can use it to specify the translation providers:
 | |
| 
 | |
| <code-example path="i18n/doc-files/main.2.ts" header="src/main.ts">
 | |
| </code-example>
 | |
| 
 | |
| Then provide the `LOCALE_ID` in the main module:
 | |
| 
 | |
| <code-example path="i18n/doc-files/app.module.ts" header="src/app/app.module.ts" linenums="false">
 | |
| </code-example>
 | |
| 
 | |
| 
 | |
| {@a missing-translation}
 | |
| ### Report missing translations
 | |
| By default, when a translation is missing, the build succeeds but generates a warning such as
 | |
| `Missing translation for message "foo"`. You can configure the level of warning that is generated by
 | |
| the Angular compiler:
 | |
| 
 | |
| * Error: throw an error. If you are using AOT compilation, the build will fail. If you are using JIT
 | |
| compilation, the app will fail to load.
 | |
| * Warning (default): show a 'Missing translation' warning in the console or shell.
 | |
| * Ignore: do nothing.
 | |
| 
 | |
| You specify the warning level in the `configurations` section your Angular CLI build configuration. The example below shows how to set the warning level to error:
 | |
| 
 | |
| ```
 | |
| "configurations": {
 | |
|   ...
 | |
|   "fr": {
 | |
|     ...
 | |
|     "i18nMissingTranslation": "error"
 | |
|   }
 | |
| }
 | |
| ```
 | |
| 
 | |
| If you use the JIT compiler, specify the warning level in the compiler config at bootstrap by adding
 | |
| the 'MissingTranslationStrategy' property. The example below shows how to set the warning level to
 | |
| error:
 | |
| 
 | |
| <code-example path="i18n/doc-files/main.3.ts" header="src/main.ts">
 | |
| </code-example>
 | |
| 
 | |
| ### Build for multiple locales
 | |
| 
 | |
| When you use the CLI `build` or `serve` command to build your application for different locales, change the output path using the `--outputPath` command option (along with the i18n-specific command options), so that the translation files are saved to different locations.
 | |
| When you are serving a locale-specific version from a subdirectory, you can also change the base URL used by your app by specifying the `--baseHref` option.
 | |
| 
 | |
| For example, if the French version of your application is served from https://myapp.com/fr/, configure the build for the French version as follows.
 | |
| 
 | |
| ```
 | |
| "configurations": {
 | |
|   "fr": {
 | |
|     "aot": true,
 | |
|     "outputPath": "dist/my-project-fr/",
 | |
|     "baseHref": "/fr/",
 | |
|     "i18nFile": "src/locale/messages.fr.xlf",
 | |
|     "i18nFormat": "xlf",
 | |
|     "i18nLocale": "fr",
 | |
|     "i18nMissingTranslation": "error",
 | |
|   }
 | |
| ```
 | |
| 
 | |
| For more details about how to create scripts to generate an app in multiple languages and how to set up Apache 2 and NGINX to serve them from different subdirectories, read [this tutorial by Philippe Martin](https://dev.to/angular/deploying-an-i18n-angular-app-with-angular-cli-2fb9).
 |