如何在 React Router v7 中为不同的语言环境格式化数字
使用特定语言环境的分隔符显示数字
问题
世界各地的数字书写方式各不相同。在美国,10,000.5 表示一万点五,而在德国则写作 10.000,5——逗号和句号的作用完全对调。这不仅仅是偏好或风格的问题,而是可读性的问题。一位德国用户看到 10,000.5 可能会将其读作十,忽略分组分隔符。而一位美国用户看到 10.000,5 可能会将其读作一万,忽略小数点分隔符。
相同的数字根据读者的地区习惯可能传达完全相反的含义。当应用程序显示未经本地化格式化的原始数字值时,可能会让用户感到困惑,从而削弱对所呈现数据的信任。
解决方案
根据用户的地区格式化数字,使用区域规则来处理小数点和分组分隔符。这将数字值转换为符合用户所在地区格式规则的字符串。
React-intl 提供了利用浏览器内置的 Intl.NumberFormat API 的格式化方法,该 API 处理区域数字习惯的复杂性。通过将数字值传递给这些格式化器,应用程序可以生成符合用户期望的输出,而无需手动处理分隔符逻辑。
步骤
1. 创建一个使用 useIntl 格式化数字的组件
useIntl 钩子提供了访问格式化方法的能力,包括 formatNumber,它接受一个数字值并返回一个本地化格式的字符串。
import { useIntl } from "react-intl";
export default function ProductPrice() {
const intl = useIntl();
const price = 1234.56;
return (
<div>
<p>价格: {intl.formatNumber(price)}</p>
</div>
);
}
formatNumber 方法会自动为当前地区应用正确的分隔符。一位使用 en-US 地区的用户会看到 "1,234.56",而一位使用 de-DE 地区的用户会看到 "1.234,56"。
2. 使用样式选项格式化货币值
formatNumber 方法接受符合 Intl.NumberFormatOptions 的选项,包括货币格式化。
import { useIntl } from "react-intl";
export default function ProductPrice() {
const intl = useIntl();
const price = 1234.56;
return (
<div>
<p>
{intl.formatNumber(price, {
style: "currency",
currency: "USD",
})}
</p>
</div>
);
}
对于 en-US,这将生成 "$1,234.56";对于 de-DE,则生成 "1.234,56 $",应用了分隔符和货币符号的约定。
3. 使用 FormattedNumber 进行声明式格式化
FormattedNumber 组件提供了一种声明式的替代方法,它接受与属性相同的选项。
import { FormattedNumber } from "react-intl";
export default function Statistics() {
const totalUsers = 1500000;
const growthRate = 0.23;
return (
<div>
<p>
总用户数:<FormattedNumber value={totalUsers} />
</p>
<p>
增长率:<FormattedNumber value={growthRate} style="percent" />
</p>
</div>
);
}
该组件直接将格式化后的数字渲染到 DOM 中。对于 en-US,显示为 "1,500,000" 和 "23%";对于 de-DE,显示为 "1.500.000" 和 "23 %"。
4. 从加载器数据中格式化数字
在 React Router 7 中,路由组件通过 useLoaderData 钩子访问加载器数据。结合数字格式化,可以显示服务器提供的值。
import { useLoaderData } from "react-router";
import { FormattedNumber } from "react-intl";
export async function loader() {
return {
revenue: 45678.9,
units: 12500,
};
}
export default function Dashboard() {
const { revenue, units } = useLoaderData<typeof loader>();
return (
<div>
<h1>仪表盘</h1>
<p>
收入:<FormattedNumber value={revenue} style="currency" currency="USD" />
</p>
<p>
销售单位:<FormattedNumber value={units} />
</p>
</div>
);
}
加载器提供原始的数字数据,组件根据用户的语言环境对其进行格式化。这种分离使数据获取与展示逻辑保持独立。