如何显示语言名称,例如 English、Español、日本語?
使用 Intl.DisplayNames 在语言选择器和国际化界面中以本地脚本显示语言名称。
介绍
当您构建语言选择器或显示可用语言列表时,需要以用户能够识别的方式显示每种语言的名称。法语使用者会寻找“Français”,西班牙语使用者会寻找“Español”,而日语使用者会寻找“日本語”。用户通过其母语的文字和拼写来识别语言。
硬编码这些翻译无法扩展。您需要维护每种语言名称到其他所有语言的翻译。Intl.DisplayNames API 通过提供标准化的、符合语言环境的语言、国家/地区、脚本和货币名称,解决了这个问题。
硬编码语言名称的问题
您可以通过在对象中硬编码语言名称来创建语言选择器。
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 年 3 月起,主流浏览器(包括 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 不受支持");
}
对于较旧的浏览器,您需要提供一个回退方案或使用 polyfill。一个简单的回退方案是使用硬编码的语言代码到名称的映射。
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 的浏览器中也能正常工作,但您将失去自动本地化功能。