JavaScriptの数値フォーマット完全ガイド:Intl.NumberFormatで国際化対応
📷 Antoine Dautry / PexelsJavaScriptの数値フォーマット完全ガイド:Intl.NumberFormatで国際化対応
Intl.NumberFormat APIを使って、ロケールに対応した数値・通貨・パーセントの表示を実装する方法を解説します。国際化対応の実践的なJavaScriptコード例も紹介。
Webアプリを国際展開するとき、数値の表示が思わぬ問題を引き起こすことがあります。「なぜドイツのユーザーから数字がおかしいと言われるんだろう?」と首をかしげた経験は、多くの開発者が持っているはずです。
実は日本では1,234,567.89(カンマが桁区切り、ピリオドが小数点)が当たり前ですが、ドイツでは1.234.567,89(ピリオドが桁区切り、カンマが小数点)が標準です。金融系アプリでこれを間違えると、ユーザーに深刻な混乱を与えかねません。
この記事では、JavaScriptのIntl.NumberFormat APIを使って数値フォーマットを正しく実装する方法を、実際のコード例とともに解説します。
国によって数値の表記が異なる問題
数値1234567.89を世界各地の慣習に従って表示すると:
- 日本 / アメリカ:
1,234,567.89(カンマが桁区切り、ピリオドが小数点) - ドイツ / オーストリア:
1.234.567,89(ピリオドが桁区切り、カンマが小数点) - フランス:
1 234 567,89(スペースが桁区切り、カンマが小数点) - スイス:
1'234'567.89(アポストロフィが桁区切り) - インド:
12,34,567.89(3桁+2桁グルーピング)
こういった違いを自前の文字列操作で対処しようとすると、例外ケースが無限に出てきます。JavaScriptにはIntl.NumberFormatという強力なAPIがあるので、それを活用しましょう。
Intl.NumberFormatの基本
Intl名前空間はES2015から導入された国際化APIのコレクションです。Intl.NumberFormatはその中で数値フォーマットを担当します。
// 基本的な使い方
const formatter = new Intl.NumberFormat('ja-JP');
formatter.format(1234567.89);
// "1,234,567.89"
// ドイツ語ロケール
new Intl.NumberFormat('de-DE').format(1234567.89);
// "1.234.567,89"
// フランス語ロケール
new Intl.NumberFormat('fr-FR').format(1234567.89);
// "1 234 567,89"
// ヒンディー語(インド)
new Intl.NumberFormat('hi-IN').format(1234567.89);
// "12,34,567.89"
ロケールを変えるだけで、各国の表記規則が自動的に適用されます。日本語ロケールはアメリカと同じ方式なので変化がありませんが、他の国では明確な違いが出ます。
小数点以下の桁数を制御する
// 常に小数点以下2桁を表示
new Intl.NumberFormat('ja-JP', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(1234.5);
// "1,234.50"
// 最大3桁まで、末尾の0は削除
new Intl.NumberFormat('ja-JP', {
minimumFractionDigits: 0,
maximumFractionDigits: 3
}).format(1234.5);
// "1,234.5"
桁区切りを無効にする
年号やIDなど、桁区切りが不要な場合:
new Intl.NumberFormat('ja-JP', {
useGrouping: false
}).format(2024);
// "2024"("2,024"にならない)
通貨フォーマット
通貨表示はIntl.NumberFormatが最も力を発揮する場面です。通貨ごとに小数点以下の桁数が異なり(円は0桁、ドルは2桁)、記号の位置も異なります。
// 日本円
new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
}).format(1234);
// "¥1,234"(小数点なし)
// 米ドル
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(1234.56);
// "$1,234.56"
// ユーロ(ドイツ式)
new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
}).format(1234.56);
// "1.234,56 €"
// 韓国ウォン
new Intl.NumberFormat('ko-KR', {
style: 'currency',
currency: 'KRW'
}).format(1234567);
// "₩1,234,567"
重要なポイント: currencyオプション(通貨の種類)とロケール(表示形式)は独立しています。日本語ロケールでUSDを表示することも可能です:
new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'USD'
}).format(1234.56);
// "$1,234.56"
通貨の表示方法を選ぶ
const amount = 1234.56;
// 記号で表示(デフォルト)
new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol'
}).format(amount);
// "$1,234.56"
// ISOコードで表示
new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'code'
}).format(amount);
// "USD 1,234.56"
// 通貨名を表示
new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'name'
}).format(amount);
// "1,234.56 米ドル"
currencyDisplay: 'name'を日本語ロケールで使うと「米ドル」と日本語で表示されます。これはIntl APIの強みです。
注意点: 円(JPY)や韓国ウォン(KRW)など、サブユニットがない通貨はcurrencyスタイルで使用すると小数点以下が表示されません。小数点以下の値を渡すと自動的に四捨五入されます。
パーセントフォーマット
パーセント表示には落とし穴があります:
// 注意:小数として渡す(0.75 = 75%)
new Intl.NumberFormat('ja-JP', {
style: 'percent'
}).format(0.75);
// "75%"
// 小数点以下1桁
new Intl.NumberFormat('ja-JP', {
style: 'percent',
minimumFractionDigits: 1,
maximumFractionDigits: 1
}).format(0.7523);
// "75.2%"
// ドイツ語ロケール
new Intl.NumberFormat('de-DE', {
style: 'percent'
}).format(0.75);
// "75 %" (%の前にスペースが入る)
よくあるミス: percentスタイルは入力値を100倍します。75を渡すと7500%になります。パーセント値(75)をそのまま持っている場合は必ず100で割って渡してください:
const percentValue = 75;
new Intl.NumberFormat('ja-JP', {
style: 'percent'
}).format(percentValue / 100);
// "75%"
このミスは実際のプロジェクトで何度か見かけました。ドキュメントを確認して確実に対処しましょう。
科学的表記法
科学・工学系の計算結果を表示する場合:
new Intl.NumberFormat('ja-JP', {
notation: 'scientific'
}).format(1234567890);
// "1.235E9"
new Intl.NumberFormat('ja-JP', {
notation: 'engineering'
}).format(1234567890);
// "1.235E9"
コンパクト表記(万・億単位)
ダッシュボードや統計表示でよく使われる機能です。日本語ロケールでは万・億などの単位が使われます:
// 日本語ロケール
new Intl.NumberFormat('ja-JP', {
notation: 'compact'
}).format(10000);
// "1万"
new Intl.NumberFormat('ja-JP', {
notation: 'compact'
}).format(35000000);
// "3500万"
new Intl.NumberFormat('ja-JP', {
notation: 'compact'
}).format(1000000000);
// "10億"
// 英語ロケール
new Intl.NumberFormat('en-US', {
notation: 'compact'
}).format(1200);
// "1.2K"
// 中国語ロケール
new Intl.NumberFormat('zh-CN', {
notation: 'compact'
}).format(10000);
// "1万"
日本語・中国語の慣習通り、万・億単位が自動的に適用されます。これを自前で実装しようとすると意外と面倒なので、ありがたい機能です。
よくある落とし穴
NaNとInfinityの扱い:
new Intl.NumberFormat('ja-JP').format(NaN);
// "NaN"
new Intl.NumberFormat('ja-JP').format(Infinity);
// "∞"
ユーザーにNaNや∞をそのまま見せるのは良くないので、フォーマット前にバリデーションをしましょう。
パフォーマンスの最適化: Intl.NumberFormatのインスタンス生成にはコストがかかります。同じ設定で大量の数値をフォーマットする場合はインスタンスを再利用してください:
// 非効率
numbers.forEach(n => new Intl.NumberFormat('ja-JP').format(n));
// 効率的
const formatter = new Intl.NumberFormat('ja-JP');
numbers.forEach(n => formatter.format(n));
formatToParts()の活用: フォーマットされた数値の各部分を個別に操作したい場合に便利です:
new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
}).formatToParts(1234);
// [
// { type: 'currency', value: '¥' },
// { type: 'integer', value: '1' },
// { type: 'group', value: ',' },
// { type: 'integer', value: '234' }
// ]
Reactで通貨記号に特別なスタイルを適用するときに役立ちます。
Intl.NumberFormatの制限
正直に言うと、このAPIにも限界があります:
- 数値の解析(逆方向): ロケール形式の文字列を数値に戻す機能がありません。
"1.234,56"を1234.56に変換するには自前で実装が必要です。 - カスタムフォーマット文字列: Excelの
#,##0.00のようなカスタム書式は対応していません。そういった要件にはnumeral.jsのようなライブラリが適しています。 - 会計形式: マイナスを
(1,234.56)で表示する会計スタイルはcurrencySign: 'accounting'で部分的に対応しますが、完全ではありません。
通常のWebアプリのユースケースであれば、Intl.NumberFormatでほとんどカバーできます。
Number Formatterツールの活用
コードを書かずに様々な書式オプションを試してみたい場合は、ToolBox HubのNumber Formatterツールが便利です。
- フォーマットしたい数値を入力
- ロケールを選択(30以上のロケールに対応)
- スタイルを選択(decimal、currency、percent、scientific)
- 通貨を選択するとその通貨記号で表示
- 小数点以下の桁数を設定
- 桁区切りの使用有無を選択
- 結果をリアルタイムで確認、JavaScriptコードをコピー可能
見慣れないロケールで数値がどう見えるか事前に確認するのに役立ちます。
関連ツール
数値処理に役立つその他のツール:
まとめ
Intl.NumberFormatはJavaScript標準ライブラリの中でもよく設計されたAPIの一つです。表面上はシンプルに見えますが、通貨・パーセント・コンパクト表記など、実用的な機能が豊富に揃っています。
重要なポイントをまとめると:
- ユーザー向けの数値は必ず
Intl.NumberFormatでフォーマットする - 通貨コードとロケールは独立した設定が可能
percentスタイルは100倍されるので、小数形式で渡す- 日本語では
compact表記で万・億単位が自動対応 - 繰り返しフォーマットする場合はインスタンスを再利用
ユーザーが日々目にする数値を適切にフォーマットすることは、アプリの信頼性と使いやすさを高める重要な要素です。Intl.NumberFormatを使いこなして、世界中のユーザーに快適な体験を提供しましょう。