如何在 TanStack Start v1 中为不同地区格式化数字
使用符合地区习惯的分隔符显示数字
问题
世界各地的数字书写方式各不相同。在美国,10,000.5 表示一万零零点五,而在德国则写作 10.000,5——逗号和句号的作用完全对调。这不仅仅是风格或偏好的问题,而是可读性的问题。德国用户看到 10,000.5 可能会把它读作十,忽略了分组符号。美国用户看到 10.000,5 可能会把它读作一万,忽略了小数点。相同的数字,不同的含义。
如果应用程序在显示数字时没有考虑地区格式规范,就会造成混淆,甚至影响用户信任。用户期望数字遵循他们习惯的模式,偏离这些模式会让他们停下来重新理解,甚至怀疑数据是否正确。
解决方案
根据用户的地区设置格式化数字,使用本地的千位分隔符和小数点规则。这样可以将数值转换为用户熟悉的格式字符串,提升可读性和信任感。
React-intl 提供了组件和 hook,利用浏览器内置的 Intl.NumberFormat API 实现地区化格式化。只需传入数值和当前 locale,这些工具就会自动选择正确的分隔符、分组方式和其他地区规范。最终生成的字符串无需手动处理或编写地区相关逻辑,就能符合用户的预期。
步骤
1. 使用 FormattedNumber 创建数字显示组件
构建一个组件,接收数值并通过 react-intl 的 FormattedNumber 组件以本地化格式渲染。
import { FormattedNumber } from "react-intl";
interface PriceDisplayProps {
value: number;
}
export function PriceDisplay({ value }: PriceDisplayProps) {
return (
<div>
<FormattedNumber value={value} />
</div>
);
}
FormattedNumber 组件会自动应用当前 locale 的小数点和分组分隔符。它会从组件树中最近的 IntlProvider 读取 locale,并据此格式化数字。
2. 使用特定样式格式化数字
通过向 FormattedNumber 传递样式选项,可以自定义数字格式,例如货币、百分比或单位。
import { FormattedNumber } from "react-intl";
interface MetricsProps {
revenue: number;
growthRate: number;
fileSize: number;
}
export function Metrics({ revenue, growthRate, fileSize }: MetricsProps) {
return (
<div>
<p>
Revenue:{" "}
<FormattedNumber value={revenue} style="currency" currency="USD" />
</p>
<p>
Growth: <FormattedNumber value={growthRate} style="percent" />
</p>
<p>
Size:{" "}
<FormattedNumber
value={fileSize}
style="unit"
unit="megabyte"
unitDisplay="short"
/>
</p>
</div>
);
}
style 属性用于控制格式化模式。货币格式需要 currency 代码,百分比格式会自动乘以 100,单位格式需要 unit 标识符。所有样式都会遵循当前 locale 的约定。
3. 使用 useIntl 命令式格式化数字
在组件不适用的场景(如生成动态属性或为非 React API 准备数据)下,可以使用 useIntl hook 进行数字格式化。
import { useIntl } from "react-intl";
interface ChartTooltipProps {
dataPoint: number;
}
export function ChartTooltip({ dataPoint }: ChartTooltipProps) {
const intl = useIntl();
const formattedValue = intl.formatNumber(dataPoint, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
return <div title={formattedValue}>{formattedValue}</div>;
}
formatNumber 方法会立即返回格式化后的字符串,适用于属性、aria 标签或任何需要字符串而非 React 元素的场景。
4. 应用自定义格式化选项
通过向 Intl.NumberFormatOptions 传递参数,可以控制精度、分组和记数法,无论是用于 FormattedNumber 还是 formatNumber。
import { FormattedNumber } from "react-intl";
interface StatisticProps {
value: number;
compact?: boolean;
}
export function Statistic({ value, compact }: StatisticProps) {
return (
<div>
<FormattedNumber
value={value}
notation={compact ? "compact" : "standard"}
minimumFractionDigits={0}
maximumFractionDigits={2}
/>
</div>
);
}
像 notation、minimumFractionDigits 和 maximumFractionDigits 这样的选项可以控制数字的显示方式。紧凑记数法会将大数字转换为类似 “1.2M” 的缩写形式,并遵循 locale 的缩写规则。