Intl.DisplayNames API

将语言、地区、货币和脚本代码转换为可读名称

简介

您的应用拥有国家代码 US,但用户看到的文本是“United States”。您有语言代码 fr,但语言切换器显示为“French”。您有货币代码 EUR,但结账页面显示为“Euro”。

浏览器维护了大量本地化数据,用于以不同语言渲染自身界面。Intl.DisplayNames API 向 JavaScript 暴露这些数据,将标准化代码转换为任何语言下的可读名称。

这样无需第三方库或自定义查找表,也无需额外维护和本地化。浏览器会自动处理数据和翻译。

将地区代码转换为国家名称

最常见的用例是将 ISO 国家代码转换为国家名称。创建一个 DisplayNames 实例,指定 locale 和 type,然后使用国家代码调用 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 标准的 locale 代码数组。浏览器会使用数组中第一个支持的 locale。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")); // "月"

有效的字段标识符包括 erayearquartermonthweekOfYearweekdaydaydayPeriodhourminutesecondtimeZoneName

该模式支持构建可访问性良好的日期选择器、日历界面和时间选择组件,并能正确本地化标签。

通过样式选项控制显示长度

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 样式(默认)会显示全名。shortnarrow 样式在可用时会显示缩写形式,但并非所有代码都有简短变体。

当显示语言名称时,样式选项更为重要:

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 以显示完整标签。在移动端导航或空间受限的 UI 元素中,使用 shortnarrow 以显示紧凑标签。

使用 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 "Unknown region";
  }
  return name;
}

console.log(getRegionName("US")); // "United States"
console.log(getRegionName("INVALID")); // "Unknown region"

构建国家选择器组件

Intl.DisplayNames API 可直接集成到界面组件中。以下示例构建了一个国家选择器,能够以用户的语言显示国家名称:

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="">Select a country</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="">Select currency</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="">Select a country</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(["en"], { type: "region" });

console.log(regionNames.of("US")); // "United States" (ISO 3166-1)
console.log(regionNames.of("001")); // "world" (UN M.49)
console.log(regionNames.of("150")); // "Europe" (UN M.49)

语言代码遵循 BCP 47,将 ISO 639 语言代码与可选的区域和脚本子标签组合:

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

console.log(languageNames.of("en")); // "English"
console.log(languageNames.of("en-US")); // "American English"
console.log(languageNames.of("zh-Hans")); // "Simplified Chinese"
console.log(languageNames.of("zh-Hans-CN")); // "Simplified Chinese (China)"

货币代码遵循 ISO 4217(三个字母):

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

console.log(currencyNames.of("USD")); // "US Dollar"
console.log(currencyNames.of("EUR")); // "Euro"

脚本代码遵循 ISO 15924(四个大写字母):

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

console.log(scriptNames.of("Latn")); // "Latin"
console.log(scriptNames.of("Arab")); // "Arabic"

代码比较不区分大小写,但按照标准大小写书写可提升可读性:

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

console.log(regionNames.of("US")); // "United States"
console.log(regionNames.of("us")); // "United States"
console.log(regionNames.of("Us")); // "United States"

浏览器支持与兼容性

Intl.DisplayNames API 自 2021 年起在所有主流浏览器中可用。现代应用可直接使用,无需 polyfill。

基础 API 及 languageregionscriptcurrency 类型已获得全面支持。calendardateTimeField 类型在后续浏览器版本中出现,截至 2025 年已广泛支持。

如有需要,请在运行时检测功能支持情况:

if (typeof Intl.DisplayNames !== "undefined") {
  const regionNames = new Intl.DisplayNames(["en"], { type: "region" });
  console.log(regionNames.of("US"));
} else {
  console.log("Intl.DisplayNames not supported");
}

如需支持旧版浏览器,可在 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"

缓存会根据 locale 和类型存储实例。后续调用会复用已有实例,而不是新建实例。

这种模式在高频代码路径(如渲染大量本地化数据表格时)尤为重要,因为会涉及数百甚至数千次代码转换。

与其他方法的对比

Intl.DisplayNames API 出现之前,应用通常采用多种方式将代码转换为名称。

硬编码查找表需要维护,并且只能支持预设的语言:

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

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

当添加新语言时,这种方式会失效,因为每种语言都需要单独的查找表。

第三方库虽然提供本地化数据,但会增加 bundle 体积:

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"

这些库会为 bundle 增加数 KB 的数据,并且在有新国家或名称变更时需要更新。

Intl.DisplayNames API 解决了这两个问题。浏览器会维护数据,确保其最新,并消除了 bundle 体积的顾虑。数据支持所有浏览器支持的语言,无需额外下载。