В экосистеме интернационализации JavaScript библиотека Globalize (software) опирается на модель, в которой локаль рассматривается как единый управляемый контекст. Центральное управление локалями позволяет исключить дублирование настроек форматов, обеспечить согласованность представления данных и упростить переключение языковых окружений без изменения бизнес-логики приложения.
Локаль в Globalize представляет собой идентификатор культурного окружения, включающий язык, регион и правила форматирования. Типичные значения:
enen-GBruru-KZfr-FRВнутри приложения локаль становится параметром, определяющим поведение всех операций форматирования: дат, чисел, валют, сообщений и правил pluralization.
Централизованное управление локалью означает, что:
Globalize не содержит встроенных языковых данных. Все правила берутся из CLDR (Unicode Common Locale Data Repository).
Минимальный набор для работы включает:
Загрузка данных выполняется один раз при инициализации приложения:
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__);
Централизованное управление исключает расхождение отображения между слоями системы.
Форматтеры зависят от текущей локали, поэтому кэширование должно учитывать её как часть ключа:
Игнорирование локали в кэше приводит к некорректному отображению данных после переключения языка.
При увеличении количества поддерживаемых локалей централизованная модель остаётся устойчивой при соблюдении условий:
Такая структура обеспечивает предсказуемое поведение интернационализации независимо от размера приложения и количества поддерживаемых культурных окружений