Intl.DisplayNames API

言語、地域、通貨、スクリプトコードを人間が読める名前に変換

はじめに

アプリケーションには国コード US がありますが、ユーザーには「United States」というテキストが表示されます。言語コード fr がありますが、言語切り替えには「French」と表示されます。通貨コード EUR がありますが、決済ページには「Euro」と表示されます。

ブラウザは独自のインターフェースを異なる言語でレンダリングするための広範なローカリゼーションデータを保持しています。Intl.DisplayNames APIはこのデータを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"を設定して、3文字の通貨コードを通貨名に変換します:

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"を設定することで、4文字のスクリプトコードをスクリプト名に変換できます:

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オプションは出力の詳細度を制御します。3つの値で異なる長さが生成されます:

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要素などのコンパクトな表示には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 "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 propを受け取ります。locale propを変更すると、翻訳された国名でドロップダウンが再レンダリングされます。

言語切替コンポーネントの構築

言語切替機能では、各言語をその言語自身の表記システムで表示します。各言語に対して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(2文字)またはUN M.49(3桁)に準拠しています:

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(3文字)に準拠しています:

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

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

スクリプトコードはISO 15924(4文字、大文字)に準拠しています:

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年に全ての主要ブラウザで利用可能になりました。最新のアプリケーションではポリフィルなしで使用できます。

languageregionscriptcurrencyタイプを含む基本APIは普遍的にサポートされています。calendarおよびdateTimeFieldタイプは後のブラウザバージョンで登場しましたが、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"

このキャッシュはロケールとタイプによってキー付けされたインスタンスを保存します。その後の呼び出しでは、新しいインスタンスを作成するのではなく、既存のインスタンスを再利用します。

このパターンは、ローカライズされた大量のデータテーブルのレンダリングなど、数百または数千のコードを変換するホットコードパスで最も重要です。

代替アプローチとの比較

Intl.DisplayNames APIが登場する前は、アプリケーションはコードを名前に変換するためにいくつかのアプローチを使用していました。

ハードコードされたルックアップテーブルはメンテナンスが必要で、事前に決められた言語のみをサポートしていました:

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"

ライブラリはバンドルにキロバイト単位のデータを追加し、新しい国が登場したり名前が変更されたりした場合には更新が必要です。

Intl.DisplayNames APIはこれらの問題を両方とも解消します。ブラウザがデータを維持し、最新の状態を保ち、バンドルサイズの懸念を排除します。このデータは追加のダウンロードなしでブラウザがサポートするすべての言語をサポートします。