i18n. Localization in Angular

When I received the task of translating a rather large project, to be honest, I was a little lost. There are several library options that help with this task, but I settled on i18n for Angular and here’s why. In my subjective opinion, the library does an excellent job of localizing a ready-made project. But even so, you will have to tinker a little, without this you can’t get anywhere.

Let me clarify that this article describes processes for Angular v.9 and higher. I hope the information will be useful to you.

Step 1: Installation

To work with i18n you need to install the package @angular/localize. You can use any package manager you are familiar with or use the CLI from Angular.

ng add @angular/localize
npm install -D @angular/localiz
yarn add --dev @angular/localize

Next, I immediately suggest updating the settings in the config angular.json. Example below:

{
  "projects": {
    "my-project": {
      "i18n": { // Настройки для i18n. Обязательно нужно добавить.
        "sourceLocale": { // Настройка языка по умолчанию. 
          "code": "ru",
          "baseHref": "https://habr.com/ru/" // Путь до корневой папки при билде. Необязательный парамер, но мне пригодилось
        },
        "locales": { // Другие поддерживаемые языки
          "en": {
            "translation": "src/locale/messages.en.xlf", // Путь до файла с переводом
            "baseHref": "/en/"
          }
        }
      },
      "build": {
        "options": {
          "localize": true, // Флаг указывает на поддержку локализации
          "i18nMissingTranslation": "error", // Сообщает об отсутсвии перевода при билде проекта
          
          //...
        },
        "configurations": {
          "ru": {  // Конфигулации для конкретного языка, поможет при тестировании
            "localize": ["ru"]
          },
          "en" : {
            "localize": ["en"]
          }
          
          //...
        }
        
        //...
      },
      "serve": {
        "configurations": {
          "ru": {
            "browserTarget": "LkVideoAdmin:build:development,ru" // Конфигулации для при тестирования
          },
          "en": {
            "browserTarget": "LkVideoAdmin:build:development,en"
          }
          
          //...
        }
      }

      //...
    }
  }
}

Step 2. Preparing for translation

Translation in html templates

For html everything is quite simple. After installation and configuration, it becomes available to us
i18n-attribute. We simply mark the tags with the text we want to translate.

<h1 i18n>Переведи меня!!!</h1>

The attribute acts as a marker for localization. When compiled, it will be removed and the text will be replaced with a translation into the current language.

You can pass additional data to the attribute, such as value, description or id

<h1 i18n="Значение|описание@@id">Переведи меня!!!</h1>

This way you can convey the necessary context to the translator. For example, you can describe what page the text is used on or what its purpose is.

The beauty of i18n is that it can be used not only in standard html tags, but also in ng-container

<ng-container *ngIf="flag" i18n>Текст по условию</ng-container>

Note: In Angular before v.9 it was possible to use the construct

<h1 i18n>{{flag ? "Текст по условию 1" : "Текст по условию 2"}}</h1>

After v.9, such a design will not be included in the translation file.

Use ng-container

You can also translate not only the text in tags, but also the text in attributes using
i18n-{attribute_name}

<inpul i18n-placeholder placeholder="Пароль"/>

Translation in typescript files

The function is available in typescript files $localize. You can read more about it here.

It works in a similar way.

$localize`:Значение|описание@@id:Переведи меня!!!`;

Note: Some code editors tend to import the $localize function. But there is no need to import it. The function will be removed from the code during compilation, but the import will remain. Don’t repeat my mistakes))

Step 3. File generation and translation

After everything that you wanted to translate has been marked, you can generate a file with texts. For this purpose, the Angular CLI has a separate extract-i18n command. If desired, it can be configured in the Angular config

{
  
  //...
  "projects": {
    "my-project": {
      
      //...
      "architect": {
        
        //...
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "my-project:build",
            "format": "xlf", // формат для файлов с переводом
            "outputPath": "src/locale" // Путь для файлов с переводом
          }
        }
      }
    }
  }

More details here.

Just run the command

ng extract-i18n

With the settings above you will receive a file messages.xlf with collected texts along the way src/locale.

<?xml version="1.0" encoding="UTF-8" ?>

<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="ru" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="id" datatype="html">
        <source>Переведи меня</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">1</context>
        </context-group>
        <note priority="1" from="description">Значение</note>
        <note priority="1" from="meaning">описание</note>
      </trans-unit>
    </body>
  </file>
</xliff>

Now duplicate the file and change its name to messages.en.xlf, you should get 2 files, one with the default language, the second with the translation. All that remains is to translate the texts by replacing the text in the field source for translation. Don’t forget to change the attribute source-language in the tag file to “en”

You can check whether everything has been translated correctly using the command

ng serve --configuration=en --open

A project with translated texts will be launched. This way you can check the translation and whether the layout has gone wrong during the translation.

All that remains is to build the project, and for this we already have everything ready. run the command
ng build.

As a result, we get the file structure

dist
  ru
    /// файлы на русском
  en
    /// файлы на английском

Step 4. Project changes

When developing a project, there are no changes anywhere. Something needs to be added, removed or changed. And texts are no exception.

Let’s change our old version

<h1 i18n="Значение|описание@@id">Переведи меня!!!</h1>

<p i18n="Значение2|описание2@@id-2">Новый текст...</p>

Let’s run the command we already know again

ng extract-i18n

It will automatically replace the contents of the file messages.xlf for something new.

<?xml version="1.0" encoding="UTF-8" ?>

<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="ru" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="id" datatype="html">
        <source>Переведи меня</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">1</context>
        </context-group>
        <note priority="1" from="description">Значение</note>
        <note priority="1" from="meaning">описание</note>
      </trans-unit>
      <trans-unit id="id2" datatype="html">
        <source>Новый текст...</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">3</context>
        </context-group>
        <note priority="1" from="description">Значение2</note>
        <note priority="1" from="meaning">описание2</note>
      </trans-unit>
    </body>
  </file>
</xliff>

But the file messages.en.xlf will remain unchanged. And when you try to build a project with the settings in step 1, an error will occur. To avoid this, you must manually add a new translation to the file messages.en.xlf.

<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="id" datatype="html">
        <source> Transfer me</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">1</context>
        </context-group>
        <note priority="1" from="description">Значение</note>
        <note priority="1" from="meaning">описание</note>
      </trans-unit>
      <trans-unit id="id2" datatype="html">
        <source> New text...</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">3</context>
        </context-group>
        <note priority="1" from="description">Значение2</note>
        <note priority="1" from="meaning">описание2</note>
      </trans-unit>
    </body>
  </file>
</xliff>

Bottom line

I18n is quite simple and easy to use, and to work with the format xliff there are convenient programs. In this article I described the path from installation and configuration to compilation. I hope it will be useful.

Finally, I will share links to i18n capabilities not described in this article.

Declension by numbers (plural) – allows you to specify different declensions for a word (day, day, days).

Selecting an alternative option (select) – allows you to indicate alternative text options by text key (men’s clothing, women’s clothing).

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *