如何以不同语言显示国家名称?
使用 Intl.DisplayNames 将国家代码转换为国际用户的本地化国家名称。
介绍
当您构建一个运输表单、用户个人资料页面或地址选择器时,您需要显示国家名称。用户会看到英文的 "France",西班牙语的 "Francia",德语的 "Frankreich",以及日语的 "フランス"。每个用户都希望看到以他们自己的语言书写的国家名称。
您的应用程序在数据库和 API 中存储国家代码,例如 FR、US 或 JP。这些标准化代码可以在所有系统中使用,但用户需要可读的国家名称。Intl.DisplayNames API 可以将国家代码转换为任何语言的本地化国家名称,而无需维护翻译表或依赖外部库。
了解国家代码
国家通过 ISO 3166-1 alpha-2 标准定义的两位字母代码进行标识。每个国家都有一个唯一的代码,该代码在所有语言和系统中保持不变。
// 常见的国家代码
// US = 美国
// GB = 英国(联合王国)
// FR = 法国
// DE = 德国(Deutschland)
// JP = 日本
// CN = 中国
// BR = 巴西
// IN = 印度
这些代码出现在表单、URL、数据库和 API 中。代码 US 始终表示美国,无论您的应用程序是以英语、西班牙语、日语还是其他任何语言运行。代码提供了一个稳定的标识符,而显示名称会根据用户的语言而变化。
使用 Intl.DisplayNames 获取国家名称
Intl.DisplayNames 构造函数创建一个格式化器,用于将国家代码转换为国家名称。您需要指定一个语言环境,并将类型设置为 "region" 以获取国家名称。
const countryNames = new Intl.DisplayNames(["en"], { type: "region" });
console.log(countryNames.of("US"));
// "United States"
console.log(countryNames.of("FR"));
// "France"
console.log(countryNames.of("JP"));
// "Japan"
第一个参数是一个语言环境标识符数组。type: "region" 选项告诉格式化器您需要国家或地区名称。of() 方法接受一个国家代码并返回其本地化名称。
术语 "region" 包括国家、地区和地理区域。这包括像法国这样的独立国家、像波多黎各这样的地区,以及像欧盟这样的特殊区域。
在不同语言中显示国家名称
相同的国家代码在不同语言中会生成不同的名称。为不同的语言环境创建格式化器,查看国家名称如何变化。
const englishNames = new Intl.DisplayNames(["en"], { type: "region" });
const spanishNames = new Intl.DisplayNames(["es"], { type: "region" });
const germanNames = new Intl.DisplayNames(["de"], { type: "region" });
const japaneseNames = new Intl.DisplayNames(["ja"], { type: "region" });
console.log(englishNames.of("FR"));
// "France"
console.log(spanishNames.of("FR"));
// "Francia"
console.log(germanNames.of("FR"));
// "Frankreich"
console.log(japaneseNames.of("FR"));
// "フランス"
每个格式化器都会返回其显示语言环境中的国家名称。这处理了跨语言维护国家名称翻译的所有复杂性。
您可以创建一个函数来获取任何语言中的国家名称。
function getCountryName(countryCode, locale) {
const names = new Intl.DisplayNames([locale], { type: "region" });
return names.of(countryCode);
}
console.log(getCountryName("US", "en"));
// "United States"
console.log(getCountryName("US", "fr"));
// "États-Unis"
console.log(getCountryName("US", "ar"));
// "الولايات المتحدة"
console.log(getCountryName("DE", "en"));
// "Germany"
console.log(getCountryName("DE", "de"));
// "Deutschland"
console.log(getCountryName("DE", "es"));
// "Alemania"
此函数适用于任何国家代码和语言环境的组合。浏览器会自动提供翻译。
构建国家选择器
一个常见的用例是构建一个下拉菜单,用户可以选择他们的国家。国家名称应以用户的语言显示。
function createCountrySelector(locale) {
const countryNames = new Intl.DisplayNames([locale], { type: "region" });
const countries = [
"US", "GB", "CA", "AU", "FR", "DE", "ES", "IT",
"JP", "CN", "KR", "IN", "BR", "MX", "AR", "RU"
];
const select = document.createElement("select");
select.id = "country";
select.name = "country";
const placeholder = document.createElement("option");
placeholder.value = "";
placeholder.textContent = "选择一个国家";
select.appendChild(placeholder);
countries.forEach((code) => {
const option = document.createElement("option");
option.value = code;
option.textContent = countryNames.of(code);
select.appendChild(option);
});
return select;
}
const selector = createCountrySelector("en");
document.body.appendChild(selector);
这会创建一个以英语显示国家名称的下拉菜单。将语言环境更改为 "es",相同的函数会生成一个以西班牙语显示国家名称的下拉菜单。将其更改为 "ja",名称将以日语显示。
您可以让选择器响应用户的浏览器语言。
function createLocalizedCountrySelector() {
const userLocale = navigator.language;
return createCountrySelector(userLocale);
}
const selector = createLocalizedCountrySelector();
document.body.appendChild(selector);
选择器会根据用户的浏览器设置,自动以用户的首选语言显示国家名称。
获取所有可用的国家
Intl.supportedValuesOf() 方法返回一个包含所有支持的国家代码的数组。这消除了维护硬编码列表的需求。
const allCountries = Intl.supportedValuesOf("region");
console.log(allCountries.length);
// 249(截至 2025 年的大致数量)
console.log(allCountries.slice(0, 10));
// ["AC", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ"]
该方法按代码的字母顺序返回代码,而不是按国家名称的顺序。如果您希望按特定语言的字母顺序排列,则需要按本地化名称进行排序。
function getSortedCountries(locale) {
const countryNames = new Intl.DisplayNames([locale], { type: "region" });
const allCountries = Intl.supportedValuesOf("region");
return allCountries
.map((code) => ({
code,
name: countryNames.of(code)
}))
.sort((a, b) => a.name.localeCompare(b.name, locale));
}
const sortedEnglish = getSortedCountries("en");
console.log(sortedEnglish.slice(0, 5));
// [
// { code: "AF", name: "Afghanistan" },
// { code: "AX", name: "Åland Islands" },
// { code: "AL", name: "Albania" },
// { code: "DZ", name: "Algeria" },
// { code: "AS", name: "American Samoa" }
// ]
const sortedSpanish = getSortedCountries("es");
console.log(sortedSpanish.slice(0, 5));
// [
// { code: "AF", name: "Afganistán" },
// { code: "AL", name: "Albania" },
// { code: "DE", name: "Alemania" },
// { code: "AD", name: "Andorra" },
// { code: "AO", name: "Angola" }
// ]
由于不同语言的字母表和排序规则不同,排序顺序在不同语言之间会有所差异。
构建一个全面的国家选择器
结合 Intl.supportedValuesOf() 和 Intl.DisplayNames 来创建一个包含所有可用国家的选择器。
function createComprehensiveCountrySelector(locale) {
const countryNames = new Intl.DisplayNames([locale], { type: "region" });
const allCountries = Intl.supportedValuesOf("region");
const sortedCountries = allCountries
.map((code) => ({
code,
name: countryNames.of(code)
}))
.sort((a, b) => a.name.localeCompare(b.name, locale));
const select = document.createElement("select");
select.id = "country";
select.name = "country";
const placeholder = document.createElement("option");
placeholder.value = "";
placeholder.textContent = "选择一个国家";
select.appendChild(placeholder);
sortedCountries.forEach(({ code, name }) => {
const option = document.createElement("option");
option.value = code;
option.textContent = name;
select.appendChild(option);
});
return select;
}
const selector = createComprehensiveCountrySelector("en");
document.body.appendChild(selector);
此选择器包含浏览器支持的所有 249 个国家和地区,并按用户语言的字母顺序排列。
处理无效的国家代码
并非所有的两位字符串都是有效的国家代码。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("US"));
// "United States"
console.log(withCodeFallback.of("XX"));
// "XX"
console.log(withNoneFallback.of("US"));
// "United States"
console.log(withNoneFallback.of("XX"));
// undefined
fallback: "code" 选项在没有对应国家时返回输入代码。fallback: "none" 选项对无效代码返回 undefined。
当需要检测无效代码并显式处理时,请使用 fallback: "none"。
function getValidatedCountryName(code, locale) {
const names = new Intl.DisplayNames([locale], {
type: "region",
fallback: "none"
});
const name = names.of(code);
if (name === undefined) {
return "未知国家";
}
return name;
}
console.log(getValidatedCountryName("US", "en"));
// "United States"
console.log(getValidatedCountryName("INVALID", "en"));
// "未知国家"
这种模式有助于验证用户输入或外部数据。
使用样式控制国家名称长度
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 样式在可用时返回缩写形式。对于大多数国家,short 和 narrow 样式返回国家代码本身。
某些国家有独特的短形式。
const longNames = new Intl.DisplayNames(["en"], {
type: "region",
style: "long"
});
const shortNames = new Intl.DisplayNames(["en"], {
type: "region",
style: "short"
});
console.log(longNames.of("GB"));
// "United Kingdom"
console.log(shortNames.of("GB"));
// "UK"
console.log(longNames.of("BO"));
// "Bolivia"
console.log(shortNames.of("BO"));
// "Bolivia"
在大多数界面中使用默认的 long 样式。在空间有限的情况下,例如移动导航或紧凑表格中,使用 short 或 narrow 样式。
显示地区的区域名称
ISO 3166-1 标准包括独立国家以外的地区、属地和特殊区域。Intl.DisplayNames API 也可以处理这些。
const regionNames = new Intl.DisplayNames(["en"], { type: "region" });
console.log(regionNames.of("PR"));
// "Puerto Rico"
console.log(regionNames.of("GU"));
// "Guam"
console.log(regionNames.of("HK"));
// "Hong Kong"
console.log(regionNames.of("MQ"));
// "Martinique"
console.log(regionNames.of("GF"));
// "French Guiana"
这些代码的工作方式与国家代码相同。您的应用程序可以统一处理它们,而浏览器会提供适当的本地化名称。
使用数字区域代码
ISO 3166-1 标准还定义了数字代码。Intl.DisplayNames API 除了接受两字母代码外,还接受联合国 M.49 数字区域代码。
const regionNames = new Intl.DisplayNames(["en"], { type: "region" });
console.log(regionNames.of("840"));
// "United States"
console.log(regionNames.of("250"));
// "France"
console.log(regionNames.of("392"));
// "Japan"
数字代码还可以表示更大的地理区域。
const regionNames = new Intl.DisplayNames(["en"], { type: "region" });
console.log(regionNames.of("150"));
// "Europe"
console.log(regionNames.of("019"));
// "Americas"
console.log(regionNames.of("142"));
// "Asia"
console.log(regionNames.of("002"));
// "Africa"
console.log(regionNames.of("009"));
// "Oceania"
这些代码可以跨语言使用。
const englishRegions = new Intl.DisplayNames(["en"], { type: "region" });
const spanishRegions = new Intl.DisplayNames(["es"], { type: "region" });
console.log(englishRegions.of("150"));
// "Europe"
console.log(spanishRegions.of("150"));
// "Europa"
当您需要避免字符编码问题或与使用联合国 M.49 代码的系统协作时,可以使用数字代码。
缓存 DisplayNames 实例以提高性能
创建 Intl.DisplayNames 实例的开销很小,但对于需要转换大量国家代码的应用程序来说,缓存格式化器会带来好处。
const displayNamesCache = new Map();
function getDisplayNames(locale, type) {
const key = `${locale}-${type}`;
if (!displayNamesCache.has(key)) {
displayNamesCache.set(
key,
new Intl.DisplayNames([locale], { type })
);
}
return displayNamesCache.get(key);
}
function getCountryName(code, locale) {
const formatter = getDisplayNames(locale, "region");
return formatter.of(code);
}
console.log(getCountryName("US", "en"));
// "United States"
console.log(getCountryName("FR", "en"));
// "France"
console.log(getCountryName("US", "es"));
// "Estados Unidos"
缓存以区域和类型为键存储格式化器。后续调用会重用现有的格式化器,而不是创建新的。
当渲染大量国家列表或在表格或数据网格中处理数百个国家代码时,这种优化尤为重要。
处理语言环境回退
Intl.DisplayNames 构造函数接受一个语言环境数组。如果第一个语言环境不受支持,浏览器会回退到数组中的下一个语言环境。
const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "region" });
console.log(names.of("US"));
// "United States"
浏览器首先尝试 "xx-XX",但该语言环境不存在,因此回退到 "en"。这确保了即使请求的语言环境不可用,代码也能正常运行。
您可以检查格式化器实际使用的语言环境。
const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "region" });
console.log(names.resolvedOptions().locale);
// "en"
resolvedOptions() 方法返回格式化器在回退处理后解析到的语言环境。
比较不同语言中的国家名称
不同语言对国家名称的格式化方式不同。有些语言将国家名称大写,而有些则不会。有些语言包含冠词,而有些则没有。
const english = new Intl.DisplayNames(["en"], { type: "region" });
const french = new Intl.DisplayNames(["fr"], { type: "region" });
const german = new Intl.DisplayNames(["de"], { type: "region" });
console.log(english.of("US"));
// "United States"
console.log(french.of("US"));
// "États-Unis"
console.log(german.of("US"));
// "Vereinigte Staaten"
console.log(english.of("NL"));
// "Netherlands"
console.log(french.of("NL"));
// "Pays-Bas"
console.log(german.of("NL"));
// "Niederlande"
格式化器会自动处理所有这些语言习惯。您无需了解每种语言的语法规则。
浏览器支持
Intl.DisplayNames API(带有 type: "region")在所有现代浏览器中均可用。自 2021 年起,包括 Chrome、Firefox、Safari 和 Edge 在内的主流浏览器都已支持该功能。
现代应用程序可以直接使用此 API,而无需使用 polyfill 或回退。浏览器会维护国家名称数据,并随着国家和地区的变化保持更新。
您可以在使用该 API 之前检查其是否可用。
if (typeof Intl.DisplayNames !== "undefined") {
const names = new Intl.DisplayNames(["en"], { type: "region" });
console.log(names.of("US"));
} else {
console.log("Intl.DisplayNames is not supported");
}
对于支持旧版浏览器的应用程序,可以使用静态查找表提供回退。
function getCountryName(code, locale) {
if (typeof Intl.DisplayNames !== "undefined") {
const names = new Intl.DisplayNames([locale], { type: "region" });
return names.of(code);
}
const fallbackNames = {
US: "United States",
GB: "United Kingdom",
FR: "France",
DE: "Germany",
JP: "Japan"
};
return fallbackNames[code] || code;
}
console.log(getCountryName("US", "en"));
// "United States"
这确保了您的应用程序可以在所有浏览器中运行,尽管旧版浏览器会失去自动本地化功能。