API Intl.DisplayNames

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

Введение

Ваше приложение использует код страны US, но пользователи видят текст "Соединенные Штаты". У вас есть код языка fr, но переключатель языка отображает "Французский". У вас есть код валюты EUR, но на странице оформления заказа отображается "Евро".

Браузеры содержат обширные данные локализации для отображения своих интерфейсов на разных языках. API Intl.DisplayNames предоставляет доступ к этим данным в JavaScript, преобразуя стандартизированные коды в читаемые названия, локализованные для любого языка.

Это устраняет необходимость в сторонних библиотеках или пользовательских таблицах поиска, которые требуют поддержки и локализации. Браузер берет на себя как данные, так и переводы.

Преобразование кодов регионов в названия стран

Наиболее распространенный случай использования — преобразование кодов стран ISO в названия стран. Создайте экземпляр DisplayNames с указанием локали и типа, затем вызовите метод of() с кодом страны:

const regionNames = new Intl.DisplayNames(["en"], { type: "region" });

console.log(regionNames.of("US")); // "United States"
console.log(regionNames.of("GB")); // "United Kingdom"
console.log(regionNames.of("JP")); // "Japan"

Первый параметр принимает массив кодов локалей в соответствии со стандартом BCP 47. Браузер использует первую поддерживаемую локаль из массива. Опция type указывает, какой тип кода вы хотите преобразовать.

Одни и те же коды дают разные результаты при локализации для разных языков:

const englishRegions = new Intl.DisplayNames(["en"], { type: "region" });
const japaneseRegions = new Intl.DisplayNames(["ja"], { type: "region" });
const spanishRegions = new Intl.DisplayNames(["es"], { type: "region" });

console.log(englishRegions.of("FR")); // "France"
console.log(japaneseRegions.of("FR")); // "フランス"
console.log(spanishRegions.of("FR")); // "Francia"

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

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

Языковые коды используют тот же шаблон, что и региональные коды. Установите type: "language", чтобы преобразовать языковые коды в названия языков:

const languageNames = new Intl.DisplayNames(["en"], { type: "language" });

console.log(languageNames.of("en")); // "English"
console.log(languageNames.of("es")); // "Spanish"
console.log(languageNames.of("zh")); // "Chinese"
console.log(languageNames.of("ar")); // "Arabic"

Языковые коды могут включать региональные подметки для региональных вариантов:

const languageNames = new Intl.DisplayNames(["en"], { type: "language" });

console.log(languageNames.of("en-US")); // "American English"
console.log(languageNames.of("en-GB")); // "British English"
console.log(languageNames.of("fr-CA")); // "Canadian French"
console.log(languageNames.of("pt-BR")); // "Brazilian Portuguese"

Это преобразует языковые коды в названия, подходящие для переключателей языков, интерфейсов перевода и селекторов языковых предпочтений.

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

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

const english = new Intl.DisplayNames(["en"], { type: "language" });
const french = new Intl.DisplayNames(["fr"], { type: "language" });
const japanese = new Intl.DisplayNames(["ja"], { type: "language" });
const arabic = new Intl.DisplayNames(["ar"], { type: "language" });

console.log(english.of("en")); // "English"
console.log(french.of("fr")); // "français"
console.log(japanese.of("ja")); // "日本語"
console.log(arabic.of("ar")); // "العربية"

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

Преобразование кодов валют в названия валют

Коды валют соответствуют стандарту ISO 4217. Установите type: "currency", чтобы преобразовать трехбуквенные коды валют в названия валют:

const currencyNames = new Intl.DisplayNames(["en"], { type: "currency" });

console.log(currencyNames.of("USD")); // "US Dollar"
console.log(currencyNames.of("EUR")); // "Euro"
console.log(currencyNames.of("GBP")); // "British Pound"
console.log(currencyNames.of("JPY")); // "Japanese Yen"

Названия валют локализуются в зависимости от языка отображения:

const englishCurrency = new Intl.DisplayNames(["en"], { type: "currency" });
const germanCurrency = new Intl.DisplayNames(["de"], { type: "currency" });
const japaneseCurrency = new Intl.DisplayNames(["ja"], { type: "currency" });

console.log(englishCurrency.of("EUR")); // "Euro"
console.log(germanCurrency.of("EUR")); // "Euro"
console.log(japaneseCurrency.of("EUR")); // "ユーロ"

Этот шаблон подходит для селекторов валют в процессах оформления заказа, финансовых панелей и интерфейсов конвертации валют.

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

Коды письменности используют стандарт ISO 15924. Установите type: "script", чтобы преобразовать четырехбуквенные коды письменности в их названия:

const scriptNames = new Intl.DisplayNames(["en"], { type: "script" });

