Intl.Locale API

構造化されたJavaScriptオブジェクトでロケール識別子を解析、操作、クエリする

はじめに

複数の言語や地域向けのアプリケーションを構築する際、en-USfr-FRzh-Hans-CNのようなロケール識別子に遭遇します。これらの文字列は、ブラウザAPI、HTTPヘッダー、ユーザー設定に表示されます。言語、地域、書記体系、フォーマット設定に関する情報をエンコードしています。

Intl.Locale APIは、これらの不透明な文字列を、検査および操作可能な構造化オブジェクトに変換します。文字列を手動で解析したり、zh-Hans-CNが何を意味するか推測したりする代わりに、ロケールオブジェクトを作成し、そのプロパティを直接読み取ることができます。

このガイドでは、ロケール識別子の仕組み、Intl.Locale APIを使用してそれらを操作する方法、および構造化ロケールオブジェクトが実際の問題を解決するのに役立つ場合について説明します。

ロケール識別子の理解

ロケール識別子は、日付、数値、通貨、テキストのフォーマットに関する文化的設定を指定する文字列です。識別子には、ハイフンで区切られた複数のコンポーネントが含まれます。

最も一般的な構造は、BCP 47標準に従います。

language-script-region-variant-extensions

言語コードを除き、各コンポーネントはオプションです。

言語コード

言語コードは、ISO 639の2文字または3文字を使用します。一般的な例:

  • enは英語
  • esはスペイン語
  • frはフランス語
  • deはドイツ語
  • jaは日本語
  • zhは中国語
  • arはアラビア語

言語コードは常に小文字で、識別子の最初に表示されます。

地域コード

地域コードは、ISO 3166-1の2文字の大文字を使用して地理的領域を指定します。使用する言語のバリアントを示します。

  • en-US アメリカ英語
  • en-GB イギリス英語
  • es-ES ヨーロッパスペイン語
  • es-MX メキシコスペイン語
  • fr-FR フランスで話されるフランス語
  • fr-CA カナダフランス語

地域コードは書式規則を変更します。アメリカ英語では MM/DD/YYYY 形式の日付を使用しますが、イギリス英語では DD/MM/YYYY 形式を使用します。

文字体系コード

文字体系コードは、最初の文字を大文字にした4文字で表記体系を指定します。複数の文字体系で書かれる言語では重要です。

  • zh-Hans 簡体字中国語
  • zh-Hant 繁体字中国語
  • sr-Cyrl キリル文字のセルビア語
  • sr-Latn ラテン文字のセルビア語

ほとんどのロケールでは、言語がデフォルトの文字体系を暗示するため、文字体系コードを省略します。英語はデフォルトでラテン文字を使用するため、{/* INLINE_CODE_PLACEHOLDER_26de9b72be6ddbf49d2f3fa0124ae92b */} ではなく en と記述します。

拡張タグ

拡張タグは、ロケール識別子に書式設定の設定を追加します。-u- で始まり、その後にキーと値のペアが続きます。

en-US-u-ca-gregory-nu-latn-hc-h12

一般的な拡張キー:

  • ca 暦体系(gregorybuddhistislamic)
  • nu 数字体系(latnarabhanidec)
  • hc 時刻表示形式(h12h23h11h24)

拡張機能は、言語や地域を変更することなく、フォーマッタがデータを表示する方法をカスタマイズします。

ロケールオブジェクトの作成

Intl.Locale コンストラクタは、ロケール識別子文字列を受け取り、構造化されたオブジェクトを返します。

const locale = new Intl.Locale("en-US");

console.log(locale.language); // "en"
console.log(locale.region); // "US"

オプションオブジェクトを渡してプロパティを上書きまたは追加することもできます:

const locale = new Intl.Locale("en", {
  region: "GB",
  hourCycle: "h23"
});

console.log(locale.baseName); // "en-GB"
console.log(locale.hourCycle); // "h23"

識別子が無効な場合、コンストラクタはRangeErrorをスローします:

try {
  const invalid = new Intl.Locale("invalid-locale-code");
} catch (error) {
  console.error(error.message); // "invalid language subtag: invalid"
}

この検証により、フォーマッタに渡す前に不正な形式のロケール識別子を検出できます。

ロケールプロパティの読み取り

ロケールオブジェクトは、識別子文字列のコンポーネントに対応するプロパティを公開します。すべてのプロパティは読み取り専用です。

