JavaScriptのIntlで多言語・多通貨対応

React Native Expo アプリの多言語化で JavaScript ライブラリの Intl を利用しました。Intl で多言語/多通貨対応するためには、ロケール情報を理解するとともに、Intl のパラメータとして指定する通貨コードをロケールから導き出す必要があります。ここでは、「ロケール」について説明しつつ、ロケールと通貨コードをどのようにマッピングしたかご説明します。

JavaScript の Intl オブジェクトとは

Intl オブジェクトは JavaScript の標準組み込みオブジェクトで、ウェブサイトを多言語化する際に使えます。特に、数値や日付は国によって表記が異なります。自力で対応するよりもライブラリを使いたいところです。

Intl - JavaScript | MDN

Intl オブジェクトは、 ECMAScript の国際化 API の名前空間で、言語に依存した文字列の比較、数値フォーマット、日付フォーマットを提供します。

数値をフォーマットしてくれる Intl.NumberFormat を使う場合、Intl オブジェクトにロケールの文字列と数値を渡すことで、ロケールごとに適切なフォーマットに数値を変換してくれます。例えば、日本ではカンマを 1,000 の区切り文字、ドットを小数点数の区切り文字として使いますが、ドイツではカンマとドットが逆になります。

Intl.NumberFormat - JavaScript | MDN

var number = 123456.789;

// ドイツではカンマを小数、ピリオドを千単位の区切りに用います
console.log(new Intl.NumberFormat("de-DE").format(number));
// → 123.456,789

ロケールとは

Intl オブジェクトの関数に渡すロケールは、言語と地域を表現する文字列です。例えばja-jpは、言語が日本語ja、地域(国)が日本jpであることを意味します。en-jpなら言語が英語en、地域が日本jpになります。

言語は地域と必ずしも紐づきません。日本では使われている言語が日本語のみなのであまり意識しませんが、海外では複数の言葉が使われている国は珍しくありません。例えば、日本にいるけど母語は英語なので、言語は英語を使いたいという方はいるはずです。

通貨をパラメータとして用意する

Intl.NumberFormat は数値だけでなく、通貨も扱うことができます。ただし、通貨を整形する場合には currency をパラメータとして与える必要があります。

Intl.NumberFormat - JavaScript | MDN

// 通貨フォーマットを用います
console.log(new Intl.NumberFormat(‘de-DE, { style: ‘currency’, currency:EUR}).format(number));
// → 123.456,79 €

通貨は地域(国)と紐づきます。地域で使われている主な通貨は、スマホ利用者の母語がどの言語なのかに影響しません。海外旅行するときには、旅行先の地域で使われている通貨に両替することになります。

しかし、通貨と地域は 1 対 1 ではありません。例えばユーロは EU 加盟国それぞれで使われています。どの通過を使うべきなのかロケール情報だけでは判断できないため、ロケールと通過を紐づける必要が出てきます。

ISO 4217 通貨コードとロケールを紐づける

通貨はISO 4217通貨コードとして標準化されています。以下の Wikipedia ページに「有効な ISO 4217 通貨コード」の表が掲載されています。これを参照することで通貨コードと国を紐づけられます。

ISO 4217 - Wikipedia

ISO 4217 は、1978 年に国際標準化機構(ISO)が発行した国際規格で、各種の通貨を表すコードについて規定している。一般に通貨コードと呼ばれる。 (中略) 最初の 2 文字は ISO 3166-1 alpha-2 で定義された国名コードであり、残りの 1 文字は通貨名の頭文字である。例えば日本円の通貨名コードは、日本の国別コードが"JP"で、円(yen)の頭文字が"Y"であることから、"JPY"となる。この仕組みにより、ドルやフランあるいはポンドなど、多くの国で同じ名前の通貨が使われていても、別のコードを割り当てることができる。

ISO 3166-1 - Wikipedia

ISO 3166-1 は、ISO によって発行されている ISO 3166 の第一の部分で国名コードの標準。日本では JIS X 0304 として標準化されている。

ロケールの地域と通貨コードをマッピングした情報をアプリに持たせます。ロケールの文字列から対応する通貨コードを取得して Intl オブジェクトの関数に渡すことで、多通貨対応が可能になります。