Локаль устройства формируется на уровне операционной системы и среды выполнения JavaScript и отражает предпочтения пользователя в отношении языка, региона и правил форматирования данных. В экосистеме интернационализации она выступает базовым источником, от которого выстраивается дальнейшая работа с форматированием дат, чисел, валют и текстов.
В библиотеке Globalize локаль устройства используется как первичный ориентир при выборе набора правил форматирования и локализованных ресурсов, загруженных из CLDR (Common Locale Data Repository). Однако сама библиотека не выполняет автоматического «угадывания» локали — она опирается на данные среды выполнения.
Определение локали происходит через несколько стандартных каналов:
1. Браузерное API
Основной источник в веб-среде:
navigator.languagenavigator.languagesnavigator.language; // "ru-RU"
navigator.languages; // ["ru-RU", "en-US", "en"]
navigator.languages имеет более высокий приоритет,
поскольку отражает список предпочтительных языков пользователя.
2. Node.js окружение
В серверной среде локаль часто определяется через:
Intl.DateTimeFormat().resolvedOptions().localeLANG, LC_ALL)const locale = Intl.DateTimeFormat().resolvedOptions().locale;
3. API Intl как источник фактической локали
const locale = new Intl.NumberFormat().resolvedOptions().locale;
Этот механизм отражает реальную локаль, которую использует движок JavaScript.
Библиотека Globalize не использует системную локаль автоматически в момент вызова форматирующих функций. Вместо этого она требует явного задания локали:
Globalize.locale("ru");
или
Globalize.locale("ru-RU");
Таким образом разделяется два уровня:
Системная локаль часто содержит региональную часть
(ru-RU, en-US, fr-FR). Globalize
использует CLDR-идентификаторы, которые совместимы с таким форматом, но
могут требовать нормализации.
Типичные преобразования:
ru-RU → ruen-US → enpt-BR → pt-BR (сохраняется регион)function normalizeLocale(locale) {
if (!locale) return "en";
const parts = locale.split("-");
return parts.length > 1 ? `${parts[0]}-${parts[1]}` : parts[0];
}
При интеграции с браузером часто используется цепочка приоритетов:
navigator.languages[0]navigator.languageconst locale =
(navigator.languages && navigator.languages[0]) ||
navigator.language ||
"en";
Globalize.locale(locale);
Если локаль устройства отсутствует в загруженных данных CLDR, Globalize выполняет fallback:
fr-CA →
fr)Для корректной работы Globalize требует загрузки структурированных данных:
Globalize.load(
require("cldr-data").entireSupplemental(),
require("cldr-data").entireMainFor("ru")
);
Без этих данных локаль, определённая устройством, не приводит к корректному форматированию.
В реальных системах интернационализации используется многоуровневая модель:
const userLocale = getUserSettingsLocale();
const deviceLocale =
navigator.languages?.[0] ||
navigator.language;
Globalize.locale(userLocale || deviceLocale || "en");
Различия между локалями могут влиять на форматирование:
en-US — месяц/день/год, долларen-GB — день/месяц/год, фунтru-RU — день.месяц.год, рубльGlobalize интерпретирует эти различия через CLDR, поэтому корректность локали критична.
При отсутствии явной локализации в Globalize можно использовать стандартный API:
const formatter = new Intl.DateTimeFormat(undefined, {
dateStyle: "long"
});
formatter.format(new Date());
undefined заставляет движок использовать локаль
устройства, что часто применяется как fallback до инициализации
Globalize.
Типовые проблемы:
navigator.languages в устаревших
окруженияхКаждая из этих ситуаций приводит к необходимости явного контроля локали на уровне приложения, а не доверия автоматическим механизмам среды.