フォーマッターが実際に使用しているロケールとオプションを確認するにはどうすればよいですか?

resolvedOptions()メソッドを使用して、任意のIntlフォーマッターの実際の構成を調査する

はじめに

JavaScriptでIntlフォーマッターを作成する際、リクエストしたオプションが常に取得するオプションとは限りません。ブラウザはロケールのネゴシエーションを実行し、デフォルト値を埋め、設定を正規化して最終的な構成を作成します。resolvedOptions()メソッドを使用すると、フォーマッターが実際に使用している内容を正確に調査できます。

Intl APIのすべてのフォーマッターにはresolvedOptions()メソッドがあります。これにはIntl.DateTimeFormatIntl.NumberFormatIntl.ListFormatIntl.PluralRulesIntl.Collatorなどが含まれます。このメソッドは、入力を処理した後にフォーマッターが最終的に持つすべての構成詳細を含むオブジェクトを返します。

このメソッドは主にデバッグ、ブラウザの動作の理解、および現在の環境で利用可能な機能の検出に役立ちます。

基本的な構文

resolvedOptions()メソッドはパラメータを取りません。任意のフォーマッターインスタンスで呼び出すと、オブジェクトを返します。

const formatter = new Intl.DateTimeFormat('en-US');
const options = formatter.resolvedOptions();

console.log(options);
// {
//   locale: 'en-US',
//   calendar: 'gregory',
//   numberingSystem: 'latn',
//   timeZone: 'America/Los_Angeles',
//   ...
// }

返されるオブジェクトには、日付フォーマッターの場合は最低限localecalendarnumberingSystemプロパティが、数値フォーマッターの場合はlocalenumberingSystemが常に含まれます。追加のプロパティは、指定したオプションとフォーマッタータイプがサポートする内容によって異なります。

リクエストされたオプションが解決されたオプションと異なる理由

リクエストしたオプションが解決されたオプションと異なる主な理由は3つあります。

第一に、ロケールネゴシエーションは、正確なリクエストがサポートされていない場合に利用可能な最適なロケールを見つけます。de-ATをリクエストしても、ブラウザがdeしか持っていない場合、解決されるロケールはdeになります。

const formatter = new Intl.DateTimeFormat('de-AT-u-ca-buddhist');
const options = formatter.resolvedOptions();

console.log(options.locale);
// おそらく出力: 'de-AT'または'de'

console.log(options.calendar);
// おそらく出力: 'gregory'(仏教暦がサポートされていない場合)

第二に、ブラウザは指定しなかったオプションにデフォルト値を設定します。これらのデフォルトはロケール固有です。

const formatter = new Intl.NumberFormat('en-US');
const options = formatter.resolvedOptions();

console.log(options.style);
// 出力: 'decimal'

console.log(options.minimumFractionDigits);
// 出力: 0

console.log(options.maximumFractionDigits);
// 出力: 3

第三に、ブラウザは特定のオプションを正規形式に正規化します。dateStyletimeStyleを使用する場合、ブラウザはこれらを解決されたオプションに含めません。代わりに、それらが展開される個々のコンポーネントオプションが含まれます。

使用されている実際のロケールを確認する

locale プロパティは、フォーマッターが使用している正確なロケールを示します。これはロケールネゴシエーションの結果です。

const formatter = new Intl.DateTimeFormat(['zh-TW', 'zh-CN', 'en-US']);
const options = formatter.resolvedOptions();

console.log(options.locale);
// リストから最初にサポートされているロケールを出力

Unicodeの拡張キーワードを含むロケールをリクエストした場合、それらのキーワードがサポートされていないか、別のオプションとして適用された場合、解決されたロケールにはそれらのキーワードが含まれない可能性があります。

const formatter = new Intl.NumberFormat('en-US-u-nu-arab');
const options = formatter.resolvedOptions();

console.log(options.locale);
// 出力例: 'en-US'

console.log(options.numberingSystem);
// サポート状況に応じて 'arab' または 'latn' を出力

日付と時刻のフォーマットオプションを検査する

Intl.DateTimeFormat の場合、解決されたオプションには、表示される日付と時刻のコンポーネントとその表示方法に関する詳細が含まれます。

const formatter = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  timeZone: 'America/New_York'
});

const options = formatter.resolvedOptions();

console.log(options.year);
// 出力: 'numeric'

console.log(options.month);
// 出力: 'long'

console.log(options.day);
// 出力: 'numeric'

console.log(options.timeZone);
// 出力: 'America/New_York'

console.log(options.calendar);
// 出力: 'gregory'

dateStyle または timeStyle を使用する場合、これらのショートカットは解決されたオプションには含まれません。ブラウザはロケールに基づいて個々のコンポーネントオプションに展開します。

const formatter = new Intl.DateTimeFormat('en-US', {
  dateStyle: 'full'
});

const options = formatter.resolvedOptions();

console.log(options.dateStyle);
// 出力: undefined

console.log(options.weekday);
// 出力: 'long'

