1020 lines
37 KiB
Markdown
1020 lines
37 KiB
Markdown
# Internationalization (i18n)
|
||
|
||
# 国际化(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.
|
||
|
||
可以把这个翻译为法语版的 AOT 应用<live-example downloadOnly name="i18n">i18n 例子</live-example>作为一个简单的例子。
|
||
|
||
{@a angular-i18n}
|
||
|
||
## Angular and i18n
|
||
|
||
Angular simplifies the following aspects of internationalization:
|
||
|
||
* Displaying dates, number, percentages, and currencies in a local format.
|
||
|
||
* Translating text in component templates.
|
||
|
||
* Handling plural forms of words.
|
||
|
||
* Handling alternative text.
|
||
|
||
This document focuses on [**Angular CLI**](https://cli.angular.io/) projects, in which the Angular
|
||
CLI generates most of the boilerplate necessary to write your app in multiple languages.
|
||
|
||
{@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.
|
||
|
||
To set your app's locale to another value, use the CLI parameter `--locale` with the value
|
||
of the locale id that you want to use:
|
||
|
||
<code-example language="sh" class="code-shell">
|
||
|
||
ng serve --aot --locale fr
|
||
|
||
</code-example>
|
||
|
||
If you use JIT, you also need to define the `LOCALE_ID` provider in your main module:
|
||
|
||
<code-example path="i18n/doc-files/app.module.ts" title="src/app/app.module.ts" linenums="false">
|
||
|
||
</code-example>
|
||
|
||
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 `--locale` 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" title="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" title="src/app/app.module.ts" linenums="false">
|
||
|
||
</code-example>
|
||
|
||
<div class="l-sub-section">
|
||
|
||
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="l-sub-section">
|
||
|
||
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. An Angular i18n tool extracts the marked text into an industry standard translation source file.
|
||
|
||
3. A translator edits that file, translating the extracted text into the target language,
|
||
and returns the file to you.
|
||
|
||
4. The Angular compiler imports the completed translation files,
|
||
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" title="src/app/app.component.html" linenums="false">
|
||
|
||
</code-example>
|
||
|
||
To mark the greeting for translation, add the `i18n` attribute to the `<h1>` tag.
|
||
|
||
添加 `i18n` 属性到该标签上,把它标记为需要翻译的文本。
|
||
|
||
<code-example path="i18n/doc-files/app.component.html" region="i18n-attribute" title="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" title="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" title="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.
|
||
|
||
如果所有地方出现的文本具有**相同**含义时,它们应该有**相同**的翻译,
|
||
但是如果在某些地方它具有**不同含义**,那么它应该有不同的翻译。
|
||
Angular 的提取工具在翻译源文件中保留**含义**和**描述**,以支持符合特定上下文的翻译。
|
||
|
||
{@a custom-id}
|
||
|
||
### Set a custom id for persistence and maintenance
|
||
|
||
### 设置一个自定义的 `id` 来提升可搜索性和可维护性
|
||
|
||
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:
|
||
|
||
Angular 的 `i18n` 提取工具会为模板中每个带有 `i18n` 属性的元素生成一个*翻译单元(translation unit)*条目,并保存到一个文件中。默认情况下,它为每个翻译单元指定一个唯一的 `id`,就像这样:
|
||
|
||
<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.
|
||
|
||
当我们修改这段可翻译的文字时,提取工具会为那个翻译单元生成一个新的 `id`。
|
||
我们就要使用这个新的 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' title='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.
|
||
|
||
现在,提取工具和编译器就会用*你的自定义 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' title='app/app.component.html' linenums="false">
|
||
|
||
</code-example>
|
||
|
||
You also can add a meaning, as shown in this example:
|
||
|
||
下面这个例子带有*含义*和*描述*,最后是 `id`:
|
||
|
||
<code-example path='i18n/doc-files/app.component.html' region='i18n-attribute-meaning-and-id' title='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.
|
||
|
||
为了确保定义出*唯一*的自定义 id。如果我们对两个*不同的*文本块使用了同一个 id,那么就只有一个会被提取出来,然后其翻译结果会被用于全部文本块。
|
||
|
||
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:
|
||
|
||
如果要翻译一段纯文本,我们就可以把它用 `<span>` 标签包裹起来。
|
||
但如果由于某些原因(比如 CSS 结构方面的考虑),我们可能不希望仅仅为了翻译而创建一个新的 DOM 元素,那么也可以把这段文本包裹进一个 `<ng-container>` 元素中。`<ng-container>` 将被转换成一个 HTML 注释:
|
||
|
||
<code-example path="i18n/src/app/app.component.html" region="i18n-ng-container" title="src/app/app.component.html" linenums="false">
|
||
|
||
</code-example>
|
||
|
||
{@a translate-attributes}
|
||
|
||
## Add i18n translation attributes
|
||
|
||
## 添加 *i18n* 翻译属性
|
||
|
||
You also can translate attributes.
|
||
For example, assume that your template has an image with a `title` attribute:
|
||
|
||
我们还可以翻译属性。
|
||
比如,假设我们的模板具有一个带 `title` 属性的图片:
|
||
|
||
<code-example path="i18n/doc-files/app.component.html" region="i18n-title" title="src/app/app.component.html" linenums="false">
|
||
|
||
</code-example>
|
||
|
||
This `title` attribute needs to be translated.
|
||
|
||
这个 `title` 属性也需要翻译。
|
||
|
||
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" title="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.
|
||
|
||
我们也同样可以使用 `i18n-x="<meaning>|<description>@@<id>"` 语法来指定一个含义和描述。
|
||
|
||
{@a plural-ICU}
|
||
|
||
## Translate singular and plural
|
||
|
||
## 处理单数与复数
|
||
|
||
Different languages have different pluralization rules.
|
||
|
||
不同的语言有不同的单复数规则。
|
||
|
||
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.
|
||
|
||
假设应用中需要谈论一些狼。
|
||
在英语中,根据狼的数量,可能要显示为"no wolves"、"one wolf"、"two wolves"或"a wolf pack"。
|
||
而在其它语言中则可能会有不同的**基数**规则。
|
||
|
||
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" title="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.
|
||
|
||
第一个参数是 key。它绑定到了组件中表示狼的数量的 `wolves` 属性。
|
||
|
||
* The second parameter identifies this as a `plural` translation type.
|
||
|
||
第二个参数表示这是一个 `plural`(复数)翻译类型。
|
||
|
||
* The third parameter defines a pluralization pattern consisting of pluralization categories and their matching values.
|
||
|
||
第三个参数定义了一组复数表示模式,这个模式由复数类别和它们所匹配的值组成。
|
||
|
||
<div class="l-sub-section">
|
||
|
||
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)
|
||
|
||
=0 (或其它数字)
|
||
|
||
* zero
|
||
|
||
zero(零)
|
||
|
||
* one
|
||
|
||
one(一个)
|
||
|
||
* two
|
||
|
||
two(两个)
|
||
|
||
* few
|
||
|
||
few(少数)
|
||
|
||
* many
|
||
|
||
many(很多)
|
||
|
||
* other
|
||
|
||
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 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="l-sub-section">
|
||
|
||
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` ICU 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: "m", "f" or "o".
|
||
The message maps those values to the appropriate translations:
|
||
|
||
组件模板中的下列消息格式绑定到了组件的 `gender` 属性,这个属性的取值是 "m" 或 "f" 或 "o"。
|
||
这个消息会把那些值映射到适当的翻译文本:
|
||
|
||
<code-example path="i18n/src/app/app.component.html" region="i18n-select" title="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:
|
||
|
||
我们也可以把不同的 ICU 表达式嵌套在一起,比如:
|
||
|
||
<code-example path="i18n/src/app/app.component.html" region="i18n-nested" title="src/app/app.component.html">
|
||
|
||
</code-example>
|
||
|
||
{@a ng-xi18n}
|
||
|
||
## Create a translation source file with _ng xi18n_
|
||
|
||
## 使用 *ng-xi18n* 工具创建翻译源文件
|
||
|
||
Use the `ng xi18n` command provided by the CLI to extract the text messages marked with `i18n` into
|
||
a translation source file.
|
||
|
||
使用 `ng-xi18n` 提取工具来将带 `i18n` 标记的文本提取到一个翻译源文件中。
|
||
|
||
Open a terminal window at the root of the app project and enter the `ng xi18n` command:
|
||
|
||
在应用的项目根目录打开一个终端窗口,并输入 `ng-xi18n` 命令:
|
||
|
||
<code-example language="sh" class="code-shell">
|
||
|
||
ng xi18n
|
||
|
||
</code-example>
|
||
|
||
By default, the tool 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>.
|
||
|
||
<div class="l-sub-section">
|
||
|
||
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 [i18n in the CLI documentation](https://github.com/angular/angular-cli/wiki/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}
|
||
|
||
### Other translation formats
|
||
|
||
### 其它翻译格式
|
||
|
||
Angular i18n tooling supports 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` flag as illustrated in
|
||
these example commands:
|
||
|
||
我们可以使用 `--i18nFormat` 来明确指定想用的格式,范例如下:
|
||
|
||
<code-example language="sh" class="code-shell">
|
||
|
||
ng xi18n --i18nFormat=xlf
|
||
ng xi18n --i18nFormat=xlf2
|
||
ng xi18n --i18nFormat=xmb
|
||
|
||
</code-example>
|
||
|
||
The sample in this guide uses the default XLIFF 1.2 format.
|
||
|
||
<div class="l-sub-section">
|
||
|
||
XLIFF files have the extension .xlf. The XMB format generates .xmb source files but uses
|
||
.xtb (XML Translation Bundle: XTB) translation files.
|
||
|
||
</div>
|
||
|
||
{@a ng-xi18n-options}
|
||
|
||
### Other options
|
||
|
||
### 其它选项
|
||
|
||
You can specify the output path used by the CLI to extract your translation source file with
|
||
the parameter `--outputPath`:
|
||
|
||
我们还可能需要指定其它选项。
|
||
比如,如果 TypeScript 的配置文件 `tsconfig.json` 位于其它地方而不是根目录,我们就要通过 `-p` 选项来明确指出它的路径。
|
||
|
||
<code-example language="sh" class="code-shell">
|
||
|
||
ng xi18n --outputPath src/locale
|
||
|
||
</code-example>
|
||
|
||
You can change the name of the translation source file that is generated by the extraction tool with
|
||
the parameter `--outFile`:
|
||
|
||
<code-example language="sh" class="code-shell">
|
||
|
||
ng xi18n --outFile source.xlf
|
||
|
||
</code-example>
|
||
|
||
You can specify the base locale of your app with the parameter `--locale`:
|
||
|
||
<code-example language="sh" class="code-shell">
|
||
|
||
ng xi18n --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 text messages
|
||
|
||
## 翻译文本信息
|
||
|
||
The `ng xi18n` command generates a translation source file named `messages.xlf` in the project `src`
|
||
folder.
|
||
|
||
`ng xi18n` 命令在项目根目录生成一个名为 `messages.xlf` 的翻译源文件。
|
||
|
||
The next step is to translate this source file into the specific language
|
||
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="l-sub-section">
|
||
|
||
Localization and internationalization are
|
||
<a href="https://en.wikipedia.org/wiki/Internationalization_and_localization">different but
|
||
closely related terms</a>.
|
||
|
||
本土化和国际化是<a href="https://en.wikipedia.org/wiki/Internationalization_and_localization" target="_blank">不同但是很相近的概念</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.
|
||
|
||
在现实世界中,`messages.fr.xlf` 文件会被发给法语翻译,他们使用<a href="https://en.wikipedia.org/wiki/XLIFF#Editors" target="_blank">这些 XLIFF 文件编辑器</a>中的一种来翻译它。
|
||
|
||
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" title="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 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" title="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" title="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}
|
||
|
||
## Translate plural and select expressions
|
||
|
||
_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:
|
||
|
||
要翻译一个复数,就要翻译它的 ICU 格式中匹配的值:
|
||
|
||
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-plural" title="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_
|
||
|
||
### 翻译*选择*(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" title="src/app/app.component.html" linenums="false">
|
||
|
||
</code-example>
|
||
|
||
The extraction tool broke that into two translation units because ICU expressions are extracted
|
||
separately.
|
||
|
||
提取工具会把它拆成*两个*翻译单元,因为 ICU 表达式是分别提取的。
|
||
|
||
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.
|
||
|
||
第一个单元包含 `select` 之外的文本。
|
||
这里的 `select` 是一个占位符 `<x id="ICU">`,用来表示 `select` 中的消息。
|
||
翻译这段文本,并把占位符放在那里。
|
||
|
||
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-select-1" title="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.
|
||
|
||
第一个翻译单元的紧下方就是第二个翻译单元,包含 `select` 中的消息。翻译它。
|
||
|
||
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-select-2" title="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" title="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" title="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" title="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" title="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 title="src/app/app.component.html" path="i18n/src/app/app.component.html">
|
||
</code-pane>
|
||
<code-pane title="src/app/app.component.ts" path="i18n/src/app/app.component.ts">
|
||
</code-pane>
|
||
<code-pane title="src/app/app.module.ts" path="i18n/src/app/app.module.ts">
|
||
</code-pane>
|
||
<code-pane title="src/main.ts" path="i18n/doc-files/main.1.ts">
|
||
</code-pane>
|
||
<code-pane title="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 a CLI parameter.
|
||
|
||
* With [JIT](guide/i18n#merge-jit), you provide the information at bootstrap time.
|
||
|
||
{@a merge-aot}
|
||
|
||
### Merge with the AOT compiler
|
||
|
||
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 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.
|
||
|
||
You also need to instruct the AOT compiler to use your translation file. To do so, you use three
|
||
options with the `ng serve` or `ng build` commands:
|
||
|
||
* `--i18nFile`: the path to the translation file.
|
||
|
||
`--i18nFile`: 翻译文件的路径
|
||
|
||
* `--i18nFormat`: the format of the translation file.
|
||
|
||
* `--locale`: the locale id.
|
||
|
||
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 --aot --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr
|
||
|
||
</code-example>
|
||
|
||
{@a merge-jit}
|
||
|
||
### Merge with the JIT compiler
|
||
|
||
### 用 JiT 编译器合并
|
||
|
||
The JIT compiler compiles the app in the browser as the app loads.
|
||
Translation with the JIT compiler is a dynamic process of:
|
||
|
||
JiT(即时)编译器在应用程序加载时,在浏览器中编译应用。
|
||
在使用 JiT 编译器的环境中翻译是一个动态的流程,包括:
|
||
|
||
1. Importing the appropriate language translation file as a string constant.
|
||
|
||
把合适的语言翻译文件导入成一个字符串常量
|
||
|
||
2. Creating corresponding translation providers for the JIT compiler.
|
||
|
||
为 JiT 编译器创建相应的翻译提供商。
|
||
|
||
3. Bootstrapping 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:
|
||
|
||
三种提供商帮助 JiT 编译在编译应用时,将模板文本翻译到某种语言:
|
||
|
||
* `TRANSLATIONS` is a string containing the content of the translation file.
|
||
|
||
`TRANSLATIONS` 是含有翻译文件内容的字符串。
|
||
|
||
* `TRANSLATIONS_FORMAT` is the format of the file: `xlf`, `xlf2`, or `xtb`.
|
||
|
||
`TRANSLATIONS_FORMAT` 是文件的格式: `xlf`、`xlif` 或 `xtb`。
|
||
|
||
* `LOCALE_ID` is the locale of the target language.
|
||
|
||
`LOCALE_ID` 是目标语言的语言环境。
|
||
|
||
The Angular `bootstrapModule` method has a second `compilerOptions` parameter that can influence the
|
||
behavior of the compiler. You can use it to provide the translation providers:
|
||
|
||
在下面的 `src/app/i18n-providers.ts` 文件的 `getTranslationProviders()` 函数中,根据用户的**语言环境**和对应的翻译文件构建这些提供商:
|
||
|
||
<code-example path="i18n/doc-files/main.2.ts" title="src/main.ts">
|
||
|
||
</code-example>
|
||
|
||
Then provide the `LOCALE_ID` in the main module:
|
||
|
||
<code-example path="i18n/doc-files/app.module.ts" title="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.
|
||
|
||
If you use the AOT compiler, specify the warning level by using the CLI parameter
|
||
`--missingTranslation`. The example below shows how to set the warning level to error:
|
||
|
||
<code-example language="sh" class="code-shell">
|
||
|
||
ng serve --aot --missingTranslation=error
|
||
|
||
</code-example>
|
||
|
||
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" title="src/main.ts">
|
||
|
||
</code-example>
|