コアプロパティ

languageプロパティは言語コードを返します:

const locale = new Intl.Locale("fr-CA");
console.log(locale.language); // "fr"

regionプロパティは地域コードを返します:

const locale = new Intl.Locale("fr-CA");
console.log(locale.region); // "CA"

scriptプロパティは、存在する場合にスクリプトコードを返します:

const locale = new Intl.Locale("zh-Hans-CN");
console.log(locale.script); // "Hans"

baseNameプロパティは、拡張を除いた完全なコア識別子を返します:

const locale = new Intl.Locale("en-US-u-ca-gregory-nu-latn");
console.log(locale.baseName); // "en-US"

言語と地域が必要で、書式設定の設定を無視したい場合はbaseNameを使用してください。

拡張プロパティ

拡張プロパティは、-u-拡張タグからの値を返すか、指定されていない場合はundefinedを返します。

calendarプロパティは暦システムを返します:

const locale = new Intl.Locale("ar-SA-u-ca-islamic");
console.log(locale.calendar); // "islamic"

numberingSystemプロパティは数字システムを返します:

const locale = new Intl.Locale("ar-EG-u-nu-arab");
console.log(locale.numberingSystem); // "arab"

hourCycleプロパティは時刻サイクルの設定を返します:

const locale = new Intl.Locale("en-US-u-hc-h23");
console.log(locale.hourCycle); // "h23"

caseFirstプロパティは照合の大文字小文字の設定を返します。

const locale = new Intl.Locale("en-US-u-kf-upper");
console.log(locale.caseFirst); // "upper"

numericプロパティは数値照合が有効かどうかを示します。

const locale = new Intl.Locale("en-US-u-kn-true");
console.log(locale.numeric); // true

これらのプロパティを使用すると、拡張文字列を手動で解析することなく、書式設定の設定を確認できます。

ロケール情報の照会

Intl.Locale APIは、ロケールで使用可能なオプションの配列を返すメソッドを提供します。これらのメソッドは、ユーザーインターフェースの構築と書式設定の選択肢の検証に役立ちます。

使用可能な暦

getCalendars()メソッドは、ロケールで一般的に使用される暦体系を返します。

const locale = new Intl.Locale("th-TH");
const calendars = locale.getCalendars();
console.log(calendars); // ["buddhist", "gregory"]

最初の要素がデフォルトの暦です。タイのロケールは仏暦をデフォルトとしますが、グレゴリオ暦も使用します。

使用可能な照合

getCollations()メソッドは、文字列をソートするための照合タイプを返します。

const locale = new Intl.Locale("de-DE");
const collations = locale.getCollations();
console.log(collations); // ["phonebk", "emoji", "eor"]

ドイツ語には、標準のUnicode照合とは異なる方法で文字列をソートする電話帳照合があります。

使用可能な時刻表記

getHourCycles()メソッドは、時刻表記の形式を返します。

const locale = new Intl.Locale("en-US");
const hourCycles = locale.getHourCycles();
console.log(hourCycles); // ["h12"]

アメリカ英語はデフォルトで12時間制を使用します。他の多くのロケールは24時間制の["h23"]を返します。

使用可能な数字体系

getNumberingSystems()メソッドは、ロケールで一般的に使用される数字体系を返します。

const locale = new Intl.Locale("ar-EG");
const numberingSystems = locale.getNumberingSystems();
console.log(numberingSystems); // ["arab", "latn"]

アラビア語のロケールは、アラビア・インド数字とラテン数字の両方をサポートすることがよくあります。

テキストの方向

getTextInfo()メソッドはテキストの並び順情報を返します:

const locale = new Intl.Locale("ar-SA");
const textInfo = locale.getTextInfo();
console.log(textInfo.direction); // "rtl"

アラビア語やヘブライ語などの右から左へ記述する言語は"rtl"を返します。左から右へ記述する言語は"ltr"を返します。

週の規則

getWeekInfo()メソッドはロケールの週構造を返します:

const locale = new Intl.Locale("en-US");
const weekInfo = locale.getWeekInfo();
console.log(weekInfo.firstDay); // 7 (Sunday)
console.log(weekInfo.weekend); // [6, 7] (Saturday, Sunday)
console.log(weekInfo.minimalDays); // 1

週の規則は地域によって異なります。アメリカの週は日曜日から始まりますが、ヨーロッパのほとんどの週は月曜日から始まります。

