Как отобразить названия языков, такие как English, Español, 日本語?
Используйте Intl.DisplayNames, чтобы отображать названия языков в их родных скриптах для языковых селекторов и интернационализированных интерфейсов.
Введение
Когда вы создаёте языковой переключатель или отображаете список доступных языков, необходимо показывать названия языков так, чтобы пользователи могли их распознать. Франкоговорящий пользователь ищет "Français", испаноговорящий — "Español", а японоговорящий — "日本語". Пользователи идентифицируют свой язык по его родному написанию и орфографии.
Жёсткое кодирование этих переводов не масштабируется. Вам пришлось бы поддерживать переводы каждого названия языка на все остальные языки. API Intl.DisplayNames решает эту проблему, предоставляя стандартизированные, локализованные названия для языков, стран, систем письма и валют.
Проблема жёсткого кодирования названий языков
Вы можете создать языковой переключатель, жёстко закодировав названия языков в объекте.
const languageNames = {
en: "English",
es: "Spanish",
fr: "French",
de: "German",
ja: "Japanese"
};
console.log(languageNames.en);
// "English"
У этого подхода есть три проблемы. Во-первых, эти названия работают только для англоговорящих пользователей. Во-вторых, пользователи не могут распознать свой язык, если он отображается на английском. Японский пользователь, просматривая список, ищет японские символы, а не слово "Japanese". В-третьих, вам придётся вручную поддерживать переводы каждого языка на все остальные языки.
const languageNames = {
en: {
en: "English",
es: "Spanish",
fr: "French",
de: "German",
ja: "Japanese"
},
es: {
en: "Inglés",
es: "Español",
fr: "Francés",
de: "Alemán",
ja: "Japonés"
}
// ... больше языков
};
Это быстро становится неудобным для поддержки. Вам нужно лучшее решение.
Использование Intl.DisplayNames для получения названий языков
Конструктор Intl.DisplayNames создаёт форматтер, который преобразует языковые коды в читаемые названия. Вы указываете локаль и тип названий, которые хотите отображать.
const names = new Intl.DisplayNames(["en"], { type: "language" });
console.log(names.of("en"));
// "English"
Первый аргумент — это массив идентификаторов локалей. Второй аргумент — это объект с опциями, где type: "language" указывает форматтеру, что вы хотите получить названия языков. Метод of() принимает код языка и возвращает его название.
Вы можете получить названия на любом языке, изменив локаль.
const enNames = new Intl.DisplayNames(["en"], { type: "language" });
const esNames = new Intl.DisplayNames(["es"], { type: "language" });
const frNames = new Intl.DisplayNames(["fr"], { type: "language" });
console.log(enNames.of("es"));
// "Spanish"
console.log(esNames.of("es"));
// "español"
console.log(frNames.of("es"));
// "espagnol"
Каждый форматтер возвращает название языка в своей локали отображения. Это решает все сложности, связанные с поддержкой переводов названий языков.
Отображение названий языков в их родной форме
Лучшей практикой для языковых селекторов является отображение каждого языка на его собственном алфавите. Пользователи быстрее узнают свой язык, когда видят его написанным знакомыми символами.
const names = new Intl.DisplayNames(["ja"], { type: "language" });
console.log(names.of("ja"));
// "日本語"
Чтобы получить родное название для каждого языка, создайте форматтер, используя целевой язык в качестве локали отображения.
function getNativeName(languageCode) {
const names = new Intl.DisplayNames([languageCode], { type: "language" });
return names.of(languageCode);
}
console.log(getNativeName("en"));
// "English"
console.log(getNativeName("es"));
// "español"
console.log(getNativeName("fr"));
// "français"
console.log(getNativeName("de"));
// "Deutsch"
console.log(getNativeName("ja"));
// "日本語"
console.log(getNativeName("ar"));
// "العربية"
console.log(getNativeName("zh"));
// "中文"
Этот шаблон работает для любого кода языка. Форматтер возвращает название в том алфавите и форме, которые используют носители языка.
Понимание форматов кодов языков
Метод of() принимает коды языков в нескольких форматах. Вы можете использовать базовые коды, такие как "en", или полные идентификаторы локалей, такие как "en-US".
const names = new Intl.DisplayNames(["en"], { type: "language" });
console.log(names.of("en"));
// "English"
console.log(names.of("en-US"));
// "American English"
console.log(names.of("en-GB"));
// "British English"
console.log(names.of("zh"));
// "Chinese"
console.log(names.of("zh-Hans"));
// "Simplified Chinese"
console.log(names.of("zh-Hant"));
// "Traditional Chinese"
Форматтер распознает как короткие коды, так и расширенные идентификаторы с региональными или скриптовыми подметками. Это позволяет различать варианты языков.
Управление отображением названий языков
Опция languageDisplay управляет уровнем детализации в возвращаемых названиях. Она принимает два значения.
Значение "standard" возвращает полные названия, включая информацию о диалектах. Это значение используется по умолчанию.
const names = new Intl.DisplayNames(["en"], {
type: "language",
languageDisplay: "standard"
});
console.log(names.of("en-US"));
// "American English"
console.log(names.of("en-GB"));
// "British English"
console.log(names.of("pt-BR"));
// "Brazilian Portuguese"
console.log(names.of("pt-PT"));
// "European Portuguese"
Значение "dialect" также возвращает полные названия с информацией о диалектах. В большинстве случаев оно дает тот же результат, что и "standard".
const names = new Intl.DisplayNames(["en"], {
type: "language",
languageDisplay: "dialect"
});
console.log(names.of("en-US"));
// "American English"
console.log(names.of("pt-BR"));
// "Brazilian Portuguese"
Для языковых селекторов стандартный формат помогает пользователям выбрать правильный вариант, если доступно несколько диалектов.
Локализация названий языков для пользовательского интерфейса
Когда вы создаете страницу настроек или селектор языка, необходимо отображать названия языков на текущем языке интерфейса пользователя. Создайте форматтер, используя локаль пользователя.
function getLocalizedLanguageName(languageCode, userLocale) {
const names = new Intl.DisplayNames([userLocale], { type: "language" });
return names.of(languageCode);
}
// Пользовательский интерфейс на английском
console.log(getLocalizedLanguageName("ja", "en"));
// "Japanese"
// Пользовательский интерфейс на французском
console.log(getLocalizedLanguageName("ja", "fr"));
// "japonais"
// Пользовательский интерфейс на испанском
console.log(getLocalizedLanguageName("ja", "es"));
// "japonés"
Этот подход отображает описательные названия на языке, который понимает пользователь. Совместите это с названиями на родном языке, чтобы создать гибридные метки, такие как "日本語 (Japanese)", которые подходят как для носителей языка, так и для других пользователей.
Создание селектора языка с названиями на родном языке
Распространенный случай использования — создание выпадающего списка или списка, где пользователи выбирают предпочитаемый язык. Отображайте каждый язык в его родной форме, чтобы пользователи могли быстро найти свой вариант.
const supportedLanguages = ["en", "es", "fr", "de", "ja", "ar", "zh"];
function createLanguageOptions() {
return supportedLanguages.map((code) => {
const names = new Intl.DisplayNames([code], { type: "language" });
const nativeName = names.of(code);
return { code, name: nativeName };
});
}
const options = createLanguageOptions();
console.log(options);
Это создает массив языковых опций с названиями на родном языке.
[
{ code: "en", name: "English" },
{ code: "es", name: "español" },
{ code: "fr", name: "français" },
{ code: "de", name: "Deutsch" },
{ code: "ja", name: "日本語" },
{ code: "ar", name: "العربية" },
{ code: "zh", name: "中文" }
]
Вы можете отобразить эти опции в HTML, чтобы создать селектор языка.
function renderLanguageSelector() {
const options = createLanguageOptions();
const select = document.createElement("select");
select.id = "language-selector";
options.forEach((option) => {
const optionElement = document.createElement("option");
optionElement.value = option.code;
optionElement.textContent = option.name;
select.appendChild(optionElement);
});
return select;
}
const selector = renderLanguageSelector();
document.body.appendChild(selector);
Это создает выпадающий список, где каждый язык отображается в его родной письменной форме, что упрощает пользователям выбор своего языка.
Создание гибридных языковых меток
Некоторые интерфейсы отображают как название на родном языке, так и перевод на языке пользователя. Это помогает пользователям, которые могут не распознавать все алфавиты, и делает интерфейс более доступным.
function createHybridLabel(languageCode, userLocale) {
const nativeNames = new Intl.DisplayNames([languageCode], {
type: "language"
});
const localizedNames = new Intl.DisplayNames([userLocale], {
type: "language"
});
const nativeName = nativeNames.of(languageCode);
const localizedName = localizedNames.of(languageCode);
if (nativeName === localizedName) {
return nativeName;
}
return `${nativeName} (${localizedName})`;
}
// Интерфейс пользователя на английском
console.log(createHybridLabel("ja", "en"));
// "日本語 (Japanese)"
console.log(createHybridLabel("ar", "en"));
// "العربية (Arabic)"
console.log(createHybridLabel("en", "en"));
// "English"
// Интерфейс пользователя на испанском
console.log(createHybridLabel("ja", "es"));
// "日本語 (japonés)"
Этот подход сочетает преимущества узнаваемости родных названий с ясностью локализованных переводов.
Обработка резервных локалей
Конструктор Intl.DisplayNames принимает массив локалей. Если первая локаль недоступна, форматтер использует следующую локаль в массиве.
const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "language" });
console.log(names.of("fr"));
// "French"
Форматтер сначала пытается использовать "xx-XX", которая не существует, затем переходит к "en". Это гарантирует, что ваш код будет работать, даже если запрашиваемая локаль недоступна.
Вы можете проверить, какую локаль форматтер фактически использует, с помощью метода resolvedOptions().
const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "language" });
console.log(names.resolvedOptions().locale);
// "en"
Это показывает, что форматтер выбрал английский после резервного перехода.
Как разные локали форматируют названия языков
Каждая локаль имеет свои собственные правила для названий языков. Форматтер применяет их автоматически.
const supportedLanguages = ["en", "es", "fr", "de", "ja"];
function showLanguageNamesInLocale(locale) {
const names = new Intl.DisplayNames([locale], { type: "language" });
return supportedLanguages.map((code) => ({
code,
name: names.of(code)
}));
}
console.log(showLanguageNamesInLocale("en"));
// [
// { code: "en", name: "English" },
// { code: "es", name: "Spanish" },
// { code: "fr", name: "French" },
// { code: "de", name: "German" },
// { code: "ja", name: "Japanese" }
// ]
console.log(showLanguageNamesInLocale("es"));
// [
// { code: "en", name: "inglés" },
// { code: "es", name: "español" },
// { code: "fr", name: "francés" },
// { code: "de", name: "alemán" },
// { code: "ja", name: "japonés" }
// ]
console.log(showLanguageNamesInLocale("ja"));
// [
// { code: "en", name: "英語" },
// { code: "es", name: "スペイン語" },
// { code: "fr", name: "フランス語" },
// { code: "de", name: "ドイツ語" },
// { code: "ja", name: "日本語" }
// ]
Форматтер автоматически учитывает правила капитализации, алфавита и лингвистические особенности для каждого языка.
Поддержка браузеров
Intl.DisplayNames API доступен во всех современных браузерах. Он поддерживается с марта 2021 года в основных браузерах, включая Chrome, Firefox, Safari и Edge.
Вы можете проверить доступность API перед его использованием.
if (typeof Intl.DisplayNames !== "undefined") {
const names = new Intl.DisplayNames(["en"], { type: "language" });
console.log(names.of("fr"));
} else {
console.log("Intl.DisplayNames не поддерживается");
}
Для старых браузеров необходимо предоставить запасной вариант или использовать полифил. Простой запасной вариант использует жестко закодированное сопоставление кодов языков с их названиями.
function getLanguageName(code, locale) {
if (typeof Intl.DisplayNames !== "undefined") {
const names = new Intl.DisplayNames([locale], { type: "language" });
return names.of(code);
}
// Запасной вариант для старых браузеров
const fallbackNames = {
en: "English",
es: "español",
fr: "français",
de: "Deutsch",
ja: "日本語"
};
return fallbackNames[code] || code;
}
console.log(getLanguageName("es", "en"));
// "español" (или "Spanish", если вы настроите запасной вариант для локализации)
Это гарантирует, что ваш код будет работать даже в браузерах без поддержки Intl.DisplayNames, хотя вы потеряете автоматические функции локализации.