Названия языков

Работа с названиями языков в JavaScript строится на стандарте BCP 47 и наборе международных правил локализации. В основе лежит задача преобразования языковых тегов вида en, en-US, zh-Hans, sr-Cyrl в человекочитаемые названия, зависящие от выбранной локали отображения.

Ключевым инструментом выступает Intl.DisplayNames, позволяющий получать корректные локализованные названия языков без ручных словарей и условных конструкций.


BCP 47 как основа языковых идентификаторов

Языковые коды представляют собой структурированные строки, состоящие из нескольких компонентов:

  • язык: en, ru, fr, zh
  • регион: US, GB, CN, RU
  • письменность (script): Latn, Cyrl, Hans, Hant

Примеры:

  • en — английский
  • en-US — американский английский
  • en-GB — британский английский
  • zh-Hans — китайский (упрощённая письменность)
  • zh-Hant — китайский (традиционная письменность)
  • sr-Cyrl — сербский (кириллица)

Структура BCP 47 важна тем, что позволяет точно идентифицировать вариант языка, а не только его базовую форму.


Intl.DisplayNames и тип language

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

const displayNames = new Intl.DisplayNames('ru', { type: 'language' });

Первый аргумент определяет локаль вывода, второй — тип отображаемых сущностей.

Базовое использование

const dn = new Intl.DisplayNames('ru', { type: 'language' });

dn.of('en');      // "английский"
dn.of('fr');      // "французский"
dn.of('ja');      // "японский"
dn.of('zh');      // "китайский"

Вывод зависит от выбранной локали отображения. Например:

const dn = new Intl.DisplayNames('en', { type: 'language' });

dn.of('ru'); // "Russian"
dn.of('de'); // "German"

Отображение языковых вариантов

При использовании составных кодов учитываются региональные и письменные расширения.

const dn = new Intl.DisplayNames('ru', { type: 'language' });

dn.of('en-US'); // "американский английский"
dn.of('en-GB'); // "британский английский"
dn.of('zh-Hans'); // "китайский (упрощённое письмо)"
dn.of('zh-Hant'); // "китайский (традиционное письмо)"

В разных локалях результат будет различаться:

const dnEn = new Intl.DisplayNames('en', { type: 'language' });

dnEn.of('zh-Hans'); // "Simplified Chinese"
dnEn.of('zh-Hant'); // "Traditional Chinese"

languageDisplay: стандартное и диалектное представление

Опция languageDisplay управляет уровнем детализации отображаемого языка.

Доступные значения:

  • standard — стандартное название языка
  • dialect — диалектная форма с акцентом на региональные различия

Пример использования

const standard = new Intl.DisplayNames('ru', {
  type: 'language',
  languageDisplay: 'standard'
});

const dialect = new Intl.DisplayNames('ru', {
  type: 'language',
  languageDisplay: 'dialect'
});

standard.of('en-US');
dialect.of('en-US');

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


Поведение при неизвестных или нестандартных кодах

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

  • может возвращаться исходный код
  • может применяться fallback-логика
  • может возвращаться нейтральное представление
const dn = new Intl.DisplayNames('ru', { type: 'language' });

dn.of('qaa'); // поведение зависит от движка

В современных реализациях чаще всего применяется безопасный fallback, не вызывающий ошибок.


Поддержка скриптов и сложных языковых систем

Некоторые языки требуют явного указания письменности:

  • китайский: zh-Hans, zh-Hant
  • сербский: sr-Cyrl, sr-Latn
  • узбекский: uz-Cyrl, uz-Latn
const dn = new Intl.DisplayNames('ru', { type: 'language' });

dn.of('sr-Cyrl'); // "сербский (кириллица)"
dn.of('sr-Latn'); // "сербский (латиница)"

Эта детализация критична для интерфейсов, где различие письменности влияет на восприятие текста.


Зависимость результата от локали отображения

Один и тот же код языка может иметь разные отображения:

const ru = new Intl.DisplayNames('ru', { type: 'language' });
const de = new Intl.DisplayNames('de', { type: 'language' });

ru.of('de'); // "немецкий"
de.of('de'); // "Deutsch"

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


Сравнение языковых групп

При работе с наборами языков часто используется единый экземпляр DisplayNames, позволяющий избежать ручных таблиц соответствий:

const dn = new Intl.DisplayNames('ru', { type: 'language' });

const languages = ['en', 'fr', 'de', 'es', 'ja'];

languages.map(code => dn.of(code));

Результат формируется динамически на основе локали и встроенных данных движка JavaScript.


Использование с BCP 47 в реальных данных

Языковые коды часто поступают из API, браузерных настроек или баз данных пользователей:

  • navigator.language
  • Accept-Language HTTP заголовок
  • профили пользователей
const userLang = 'en-GB';
const dn = new Intl.DisplayNames('ru', { type: 'language' });

dn.of(userLang); // "британский английский"

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


Взаимодействие с Intl.Locale

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

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

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

В сочетании с Intl.DisplayNames это используется для построения интерфейсов локализации:

const dn = new Intl.DisplayNames('ru', { type: 'language' });

dn.of(locale.toString()); // "китайский (упрощённое письмо, Китай)"

Производительность и повторное использование экземпляров

Создание Intl.DisplayNames включает инициализацию локализационных данных, поэтому повторное использование экземпляра предпочтительнее многократного создания:

const dn = new Intl.DisplayNames('ru', { type: 'language' });

// повторное использование
dn.of('en');
dn.of('fr');
dn.of('de');

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


Особенности локализации языковых названий

Названия языков не являются статическими строками. Они зависят от:

  • локали отображения
  • версии данных ICU
  • параметров languageDisplay
  • особенностей движка JavaScript

В разных средах возможны незначительные различия в формулировках, порядке слов и наличии уточнений (например, указание письменности или региона).


Обработка массивов языков и нормализация вывода

При работе с пользовательскими интерфейсами часто требуется нормализация:

const dn = new Intl.DisplayNames('ru', { type: 'language' });

const map = Object.fromEntries(
  ['en-US', 'en-GB', 'fr', 'de'].map(code => [code, dn.of(code)])
);

Такая структура позволяет строить словари отображения без ручного перевода.


Расширенные сценарии применения

Механизм отображения языков используется в следующих областях:

  • переключатели языка интерфейса
  • настройки локализации
  • мультиязычные каталоги
  • CMS и редакторские системы
  • API профилей пользователей

В этих сценариях критична консистентность отображения и соответствие международным стандартам, что обеспечивается встроенной поддержкой ICU и Intl.DisplayNames.