<h1 i18n>Hello baby!</h1>
Для маркера можно указывать дополнительные параметры которые отображаются в специализированных редакторах использующихся для перевода и дополняют переводимый текст служебной информацией призванной помочь переводчику. Это параметры передаются в формате «Значение|Описание» или только «Описание».
<h1 i18n="An introduction header for this sample">Hello baby!</h1> <h1 i18n="User welcome|An introduction header for this sample">Hello baby!</h1>
Возможно указать маркер и для текста который не окружен тегом. Для этого используется либо специальный пустой тег который не рендерится в финальный код.
<ng-container i18n>I don't output any element</ng-container>
или специальный комментарий
<!--i18n: optional meaning|optional description --> I don't output any element either<!--/i18n-->
Возможно так же делать перевод для аттрибутов тегов. Таких как alt, title,…
<img [src]="logo" i18n-title title="Angular logo" />
Plural
Окончание слов для множественного числа основано на правилах http://unisource.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules и http://cldr.unisource.org/index/cldr-spec/plural-rules в формате:
<span i18n>{wolves, plural, =0 {no wolves} =1 {one wolf} =2 {two wolves} other {a wolf pack}}</span>
wolves — название переменной содержащей число
plural — название типа преобразования
=0 — возможное значение переменной, {no wolves} — отображаемый текст для данного значения
=1 — возможное значение переменной, {one wolf} — отображаемый текст для данного значения
=2 — возможное значение переменной, {two wolves} — отображаемый текст для данного значения
other — если значение переменной не задано, {a wolf pack} — отображаемый текст для данного значения
Возможные следующие варианты:
- =0
- =1
- =2
- few (...3-10 или 5-10, зависит от правил локализации)
- other (дефолтное значение для всех неуказанных вариантов)
Select
Дает возможность выбирать значение на базе литеральной переменной:
<span i18n>The hero is {gender, select, m {male} f {female}}</span>
gender — название переменной содержащей значение
select — название типа преобразования
m — возможное значение переменной, {male} — отображаемый текст для данного значения
f — возможное значение переменной, {female} — отображаемый текст для данного значения
ng-xi18n
Для извлечения строк из аппликации используется специальная утилита ng-xi18n входящая в состав angular-cli:
./node_modules/.bin/ng-xi18n -p src/tsconfig.json
Данная утилита ищет маркер i18n в шаблонах и копирует соответствующий текст формируя из него XML файл XLIFF формата (версии 1.2).
Так же поддерживается формат XML Message Bundle (XMB). Для этого нужно задать соответствующий ключ:
./node_modules/.bin/ng-xi18n --i18nFormat=xmb -p src/tsconfig.json
Далее XML файл может быть отправлен переводчику который сможет редактировать его одним из специализированных редакторов. Полученный в итоге файл должен быть сохранен в папке i18n и содержать в своем названии язык локализации. Например в случае испанского языка, из исходного messages.xlf получится messages.es.xlf. Для каждого языка интерфейса должен быть создан отдельный файл.
Для того что бы файл с переводом мог быть использован Ангуларом необходимо добавить следующий код в main.ts:
// Указать нужные зависимости import {TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID} from '@angular/core'; // Задать ссылку на XML файл содержащий перевод let current_language = 'ru'; import {RU_TRANS} from './i18n/messages.' + current_language;
Тут есть одно замечание. Если мы используем angular-cli, то в настоящее время мы не можем самостоятельно (официально) менять конфигурацию webpack и соответственно не можем добавить правило raw для файлов с расширением xlf позволяющее импортировать их напрямую. Поэтому пока приходится вставлять их в файл обертку (messages.ru.ts):
export const RU_TRANS = ` //Обратные кавычки в файле позволяют многострочный контент. // сюда нужно скопировать содержимое XML файла messages.ru.xlf `;
Конфигурируем в main.ts
platformBrowserDynamic().bootstrapModule(AppModule, { providers: [ {provide: TRANSLATIONS, useValue: RU_TRANS}, {provide: TRANSLATIONS_FORMAT, useValue: 'xlf'}, {provide: LOCALE_ID, useValue: current_language} ] });
К сожалению описанная выше интернализация имеет ряд подводных камней и ограничений из-за которых она может быть использована только в проектах с самым простым интерфейсом:
- при смене содержимого тега даже не относящегося к переводимому тексту при последующей экстракции может поменяться ID, что в свою очередь приводит к ошибкам компиляции приложения.
- экстракция происходит только из HTML файлов и невозможна для динамического контента (например каких либо списков или дропбоксов)
Это ставит крест на данном подходе для использования в большинстве проектов насыщенных динамическим контентом и использующие взаимосвязанные дропбоксы.
Работа по решению данных вопросов происходит и возможно в версиях Ангулар 4 или 5 интернационализация будет доведена до ума.
Поэтому пока единственным рабочим решением, по прежнему, остается ng2-translate.
ng2-translate
ngx-translate.com
Является непрямым наследником хорошо известного модуля angular-translate.
Так же использует translate фильтр. Кроме того тексты с переводом хранятся в файлах JSON в том же формате как и в angular-translate.
Все это позволяет очень просто перенести шаблоны из ng1 в ng2. По сути все что требуется это сделать следующее:
Добавить зависимость в модуль аппликации в файл src/app/app.module.ts
import { HttpModule, Http } from '@angular/http'; import { TranslateModule, TranslateLoader, TranslateStaticLoader } from 'ng2-translate/ng2-translate'; @NgModule({ ... imports: [ ... HttpModule, TranslateModule.forRoot({ provide: TranslateLoader, // можно указать свой путь к папке i18n где находятся файлы с переводом useFactory: (http: Http) => new TranslateStaticLoader(http, '/assets/i18n', '.json'), deps: [Http] }) ], providers: [], bootstrap: [AppComponent] })
Вышеприведенный пример загрузки зависимости актуален для 5-ой версии ng2-translate.
Модуль сам подключает JSON файлы находящиеся в папке i18n. Поэтому импортировать вручную их не требуется.
Так же необходимо в корневом компоненте указать используемый язык:
import {TranslateService} from 'ng2-translate'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app works!'; constructor(translate: TranslateService) { // this language will be used as a fallback when a translation isn't found in the current language translate.setDefaultLang('ru'); // the lang to use, if the lang isn't available, it will use the current loader to get them translate.use('ru'); } }
Собственно это все что необходимо. Модуль готов к работе.
Формат JSON файла очень простой (ключ: перевод):
{ "HELLO": "Привет" }
далее в HTML можно соответственно использовать translate в следующих формах:
<div>{{'HELLO' | translate}}</div> <div [translate]="'HELLO'" [translateParams]="{value: 'world'}"></div> <div translate [translateParams]="{value: 'world'}">HELLO</div>
Так же можно использовать TranslateService в компонентах.
Update (4.3.2017):
Буквально накануне вышла 6-я версия, в которой ng2-translate был переименован в ngx-translate для соответствия официальной конвенции.
Кроме этого принципиальных изменений не произошло. Единственное TranslateStaticLoader был вынесен в самостоятельный модуль и переименован в TranslateHttpLoader. Соответственно синтаксис загрузки модуля в app.module.ts стал следующим:
import { HttpModule, Http } from '@angular/http'; import {TranslateModule, TranslateLoader} from "@ngx-translate/core"; //изменилось import {TranslateHttpLoader} from "@ngx-translate/http-loader"; //изменилось @NgModule({ ... imports: [ ... HttpModule, TranslateModule.forRoot({ provide: TranslateLoader, // можно указать свой путь к папке i18n где находятся файлы с переводом useFactory: (http: Http) => new TranslateHttpLoader(http, "i18n/", ".json"), //изменилось deps: [Http] }) ], providers: [], bootstrap: [AppComponent] })