タイムゾーン

getTimeZones()メソッドはロケールの地域のタイムゾーンを返します:

const locale = new Intl.Locale("en-US");
const timeZones = locale.getTimeZones();
console.log(timeZones); // ["America/New_York", "America/Chicago", ...]

このメソッドは地域コードのIANAタイムゾーン識別子を返します。

ロケール識別子の最大化

maximize()メソッドは、可能性の高いサブタグを追加して完全な識別子を作成します。言語データに基づいて、欠落している文字体系と地域コードを推測します。

言語コードのみを指定した場合、maximize()は最も一般的な文字体系と地域を追加します:

const locale = new Intl.Locale("en");
const maximized = locale.maximize();
console.log(maximized.baseName); // "en-Latn-US"

英語は、最も一般的な関連付けであるため、ラテン文字体系とアメリカ合衆国地域がデフォルトになります。

中国語の最大化は文字体系によって異なります:

const simplified = new Intl.Locale("zh-Hans");
const maximized = simplified.maximize();
console.log(maximized.baseName); // "zh-Hans-CN"

const traditional = new Intl.Locale("zh-Hant");
const maximizedTrad = traditional.maximize();
console.log(maximizedTrad.baseName); // "zh-Hant-TW"

簡体字中国語は中国と関連付けられ、繁体字中国語は台湾と関連付けられます。

ユーザー入力を正規化する場合やロケール識別子を比較する場合は、maximize()を使用してください。暗黙的な情報を明示的にします。

ロケール識別子の最小化

minimize()メソッドは、冗長なサブタグを削除して最短の同等の識別子を作成します。文字体系と地域コードが可能性の高いデフォルトと一致する場合、それらを削除します。

ロケールがデフォルトの文字体系と地域を使用している場合、minimize()はそれらを削除します:

const locale = new Intl.Locale("en-Latn-US");
const minimized = locale.minimize();
console.log(minimized.baseName); // "en"

ラテン文字体系とアメリカ合衆国地域は英語のデフォルトであるため、情報を失うことなく削除できます。

デフォルト以外の地域を持つロケールの場合、minimize()は地域を保持します:

const locale = new Intl.Locale("en-Latn-GB");
const minimized = locale.minimize();
console.log(minimized.baseName); // "en-GB"

イギリス英語はデフォルトと異なるため、地域コードが必要です。

minimize()を使用して、意味を保持しながらストレージやURLのためのコンパクトな識別子を作成します。

文字列への変換

toString()メソッドは、拡張を含む完全なロケール識別子を返します:

const locale = new Intl.Locale("en-US", {
  calendar: "gregory",
  numberingSystem: "latn",
  hourCycle: "h12"
});

console.log(locale.toString()); // "en-US-u-ca-gregory-hc-h12-nu-latn"

文字列表現は、他のIntl APIに渡したり、設定データとして保存したりするのに有効です。

ロケールオブジェクトを暗黙的に文字列に変換することもできます:

const locale = new Intl.Locale("fr-FR");
const formatter = new Intl.DateTimeFormat(locale);

DateTimeFormatコンストラクタはロケールオブジェクトを直接受け入れ、内部的にtoString()を呼び出します。

実用的なユースケース

Intl.Locale APIは、国際化されたアプリケーションを構築する際のいくつかの一般的な問題を解決します。

ロケールセレクタの構築

ロケールセレクタを使用すると、ユーザーは言語と地域を選択できます。Intl.Locale APIは、ユーザーの選択を解析および検証するのに役立ちます:

function createLocaleSelector(locales) {
  const options = locales.map(identifier => {
    const locale = new Intl.Locale(identifier);
    const displayName = new Intl.DisplayNames([identifier], { type: "language" });

    return {
      value: locale.toString(),
      label: displayName.of(locale.language),
      region: locale.region
    };
  });

  return options;
}

const options = createLocaleSelector(["en-US", "en-GB", "fr-FR", "es-MX"]);
console.log(options);
// [
//   { value: "en-US", label: "English", region: "US" },
//   { value: "en-GB", label: "English", region: "GB" },
//   { value: "fr-FR", label: "French", region: "FR" },
//   { value: "es-MX", label: "Spanish", region: "MX" }
// ]

ロケール入力の検証

ユーザー入力や設定ファイルからロケール識別子を受け入れる場合は、使用前に検証します:

