Язык, регион, письменность

В основе интернационализации в JavaScript лежит стандарт BCP 47 Language Tags, определяющий формат строк локали. Эти строки используются во всех основных конструкциях Intl и описывают комбинацию языка, региона, письменности и дополнительных параметров.

Структура языкового тега:

language[-script][-region][-variant][-extension]

Минимальный вариант — язык:

"en"   // английский
"ru"   // русский

Расширенные формы позволяют точно указать контекст форматирования:

"en-US"        // английский (США)
"en-GB"        // английский (Великобритания)
"zh-Hans-CN"   // китайский, упрощённая письменность, Китай
"sr-Cyrl-RS"   // сербский, кириллица, Сербия

Каждый элемент играет отдельную роль в интерпретации данных, форматировании чисел, дат, сортировке и отображении текста.


Язык как базовый компонент локали

Первая часть идентификатора — код языка по стандарту ISO 639:

ru, en, fr, de, ja, zh

Язык определяет:

  • правила грамматики в языково-зависимых форматах;
  • шаблоны отображения дат и времени;
  • символы и словари для форматирования чисел и валют;
  • поведение сортировки строк (collation).

Примеры:

"fr"  // французский
"de"  // немецкий
"ja"  // японский

В Intl язык влияет на выбор локализованных ресурсов:

new Intl.DateTimeFormat("fr").format(new Date());

Регион как уточнение культурного контекста

Региональная часть тега локали указывается по стандарту ISO 3166-1 alpha-2:

US, GB, FR, DE, CN, JP, KZ

Регион влияет не на язык как таковой, а на:

  • формат чисел (разделители);
  • формат дат;
  • валютные обозначения;
  • предпочтения календарей и единиц измерения.

Примеры различий:

"en-US" → 1,000.50
"en-GB" → 1,000.50 (но другие даты)
"de-DE" → 1.000,50

В коде:

new Intl.NumberFormat("de-DE").format(1234567.89);
// "1.234.567,89"

Региональная часть особенно важна для языков, распространённых в нескольких странах:

  • английский (США, Великобритания, Канада, Австралия)
  • французский (Франция, Канада, Бельгия)
  • португальский (Португалия, Бразилия)

Письменность (script) как способ записи языка

Письменность задаётся по стандарту ISO 15924 и указывается между языком и регионом:

"zh-Hans"   // упрощённая китайская письменность
"zh-Hant"   // традиционная китайская письменность
"sr-Cyrl"   // кириллица
"sr-Latn"   // латиница

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

Примеры влияния письменности

Китайский язык

new Intl.DisplayNames("zh-Hans", { type: "language" }).of("en");
// "英语"
new Intl.DisplayNames("zh-Hant", { type: "language" }).of("en");
// "英語"

Разница заключается исключительно в наборе символов.


Сербский язык

new Intl.DateTimeFormat("sr-Cyrl").format(new Date());
new Intl.DateTimeFormat("sr-Latn").format(new Date());

Обе локали описывают один язык, но разные алфавиты.


Полная структура языкового тега

Комбинация всех компонентов:

language-script-region

Примеры:

"en-Latn-US"
"zh-Hans-CN"
"sr-Cyrl-RS"

Каждая часть выполняет независимую роль:

Компонент Назначение
language язык
script письменность
region страна/регион

Локали в Intl API

Практически все классы Intl принимают локаль:

  • Intl.DateTimeFormat
  • Intl.NumberFormat
  • Intl.Collator
  • Intl.RelativeTimeFormat
  • Intl.DisplayNames
  • Intl.PluralRules

Пример:

new Intl.NumberFormat("ru-RU").format(1234567.89);
// "1 234 567,89"
new Intl.NumberFormat("en-US").format(1234567.89);
// "1,234,567.89"

Автоматическое определение локали

Если локаль не указана, используется среда выполнения:

new Intl.DateTimeFormat().resolvedOptions().locale;

Результат зависит от:

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

Наследование и fallback локалей

Если точная локаль недоступна, применяется механизм fallback:

"en-US" → "en" → дефолтная локаль движка

Пример:

new Intl.NumberFormat("en-XX").format(1000);

Если en-XX не поддерживается, используется en.


Различие между языком и регионом в форматировании

Язык влияет на текстовую составляющую, регион — на формат данных.

Язык:

  • названия месяцев
  • словесные формы чисел
  • склонения

Регион:

  • разделители чисел
  • порядок даты
  • валюта

Пример даты:

new Intl.DateTimeFormat("en-US").format(new Date());
// "05/26/2026"

new Intl.DateTimeFormat("en-GB").format(new Date());
// "26/05/2026"

Смешанные локали и их поведение

Некоторые комбинации выглядят противоречиво:

"en-KZ"
"ru-US"
"fr-JP"

В таких случаях:

  • язык остаётся основным;
  • регион влияет на форматирование;
  • ресурсы могут частично заимствоваться.

Пример:

new Intl.NumberFormat("ru-US").format(1234.56);

Unicode Extensions в локалях

Дополнительно используются расширения:

-u-ca-    // календарь
-u-nu-    // система чисел
-u-hc-    // формат времени

Пример:

"en-US-u-ca-gregory"
"ar-EG-u-nu-arab"

Это расширяет поведение без изменения базового языка.


Intl.Locale как объект описания локали

Intl.Locale предоставляет структурированный доступ к компонентам:

const locale = new Intl.Locale("zh-Hans-CN");

locale.language; // "zh"
locale.script;   // "Hans"
locale.region;   // "CN"

Дополнительно:

locale.baseName; // "zh-Hans-CN"

Поддерживаются расширенные параметры:

new Intl.Locale("en-US-u-ca-buddhist");

Использование локалей в сортировке

["ä", "a", "z"].sort(new Intl.Collator("de").compare);

Результат зависит от языковых правил:

  • немецкий учитывает умляуты;
  • английский сортирует иначе.

Языковые различия в числах и валютах

new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD"
}).format(1234.5);
new Intl.NumberFormat("ru-RU", {
  style: "currency",
  currency: "RUB"
}).format(1234.5);

Различия:

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

Иерархия влияния компонентов локали

При интерпретации строки локали порядок приоритетов:

  1. язык (основная семантика)
  2. письменность (графика)
  3. регион (формат)
  4. расширения Unicode (специфические настройки)

Эта модель обеспечивает предсказуемое поведение Intl при любом наборе входных данных.