include ../_util-fns

:marked
  Angular's _internationalization_ ("_i18n_") tools help make your app available in multiple languages.

  Angular的**国际化**（"_i18n_"）工具可以帮助我们使用多个语言发布应用。
  
  <a id="top"></a>
  ## Table of contents

  ## 目录
    
    * [Angular and i18n template translation](#angular-i18n)

    * [Angular和i18n模板翻译](#angular-i18n)

    * [Mark text with the _i18n_ attribute](#i18n-attribute)

    * [使用_i18n_属性标记文本](#i18n-attribute)

    * [Create a translation source file with the _ng-xi18n_ tool](#ng-xi18n)

    * [使用_ng-xi18n_工具创建翻译源文件](#ng-xi18n)

    * [Translate](#translate)

    * [翻译](#translate)

    * [Merge the completed translation file into the app](#merge)

    * [合并翻译完成的文件到应用中](#merge)

      * [JiT configuration](#jit)

      * [JiT配置](#jit)

      * [AoT configuration](#aot)

      * [AoT配置](#aot)

:marked
  **Try this** <live-example name="cb-i18n">live example</live-example> of a JiT-compiled app, translated into French.

  **试试** 这个翻译为法语版JiT编译应用的<live-example name="cb-i18n">在线例子</live-example>。
  
a#angular-i18n
.l-main-section
:marked
  ## Angular and _i18n_ template translation
  
  ## Angular和_i18n_模板翻译

  Application internationalization is a challenging, many-faceted effort that 
  takes dedication and enduring commitment.
  Angular's _i18n_ internationalization facilities can help.

  应用程序国际化很具有挑战性，多方面的努力，需要持久的奉献和决心。
  Angular的_i18n_国际化工具可以帮助你。

  This page describes the _i18n_ tools to assist translation of component template text
  into multiple languages.

  本章描述了_i18n_是如何协助翻译组件模板文本到多种语言的。


.l-sub-section
  :marked
    Practitioners of _internationalization_ refer to a translatable text as a "_message_".
    This page uses the words "_text_" and "_message_" interchangably and in the combination, "_text message_".

    **国际化**工作者通常将一个可翻译的文本叫作“信息”。
    本章使用了“文本”和“信息”，它们可以互换，也可以组合“文本信息”。
  
:marked
  The _i18n_ template translation process has four phases:

  _i18n_模板翻译流程有四个阶段：  

  1. Mark static text messages in your component templates for translation.

  1. 在组件模板中标记需要翻译的静态文本信息。
  
  1. An angular _i18n_ tool extracts the marked messages into an industry standard translation source file.

  1. Angular的_i18n_工具将标记的信息提取到一个行业标准的翻译源文件。

  1. A translator edits that file, translating the extracted text messages into the target language, 
  and returns the file to you.

  1. 翻译人员编辑该文件，翻译提取出来的文本信息到目标语言，并将该文件还给你。

  1. The Angular compiler imports the completed translation files, 
  replaces the original messages with translated text, and generates a new version of the application
  in the target language.

  1. Angular编译器导入完成翻译的文件，使用翻译的文本替换原始信息，并生成新的目标语言版本的应用程序。

  You build and deploy a separate version of the application for each supported language.

  你可以为每种支持的语言构建和部署单独的应用程序版本。

a#i18n-attribute
.l-main-section
:marked
  ## Mark text with the _i18n_ attribute
  
  ## 使用_i18n_属性标记文本

  The Angular `i18n` attribute is a marker for translatable content.
  Place it on every element tag whose fixed text should be translated.

  Angular的`i18n`属性是可翻译内容的标记。
  将它放到每个固定文本需要翻译的元素标签中。

.alert.is-helpful
  :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.

    `i18n`不是Angular指令。
    它是一个自定义**属性**，Angular工具和编译器认识它。
    它将在完成翻译**之后**，被编译器移除。

:marked
  In the accompanying sample, an `<h1>` tag displays a simple English language greeting which you will translate to French:

  在例子中，`<h1>`标签显示了一句简单的英文问候语，它将被翻译为法语：

+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.

  添加`i18n`属性到该标签上，把它标记为需要翻译的文本。

+makeExample('cb-i18n/ts/app/app.component.1.html', 'i18n-attribute', 'app/app.component.html')(format=".")

:marked
  The translator may need a description of the message to translate it accurately.
  Assign a description to the i18n attribute:

  翻译人员可能需要待翻译文本的描述才能翻译准确。
  为i18n属性添加描述：
  
+makeExample('cb-i18n/ts/app/app.component.1.html', 'i18n-attribute-desc', 'app/app.component.html')(format=".")

:marked
  The true _meaning_ of the text may require some application context.
  Add a contextual meaning to the assigned string, separating it from the description with the `|` character:

  文本的准确**意思**可能需要一些应用上下文。
  在制定的字符串中添加上下文含义，用`|`将其与描述文字隔开。
  
+makeExample('cb-i18n/ts/app/app.component.html', 'i18n-attribute-meaning', 'app/app.component.html')(format=".")

:marked
  While all appearance of a message with the _same_ meaning should have the _same_ translation, 
  a message with *different 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.

  如果所有地方出现的文本具有**相同**含义时，它们应该有**相同**的翻译，
  但是如果在某些地方它具有**不同含义**，那么它应该有不同的翻译。
  Angular的提取工具在翻译源文件中保留**含义**和**描述**，以支持符合特定上下文的翻译。

a#ng-xi18n
.l-main-section
:marked
  ## Create a translation source file with the _ng-xi18n_ tool

  ## 使用_ng-xi18n_工具创建翻译源文件
  
  Use the `ng-xi18n` extraction tool to extract the `i18n`-marked texts 
  into a translation source file in an industry standard format.

  使用`ng-xi18n`提取工具来将`i18n`标记的文本提取到一个符合行业标准格式的翻译源文件。
  
  This is an Angular CLI tool in the `@angular/compiler-cli` npm package.
  If you haven't already installed the CLI and its `platform-server` peer dependency, do so now:

  它是在`@angular/compiler-cli` npm包中的一个Angular CLI工具。
  如果你还没有安装这个CLI和它的 `platform-server`，安装它们：
  
code-example(language="sh" class="code-shell").
  npm install @angular/compiler-cli @angular/platform-server --save

:marked
  Open a terminal window at the root of the application project and enter the `ng-xi18n` command:

  在应用的项目根目录打开一个终端窗口，并输入`ng-xi18n`命令：
 
code-example(language="sh" class="code-shell").
  ./node_modules/.bin/ng-xi18n

:marked
  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>.

  工具默认生成一个名为**`messages.xlf`**的翻译文件，格式为<a href="https://en.wikipedia.org/wiki/XLIFF" target="_blank">XML本土化互换文件格式(XLIFF, version 1.2)</a>。

code-example(language="sh" class="code-shell").
  ./node_modules/.bin/ng-xi18n  --i18nFormat=xmb

.l-sub-section
  :marked
    Windows users may have to quote the command:

    Windows用户可能需要双引号这个命令：

  code-example(language="sh").
    "./node_modules/.bin/ng-xi18n"
  :marked
    Consider adding a convenience shortcut to the `scripts` section of the `package.json`
    to make the command easier to remember and run:

    建议在`package.json`文件的`scripts`部分添加一个便利的快捷方式，让这个命令更容易被记住和运行：
  code-example(format='.').
    "scripts": {
      "i18n": "ng-xi18n", 
      ...
    }
  :marked
    Now you can enter:

    现在你只需要输入：
  code-example(language="sh" class="code-shell").
    npm run i18n

:marked
  ### Other translation formats

  ### 其他翻译格式

  You can generate a file named **`messages.xmb`** in the 
  <a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb"  target="_blank">XML Message Bundle (XMB)</a> format
  by adding the `--i18nFormat=xmb` switch.

  你可以通过添加`--i18nFormat=xmb`开关，来生成名为**`messages.xmb`**的翻译文件，它的格式为<a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb"  target="_blank">XML信息捆绑包(XMB)</a>。

  This sample sticks with the _XLIFF_ format.

  本例采用_XLIFF_格式。

a#translate
.l-main-section
:marked
  ## Translate _le message textuel_
  
  ## 翻译
  
  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
  files. The cookbook sample creates a French translation file.

  `ng-xi18n`命令在项目根目录生成一个名为`messages.xlf`的翻译源文件。
  下一步是将英文模板文本翻译到目标语言的翻译文件。
  本烹饪书创建了一个法语翻译文件。

a#localization-folder
:marked
  ### Create a localization folder

  ### 新建一个本土化目录

  You will probably translate into more than one other language so it's a good idea
  for the project structure to reflect your entire internationalization effort.

  你很有可能翻译到更多其他语言，所以为全部国际化工作做适当的调整项目目录结构是理所当然的。
  
  One approach is to dedicate a folder to localization and store related assets 
  (e.g. 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>.

    本土化和国际化是<a href="https://en.wikipedia.org/wiki/Internationalization_and_localization" target="_blank">不同但是很相近的概念</a>。
:marked
  This sample follows that suggestion. It has `locale` folder immediately 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>.

  本例遵循这个建议。项目根目录有`locale`目录。
  目录的资源的文件名都匹配有一个语言代码后缀，参见<a href="https://msdn.microsoft.com/en-us/library/ee825488(v=cs.20).aspx" target="_blank">语言代码对照表</a>.

  Move `messages.xlf` into the `locale` folder where it will become the source for all language-specific translations.
  Then make a copy for the French language named `messages.fr.xlf` .

  将`messages.xlf`移到`locale`目录，这里将存放所有语言与翻译相关的文件。
  然后为法语复制这个文件，名为`messages.fr.xlf`。

  Follow the same convention for each target language.

  对所有目标语言都采用同样的约定。

  ### Translate

  ### 翻译

  In the real world, you send the `messages.fr.xlf` file to a French translator who would fill in the translations
  using one of the 
  <a href="https://en.wikipedia.org/wiki/XLIFF#Editors" target="_blank">many XLIFF file editors</a>.

  在现实世界中，`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.
  Open `messages.fr.xlf` and find the `<trans-unit>` section:

  我们不需要任何编辑器或者法语知识就可以轻易的翻译本例子文件。
  打开`messages.fr.xlf`并找到`<trans-unit>`节点：

+makeExample('cb-i18n/ts/locale/trans-unit.html', '', 'locale/messages.fr.xlf (<trans-unit>)')(format=".")
:marked
  This XML element represents the translation of the `<h1>` greeting tag you marked with the `i18n` attribute. 

  这个XML元素代表了你使用`i18n`属性标记的`<h1>`问候语标签的翻译。
  
  Using the _source_, _description_, and _meaning_ elements to guide your translation,
  replace the `<target/>` tag with the French greeting:

  翻译中利用_source_、_description_和_meaning_元素的信息，替换`<target/>`标签为法语问候语：

+makeExample('cb-i18n/ts/locale/messages.fr.xlf.html', 'trans-unit', 'locale/messages.fr.xlf (<trans-unit>, after translation)')(format=".")
:marked
  Note that the `id` is generated by the tool. 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.

  注意`id`是工具生成的。不要修改它。
  它的值取决于两个因素：信息的内容和其指定的含义。
  改变任何一个因素，`id`就会改变。
.alert.is-helpful
  :marked
    Repeat the extraction process whenever you add new app messages or edit existing ones.
    Be careful not to lose the previous translations.
    Specialized software can help manage the change process.

    每当你添加或者编辑应用信息，重复提取流程。
    小心不要丢失之前的翻译。专门的软件可以帮助你管理变更流程。

#app-pre-translation
:marked
  ### The app before translation
  
  ### 翻译前的应用程序

  After the previous steps, the sample app _and_ its translation file are as follows:

  如下所示，是完成前面的步骤后的例子应用**和**它的翻译文件：

+makeTabs(`
  cb-i18n/ts/app/app.component.html,
  cb-i18n/ts/app/app.component.ts,
  cb-i18n/ts/app/app.module.ts,
  cb-i18n/ts/app/main.1.ts,
  cb-i18n/ts/locale/messages.fr.xlf.html
`, '', `
  app/app.component.html,
  app/app.component.ts,
  app/app.module.ts,
  app/main.ts,
  locale/messages.fr.xlf
`)

a#merge
.l-main-section
:marked
  ## Merge the completed translation file

  ## 合并已经翻译的文件

  To merge the translated text into component templates,
  you 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.

  要合并已经翻译的文件到组件模板，使用翻译过的文件编译应用。
  不管文件是`.xlf`格式还是其他Angular接受的格式（`.xlif`和`.xtb`），流程是一样的。
  
  You provide the Angular compiler with three new pieces of information:

  你为Angular编译器提供下列三种新信息：

    * the translation file

    * 翻译文件

    * the translation file format

    * 翻译文件的格式

    * the   <a href="https://en.wikipedia.org/wiki/XLIFF" target="_blank">_Locale ID_</a>
    (`fr` or `en-US` for instance)

    * 目标<a href="https://en.wikipedia.org/wiki/XLIFF" target="_blank">_语言环境ID_</a>
    (例如`fr`或`en-US`)
  
  _How_ you provide this information depends upon whether you compile with
  the JiT (_Just-in-Time_) compiler or the AoT (_Ahead-of-Time_) compiler. 

  你如何提供这些信息取决于你使用的是JiT（即时）编译器还是AoT（预先）编译器。
  
    * with [JiT](#jit), you provide the information at bootstrap time.

    * 使用[JiT](#jit)时，在引导时提供

    * with [AoT](#aot), you pass the information as `ngc` options.

    * 使用[AoT](#aot)时，在`ngc`命令的选项里提供

a#jit
.l-main-section
:marked
  ### Merge with the JiT compiler

  ### 用JiT编译器合并
  
  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 ...

  JiT（即时）编译器在应用程序加载时，在浏览器中编译应用。
  在使用JiT编译器的环境中翻译是一个动态的流程，包括：

  1. determining the language version for the current user,

  1. 决定当前用户的语言，

  2. importing the appropriate language translation file as a string constant,

  2. 导入合适的语言翻译文件到一个字符串常量，

  3. creating corresponding translation providers to guide the JiT compiler,

  3. 新建对应的翻译提供商来指导JiT编译器，

  4. bootstrapping the application with those providers.

  4. 使用这些提供商来启动应用。

  Open `index.html` and revise the launch script as shown here:

  打开`index.html`并这样修改加载脚本：

+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
  in the `index.html`.

  在本例中，用户的语言在`index.html`中被硬编码到一个全局的`document.locale`变量中。

a#text-plugin
:marked
  ### SystemJS Text plugin

  ### SystemJS文本插件

  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
  return the contents as a string.
  You'll need it to import the language translation file.

  注意SystemJS将`text`映射为`systemjs-text-plug.js`。
  在这个文本插件的帮助下，SystemJS可以读取任何原始文件并将其内容作为字符串返回。
  你需要使用它来导入语言翻译文件。

  SystemJS doesn't ship with a raw text plugin but it's easy to add.
  Create the following `systemjs-text-plugin.js` in the root folder:

  SystemJS没有自带原始文本插件，但是我们很容易添加它。
  在根目录新建下面的`systemjs-text-plugin.js`文件：

+makeExample('cb-i18n/ts/systemjs-text-plugin.js', null, 'systemjs-text-plugin.js')(format='.')
:marked
  ### Create translation providers

  ### 新建翻译提供商

  Three providers tell the JiT compiler how to translate the template texts for a particular language
  while compiling the application:

  三种提供商帮助JiT编译在编译应用时，将模板文本翻译到某种语言：

  * `TRANSLATIONS` is a string containing the content of the translation file.

  * `TRANSLATIONS`是含有翻译文件内容的字符串。

  * `TRANSLATIONS_FORMAT` is the format of the file: `xlf`, `xlif` or `xtb`

  * `TRANSLATIONS_FORMAT`是文件的格式: `xlf`、`xlif`或`xtb`。

  * `LOCALE_ID` is the locale of the target language.

  * `LOCALE_ID`是目标语言的语言环境。

  The `getTranslationProviders` function in the following `app/i18n-providers.ts` 
  creates those providers based on the user's _locale_
  and the corresponding translation file:

  在下面的`app/i18n-providers.ts`文件的getTranslationProviders`函数中，根据用户的**语言环境**和对应的翻译文件构建这些提供商：
+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`.

  * 它从在`index.html`中设置的全局`document.locale`变量中获取语言环境。

  * 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.

  * 如果没有语言环境或者语言是美国英语（`en-US`），则就无需翻译。
    该函数以`Promise`的形式返回一个空的`noProviders`数组。
    它必须要返回`Promise`，因为这个函数可能异步从服务器读取翻译文件。

  * It creates a transaction filename from the locale according to the name and location convention 
  [described earlier](#localization-folder).

  * 根据[上面描述](#localization-folder)的名字和本土化的约定，它根据语言环境创建一个合约文件名。

  * 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). 

  * `getTranslationsWithSystemJs`方法读取翻译并以字符串的形式返回其内容。
  注意它在文件名上附加`!text`，告诉SystemJS使用[文本插件](#text-plugin)。

  * The callback composes a providers array with the three translation providers.

  * 回调函数使用这三种翻译提供商创建一个提供商数组。

  * Finally, `getTranslationProviders` returns the entire effort as a promise.

  * 最后，`getTranslationProviders`返回以承诺的形式返回全部流程的结果。

  ### Bootstrap the app with translation providers

  ### 使用翻译提供商引导应用

  The Angular `bootstrapModule` method has a second, _options_ parameter
  that can influence the behavior of the compiler.

  Angular的`bootstrapModule`方法接受**可选的**第二参数，它可以影响编译器的行为。

  You'll create an _options_ object with the translation providers from `getTranslationProviders`
  and pass it to `bootstrapModule`.
  Open the `app/main.ts` and modify the bootstrap code as follows:

  从`getTranslationProviders`返回的翻译提供商创建_options_对象，并将其传给`bootstrapModule`。
  打开`app/main.ts`并这样修改引导代码：

+makeExample('cb-i18n/ts/app/main.ts', null, 'app/main.ts')(format=".")
:marked
  Notice that it waits for the `getTranslationProviders` promise to resolve before
  bootstrapping the app.

  注意，它等待`getTranslationProviders`承诺的解析完成后，才引导应用。

  The app is now _internationalized_ for English and French and there is a clear path for adding
  more languages.

  现在，应用已经被国际化为英语版和法语版，而且我们有了清晰的添加更多语言的方法。

a#aot
.l-main-section
:marked
  ### _Internationalize_ with the AoT compiler

  ### 使用AoT编译器时的国际化
  
  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.

  JiT编译器在浏览器中动态编译应用时，将其翻译到目标语言。
  这样很灵活，但是对用户来讲，可能速度太慢。 
  
  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.

  AoT（预先）编译器是一种构建流程，出产尺寸小、速度快和可执行的应用程序包。
  在使用Aot编译器的环境中国际化，你为每种语言预先构建一个单独的应用程序包。然后，在宿主网络页面（`index.html`）中，你再决定用户需要哪种语言，并选择合适的应用程序包。

  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.

  本烹饪书不介绍如何构建多种应用程序包和如何根据用户的语言设置推送它们。
  它介绍了一些必要的步骤，来告诉AoT采用用翻译文件。

  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_.

  使用AoT编译器时的国际化，需要一些针对AoT的设置。
  以[合并翻译文件之前](#app-pre-translationStart)的应用项目开始，并参见[AoT烹饪书](aot-compiler.html)，把它变成与AoT兼容的项目。
  
  Next, issue an `ngc` compile command for each supported language (including English).
  The result is a separate version of the application for each language.

  接下来，为每种支持的语言（包括英语）运行一次`ngc`编译命令。
  结果是每种语言都有自己单独的应用版本。
  
  Tell AoT how to translate by adding three options to the `ngc` command:

  通过添加下面三种选项到`ngc`命令来告诉AoT编译器如何翻译：

    * `--i18nFile`: the path to the translation file

    * `--i18nFile`: 翻译文件的路径

    * `--locale`: the name of the locale

    * `--locale`: 语言环境的名字

    * `--i18nFormat`: the format of the localization file

    * `--i18nFormat`: 翻译文件的格式
  
  For this sample, the French language command would be

  本法语例子的命令为：
code-example(language="sh" class="code-shell").
  ./node_modules/.bin/ngc --i18nFile=./locale/messages.fr.xlf --locale=fr --i18nFormat=xlf

.l-sub-section
  :marked
    Windows users may have to quote the command:

    Windows用户可能需要双引号这个命令：
  code-example(language="sh" class="code-shell").
    "./node_modules/.bin/ngc" --i18nFile=./locale/messages.fr.xlf --locale=fr --i18nFormat=xlf
