Справочный центр

Подготовка к локализации проекта Angular

Как подготовить к локализации проект, разработанный в среде Angular
При проектировании и разработке приложения с учетом его последующей локализации нужно следовать правилам, указанным ниже
Обработчики (pipes) i18n

DatePipe, CurrencyPipe, DecimalPipe используют информацию о локали для формата вывода данных (дата, валюта, числа соответственно), которая (локаль) находится в константе LOCALE_ID.

По умолчанию Angular поддерживает только обработчики для локали en-US. Если вы хотите указать LOCALE_ID для другой локали, необходимо импортировать эти данные для нее. CLI импортирует эти данные при использовании параметра --configuration.

Вручную данные локали можно импортировать: src/app/app.module.ts
import { registerLocaleData } from '@angular/common';
import localeRu from '@angular/common/locales/ru';
import localeRuExtra from '@angular/common/locales/extra/ru';

registerLocaleData(localeRu, 'ru', localeRuExtra);
Перевод шаблонов

Перевод содержимого html-тэгов

Чтобы добавить в шаблоны Angular перевод, необходимо указать атрибут i18n в тэге, содержимое которого требует перевод:

src/app/account/account.component.html
<button i18n>Login</button>
В значении атрибута можно указать дополнительное описание, позволяющие переводчику лучше понять контекст

src/app/account/account.component.html
<button i18n="Button for login">Login</button>
Если вы хотите отделить контекст от описания разделите их символом '|':

src/app/account/account.component.html
<button i18n="login form|Button for login">Login</button>
При извлечении текста для перевода Angular генерирует уникальный идентификатор для единицы перевода. Можно указать кастомный идентификатор, используя '@@':

src/app/account/account.component.html
<button i18n="@@loginButton">Login</button>
Пример с указанием контекста, описания и идентификатора:

src/app/account/account.component.html
<button i18n="login form|Button for login@@loginButton">Login</button>
Перевод атрибутов

Для того, чтобы обозначить атрибут для перевода необходимо указать имя этого атрибута через дефис:

src/app/account/account.component.html
<input i18n-placeholder placeholder="Your login">
Перевод скриптов

Переводы в файлах скриптов на данный момент не поддерживаются фреймворком. Но существует расширение, предоставляемое разработчиками фреймворка для решения этой задачи @ngx-translate/i18n-polyfill.

  1. Установите расширение:
npm intsall @ngx-translate/i18n-polyfill --save
2. Настройте сервис в модуле:
src/app/app.module.ts
import {
  NgModule,
  TRANSLATIONS
} from '@angular/core';
import { I18n } from '@ngx-translate/i18n-polyfill';

declare const require;

@NgModule(
  providers: [
    {
      provide: TRANSLATIONS,
      useFactory: (locale: string) => {
        try {
          return require(`raw-loader!../messages.${locale}.xlf`);
        } catch (e) {
          return '';
        }
      }
    },
    { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
    I18n
  ]
)
Теперь можно использовать сервис для получения переведенных строк в скриптах:

src/app/account/account.component.ts
import {I18n} from '@ngx-translate/i18n-polyfill';

@Component({
  selector: 'app-account',
  templateUrl: './account.component.html',
  styleUrls: ['./account.component.scss']
})
export class AccountComponent {
   constructor(
     private i18n: I18n
   )

   getEmailErrorMessage() {
    if (this.emailControl.hasError('required')) {
      return this.i18n({
        value: 'Please enter email address',
        id: 'emailRequiredValidationError'
      });
    } else if (this.emailControl.hasError('email')) {
      return this.i18n({
        value: 'Email is invalid',
        id: 'emailFormatValidationError'
      });
    }

    return '';
  }
}
Создание файла перевода
Для извлечения всех текстов для перевода используйте команду:
ng xi18n
Посмотреть все доступные опции вывода можно использовав аргумент --help
В результате работы утилиты будет создан файл, содержащий все строки помеченные для перевода. Единица перевода содержится в тэге <trans-unit>:
<trans-unit id="loginHeader" datatype="html">
    <source>Login</source>
    <context-group purpose="location">
       <context context-type="sourcefile">app/account/account.component.html</context>
       <context context-type="linenumber">7</context>
    </context-group>
</trans-unit>
Перевод текста должен находиться внутри блока <trans-unit> в тэге <target>
<trans-unit id="loginHeader" datatype="html">
    <source>Login</source>
    <target>Вход</target>
    <context-group purpose="location">
       <context context-type="sourcefile">app/account/account.component.html</context>
       <context context-type="linenumber">7</context>
    </context-group>
</trans-unit>
Так как перевод текста в скриптах подключается отдельным расширением, то строки извлекаются отдельной утилитой:
ngx-extractor
Утилита дополнит файл перевода значениями из скриптов.
Сборка переводов

Angular поддерживает два типа сборки: Ahead of Time (AOT) и Just in Time (JIT). AOT подключена по умолчанию. В этом случае переводы заменяют значения в этап сборки проекта. Все значения "запекаются" в шаблоны и не могут быть изменены в ходе работы приложения. Однако, этот режим более производителен.

Для динамического подключения локализации необходимо использовать JIT:

src/main.ts
import {enableProdMode, LOCALE_ID, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';

import {AppModule} from './app/app.module';
import {environment} from './environments/environment';
import './polyfills';

declare const require;

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule, {
  providers: [
    {
      provide: LOCALE_ID,
      useValue: navigator.language
    },
    {
      provide: TRANSLATIONS,
      useFactory: (locale: string) => {
        try {
          return require(`raw-loader!./messages.${locale}.xlf`);
        } catch (e) {
          return '';
        }
      },
      deps: [LOCALE_ID]
    },
    {provide: TRANSLATIONS_FORMAT, useValue: 'xlf'}
  ]
}).catch(err => console.log(err));
Для удобства локализации можно использовать нашу онлайн-систему alingvo. Преимущество системы в том, что вы можете автоматически загружать файлы локализации в систему, использовать машинный перевод или подключить переводчика, автоматически получить переведенные файлы.

Как загружать файлы вручную и автоматически можно прочитать тут.

После перевода файлы раскладываются по нужным проектам (сборкам), это также можно сделать вручную или автоматически.

После чего проект компилируется, и вы получаете интернациональное приложение со встроенными функциями локализации и всеми необходимыми локализованными артефактами.