Централизованное управление локалями

В экосистеме интернационализации JavaScript библиотека Globalize (software) опирается на модель, в которой локаль рассматривается как единый управляемый контекст. Центральное управление локалями позволяет исключить дублирование настроек форматов, обеспечить согласованность представления данных и упростить переключение языковых окружений без изменения бизнес-логики приложения.

Локаль как глобальный контекст выполнения

Локаль в Globalize представляет собой идентификатор культурного окружения, включающий язык, регион и правила форматирования. Типичные значения:

  • en
  • en-GB
  • ru
  • ru-KZ
  • fr-FR

Внутри приложения локаль становится параметром, определяющим поведение всех операций форматирования: дат, чисел, валют, сообщений и правил pluralization.

Централизованное управление локалью означает, что:

  • локаль устанавливается один раз на уровне приложения или модуля
  • все форматтеры используют единый источник конфигурации
  • отсутствует необходимость передавать локаль в каждый вызов API

Подготовка CLDR-данных как центра локализации

Globalize не содержит встроенных языковых данных. Все правила берутся из CLDR (Unicode Common Locale Data Repository).

Минимальный набор для работы включает:

  • базовые языковые данные
  • числа и форматы чисел
  • даты и календари
  • валюты
  • plural rules

Загрузка данных выполняется один раз при инициализации приложения:

import Globalize from "globalize";
import likelySubtags from "cldr-data/supplemental/likelySubtags";
import numberingSystems from "cldr-data/supplemental/numberingSystems";
import plurals from "cldr-data/supplemental/plurals";

import ruNumbers from "cldr-data/main/ru/numbers";
import ruCurrencies from "cldr-data/main/ru/currencies";
import ruCaGregorian from "cldr-data/main/ru/ca-gregorian";

Globalize.load(
  likelySubtags,
  numberingSystems,
  plurals,
  ruNumbers,
  ruCurrencies,
  ruCaGregorian
);

Такой подход формирует централизованную базу данных, из которой далее строятся все локализованные операции.

Установка глобальной локали

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

Globalize.locale("ru");

С этого момента все форматтеры, созданные без явного указания локали, используют ru.

Важная особенность: локаль не привязана к конкретному объекту форматирования, а хранится в глобальном состоянии библиотеки.

Фабрика форматтеров как элемент централизованной модели

Globalize использует ленивую компиляцию форматтеров. Форматтер создаётся один раз для текущей локали и далее переиспользуется.

const numberFormatter = Globalize.numberFormatter();
const dateFormatter = Globalize.dateFormatter({ datetime: "medium" });

Эти функции не требуют передачи локали, так как используют глобально установленное значение.

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

Централизованное переключение локали

Смена локали затрагивает все компоненты приложения, поэтому она должна выполняться централизованно.

function setAppLocale(locale) {
  Globalize.locale(locale);
  rebuildFormatters();
}

Ключевой принцип заключается в том, что форматтеры не должны жить дольше текущей локали.

Архитектура менеджера локали

В прикладных системах над Globalize часто строится слой управления локалями.

class LocaleManager {
  constructor(defaultLocale = "en") {
    this.locale = defaultLocale;
    Globalize.locale(defaultLocale);
    this.formatters = new Map();
  }

  setLocale(locale) {
    this.locale = locale;
    Globalize.locale(locale);
    this.formatters.clear();
  }

  getNumberFormatter(options) {
    const key = JSON.stringify(options || {});
    if (!this.formatters.has(key)) {
      this.formatters.set(
        key,
        Globalize.numberFormatter(options)
      );
    }
    return this.formatters.get(key);
  }
}

Такой слой обеспечивает:

  • единый источник истины для локали
  • контроль кэширования форматтеров
  • синхронизацию между компонентами приложения

Связь локали и форматирования чисел

Числовое форматирование напрямую зависит от локали:

  • разделитель тысяч
  • десятичный разделитель
  • система цифр
Globalize.locale("ru");

const formatNumber = Globalize.numberFormatter();

formatNumber(1234567.89);

В русской локали результат будет соответствовать правилам ru, включая использование запятой как десятичного разделителя.

Централизация валютных правил

Валюты требуют не только локали, но и единых правил отображения.

const formatCurrency = Globalize.currencyFormatter("USD");

formatCurrency(25);

При смене локали меняется:

  • позиция символа валюты
  • формат разделителей
  • пробелы и группировка

Централизованная локаль гарантирует согласованность всех валютных представлений.

Работа с датами в централизованной локализации

Форматирование дат полностью зависит от локали:

const formatDate = Globalize.dateFormatter({
  datetime: "long"
});

formatDate(new Date());

При смене локали изменяются:

  • порядок компонентов даты
  • названия месяцев и дней недели
  • используемый календарь

Проблема глобального состояния и стратегии контроля

Глобальная локаль упрощает API, но создаёт риск несогласованности при асинхронных изменениях.

Основные источники проблем:

  • параллельные запросы с разными локалями
  • кэширование форматтеров без учёта контекста
  • гонки при переключении языка

Решение заключается в ограничении зоны действия локали через контролируемый слой:

function withLocale(locale, fn) {
  const prev = Globalize.locale();
  Globalize.locale(locale);
  try {
    return fn();
  } finally {
    Globalize.locale(prev);
  }
}

Интеграция с серверной и клиентской архитектурой

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

На сервере:

Globalize.locale(request.headers["accept-language"]);

На клиенте:

Globalize.locale(window.__INITIAL_LOCALE__);

Централизованное управление исключает расхождение отображения между слоями системы.

Кэширование форматтеров в условиях централизованной локали

Форматтеры зависят от текущей локали, поэтому кэширование должно учитывать её как часть ключа:

  • локаль
  • параметры форматирования
  • тип форматтера

Игнорирование локали в кэше приводит к некорректному отображению данных после переключения языка.

Масштабирование системы локалей

При увеличении количества поддерживаемых локалей централизованная модель остаётся устойчивой при соблюдении условий:

  • все CLDR-данные загружаются заранее или лениво по требованию
  • локаль изменяется только через единый интерфейс
  • форматтеры не хранятся без привязки к локали
  • отсутствует локальная переопределяемость внутри компонентов

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