Динамическая загрузка локалей

Angular поддерживает i18n и динамическое переключение локалей через встроенный механизм LOCALE_ID и библиотеку @angular/common. Динамическая загрузка локалей позволяет изменять язык приложения без перезагрузки страницы.

Регистрация локалей

Локали импортируются из @angular/common/locales и регистрируются через функцию registerLocaleData():

import { registerLocaleData } from '@angular/common';
import localeRu from '@angular/common/locales/ru';
import localeEn from '@angular/common/locales/en';

registerLocaleData(localeRu, 'ru');
registerLocaleData(localeEn, 'en');

Переключение локали на лету

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

providers: [
  {
    provide: LOCALE_ID,
    useFactory: (localeService: LocaleService) => localeService.currentLocale,
    deps: [LocaleService]
  }
]

LocaleService управляет текущей локалью приложения и уведомляет компоненты об изменениях через BehaviorSubject:

@Injectable({ providedIn: 'root' })
export class LocaleService {
  private localeSubject = new BehaviorSubject<string>('en');
  currentLocale$ = this.localeSubject.asObservable();

  get currentLocale(): string {
    return this.localeSubject.value;
  }

  setLocale(locale: string) {
    this.localeSubject.next(locale);
  }
}

Форматирование дат и чисел

После регистрации локали Angular автоматически применяет её при использовании пайпов DatePipe, CurrencyPipe, DecimalPipe:

<p>{{ today | date:'fullDate' }}</p>
<p>{{ amount | currency:'USD':'symbol' }}</p>

При изменении локали через LocaleService все пайпы автоматически начинают использовать новую локаль при следующем обновлении данных.

Загрузка локалей асинхронно

Для оптимизации можно загружать локали динамически через import():

async setLocale(locale: string) {
  const localeModule = await import(`@angular/common/locales/${locale}.mjs`);
  registerLocaleData(localeModule.default, locale);
  this.localeSubject.next(locale);
}

Такой подход уменьшает размер начального бандла и позволяет добавлять новые языки без изменения основной сборки.

Взаимодействие с компонентами

Компоненты подписываются на изменения локали через currentLocale$ и обновляют отображение:

this.localeService.currentLocale$.subscribe(locale => {
  this.refreshUI();
});

Это обеспечивает полную поддержку runtime-переключения языков без перезагрузки приложения.