ロケール固有の記号で通貨をフォーマットする方法

あらゆるロケールに対応した正確な通貨記号、位置、フォーマットで価格を表示する

はじめに

通貨記号は価格がどの通貨を表しているかを識別します。ドル記号は米ドル、ユーロ記号はユーロ、ポンド記号は英国ポンドを示します。これらの記号は国際的なアプリケーションにとって不可欠です。なぜなら、ユーザーは自分が閲覧または使用している通貨を知る必要があるからです。

国によって通貨金額の表記方法は異なります。アメリカ人は$1,234.56のように記号を金額の前に書きます。ドイツ人は1.234,56 €のように記号を金額の後ろに置き、区切り文字も異なります。フランスの表記法では1 234,56 €のように桁区切りにスペースを使用します。"$" + amountのように通貨の書式をハードコードすると、すべてのユーザーが同じ規則に従っていると仮定することになります。

JavaScriptはIntl.NumberFormat APIを提供しており、ロケールに適した記号と規則で通貨金額をフォーマットできます。このレッスンでは、通貨のフォーマットがロケールによってどのように異なるか、そしてあらゆる言語や地域に対して価格を正しくフォーマットする方法について説明します。

通貨記号はロケールによって異なる

異なる通貨は異なる記号を使用します。米ドルは$、ユーロは€、英国ポンドは£、日本円は¥、スイスフランは文脈によってFr.またはCHFを使用します。各記号はユーザーが閲覧している通貨を素早く識別するのに役立ちます。

一部の記号は複数の通貨を表します。ドル記号$は米ドル、カナダドル、オーストラリアドル、メキシコペソなど、いくつかの通貨に使用されます。追加の文脈がなければ、ユーザーは価格がどのドル通貨を表しているのか判断できません。

通貨記号の位置はロケールによって異なります。英語圏の国々は通常、$100のように記号を金額の前に配置します。多くのヨーロッパ諸国では100 €のように記号を金額の後ろに配置します。国によっては金額と記号の間にスペースを入れるところもあれば、そうでないところもあります。

これらの違いは、単に記号と数字を連結するだけではいけないことを意味します。表示される通貨とそれを閲覧するユーザーのロケールの両方を理解するフォーマットロジックが必要です。

Intl.NumberFormatで通貨をフォーマットする

Intl.NumberFormatコンストラクタは、オプションでstyle: 'currency'を渡すと通貨フォーマッタを作成します。また、ISO 4217通貨コードを使用してcurrencyオプションでフォーマットする通貨を指定する必要があります。

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

console.log(formatter.format(1234.56));
// 出力: "$1,234.56"

これにより、米ドルで金額を表示する米国英語用のフォーマッタが作成されます。format()メソッドは、数値をドル記号、桁区切り記号、小数点以下2桁を含む文字列に変換します。

currencyオプションには、3文字のISO 4217コードが必要です。一般的なコードには、米ドル用のUSD、ユーロ用のEUR、英ポンド用のGBP、日本円用のJPY、カナダドル用のCADなどがあります。

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

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

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

console.log(usdFormatter.format(100));
// 出力: "$100.00"

console.log(eurFormatter.format(100));
// 出力: "€100.00"

console.log(gbpFormatter.format(100));
// 出力: "£100.00"

各フォーマッタは適切な通貨記号を自動的に挿入します。各通貨コードに対応する記号を知る必要はありません。

ロケールによって記号の位置とフォーマットが決まる

ロケールパラメータは、記号の位置、数字のグループ化、小数点区切り文字など、通貨金額のフォーマット方法を制御します。同じ通貨コードでもロケールによって異なる出力が生成されます。

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

const deFormatter = new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
});

const frFormatter = new Intl.NumberFormat('fr-FR', {
  style: 'currency',
  currency: 'EUR'
});

console.log(usFormatter.format(1234.56));
// 出力: "€1,234.56"

console.log(deFormatter.format(1234.56));
// 出力: "1.234,56 €"

console.log(frFormatter.format(1234.56));
// 出力: "1 234,56 €"

3つのフォーマッタはすべてユーロを表示しますが、それぞれ異なる規則を使用します。米国英語のフォーマッタは記号を金額の前に配置し、小数点区切りにピリオドを使用します。ドイツのフォーマッタは記号を金額の後にスペースを入れて配置し、桁区切りにピリオドを使用し、小数点区切りにカンマを使用します。フランスのフォーマッタは桁区切りにスペースを使用します。

Intl APIは指定したロケールに基づいてこれらの違いを自動的に処理します。各ロケールのフォーマットルールを知る必要はありません。