console.log(options.year);
// 出力: 'numeric'

console.log(options.month);
// 出力: 'long'

console.log(options.day);
// 出力: 'numeric'

オプションを全く指定せずに日付フォーマッターを作成すると、解決されたオプションはブラウザがそのロケールのデフォルトとして選択したものを示します。

const formatter = new Intl.DateTimeFormat('ja-JP');
const options = formatter.resolvedOptions();

console.log(options);
// 日本語ロケールのデフォルトの日付コンポーネントオプションを表示

数値フォーマットオプションの検査

Intl.NumberFormatの場合、解決されたオプションはスタイル、精度、グループ化、その他のフォーマット詳細を示します。

const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

const options = formatter.resolvedOptions();

console.log(options.style);
// 出力: 'currency'

console.log(options.currency);
// 出力: 'USD'

console.log(options.currencyDisplay);
// 出力: 'symbol'

console.log(options.minimumFractionDigits);
// 出力: 2

console.log(options.maximumFractionDigits);
// 出力: 2

通貨のみを指定した場合でも、ブラウザがcurrencyDisplayや小数点以下の桁数にデフォルト値を設定していることがわかります。

丸めオプションを使用すると、解決されたオプションで数値がどのように丸められるかを正確に確認できます。

const formatter = new Intl.NumberFormat('en-US', {
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 5
});

const options = formatter.resolvedOptions();

console.log(options.minimumSignificantDigits);
// 出力: 3

console.log(options.maximumSignificantDigits);
// 出力: 5

その他のフォーマッタタイプの検査

resolvedOptions()メソッドはすべてのIntlフォーマッタで同じように機能します。

Intl.ListFormatの場合、タイプとスタイルが表示されます。

const formatter = new Intl.ListFormat('en-US', {
  style: 'long',
  type: 'conjunction'
});

const options = formatter.resolvedOptions();

console.log(options.locale);
// 出力: 'en-US'

console.log(options.style);
// 出力: 'long'

console.log(options.type);
// 出力: 'conjunction'

Intl.PluralRulesの場合、タイプと最小/最大桁数が表示されます。

const formatter = new Intl.PluralRules('en-US', {
  type: 'ordinal'
});

const options = formatter.resolvedOptions();

console.log(options.locale);
// 出力: 'en-US'

console.log(options.type);
// 出力: 'ordinal'

console.log(options.minimumIntegerDigits);
// 出力: 1

resolvedOptions()の一般的なユースケース

最も一般的なユースケースはデバッグです。フォーマットされた出力が期待通りに表示されない場合、resolvedOptions()はフォーマッタが実際に何をしているかを理解するのに役立ちます。

const formatter = new Intl.DateTimeFormat('en-US', {
  dateStyle: 'medium'
});

console.log(formatter.format(new Date()));
// 出力を確認

console.log(formatter.resolvedOptions());
// その出力を生成した正確なオプションを確認

もう一つのユースケースは機能検出です。特定のカレンダー、数字システム、またはその他の機能がサポートされているかどうかを、それをリクエストして実際に解決されたものを確認することで検証できます。

const formatter = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic'
});

const options = formatter.resolvedOptions();

if (options.calendar === 'islamic') {
  console.log('イスラム暦はサポートされています');
} else {
  console.log('イスラム暦はサポートされていません、' + options.calendar + 'を使用しています');
}

また、resolvedOptions()を使用してユーザーのロケール設定を取得することもできます。ロケール引数なしでフォーマッタを作成すると、ブラウザはユーザーの設定を使用します。

const formatter = new Intl.DateTimeFormat();
const options = formatter.resolvedOptions();

console.log(options.locale);
// 出力: ユーザーの優先ロケール

console.log(options.timeZone);
// 出力: ユーザーのタイムゾーン

console.log(options.hourCycle);
// 出力: ユーザーの時間表示設定(12時間制または24時間制)

最後に、解決されたオプションを使用して同一のフォーマッタを再作成できます。返されたオブジェクトはコンストラクタに渡すことができます。

const formatter1 = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

const options = formatter1.resolvedOptions();

const formatter2 = new Intl.NumberFormat(options.locale, options);

// formatter2はformatter1と同じように数値をフォーマットします

重要なポイント

resolvedOptions()メソッドは、フォーマッターが実際に使用している構成を含むオブジェクトを返します。この構成は、ロケールのネゴシエーション、デフォルト値、正規化により、リクエストした内容と異なる場合があります。

すべてのIntlフォーマッターにこのメソッドがあります。パラメータなしで呼び出すと、localecalendarnumberingSystem、およびフォーマッター固有のオプションなどのプロパティを持つオブジェクトを受け取ります。

resolvedOptions()は主にフォーマッターの動作のデバッグ、利用可能な機能の検出、ブラウザがオプションをどのように解釈したかを理解するために使用します。返されるオブジェクトは、同一のフォーマッターを再作成したり、ユーザー設定を調査したりするためにも使用できます。