Локаль в JavaScript представляется строкой, соответствующей стандарту
BCP 47. Помимо базовой структуры вида
language-region-script, стандарт поддерживает механизм
расширений Unicode, позволяющий задавать дополнительные параметры
форматирования без изменения самой локали. Эти расширения начинаются с
ключа -u- и образуют набор ключ-значение, который
интерпретируется через Intl API.
Общий вид:
language[-script][-region][-variants]-u-key1-value1-key2-value2
Пример:
en-US-u-ca-gregory-nu-latn
Здесь:
ca-gregory — календарь Gregoriannu-latn — латинская система чиселКаждый ключ имеет фиксированное значение из реестра Unicode CLDR, что обеспечивает переносимость между реализациями.
Объект Intl.Locale позволяет декодировать Unicode
extensions и работать с ними как со структурированными свойствами.
const locale = new Intl.Locale("en-US-u-ca-islamic-nu-arab");
console.log(locale.calendar); // "islamic"
console.log(locale.numberingSystem); // "arab"
calendar — система календаряnumberingSystem — система числовой записиcollation — правила сортировкиcaseFirst — приоритет регистра при сортировкеhourCycle — формат 12/24 часаnumeric — числовая сортировка строкКлюч ca определяет календарную систему, используемую при
форматировании дат.
gregory — григорианский календарьbuddhist — буддийский календарьislamic — исламский календарьhebrew — еврейский календарьchinese — китайский календарьconst fmt = new Intl.DateTimeFormat("en-US-u-ca-islamic");
console.log(fmt.format(new Date()));
Календарь влияет не только на отображение года, но и на структуру всего вычисления даты, включая эпоху и длину месяцев.
Ключ nu задаёт систему записи чисел.
latn — латинские цифры (0–9)arab — арабско-индийские цифрыthai — тайская системаdeva — деванагариfullwide — полноширинные символыconst fmt = new Intl.NumberFormat("ar-EG-u-nu-arab");
console.log(fmt.format(123456)); // цифры в арабской системе
Система нумерации влияет только на визуальное представление числа, не затрагивая его внутреннее значение.
Ключ co определяет алгоритм сортировки строк.
standard — стандартная сортировкаsearch — оптимизация под поискphonebk — телефонная книга (немецкий стиль)emoji — сортировка эмодзиconst collator = new Intl.Collator("de-DE-u-co-phonebk");
console.log(collator.compare("ä", "a"));
Разные режимы колляции могут радикально менять порядок строк, особенно в языках с диакритикой.
Ключ kf управляет приоритетом регистра при
сортировке.
upperlowerfalseconst collator = new Intl.Collator("en-u-kf-upper");
console.log(collator.compare("a", "A"));
При upper заглавные символы имеют приоритет.
Ключ hc определяет формат времени.
h12 — 12-часовой форматh23 — 24-часовой форматh11, h24 — региональные вариантыconst fmt = new Intl.DateTimeFormat("en-US-u-hc-h24", {
hour: "numeric",
minute: "numeric"
});
console.log(fmt.format(new Date()));
Ключ kn включает числовую интерпретацию строк.
Без kn строки сортируются лексикографически:
["file1", "file10", "file2"]
С kn включенным:
["file1", "file2", "file10"]
const collator = new Intl.Collator("en-u-kn-true");
console.log(
["file1", "file10", "file2"].sort(collator.compare)
);
Unicode extensions могут задаваться как напрямую в строке локали, так и через API опции. Однако строковое расширение имеет приоритет, если оно конфликтует с параметрами конструктора.
new Intl.NumberFormat("en-US-u-nu-arab", {
numberingSystem: "latn"
});
В этом случае результат зависит от реализации, но обычно строковое
расширение nu-arab имеет приоритет.
Intl.Locale нормализует расширения, приводя их к
каноническому виду.
const loc = new Intl.Locale("EN-us-u-Nu-LaTn");
console.log(loc.toString());
// "en-US-u-nu-latn"
Один идентификатор может содержать несколько ключей:
en-US-u-ca-gregory-nu-latn-co-phonebk-kf-upper-hc-h24
Разбор:
Поддержка ключей зависит от движка JavaScript и ICU-библиотеки. Основные ограничения:
Intl.Locale поддерживается не во всех устаревших
окруженияхUnicode extensions напрямую связаны с базой данных CLDR (Common Locale Data Repository). Именно она определяет:
Intl API выступает как слой интерпретации над CLDR-данными, обеспечивая единый интерфейс в JavaScript.
При разборе локали происходит следующий порядок:
Поддерживает:
nuco (частично через сравнение строк)kn (через Collator)Поддерживает:
cahcnuПоддерживает:
cokfknОдна и та же локаль может давать разные результаты:
const a = new Intl.NumberFormat("en-US");
const b = new Intl.NumberFormat("en-US-u-nu-arab");
console.log(a.format(12345));
console.log(b.format(12345));
Разница заключается только в системе записи чисел, тогда как логика форматирования остаётся идентичной.
Разбор строки:
fr-FR-u-ca-buddhist-nu-thai-co-emoji
Такая комбинация может использоваться для локализационных тестов, где необходимо проверить независимость компонентов форматирования.
Если движок не поддерживает конкретное расширение:
Пример:
en-US-u-ca-unknown
В этом случае ca будет проигнорирован, и используется
gregory.
Unicode extensions позволяют задавать пользовательские предпочтения на уровне локали, что особенно важно для:
Механизм обеспечивает переносимость настроек между различными частями приложения без дополнительной логики преобразования данных.