function validateLocale(identifier) {
  try {
    const locale = new Intl.Locale(identifier);
    return {
      valid: true,
      locale: locale.toString(),
      language: locale.language,
      region: locale.region
    };
  } catch (error) {
    return {
      valid: false,
      error: error.message
    };
  }
}

console.log(validateLocale("en-US")); // { valid: true, locale: "en-US", ... }
console.log(validateLocale("invalid")); // { valid: false, error: "..." }

フォールバック用の言語の抽出

言語フォールバックチェーンを実装する場合、地域なしで言語コードを抽出します:

function getLanguageFallback(identifier) {
  const locale = new Intl.Locale(identifier);
  const fallbacks = [locale.toString()];

  if (locale.region) {
    const languageOnly = new Intl.Locale(locale.language);
    fallbacks.push(languageOnly.toString());
  }

  fallbacks.push("en");

  return fallbacks;
}

console.log(getLanguageFallback("fr-CA"));
// ["fr-CA", "fr", "en"]

これにより、特定のロケール、次に地域なしの言語、次にデフォルト言語を試すフォールバックチェーンが作成されます。

フォーマッタの設定

ロケールオブジェクトを使用して、特定の設定でIntlフォーマッタを設定します:

function createFormatter(baseLocale, options = {}) {
  const locale = new Intl.Locale(baseLocale, {
    calendar: options.calendar || "gregory",
    numberingSystem: options.numberingSystem || "latn",
    hourCycle: options.hourCycle || "h23"
  });

  return {
    date: new Intl.DateTimeFormat(locale),
    number: new Intl.NumberFormat(locale),
    locale: locale.toString()
  };
}

const formatter = createFormatter("ar-SA", {
  calendar: "islamic",
  numberingSystem: "arab"
});

console.log(formatter.locale); // "ar-SA-u-ca-islamic-nu-arab"

ユーザー設定の検出

ブラウザAPIは、ユーザー設定を理解するために解析できるロケール文字列を提供します。

function getUserPreferences() {
  const userLocale = new Intl.Locale(navigator.language);
  const hourCycles = userLocale.getHourCycles();
  const calendars = userLocale.getCalendars();
  const textInfo = userLocale.getTextInfo();

  return {
    language: userLocale.language,
    region: userLocale.region,
    preferredHourCycle: hourCycles[0],
    preferredCalendar: calendars[0],
    textDirection: textInfo.direction
  };
}

const preferences = getUserPreferences();
console.log(preferences);
// { language: "en", region: "US", preferredHourCycle: "h12", ... }

これにより、ブラウザ設定に基づいたユーザー設定のプロファイルが作成されます。

ブラウザサポート

Intl.Locale APIは、すべてのモダンブラウザで動作します。Chrome、Firefox、Safari、Edgeは、このガイドで説明されているコンストラクタ、プロパティ、メソッドを完全にサポートしています。

getCalendars()getCollations()getHourCycles()getNumberingSystems()getTextInfo()getTimeZones()getWeekInfo()などの新しいメソッドは、最新のブラウザバージョンが必要です。古いブラウザをサポートする場合は、これらのメソッドを使用する前にブラウザ互換性テーブルを確認してください。

Node.jsは、バージョン12からIntl.Locale APIをサポートしており、バージョン18以降ではすべてのメソッドを完全にサポートしています。

まとめ

Intl.Locale APIは、ロケール識別子文字列を検査および操作可能な構造化オブジェクトに変換します。文字列を手動で解析する代わりに、ロケールオブジェクトを作成してそのプロパティを読み取ります。

主要な概念:

  • ロケール識別子には、言語、文字体系、地域、拡張コンポーネントが含まれます
  • Intl.Localeコンストラクタは識別子を検証してオブジェクトを作成します
  • languageregioncalendarなどのプロパティは構造化されたアクセスを提供します
  • getCalendars()getHourCycles()などのメソッドは利用可能なオプションを返します
  • maximize()およびminimize()メソッドは識別子を正規化します
  • ロケールオブジェクトは他のIntl APIと直接連携します

ロケールセレクタの構築、ユーザー入力の検証、フォールバックチェーンの実装、またはフォーマッタの設定を行う際には、Intl.Locale APIを使用してください。これは、JavaScriptアプリケーションでロケール識別子を扱うための標準的な方法を提供します。