Прикручиваем ngx-translate в Angular приложение. Практическое пошаговое руководство
Практическая пошаговая инструкция как прикрутить динамическую локализацию (возможность выбора языков) в веб приложении на Angular 4+ используя @ngx-translate/core.
В принципе можно найти публикации на подобную тему, может быть достаточно самой документации этой библиотеки, но я хотел систематизировать эту инструкцию для более удобного применения. Такая закладка в копилку начинающего Angular разработчика. В конце статьи есть ссылка на открытый репозиторий с примером.
Сразу хочу оговориться, это инструкция по применению конкретной библиотеки. Мы не будем говорить об альтернативах, о том, что у ангуляра есть своя i18n локализация. Хотя бы потому, что с динамической сменой языка там есть вопросы.
- Ангуляр приложение, в папке
assets/locale
расположены*.json
файлы с ключами и их локализованными значениями, по одному файлу для каждого поддерживаемого языка в веб приложении. - Динамическая смена языка
- Хранение ключей в объектной структуре, то есть иметь что-то такое:
// en.json
{
Common: {
Yes: "Yes"
}
}
Это позволит группировать ключи / значения и как-то организовать json файл с локализацией. Для больших проектов весьма полезно.
- Минимальную автоматизацию и проверку на дурака. Что если забыли добавить ключ в json?
- Применение локализации как в html шаблонах, так и в ts коде
Создаем или берем готовый ангуляр проект. Версия ангуляра 4+, но лучше конечно максимально свежую.
Устанавливаем нужные библиотеки:
npm install @ngx-translate/core --save
npm install @ngx-translate/http-loader --save
@biesbjerg/ngx-translate-extract --saveDev
Библиотека@ngx-translate/http-loader
нужна для того, чтобы мы могли считывать данные о локализации из*.json
файлов. Без нее жить можно, но тогда придется полностью самостоятельно писать хранение и загрузку данных локализации. Данный подход подойдет тем, у кого данные локализации (или попросту все переведенные тексты) уже где-то хранятся.Библиотека
@biesbjerg/ngx-translate-extract
не обязательна, но довольно полезна. Она позволяет собирать по коду приложения забытые локализационные ключи и обновлять файлы локализаций. С ее помощью очень удобно обрабатывать такой сценарий: добавляем новый язык и просто запускаем команду из этой библиотеки. В результате пустой файл для нового языка наполнится всей структурой ключей и каких-то значений по умолчанию. Пример будет ниже.
- Импортируем библиотеку в главном модуле:
@NgModule({
imports: [
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
useDefaultLang: false,
})
],
})
export class AppModule { }
В настройках библиотеки присутствует HttpLoaderFactory
, ее можно описать прямо в этом же файле, она скромных размеров.
export function HttpLoaderFactory(http: HttpClient): TranslateLoader {
return new TranslateHttpLoader(http, './assets/locale/', '.json');
}
Именно тут мы указываем путь к файлам локализации. Если они хранятся как-то отдельно, или вообще различно в разных енвайронментах — поменяйте данный код на использование environment.ts
например.
- В принципе этого достаточно для основных настроек, но мы сделаем еще один дополнительный шаг — обработку ошибок, когда не найден ключ.
Для этого нужно в настройку (сразу после указания loader) добавить еще одно поле:
missingTranslationHandler: { provide: MissingTranslationHandler, useClass: MissingTranslationService },
И конечно же необходимо создать в отдельном файле саму реализацию этого обработчика:
export class MissingTranslationService implements MissingTranslationHandler {
handle(params: MissingTranslationHandlerParams) {
return `WARN: '${params.key}' is missing in '${params.translateService.currentLang}' locale`;
}
}
- Добавляем хранение доступных языков. В простом случае удобно положить их в
environment.ts
locales: ['en', 'ru'],
defaultLocale: 'en',
- Чтобы сервис начал работать, его необходимо инициализировать в файле AppComponent, при загрузке приложения:
@Component({...})
export class AppComponent implements OnInit {
constructor(private translateService: TranslateService) {}
ngOnInit(): void {
this.translateService.use(environment.defaultLocale);
}
}
- Добавляем файлы
en.json
иru.json
(в соответствии с тем, что указано в списке доступных языков). Добавьте какое-то базовое поле, чтобы это был валидный json.
Когда эти шаги сделаны, сервис начнет работать.
HTML разметка
Тут все просто. Библиотека предлагает pipe translate
, мы просто применяем его в разметке для определенных ключей.
Заметьте, я использую тут вложенные свойства, ту структуру json, о которой говорил в начале.Так же поддерживаются параметры, посмотрите про них пожалуйста в документации @ngx-translate/core. С помощью параметров можно реализовывать что-то вроде интерполирования строк.
В коде компонентов
this.translateService.get(['KEY1', 'KEY2']))
.subscribe(translations => {
console.log(translations['KEY1'])
console.log(translations['KEY2'])
});
Это надежный способ, если вы нормально относитесь к Observable и RxJs.
Если же нет — есть такой способ:
this.translateService.instant('Key')
Данный способ работает хорошо, но на этапе инициализации приложения (например ngOnInit AppComponent) данные для него могут еще быть не загружены. Будьте аккуратны.
В конце хочу показать, как использовать ngx-translate-extract
утилиту. Просто выполняете в консоли команду ngx-translate-extract -i ./src -o src/assets/locale/*.json --sort --format namespaced-json
. Данная команда запустит анализ файлов приложения, разметки и кода тайпскрипт. Все найденные в разметке и прочем коде ключи попадут в .json для всех языков, имеющиеся ключи и их значения останутся нетронутыми, разве что порядок может измениться.
Для удобства я дописываю это как скрипт в package.json
"scripts": {
"ng": "ng",
"start": "ng serve",
"update-locale": "ngx-translate-extract -i ./src -o src/assets/locale/*.json --sort --format namespaced-json"
},
Все, что я описал, можно найти собранным вместе в открытом репозитории: valentinkononov/ngx-translate-angular
Надеюсь материал будет полезен! Пишите код с удовольствием, выбирайте удобные библиотеки и делайте полезные проекты!