如何格式化诸如 5 公里或 10 磅之类的度量单位

以符合本地化的格式和单位显示距离、重量、温度及其他度量单位

介绍

测量通过单位来传达具有意义的数量。五公里表示距离,十磅表示重量,二十摄氏度表示温度。显示测量值的应用程序需要以用户能够理解的格式同时显示数值和单位。

不同的语言区域对测量值的格式化方式不同。美国人根据上下文可能会写成 "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 选项接受标准化的单位标识符。这些标识符使用小写单词并以连字符分隔。常见的标识符包括 kilometermetermilepoundkilogramcelsiusfahrenheitlitergallon

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 选项控制单位是以缩写、全称还是最小形式显示。该选项接受三个值:"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"

每种语言环境都会提供适当的翻译和语法形式的单位名称。

格式化重量单位

重量单位使用诸如 poundkilogramouncegram 的单位标识符。这些标识符的工作方式与距离单位相同。

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"

格式化器会根据值自动处理单数和复数形式。一个磅使用单数形式,而十磅使用复数形式。

格式化温度测量值

温度测量值使用类似 celsiusfahrenheit 的单位标识符。这些单位在短格式中会带有度数符号。

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 摄氏度"

console.log(fahrenheitFormatter.format(68));
// 输出: "68 华氏度"

温度格式化会自动包含每种温标的适当度数术语。

格式化体积测量值

体积测量值使用类似 litergallonmilliliterfluid-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"。

格式化复合单位

复合单位将两个简单单位以“每”的关系组合在一起。例如,速度测量值如每小时英里或每小时公里使用复合单位。燃油效率测量值如每百公里升也使用复合单位。

复合单位标识符通过 -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 英里每小时"

格式化器会自动构建复合单位短语,并使用适合语言环境的正确语法。

获取可用的单位标识符

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"

这种模式比为每个值创建一个新的格式化器更高效。当格式化包含许多测量值的数组或列表时,性能差异会变得显著。