В экосистеме Angular интеграция интернационализации через i18next требует корректной установки ядра библиотеки, адаптера Angular и вспомогательных модулей, обеспечивающих загрузку ресурсов, определение языка пользователя и реактивное обновление переводов в компонентах.
Основой выступает библиотека i18next, отвечающая за управление переводами, форматирование и переключение языков.
npm install i18next
Для работы в браузере обычно добавляются плагины, расширяющие функциональность:
npm install i18next-http-backend i18next-browser-languagedetector
В Angular-интеграциях i18next используется связующий слой, обеспечивающий реактивность и DI-интеграцию.
npm install angular-i18next
Пакет предоставляет сервисы и директивы, позволяющие использовать переводы внутри компонентов Angular без прямого обращения к API i18next.
При использовании TypeScript требуется установка типов:
npm install --save-dev @types/i18next
Это обеспечивает корректную типизацию методов t(),
конфигурации и языковых ресурсов.
Конфигурация обычно выполняется в отдельном файле и подключается при старте приложения.
import i18next from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
i18next
.use(Backend)
.use(LanguageDetector)
.init({
fallbackLng: 'en',
debug: false,
interpolation: {
escapeValue: false
},
backend: {
loadPath: '/assets/locales/{{lng}}/{{ns}}.json'
}
});
Ключевым элементом является параметр loadPath,
определяющий структуру хранения переводов в проекте Angular.
После установки адаптера необходимо зарегистрировать его в корневом модуле Angular.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { I18NextModule, I18NEXT_SERVICE } from 'angular-i18next';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
I18NextModule.forRoot()
],
providers: [
{
provide: I18NEXT_SERVICE,
useValue: i18next
}
],
bootstrap: [AppComponent]
})
export class AppModule {}
Передача экземпляра i18next через I18NEXT_SERVICE
позволяет всем компонентам Angular использовать единый экземпляр
конфигурации.
Организация локалей влияет на масштабируемость приложения.
assets/
locales/
en/
common.json
auth.json
ru/
common.json
auth.json
Файлы разбиваются по пространствам имен (namespaces), что уменьшает нагрузку на загрузку и упрощает поддержку.
Пример содержимого common.json:
{
"welcome": "Добро пожаловать",
"logout": "Выйти"
}
После настройки доступ к функциям i18next осуществляется через сервис адаптера.
import { Component } from '@angular/core';
import { ITranslationService, I18NEXT_SERVICE } from 'angular-i18next';
import { Inject } from '@angular/core';
@Component({
selector: 'app-header',
template: `
<h1>{{ title }}</h1>
<button (click)="switchLanguage('ru')">RU</button>
<button (click)="switchLanguage('en')">EN</button>
`
})
export class HeaderComponent {
title = '';
constructor(
@Inject(I18NEXT_SERVICE) private i18next: ITranslationService
) {
this.title = this.i18next.t('common:welcome');
}
switchLanguage(lang: string) {
this.i18next.changeLanguage(lang);
}
}
Метод t() выполняет извлечение перевода, учитывая
namespace и текущий язык.
Библиотека предоставляет директивный способ работы с переводами без необходимости обращаться к сервису напрямую.
<h2 [i18next]="'common:welcome'"></h2>
Также поддерживается реактивное обновление при смене языка без перезагрузки компонента.
Смена языка влияет на все активные компоненты через общий экземпляр i18next.
this.i18next.changeLanguage('ru');
После вызова происходит:
i18next поддерживает динамические значения в переводах.
{
"greeting": "Привет, {{name}}"
}
Использование в коде:
this.i18next.t('common:greeting', { name: 'Алексей' });
Интерполяция обрабатывается на уровне библиотеки и не требует дополнительной логики в Angular.
При больших приложениях важно избегать загрузки всех языков сразу. Использование backend-плагина позволяет загружать файлы по требованию.
backend: {
loadPath: '/assets/locales/{{lng}}/{{ns}}.json'
}
Механизм подстановки {{lng}} и {{ns}}
позволяет гибко управлять структурой хранения.
При отсутствии ключа используется fallback-язык или возвращается сам ключ.
i18next.init({
fallbackLng: 'en',
saveMissing: true
});
Опция saveMissing может использоваться для логирования
недостающих переводов в систему сбора ошибок.
Angular не всегда автоматически отслеживает изменения i18next, поэтому важно учитывать Change Detection.
При необходимости принудительного обновления используется
ChangeDetectorRef:
constructor(private cdr: ChangeDetectorRef) {}
ngOnInit() {
this.i18next.on('languageChanged', () => {
this.cdr.detectChanges();
});
}
Это гарантирует актуальность интерфейса при переключении языка.
Разделение переводов по модулям Angular облегчает масштабирование:
this.i18next.t('auth:loginButton');
this.i18next.t('profile:title');
Каждый namespace загружается отдельно, что снижает начальную нагрузку приложения.
i18next поддерживает правила плюрализации для различных языков.
{
"item": "{{count}} элемент",
"item_plural": "{{count}} элементов"
}
Использование:
this.i18next.t('common:item', { count: 5 });
Выбор формы выполняется автоматически на основе правил языка.
Контекстные переводы позволяют учитывать дополнительные условия:
{
"friend_male": "друг",
"friend_female": "подруга"
}
this.i18next.t('common:friend', { context: 'female' });
Для более сложной архитектуры i18next часто инкапсулируется в собственный сервис-обёртку:
@Injectable({ providedIn: 'root' })
export class TranslationFacade {
constructor(@Inject(I18NEXT_SERVICE) private i18next: ITranslationService) {}
translate(key: string, params?: any) {
return this.i18next.t(key, params);
}
}
Такой подход снижает связанность компонентов с конкретной реализацией библиотеки.
В режиме разработки полезно включать debug-режим:
i18next.init({
debug: true
});
Он выводит информацию о загрузке ресурсов, отсутствии ключей и процессе интерполяции.
При сборке Angular-приложения важно учитывать:
Структура конфигурации Angular CLI:
"assets": [
"src/favicon.ico",
"src/assets"
]
Эта настройка обеспечивает доступ к /assets/locales
после сборки.
При серверном рендеринге необходимо синхронизировать язык на сервере и клиенте. Для этого передаётся начальное состояние:
i18next.init({
lng: 'ru',
ssr: true
});
Серверная инициализация предотвращает гидрационные расхождения между HTML и клиентским состоянием.