5キロメートルや10ポンドなどの測定値をフォーマットする方法
距離、重量、温度、その他の測定値をロケールに適したフォーマットと単位で表示する
はじめに
測定値は単位を伴う数量を伝えます。5キロメートルは距離を、10ポンドは重さを、20度セルシウスは温度を示します。測定値を表示するアプリケーションは、数値と単位の両方をユーザーが理解できる形式で表示する必要があります。
異なるロケールでは測定値の表示形式が異なります。アメリカ人は文脈に応じて「5 km」または「5 kilometers」と表記します。ドイツ人は異なる間隔の規則で「5 km」と表記するかもしれません。同じ測定値でも、ロケールや望ましい詳細度によって「5 km」、「5km」、または「5 kilometers」のように表示されることがあります。地域によってメートル法を使用する場所もあれば、ヤード・ポンド法を使用する場所もありますが、単位の書式もロケールによって異なります。
JavaScriptはIntl.NumberFormat APIを提供し、ロケールに適した単位書式で測定値をフォーマットできます。このレッスンでは、距離、重さ、温度、体積、速度などの測定値を任意のロケールに対して正しい単位表示でフォーマットする方法を説明します。
測定値には文脈のための単位が必要
単位のない数字は多くの文脈で意味を持ちません。数字の5は、5キロメートル、5マイル、5メートル、または5フィートを表す可能性があります。ユーザーは測定される単位を知らなければ、その値を解釈できません。
単位は数値と一貫して表示される必要があります。「5キロメートル」と書く場合、単位「キロメートル」は不可欠な情報です。「10ポンド」と書く場合、単位「ポンド」はその測定値が通貨ではなく重さであることを示します。
同じ種類の測定に対して異なる単位系が存在します。距離はキロメートル、マイル、メートル、フィートなどの単位で測定できます。重さはキログラム、ポンド、オンス、グラムなどで測定できます。温度はセルシウス度、華氏度、ケルビンで測定できます。アプリケーションは、使用する単位系をユーザーの期待に合った方法でフォーマットする必要があります。
Intl.NumberFormatで単位をフォーマットする
Intl.NumberFormatコンストラクタは、オプションでstyle: 'unit'を渡すと単位フォーマッタを作成します。また、unitオプションで単位識別子を使用して、どの単位でフォーマットするかを指定する必要があります。
const formatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
console.log(formatter.format(5));
// 出力: "5 km"
これにより、キロメートル単位で値を表示する米国英語用のフォーマッタが作成されます。format()メソッドは数値をキロメートル単位の略称を含む文字列に変換します。
unitオプションは標準化された単位識別子を受け入れます。これらの識別子はハイフンで区切られた小文字の単語を使用します。一般的な識別子にはkilometer、meter、mile、pound、kilogram、celsius、fahrenheit、liter、gallonなどがあります。
const distanceFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
const weightFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'pound'
});
console.log(distanceFormatter.format(5));
// 出力: "5 km"
console.log(weightFormatter.format(10));
// 出力: "10 lb"
各フォーマッタは指定された単位に適切な単位略称を自動的に適用します。各単位識別子にどの略称が対応するかを知る必要はありません。
ロケールが単位のフォーマットを決定する
ロケールパラメータは、スペース、区切り文字、単位略称を含む単位のフォーマット方法を制御します。同じ単位でもロケールによって異なる出力が生成されます。
const usFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
const deFormatter = new Intl.NumberFormat('de-DE', {
style: 'unit',
unit: 'kilometer'
});
const frFormatter = new Intl.NumberFormat('fr-FR', {
style: 'unit',
unit: 'kilometer'
});
console.log(usFormatter.format(5));
// 出力: "5 km"
console.log(deFormatter.format(5));
// 出力: "5 km"
console.log(frFormatter.format(5));
// 出力: "5 km"
キロメートルはロケール間で類似した略称を使用していますが、スペースや区切り文字の規則は異なります。Intl APIはこれらのロケール固有のフォーマットルールを自動的に処理します。
単位表示の詳細度の制御
unitDisplayオプションは、単位が省略形、完全形、または最小形式で表示されるかどうかを制御します。このオプションは3つの値を受け付けます:省略形の場合は"short"、完全な単位名の場合は"long"、最小表示の場合は"narrow"です。
const shortFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'short'
});
const longFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'long'
});
const narrowFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'narrow'
});
console.log(shortFormatter.format(5));
// 出力: "5 km"
console.log(longFormatter.format(5));
// 出力: "5 kilometers"
console.log(narrowFormatter.format(5));
// 出力: "5km"
short形式は「km」や「lb」などの標準的な略語を使用します。long形式は「kilometers」や「pounds」などの完全な単位名を使用します。narrow形式は間隔を減らすか無くした最小表示を使用します。unitDisplayを指定しない場合、デフォルトはshortです。
ロケールは長形式の単位の表示方法に影響します。完全な単位名は各言語の文法規則に合わせて翻訳および調整されます。
const enFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'long'
});
const deFormatter = new Intl.NumberFormat('de-DE', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'long'
});
const esFormatter = new Intl.NumberFormat('es-ES', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'long'
});
console.log(enFormatter.format(5));
// 出力: "5 kilometers"
console.log(deFormatter.format(5));
// 出力: "5 Kilometer"
console.log(esFormatter.format(5));
// 出力: "5 kilómetros"
各ロケールは単位名に適切な翻訳と文法形式を提供します。
重量測定のフォーマット
重量測定にはpound、kilogram、ounce、gramなどの単位識別子を使用します。これらの識別子は距離単位と同じように機能します。
const poundFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'pound'
});
const kilogramFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilogram'
});
console.log(poundFormatter.format(10));
// 出力: "10 lb"
console.log(kilogramFormatter.format(10));
// 出力: "10 kg"
完全な単位名を表示するために、重量を長形式でフォーマットすることができます。
const formatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'pound',
unitDisplay: 'long'
});
console.log(formatter.format(1));
// 出力: "1 pound"
console.log(formatter.format(10));
// 出力: "10 pounds"
フォーマッタは値に基づいて単数形と複数形を自動的に処理します。1ポンドは単数形を使用し、10ポンドは複数形を使用します。
温度測定のフォーマット
温度測定では、celsiusやfahrenheitなどの単位識別子を使用します。これらの単位は短縮形で度数記号と共にフォーマットされます。
const celsiusFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'celsius'
});
const fahrenheitFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'fahrenheit'
});
console.log(celsiusFormatter.format(20));
// 出力: "20°C"
console.log(fahrenheitFormatter.format(68));
// 出力: "68°F"
長い形式では、温度スケールの完全な名称が表示されます。
const celsiusFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'celsius',
unitDisplay: 'long'
});
const fahrenheitFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'fahrenheit',
unitDisplay: 'long'
});
console.log(celsiusFormatter.format(20));
// 出力: "20 degrees Celsius"
console.log(fahrenheitFormatter.format(68));
// 出力: "68 degrees Fahrenheit"
温度フォーマットには、各スケールに適切な度数の用語が自動的に含まれます。
体積測定のフォーマット
体積測定では、liter、gallon、milliliter、fluid-ounceなどの単位識別子を使用します。これらは他の単位タイプと同様に機能します。
const literFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'liter'
});
const gallonFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'gallon'
});
console.log(literFormatter.format(2));
// 出力: "2 L"
console.log(gallonFormatter.format(2));
// 出力: "2 gal"
体積単位もロケール固有のスペルで長い形式の表示をサポートしています。
const usFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'liter',
unitDisplay: 'long'
});
const gbFormatter = new Intl.NumberFormat('en-GB', {
style: 'unit',
unit: 'liter',
unitDisplay: 'long'
});
console.log(usFormatter.format(2));
// 出力: "2 liters"
console.log(gbFormatter.format(2));
// 出力: "2 litres"
イギリス英語のロケールでは「litres」を使用し、アメリカ英語では「liters」を使用します。
複合単位のフォーマット
複合単位は、2つの単純な単位を「per(あたり)」の関係で組み合わせたものです。時速マイルや時速キロメートルなどの速度測定には複合単位を使用します。100キロメートルあたりのリットルなどの燃費測定にも複合単位を使用します。
複合単位識別子は、2つの単純な単位を -per- で結合します。例えば、mile-per-hourはマイルと時間を組み合わせ、kilometer-per-hourはキロメートルと時間を組み合わせます。
const mphFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'mile-per-hour'
});
const kphFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer-per-hour'
});
console.log(mphFormatter.format(60));
// 出力: "60 mph"
console.log(kphFormatter.format(100));
// 出力: "100 km/h"
各複合単位は、両方の単位部分を組み合わせた適切な略語でフォーマットされます。
長い形式では、複合単位は完全な名前とロケールに適した前置詞で表示されます。
const formatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'mile-per-hour',
unitDisplay: 'long'
});
console.log(formatter.format(60));
// 出力: "60 miles per hour"
フォーマッタは、ロケールに合った正しい文法を使用して複合単位のフレーズを自動的に構築します。
利用可能な単位識別子を取得する
Intl.supportedValuesOf() メソッドは、JavaScript環境でサポートされているすべての単位識別子の配列を返します。このメソッドは引数として文字列 'unit' を取ります。
const units = Intl.supportedValuesOf('unit');
console.log(units);
// 出力: 単位識別子の配列:
// ["acre", "bit", "byte", "celsius", "centimeter", "day",
// "degree", "fahrenheit", "fluid-ounce", "foot", "gallon",
// "gram", "hectare", "hour", "inch", "kilogram", "kilometer",
// "liter", "meter", "mile", "millimeter", "ounce", "pound",
// "second", "stone", "week", "yard", ...]
返される配列には、フォーマットに利用可能なすべての単純単位が含まれています。この配列のどの識別子も unit オプションで使用できます。
このメソッドは、特定の単位がサポートされているかを確認する必要がある場合や、利用可能な単位のリストをユーザーに提供したい場合に役立ちます。
const units = Intl.supportedValuesOf('unit');
const hasKilometer = units.includes('kilometer');
const hasPound = units.includes('pound');
console.log(hasKilometer);
// 出力: true
console.log(hasPound);
// 出力: true
フォーマッターを作成する前に特定の単位をチェックして、サポートレベルが異なる環境に対応できます。
数値フォーマットオプションと組み合わせる
単位フォーマッターは、他の Intl.NumberFormat スタイルと同じ数値フォーマットオプションをサポートしています。小数点以下の桁数、有効数字、その他の数値プロパティを制御できます。
const formatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
maximumFractionDigits: 2
});
console.log(formatter.format(5.123));
// 出力: "5.12 km"
console.log(formatter.format(5.5));
// 出力: "5.5 km"
フォーマッターは単位を追加する前に、四捨五入と小数点以下の桁数のルールを適用します。
桁区切り記号を使用して大きな数値をフォーマットすることもできます。
const formatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
console.log(formatter.format(12345.67));
// 出力: "12,345.67 km"
標準的な数値フォーマット機能はすべて単位フォーマットでも機能します。
ユーザーのロケールに合わせた測定値のフォーマット
特定のロケールをハードコーディングする代わりに、ユーザーのブラウザの言語設定を使用できます。navigator.languageプロパティはユーザーの優先ロケールを返します。
const userLocale = navigator.language;
const formatter = new Intl.NumberFormat(userLocale, {
style: 'unit',
unit: 'kilometer'
});
console.log(formatter.format(5));
// 出力はユーザーのロケールによって異なります
このアプローチでは、各ユーザーのフォーマット期待に従って測定値を表示します。異なるユーザーは同じ測定値を自分のロケール規則に従ってフォーマットされた形で見ることができます。
アプリケーションでの測定値の表示
単位フォーマッターはユーザーに測定値を表示するあらゆる場所で使用できます。これには、距離や重量を表示するフィットネスアプリケーション、温度を表示する天気アプリケーション、容量を表示するレシピアプリケーション、速度を表示するナビゲーションアプリケーションなどが含まれます。
const distanceFormatter = new Intl.NumberFormat(navigator.language, {
style: 'unit',
unit: 'kilometer',
maximumFractionDigits: 1
});
const distance = 5.234;
document.getElementById('distance').textContent = distanceFormatter.format(distance);
// 表示: "5.2 km"(またはロケール相当)
フォーマットされた文字列は他の文字列値と同様に機能します。テキストコンテンツ、属性、またはユーザーに情報を表示するあらゆるコンテキストに挿入できます。
単位フォーマッターの再利用
新しいIntl.NumberFormatインスタンスを作成するには、ロケールデータの読み込みとオプションの処理が必要です。同じロケールと単位で複数の測定値をフォーマットする場合は、フォーマッターを一度作成して再利用します。
const formatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
const distances = [1.5, 3.2, 5.0, 10.8];
distances.forEach(distance => {
console.log(formatter.format(distance));
});
// 出力:
// "1.5 km"
// "3.2 km"
// "5 km"
// "10.8 km"
このパターンは、各値に対して新しいフォーマッターを作成するよりも効率的です。多数の測定値を持つ配列やリストをフォーマットする場合、パフォーマンスの差は顕著になります。