通貨フォーマットには小数点以下の桁数が含まれます

通貨フォーマッタは通貨に基づいて適切な小数点以下の桁数を自動的に決定します。ほとんどの通貨はセントまたは同等の端数に対して小数点以下2桁を使用します。

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

console.log(formatter.format(100));
// 出力: "$100.00"

console.log(formatter.format(100.5));
// 出力: "$100.50"

console.log(formatter.format(100.567));
// 出力: "$100.57"

フォーマッタは米ドルに対して常に小数点以下2桁を表示し、必要に応じてゼロで埋め、入力の精度が高い場合は四捨五入します。

一部の通貨には小数点以下の桁数がありません。日本円には端数単位がないため、金額は小数点以下なしで表示されます。

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

console.log(formatter.format(1234.56));
// 出力: "¥1,235"

円の金額には端数単位が含まれないため、フォーマッタは最も近い整数に四捨五入します。Intl APIは各通貨の小数点精度を認識し、自動的に適用します。

ユーザーのロケールに合わせた通貨フォーマット

特定のロケールをハードコーディングする代わりに、ユーザーのブラウザ言語設定を使用できます。navigator.languageプロパティはユーザーの優先ロケールを返します。

const userLocale = navigator.language;

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

console.log(formatter.format(1234.56));
// 出力はユーザーのロケールによって異なります
// en-USの場合: "$1,234.56"
// de-DEの場合: "1.234,56 $"
// fr-FRの場合: "1 234,56 $US"

このアプローチでは、各ユーザーのフォーマット期待に従って通貨金額を表示します。ドイツのユーザーはドイツの区切り記号を使用して金額の後に記号を見るのに対し、アメリカのユーザーはアメリカの区切り記号を使用して金額の前に記号を見ます。

ユーザーの最優先設定が利用できない場合のフォールバック動作を有効にするために、navigator.languages配列全体を渡すこともできます。

const formatter = new Intl.NumberFormat(navigator.languages, {
  style: 'currency',
  currency: 'USD'
});

console.log(formatter.format(1234.56));

APIは配列からサポートする最初のロケールを使用し、自動フォールバック処理を提供します。

通貨フォーマッターの再利用

新しいIntl.NumberFormatインスタンスを作成すると、ロケールデータの読み込みとオプションの処理が行われます。同じロケールと通貨で複数の価格をフォーマットする場合は、フォーマッターを一度作成して再利用しましょう。

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

const prices = [19.99, 29.99, 49.99, 99.99];

prices.forEach(price => {
  console.log(formatter.format(price));
});
// 出力:
// "$19.99"
// "$29.99"
// "$49.99"
// "$99.99"

このパターンは、価格ごとに新しいフォーマッターを作成するよりも効率的です。多くの値を持つ配列やリストをフォーマットする場合、パフォーマンスの差は顕著になります。

アプリケーションでの価格表示

通貨フォーマッターは、ユーザーに価格を表示するあらゆる場所で使用できます。これには、商品リスト、ショッピングカート、チェックアウトページ、請求書、財務ダッシュボードなどが含まれます。

const formatter = new Intl.NumberFormat(navigator.language, {
  style: 'currency',
  currency: 'USD'
});

const productPrice = 29.99;
const taxAmount = 2.40;
const totalPrice = productPrice + taxAmount;

document.getElementById('product-price').textContent = formatter.format(productPrice);
document.getElementById('tax-amount').textContent = formatter.format(taxAmount);
document.getElementById('total-price').textContent = formatter.format(totalPrice);

フォーマットされた文字列は他の文字列値と同様に機能します。テキストコンテンツ、属性、またはユーザーに情報を表示するあらゆるコンテキストに挿入できます。

複数通貨の取り扱い

複数の通貨をサポートするアプリケーションでは、通貨ごとに個別のフォーマッターを作成する必要があります。通貨コードによって表示される記号が決まり、ロケールによって金額のフォーマット方法が決まります。

const locale = navigator.language;

const usdFormatter = new Intl.NumberFormat(locale, {
  style: 'currency',
  currency: 'USD'
});

const eurFormatter = new Intl.NumberFormat(locale, {
  style: 'currency',
  currency: 'EUR'
});

const gbpFormatter = new Intl.NumberFormat(locale, {
  style: 'currency',
  currency: 'GBP'
});

console.log(usdFormatter.format(100));
console.log(eurFormatter.format(100));
console.log(gbpFormatter.format(100));

各フォーマッターは適切な記号を表示し、その通貨に対するユーザーのロケール規則に従います。これにより、どの通貨やロケールの組み合わせを使用しても、価格が正確で読みやすいことが保証されます。