2023/09/22
【JavaScriptのIntl】数字や日付、価格の表示をスマートに

ツイートのいいね数やコメント数、YouTubeの投稿日時、Amazonなどネットショップのレビュー数、通貨ごとの適切な価格表示など、UX(ユーザーエクスペリエンス)の向上やコンテンツや商品の競争力を高めるためには、これらの数字をユーザーが一目で理解できるようにすることが一つのポイントになります。
また、数字が非常に長い場合は、簡潔に表示する方が読みやすいです。さらに、ユーザーの使用言語や文化に合わせて、数字を適切に表示することが良いでしょう。
上のように数字、日付、価格を簡潔に表示するために、外部ライブラリを使用せずに、JavaScript標準仕様にあるIntl APIを使用するとより簡便に実装できます。
Intl API
Intl APIはinternationalization(国際化)APIの略で、下記はMDNからの引用です。
Intl
オブジェクトは、 ECMAScript の国際化 API の名前空間で、言語に依存した文字列の比較、数値の書式化と、日付の書式化を提供します。Intl
オブジェクトは、いくつかのコンストラクターに加え、国際化コンストラクターや他の言語に関する関数に共通する機能へのアクセスを提供します。
また、internationalizationは始めのiから終わりのnまでの間に18文字入っていることでi18nと呼ばれています。
ほとんどの最新のブラウザでサポートされているため、互換性を心配せずに使用できます。
では、いくつかの使い方を紹介します。
数字を簡潔に表示
Intl.NumberFormat
を使用します。
viewsに閲覧数を表す数字を入れています。このように大きな数字をそのまま表示すると読みにくくなります。
最初の引数には言語を指定するだけで良いので、日本語の場合はja-JP
を指定します。
const views = 9741275;
const formatter = new Intl.NumberFormat('ja-JP');
console.log(formatter.format(views)); // 9,741,234
より簡潔に表示するには、2番目の引数にさまざまなオプションを指定できます。オプションの中でnotation: 'compact'
を指定するとコンパクトになります。
const views = 9741275;
const formatter = new Intl.NumberFormat('ja-JP', {
notation: 'compact'
});
console.log(formatter.format(views)); // 974万
さらに、1番目の引数に言語ブラウザのAPIでサポートされているnavigator.language
を指定すると、ユーザーがブラウザで設定した言語を自動的に取得でき、ユーザーが指定した言語に応じて数字を表示できます。
const views = 9741234;
const formatter = new Intl.NumberFormat(navigator.language, {
notation: 'compact'
});
console.log(formatter.format(views)); // 974万
価格を通貨に合わせて簡潔に表示
同様にIntl.NumberFormat
を使用します。
1番目の引数には同じく言語を、2番目の引数のオプションでstyle: 'currency'
に設定し、currencyオプションで通貨currency: 'JPY'
を指定します。
const price = 1000000;
const formatter = new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
});
console.log(formatter.format(price)); // ¥1,000,000
ここでも"compact"オプションを使用してコンパクトにすることができます。compactオプションは価格よりはいいねの数など大体の数を表す時にいいかもしれません
const price = 1000000;
const formatter = new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY',
notation: 'compact'
});
console.log(formatter.format(price)); // ¥100万
相対時間をスマートに表示
商品や記事がいつ公開されたか、何日前、何時間前に投稿されたかを表す必要もあります。相対時間をスマートに表示するためにはIntl.RelativeTimeFormat
を使用します。
format
の1番目の引数は数字で、2番目には日付か時間か月かなどを指定します。
const formatter = new Intl.RelativeTimeFormat('ja-JP');
console.log(formatter.format(1, 'day')); // 1 日後
オプションにnumeric: 'auto'
にすると言葉を変えてくれます。
const formatter = new Intl.RelativeTimeFormat('ja-JP', {
numeric: 'auto'
});
console.log(formatter.format(1, 'day')); // 明日
入社して何日経ったかを示したい場合、今日を基準にして、入社日の日付を指定し、現在までの日数を計算し、フォーマッタを使用すると、"〜日前”と表示されます。
const today = new Date();
const startDate = new Date(2021, 4, 17); // 2021年5月17日 monthは0から始まるため5→4
const daysPassed = Math.ceil((startDate - today) / (1000 * 60 * 60 * 24));
const yearsPassed = Math.ceil((startDate - today) / (1000 * 60 * 60 * 24 * 365));
const formatter = new Intl.RelativeTimeFormat('ja-JP', {
numeric: 'auto'
});
console.log(formatter.format(daysPassed, 'day')); // 857 日前
console.log(formatter.format(yearsPassed, 'year')); // 2 年前
ただし、2番目の引数は日か時間かのどちらか1つだけを指定できます。
この問題を補完できるライブラリtimeago.js
がありますが、時間がどれだけ経過したかに応じて日か時間かを自動的に表示されるので、相対的な時間のみが必要な場合に便利かと思います。
日付と時間を正確に表示
時間を表示するときには、コンパクトにしてより読みやすい場合もありますが、正確な日付を表示する必要があるときもあります。その場合はIntl.DateTimeFormat
またはtoLocalDateString
を使用します。
const today = new Date(); // 作成日基準の今日
console.log(today.toString()); // Thu Sep 21 2023 12:05:01 GMT+0900 (日本標準時)
console.log(new Intl.DateTimeFormat('ja-JP').format(today)); // 2023/9/21
これをさらに簡略化した方法もあります。
const today = new Date();
console.log(
today.toLocaleDateString('ja-JP', {
minute: 'numeric',
hour: 'numeric',
day: 'numeric',
month: 'short',
year: 'numeric',
weekday: 'short'
})
); // 2023年9月21日(木) 12:18
日付にtoLocaleDateStringを使用するだけで、内部的にはIntl APIを使用するため、より簡単にフォーマットを使用できます。言語を指定するだけでその言語に合わせたフォーマットが表示されます。さらに、さまざまなオプションを指定することもできるので、より簡単にまたはより詳しく表示できます。
まとめ
IntlはJavaScriptの標準仕様であるので、定期的に更新され常に最新の国際化に向けた実装が可能です。また、外部ライブラリに依存せずに使用できることも良い点です。もちろん一つの言語だけを対応するサイトでも使用でき、その言語に合わせたフォーマットにしてくれるので別途用意しなくて済みます。
日々の開発においても活用していきたいと思います。
参考
Author Profile

RYU
ウェブの魔法使いになりたいです✨
SHARE