console.log(scriptNames.of("Latn")); // "Latin"
console.log(scriptNames.of("Arab")); // "Arabic"
console.log(scriptNames.of("Cyrl")); // "Cyrillic"
console.log(scriptNames.of("Hans")); // "Simplified Chinese"
console.log(scriptNames.of("Hant")); // "Traditional Chinese"

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

Преобразование кодов календарей в названия календарей

Календарные системы различаются в разных культурах. Установите type: "calendar", чтобы преобразовать идентификаторы календарей в их названия:

const calendarNames = new Intl.DisplayNames(["en"], { type: "calendar" });

console.log(calendarNames.of("gregory")); // "Gregorian Calendar"
console.log(calendarNames.of("japanese")); // "Japanese Calendar"
console.log(calendarNames.of("buddhist")); // "Buddhist Calendar"
console.log(calendarNames.of("hebrew")); // "Hebrew Calendar"
console.log(calendarNames.of("islamic")); // "Islamic Calendar"
console.log(calendarNames.of("chinese")); // "Chinese Calendar"

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

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

Интерфейсы даты и времени содержат поля с метками, такие как год, месяц и день. Установите type: "dateTimeField", чтобы преобразовать идентификаторы полей в локализованные названия:

const dateFields = new Intl.DisplayNames(["en"], { type: "dateTimeField" });

console.log(dateFields.of("year")); // "year"
console.log(dateFields.of("month")); // "month"
console.log(dateFields.of("day")); // "day"
console.log(dateFields.of("hour")); // "hour"
console.log(dateFields.of("minute")); // "minute"
console.log(dateFields.of("weekday")); // "day of the week"
console.log(dateFields.of("dayPeriod")); // "AM/PM"
console.log(dateFields.of("timeZoneName")); // "time zone"

Эти названия полей локализуются для языка отображения:

const englishFields = new Intl.DisplayNames(["en"], { type: "dateTimeField" });
const spanishFields = new Intl.DisplayNames(["es"], { type: "dateTimeField" });
const japaneseFields = new Intl.DisplayNames(["ja"], { type: "dateTimeField" });

console.log(englishFields.of("month")); // "month"
console.log(spanishFields.of("month")); // "mes"
console.log(japaneseFields.of("month")); // "月"

Допустимые идентификаторы полей включают era, year, quarter, month, weekOfYear, weekday, day, dayPeriod, hour, minute, second и timeZoneName.

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

Управление длиной отображения с помощью параметров стиля

Опция style контролирует, насколько подробно отображается результат. Три значения дают разную длину:

const longNames = new Intl.DisplayNames(["en"], {
  type: "region",
  style: "long",
});

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

const narrowNames = new Intl.DisplayNames(["en"], {
  type: "region",
  style: "narrow",
});

console.log(longNames.of("US")); // "United States"
console.log(shortNames.of("US")); // "US"
console.log(narrowNames.of("US")); // "US"

Стиль long (по умолчанию) выводит полное название. Стили short и narrow создают сокращённые формы, если они доступны, хотя не все коды имеют более короткие варианты.

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

const longLanguages = new Intl.DisplayNames(["en"], {
  type: "language",
  style: "long",
});

const shortLanguages = new Intl.DisplayNames(["en"], {
  type: "language",
  style: "short",
});

console.log(longLanguages.of("en-US")); // "American English"
console.log(shortLanguages.of("en-US")); // "US English"

Используйте long для полных меток в формах и детализированных интерфейсах. Используйте short или narrow для компактного отображения, например, в мобильной навигации или элементах интерфейса с ограниченным пространством.

Обработка региональных языковых вариантов с помощью languageDisplay

Коды языков с региональными подметками могут отображаться как диалекты или как стандартные названия языков с региональными уточнениями. Опция languageDisplay управляет этим поведением и применяется только при type: "language":

const dialectNames = new Intl.DisplayNames(["en"], {
  type: "language",
  languageDisplay: "dialect",
});

const standardNames = new Intl.DisplayNames(["en"], {
  type: "language",
  languageDisplay: "standard",
});

console.log(dialectNames.of("nl-BE")); // "Flemish"
console.log(standardNames.of("nl-BE")); // "Dutch (Belgium)"

console.log(dialectNames.of("en-AU")); // "Australian English"
console.log(standardNames.of("en-AU")); // "English (Australia)"

Значение dialect (по умолчанию) отображает региональные варианты, используя их общепринятые названия. Значение standard всегда отображает базовый язык с указанием региона в скобках.

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

Управление поведением резервного механизма для недопустимых кодов

Метод of() принимает коды, которые могут не иметь соответствующих отображаемых имен. Опция fallback определяет, что происходит в таких случаях:

const withCodeFallback = new Intl.DisplayNames(["en"], {
  type: "region",
  fallback: "code",
});

const withNoneFallback = new Intl.DisplayNames(["en"], {
  type: "region",
  fallback: "none",
});

console.log(withCodeFallback.of("ZZ")); // "ZZ"
console.log(withNoneFallback.of("ZZ")); // undefined

Значение code (по умолчанию) возвращает входной код, если отображаемое имя отсутствует. Значение none возвращает undefined для кодов, которые не сопоставлены.

Используйте code, если вам всегда нужно строковое значение для отображения, даже если это будет сам код. Используйте none, если вам нужно обнаруживать недопустимые коды и обрабатывать их явно:

const regionNames = new Intl.DisplayNames(["en"], {
  type: "region",
  fallback: "none",
});

function getRegionName(code) {
  const name = regionNames.of(code);
  if (name === undefined) {
    return "Неизвестный регион";
  }
  return name;
}

console.log(getRegionName("US")); // "United States"
console.log(getRegionName("INVALID")); // "Неизвестный регион"

Создание компонента выбора страны

API Intl.DisplayNames напрямую интегрируется в интерфейсные компоненты. В этом примере создается компонент выбора страны, который отображает названия стран на языке пользователя:

function CountrySelector({ locale, value, onChange }) {
  const regionNames = new Intl.DisplayNames([locale], { type: "region" });

  const countries = [
    "US",
    "GB",
    "CA",
    "AU",
    "FR",
    "DE",
    "JP",
    "CN",
    "BR",
    "IN",
  ];

  return (
    <select value={value} onChange={(e) => onChange(e.target.value)}>
      <option value="">Выберите страну</option>
      {countries.map((code) => (
        <option key={code} value={code}>
          {regionNames.of(code)}
        </option>
      ))}
    </select>
  );
}

Компонент принимает свойство locale, которое управляет языком отображения. Изменение свойства locale перерисовывает выпадающий список с переведенными названиями стран.

Создание компонента переключателя языка

Переключатели языка отображают каждый язык в его собственной системе письма. Создайте экземпляр DisplayNames для каждого языка:

function LanguageSwitcher({ currentLocale, onLocaleChange }) {
  const languages = [
    { code: "en", name: "English" },
    { code: "es", name: "Español" },
    { code: "fr", name: "Français" },
    { code: "de", name: "Deutsch" },
    { code: "ja", name: "日本語" },
    { code: "zh", name: "中文" },
  ];

  return (
    <div>
      {languages.map((lang) => {
        const displayNames = new Intl.DisplayNames([lang.code], {
          type: "language",
        });
        const nativeName = displayNames.of(lang.code);

        return (
          <button
            key={lang.code}
            onClick={() => onLocaleChange(lang.code)}
            className={currentLocale === lang.code ? "active" : ""}
          >
            {nativeName}
          </button>
        );
      })}
    </div>
  );
}

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

Создание компонента выбора валюты

Выбор валюты выигрывает от локализованных названий валют. Этот пример создает компонент выбора валюты, который адаптируется к языку отображения:

function CurrencySelector({ locale, value, onChange }) {
  const currencyNames = new Intl.DisplayNames([locale], { type: "currency" });

  const currencies = ["USD", "EUR", "GBP", "JPY", "CNY", "CAD", "AUD"];

  return (
    <select value={value} onChange={(e) => onChange(e.target.value)}>
      <option value="">Выберите валюту</option>
      {currencies.map((code) => (
        <option key={code} value={code}>
          {code} - {currencyNames.of(code)}
        </option>
      ))}
    </select>
  );
}

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

Получение всех поддерживаемых значений

Метод Intl.supportedValuesOf() возвращает массивы всех поддерживаемых значений для каждого типа. Это исключает необходимость в жестко закодированных списках кодов:

const regions = Intl.supportedValuesOf("region");
console.log(regions); // ["AD", "AE", "AF", "AG", "AI", ...]

const languages = Intl.supportedValuesOf("language");
console.log(languages); // ["aa", "ab", "ae", "af", "ak", ...]

const currencies = Intl.supportedValuesOf("currency");
console.log(currencies); // ["AED", "AFN", "ALL", "AMD", ...]

const calendars = Intl.supportedValuesOf("calendar");
console.log(calendars); // ["buddhist", "chinese", "coptic", ...]

Создавайте динамические селекторы, которые автоматически включают все поддерживаемые значения:

