如何在 TanStack Start v1 中为不同的语言环境格式化数字
使用特定语言环境的分隔符显示数字
问题
世界各地的数字书写方式各不相同。在美国,10,000.5 表示一万点五,而在德国则写作 10.000,5——逗号和句号的作用完全对调。这不仅仅是偏好或风格的问题,而是可读性的问题。一位德国用户看到 10,000.5 可能会将其读作十,忽略分组分隔符。而一位美国用户看到 10.000,5 可能会将其读作一万,忽略小数点分隔符。同样的数字,却有相反的含义。
当应用程序在显示数字时未考虑区域格式化规则时,会引发混淆并削弱用户的信任。用户期望数字遵循他们所学的模式,偏离这些模式会迫使他们停下来重新解释,并质疑数据的正确性。
解决方案
根据用户的区域设置格式化数字,使用区域规则来处理小数点和分组分隔符。这将数值转换为符合用户所在地区格式规则的字符串。
React-intl 提供了利用浏览器内置的 Intl.NumberFormat API 的组件和钩子,用于应用区域特定的格式化规则。通过传递一个数值和当前的区域设置,这些工具会自动选择正确的分隔符、数字分组以及其他区域规则。结果是一个符合用户期望的格式化字符串,无需手动字符串操作或在组件中编写区域特定的逻辑。
步骤
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 组件会自动应用区域设置的小数点和分组分隔符。它从组件树中最近的 IntlProvider 读取区域设置,并相应地格式化数字。
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>
收入:{" "}
<FormattedNumber value={revenue} style="currency" currency="USD" />
</p>
<p>
增长率:<FormattedNumber value={growthRate} style="percent" />
</p>
<p>
大小:{" "}
<FormattedNumber
value={fileSize}
style="unit"
unit="megabyte"
unitDisplay="short"
/>
</p>
</div>
);
}
style 属性控制格式化模式。货币格式化需要提供 currency 代码,百分比格式化会自动乘以 100,而单位格式化需要提供 unit 标识符。所有样式都会遵循当前活动语言环境的约定。
3. 使用 useIntl 命令式格式化数字
在组件不适用的上下文中,例如生成动态属性或为非 React API 准备数据,可以使用 useIntl 钩子来格式化数字。
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",同时遵循语言环境特定的缩写规则。