Получение локализованных названий

Intl.DisplayNames позволяет получать локализованные человекочитаемые названия языков, регионов, валют, календарей и других стандартизированных кодов. Механизм основан на данных ECMA-402 и использует системные таблицы локализации, благодаря чему одинаковый код может отображаться по-разному в зависимости от выбранной локали.

Стандартизированные коды ISO используются во многих частях веб-экосистемы: языки (en, ru, zh), регионы (US, KZ, JP), валюты (USD, EUR, KZT), календари (gregory, islamic) и другие домены. Эти коды компактны и однозначны, но непригодны для интерфейсов без преобразования в локализованные строки.

Intl.DisplayNames решает задачу трансляции код → локализованное имя:

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

dn.of('en'); // "английский"
dn.of('ru'); // "русский"
dn.of('ja'); // "японский"

Конструктор Intl.DisplayNames

Базовая сигнатура:

new Intl.DisplayNames(locales, options)

Параметры

locales

  • строка BCP 47 ("ru", "en-US")
  • массив локалей
  • объект Intl.Locale

options

Ключевой параметр — type:

{
  type: 'language' | 'region' | 'script' | 'currency' | 'calendar' | 'dateTimeField',
  style?: 'long' | 'short' | 'narrow',
  fallback?: 'code' | 'none'
}

Поведение параметров

  • type — определяет домен кодов

  • style — влияет на форму отображения (если поддерживается локалью)

  • fallback

    • "code" — возвращает исходный код при отсутствии перевода
    • "none" — возвращает undefined

Локализация языков

Тип language используется для преобразования языковых кодов.

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

lang.of('en'); // "английский"
lang.of('fr'); // "французский"
lang.of('de'); // "немецкий"

В англоязычной локали результат меняется:

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

langEn.of('ru'); // "Russian"
langEn.of('ja'); // "Japanese"

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

Локализация регионов

Тип region работает с кодами стран ISO 3166-1 alpha-2.

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

region.of('US'); // "Соединённые Штаты"
region.of('KZ'); // "Казахстан"
region.of('JP'); // "Япония"

В англоязычной локали:

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

regionEn.of('KZ'); // "Kazakhstan"

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

Локализация валют

Тип currency преобразует ISO 4217 коды в человекочитаемые названия валют.

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

currency.of('USD'); // "доллар США"
currency.of('EUR'); // "евро"
currency.of('KZT'); // "казахстанский тенге"

В англоязычном контексте:

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

currencyEn.of('USD'); // "US Dollar"
currencyEn.of('EUR'); // "Euro"

Отображение валют не связано с форматированием чисел; для этого используется Intl.NumberFormat. DisplayNames отвечает только за наименование.

Календари и временные сущности

Тип calendar используется для отображения идентификаторов календарных систем.

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

calendar.of('gregory'); // "григорианский календарь"
calendar.of('islamic');  // "исламский календарь"
calendar.of('buddhist'); // "буддийский календарь"

Календари применяются в локализациях дат, исторических системах и альтернативных временных шкалах.

Тип dateTimeField описывает элементы даты и времени:

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

dtf.of('year');   // "год"
dtf.of('month');  // "месяц"
dtf.of('day');    // "день"

Этот тип полезен при построении UI для выбора интервалов и форматирования пользовательских фильтров.

Скрипты (письменности)

Тип script работает с кодами письменностей ISO 15924.

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

script.of('Latn'); // "латиница"
script.of('Cyrl'); // "кириллица"
script.of('Arab'); // "арабское письмо"

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

Поведение fallback

При отсутствии перевода поведение определяется опцией fallback.

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

dnCode.of('xx'); // "xx"

Если задан none:

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

dnNone.of('xx'); // undefined

Это поведение важно при работе с нестандартными или экспериментальными кодами.

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

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

const cache = new Map();

function getDisplayNames(locale, type) {
  const key = `${locale}-${type}`;

  if (!cache.has(key)) {
    cache.set(key, new Intl.DisplayNames(locale, { type }));
  }

  return cache.get(key);
}

Такой подход уменьшает накладные расходы при частых вызовах .of().

Согласование локали и поведения

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

new Intl.DisplayNames('ru', { type: 'region' }).of('US'); // "Соединённые Штаты"
new Intl.DisplayNames('uk', { type: 'region' }).of('US'); // "Сполучені Штати"

В некоторых локалях различия затрагивают длину и стилистику названий:

const shortNames = new Intl.DisplayNames('en', {
  type: 'region',
  style: 'short'
});

Интеграция с кодами стандартов

Intl.DisplayNames ориентирован на строгие стандарты кодирования:

  • ISO 639 — языки
  • ISO 3166-1 — регионы
  • ISO 4217 — валюты
  • ISO 15924 — письменности
  • CLDR — календарные и временные поля

Это обеспечивает согласованность с другими API Intl, включая Intl.DateTimeFormat и Intl.NumberFormat.

Комбинирование с другими Intl API

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

const numberFormat = new Intl.NumberFormat('ru', {
  style: 'currency',
  currency: 'USD'
});

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

const code = 'USD';

`${displayNames.of(code)}: ${numberFormat.format(1000)}`;

Результат объединяет семантическое имя и форматированное значение.

Ограничения модели отображения

  • не все коды гарантированно поддерживаются во всех локалях
  • поведение зависит от реализации движка (V8, SpiderMonkey, JavaScriptCore)
  • отсутствует гарантия наличия всех редких исторических или экспериментальных кодов
  • of() всегда возвращает строку или undefined, без исключений

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