Редкие языки и диалекты

Вся система интернационализации в JavaScript строится вокруг понятий локали и языкового тега. Локаль в контексте Intl — это строка в формате BCP 47, которая кодирует язык, письменность, регион и дополнительные параметры форматирования.

Примеры:

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

Редкие языки и диалекты становятся проблемной зоной именно на уровне таких идентификаторов: чем менее распространён язык, тем выше вероятность отсутствия полной поддержки в браузере или runtime.


Структура языкового тега и влияние на поддержку

BCP 47 разбивает локаль на несколько компонентов:

  • language — основной язык (se, moh, hsb)
  • script — письменность (Latn, Cyrl, Hans, Hant)
  • region — географический регион (NO, SE, CA)
  • variants — диалектные или исторические варианты

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

  • se — северносаамский
  • smn — инари-саамский
  • sma — южносаамский
  • moh — могавк

Отсутствие script/region в таких случаях приводит к важному поведению Intl: система начинает искать ближайший доступный вариант.


Механизм fallback и наследование локалей

Intl API не требует точного совпадения локали с поддерживаемыми данными. Вместо этого используется цепочка fallback:

  1. Полная локаль (se-FI)
  2. Упрощённая локаль (se)
  3. Дефолтная локаль окружения (en-US или системная)

Это означает, что даже при отсутствии прямой поддержки редкого языка система попытается использовать ближайший аналог.

Пример поведения:

  • Запрос: Intl.NumberFormat('smn-FI')

  • Если данных нет:

    • fallback → smn
    • fallback → fi или системный язык

Такой механизм опирается на ICU (International Components for Unicode), откуда браузеры берут локализационные данные.


Проверка доступности через supportedLocalesOf

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

Intl.DateTimeFormat.supportedLocalesOf(['moh', 'se', 'xx-YY']);

Результат показывает, какие локали реально поддерживаются движком.

Особенности:

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

Различие между «языком» и «диалектом» в Intl

Intl API не оперирует понятием «диалект» как отдельной сущностью. Диалекты моделируются через:

  • регион (pt-BR vs pt-PT)
  • письменность (zh-Hans vs zh-Hant)
  • вариант (sl-rozaj, исторические формы словенского)

Примеры диалектных различий:

  • ar-EG — египетский арабский
  • ar-MA — марокканский арабский
  • es-AR — аргентинский испанский
  • fr-CA — канадский французский

Для редких языков диалектная гранулярность часто отсутствует, и система работает на уровне базового языка.


Ограниченность данных для малых языков

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

  1. Отсутствие локализованных числовых форматов

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

    • названия месяцев и дней могут быть частично заимствованы
  3. Ограниченный набор символов

    • отсутствие корректных правил капитализации
  4. Fallback на английский

    • наиболее частый сценарий в браузерах

Это напрямую связано с источниками данных ICU/CLDR: если сообщество не поддерживает язык, данные могут отсутствовать или быть минимальными.


Intl.Locale как инструмент анализа редких языков

Intl.Locale позволяет разбирать и анализировать локаль как структуру:

const loc = new Intl.Locale('se-FI-x-test');

Доступные свойства:

  • language
  • script
  • region
  • baseName

Для редких языков это особенно важно, так как позволяет отделить:

  • язык (se)
  • регион (FI)
  • расширения (x-test)

Пример:

loc.language; // "se"
loc.region;   // "FI"

Нормализация локалей и расширения Unicode

Редкие языки часто используются с Unicode extension keys:

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

Пример:

se-FI-u-nu-latn

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


Intl.DisplayNames и редкие языки

Intl.DisplayNames позволяет получать локализованные названия языков, регионов и письменностей.

new Intl.DisplayNames(['en'], { type: 'language' }).of('moh');

Поведение при редких языках:

  • может возвращать оригинальный код ("moh")
  • может возвращать английское описание
  • может возвращать fallback-форму

Это зависит от наличия записей в CLDR.


Форматирование чисел в редких языках

Intl.NumberFormat использует локализованные правила:

new Intl.NumberFormat('se').format(1234567.89);

При отсутствии данных:

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

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


Даты и календари в малых локалях

Intl.DateTimeFormat зависит от календарных данных ICU:

new Intl.DateTimeFormat('moh', { dateStyle: 'full' });

Если календарь не определён:

  • используется григорианский календарь
  • названия месяцев берутся из fallback-языка
  • форматирование остаётся, но без локального смысла

Сортировка строк и редкие языки

Intl.Collator отвечает за сортировку:

new Intl.Collator('se').compare('á', 'a');

В редких языках проблема заключается в:

  • отсутствии правил сортировки
  • использовании дефолтного Unicode порядка
  • игнорировании диакритики или специфических букв

Это приводит к различиям между ожиданием и реальным результатом сортировки.


Реальные проблемы поддержки диалектов

Даже при наличии базового языка диалекты часто не различаются:

  • zh-HK и zh-TW могут частично совпадать в данных
  • арабские диалекты часто сводятся к стандартному ar
  • саамские языки могут не иметь полного покрытия в UI-строках

В результате система интернационализации работает не на уровне лингвистической точности, а на уровне приближений.


Поведение браузеров и движков

Разные JS-движки используют разные версии ICU:

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

Это приводит к ситуации, когда один и тот же код:

Intl.DateTimeFormat('moh').format(new Date())

может возвращать разные результаты в разных средах.


Стратегии работы с редкими языками

При проектировании приложений с Intl API обычно учитываются:

  • явный контроль fallback через supportedLocalesOf
  • выбор базовой локали при отсутствии поддержки
  • использование Intl.Locale для анализа тегов
  • отказ от критической зависимости от диалектных различий

Редкие языки в Intl API всегда находятся в зоне вероятностной поддержки, а не гарантированной локализации.