W3cubDocs

/Angular

Work with translation files

After you prepare a component for translation, use the extract-i18n Angular CLI command to extract the marked text in the component into a source language file.

The marked text includes text marked with i18n, attributes marked with i18n-attribute, and text tagged with $localize as described in Prepare component for translation.

Complete the following steps to create and update translation files for your project.

  1. Extract the source language file.
    1. Optionally, change the location, format, and name.
  2. Copy the source language file to create a translation file for each language.
  3. Translate each translation file.
  4. Translate plurals and alternate expressions separately.
    1. Translate plurals.
    2. Translate alternate expressions.
    3. Translate nested expressions.

Extract the source language file

To extract the source language file, complete the following actions.

  1. Open a terminal window.

  2. Change to the root directory of your project.

  3. Run the following CLI command.

    ng extract-i18n

The extract-i18n command creates a source language file named messages.xlf in the root directory of your project. For more information about the XML Localization Interchange File Format (XLIFF, version 1.2), see XLIFF.

Use the following extract-i18n command options to change the source language file location, format, and file name.

Command option Details
--format Set the format of the output file
--out-file Set the name of the output file
--output-path Set the path of the output directory

Change the source language file location

To create a file in the src/locale directory, specify the output path as an option.

extract-i18n --output-path example

The following example specifies the output path as an option.

ng extract-i18n --output-path src/locale

Change the source language file format

The extract-i18n command creates files in the following translation formats.

Translation format Details File extension
ARB Application Resource Bundle .arb
JSON JavaScript Object Notation .json
XLIFF 1.2 XML Localization Interchange File Format, version 1.2 .xlf
XLIFF 2 XML Localization Interchange File Format, version 2 .xlf
XMB XML Message Bundle .xmb (.xtb)

Specify the translation format explicitly with the --format command option.

The XMB format generates .xmb source language files, but uses.xtb translation files.

extract-i18n --format example

The following example demonstrates several translation formats.

ng extract-i18n --format=xlf
ng extract-i18n --format=xlf2
ng extract-i18n --format=xmb
ng extract-i18n --format=json
ng extract-i18n --format=arb

Change the source language file name

To change the name of the source language file generated by the extraction tool, use the --out-file command option.

extract-i18n --out-file example

The following example demonstrates naming the output file.

ng extract-i18n --out-file source.xlf

Create a translation file for each language

To create a translation file for a locale or language, complete the following actions.

  1. Extract the source language file.

  2. Make a copy of the source language file to create a translation file for each language.

  3. Rename the translation file to add the locale.

    messages.xlf --> messages.{locale}.xlf
  4. Create a new directory at your project root named locale.

    src/locale
  5. Move the translation file to the new directory.

  6. Send the translation file to your translator.

  7. Repeat the above steps for each language you want to add to your application.

extract-i18n example for French

For example, to create a French translation file, complete the following actions.

  1. Run the extract-i18n command.
  2. Make a copy of the messages.xlf source language file.
  3. Rename the copy to messages.fr.xlf for the French language (fr) translation.
  4. Move the fr translation file to the src/locale directory.
  5. Send the fr translation file to the translator.

Translate each translation file

Unless you are fluent in the language and have the time to edit translations, you will likely complete the following steps.

  1. Send each translation file to a translator.
  2. The translator uses an XLIFF file editor to complete the following actions.
    1. Create the translation.
    2. Edit the translation.

Translation process example for French

To demonstrate the process, review the messages.fr.xlf file in the Example Angular Internationalization application. The Example Angular Internationalization application includes a French translation for you to edit without a special XLIFF editor or knowledge of French.

The following actions describe the translation process for French.

  1. Open messages.fr.xlf and find the first <trans-unit> element. This is a translation unit, also known as a text node, that represents the translation of the <h1> greeting tag that was previously marked with the i18n attribute.

    <trans-unit id="introductionHeader" datatype="html">
      <source>Hello i18n!</source>
      <note priority="1" from="description">An introduction header for this sample</note>
      <note priority="1" from="meaning">User welcome</note>
    </trans-unit>

    The id="introductionHeader" is a custom ID, but without the @@ prefix required in the source HTML.

  2. Duplicate the <source>... </source> element in the text node, rename it to target, and then replace the content with the French text.

    <trans-unit id="introductionHeader" datatype="html">
      <source>Hello i18n!</source>
      <target>Bonjour i18n !</target>
      <note priority="1" from="description">An introduction header for this sample</note>
      <note priority="1" from="meaning">User welcome</note>
    </trans-unit>

    In a more complex translation, the information and context in the description and meaning elements help you choose the right words for translation.

  3. Translate the other text nodes. The following example displays the way to translate.

    <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">
      <source>I don&apos;t output any element</source>
      <target>Je n'affiche aucun élément</target>
    </trans-unit>
    <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">
      <source>Angular logo</source>
      <target>Logo d'Angular</target>
    </trans-unit>

    Don't change the IDs for translation units. Each id attribute is generated by Angular and depends on the content of the component text and the assigned meaning. If you change either the text or the meaning, then the id attribute changes. For more about managing text updates and IDs, see custom IDs.

Translate plurals

Add or remove plural cases as needed for each language.

For language plural rules, see CLDR plural rules.

minute plural example

To translate a plural, translate the ICU format match values.

  • just now
  • one minute ago
  • <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago

The following example displays the way to translate.

<trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" datatype="html">
  <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago} }</source>
  <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>
</trans-unit>

Translate alternate expressions

Angular also extracts alternate select ICU expressions as separate translation units.

gender select example

The following example displays a select ICU expression in the component template.

<span i18n>The author is {gender, select, male {male} female {female} other {other}}</span>

In this example, Angular extracts the expression into two translation units. The first contains the text outside of the select clause, and uses a placeholder for select (<x id="ICU">):

<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
  <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
  <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
</trans-unit>

When you translate the text, move the placeholder if necessary, but don't remove it. If you remove the placeholder, the ICU expression is removed from your translated application.

The following example displays the second translation unit that contains the select clause.

<trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">
  <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>
  <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>
</trans-unit>

The following example displays both translation units after translation is complete.

<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
  <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
  <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
</trans-unit>
<trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">
  <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>
  <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>
</trans-unit>

Translate nested expressions

Angular treats a nested expression in the same manner as an alternate expression. Angular extracts the expression into two translation units.

Nested plural example

The following example displays the first translation unit that contains the text outside of the nested expression.

<trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">
  <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>
  <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>
</trans-unit>

The following example displays the second translation unit that contains the complete nested expression.

<trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">
  <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>
  <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>
</trans-unit>

The following example displays both translation units after translating.

<trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">
  <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>
  <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>
</trans-unit>
<trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">
  <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>
  <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>
</trans-unit>

What's next

Last reviewed on Mon Feb 28 2022

© 2010–2023 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://angular.io/guide/i18n-common-translation-files