function UniversalCountrySelector({ locale, value, onChange }) {
  const regionNames = new Intl.DisplayNames([locale], { type: "region" });
  const allRegions = Intl.supportedValuesOf("region");

  return (
    <select value={value} onChange={(e) => onChange(e.target.value)}>
      <option value="">Выберите страну</option>
      {allRegions.map((code) => (
        <option key={code} value={code}>
          {regionNames.of(code)}
        </option>
      ))}
    </select>
  );
}

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

Понимание требований к форматам кодов

Каждый тип ожидает коды в определённых форматах. Неправильные форматы приводят к поведению по умолчанию, а не к отображению имён.

Коды регионов соответствуют ISO 3166-1 alpha-2 (две буквы) или UN M.49 (три цифры):

const regionNames = new Intl.DisplayNames(["ru"], { type: "region" });

console.log(regionNames.of("US")); // "Соединённые Штаты" (ISO 3166-1)
console.log(regionNames.of("001")); // "мир" (UN M.49)
console.log(regionNames.of("150")); // "Европа" (UN M.49)

Коды языков соответствуют BCP 47, который объединяет языковые коды ISO 639 с необязательными субтегами региона и скрипта:

const languageNames = new Intl.DisplayNames(["ru"], { type: "language" });

console.log(languageNames.of("en")); // "английский"
console.log(languageNames.of("en-US")); // "американский английский"
console.log(languageNames.of("zh-Hans")); // "упрощённый китайский"
console.log(languageNames.of("zh-Hans-CN")); // "упрощённый китайский (Китай)"

Коды валют соответствуют ISO 4217 (три буквы):

const currencyNames = new Intl.DisplayNames(["ru"], { type: "currency" });

console.log(currencyNames.of("USD")); // "доллар США"
console.log(currencyNames.of("EUR")); // "евро"

Коды скриптов соответствуют ISO 15924 (четыре буквы, с заглавной первой буквой):

const scriptNames = new Intl.DisplayNames(["ru"], { type: "script" });

console.log(scriptNames.of("Latn")); // "латиница"
console.log(scriptNames.of("Arab")); // "арабский"

Сравнение кодов нечувствительно к регистру, но следование стандартной капитализации улучшает читаемость:

const regionNames = new Intl.DisplayNames(["ru"], { type: "region" });

console.log(regionNames.of("US")); // "Соединённые Штаты"
console.log(regionNames.of("us")); // "Соединённые Штаты"
console.log(regionNames.of("Us")); // "Соединённые Штаты"

Поддержка браузерами и совместимость

API Intl.DisplayNames стало доступно во всех основных браузерах в 2021 году. Современные приложения могут использовать его без полифилов.

Базовое API с типами language, region, script и currency имеет универсальную поддержку. Типы calendar и dateTimeField появились в более поздних версиях браузеров, но имеют широкую поддержку по состоянию на 2025 год.

Проверяйте поддержку функций во время выполнения, если это необходимо:

if (typeof Intl.DisplayNames !== "undefined") {
  const regionNames = new Intl.DisplayNames(["ru"], { type: "region" });
  console.log(regionNames.of("US"));
} else {
  console.log("Intl.DisplayNames не поддерживается");
}

Для приложений, поддерживающих старые браузеры, используйте статические таблицы поиска или сторонние библиотеки, если API недоступно.

Оптимизация производительности с помощью кэширования

Создание экземпляров 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);
}

function getCountryName(locale, code) {
  const displayNames = getDisplayNames(locale, "region");
  return displayNames.of(code);
}

console.log(getCountryName("en", "US")); // "United States"
console.log(getCountryName("en", "FR")); // "France"
console.log(getCountryName("es", "US")); // "Estados Unidos"

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

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

Сравнение с альтернативными подходами

До появления API Intl.DisplayNames приложения использовали несколько подходов для преобразования кодов в названия.

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

const countryNames = {
  US: "United States",
  GB: "United Kingdom",
  FR: "France",
};

function getCountryName(code) {
  return countryNames[code] || code;
}

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

Сторонние библиотеки предоставляли данные для локализации, но увеличивали размер пакета:

import countries from "i18n-iso-countries";
import countriesEN from "i18n-iso-countries/langs/en.json";
import countriesES from "i18n-iso-countries/langs/es.json";

countries.registerLocale(countriesEN);
countries.registerLocale(countriesES);

console.log(countries.getName("US", "en")); // "United States"
console.log(countries.getName("US", "es")); // "Estados Unidos"

Библиотеки добавляют килобайты данных в пакет и требуют обновлений при появлении новых стран или изменении названий.

API Intl.DisplayNames устраняет обе проблемы. Браузер поддерживает данные в актуальном состоянии, устраняя проблемы с размером пакета. Данные поддерживают все языки, которые поддерживает браузер, без дополнительных загрузок.