如何在 TanStack Start v1 中格式化货币金额
使用货币符号和分隔符显示价格
问题
价格的本地化涉及两个挑战:货币表示和数字格式化。同样的金额在美国显示为 $1,200.50,在德国则为 1 200,50 €。货币符号的位置、千位分隔符和小数点符号都会变化,甚至空格的用法也不同。
这些规范不是个人偏好,而是用户的预期。如果价格格式不符合本地习惯,用户会怀疑金额是否正确。例如,德国用户看到“1200.50 EUR”,或美国用户看到“1.200,50$”,都会产生困惑,降低信任感。
解决方案
应根据货币类型和用户的语言环境格式化金额。这样可以结合货币符号的位置和本地数字格式规则,确保价格显示符合各地区用户对货币的认知习惯。
使用 react-intl 的 formatNumber 方法,并结合 style: 'currency' 选项,可以同时应用货币代码和用户本地的格式化规则。浏览器的 Intl.NumberFormat API 会自动处理符号位置、分隔符和空格。
步骤
1. 创建货币格式化组件
构建一个可复用组件,接收数值和货币代码,并根据用户的语言环境格式化价格。
import { useIntl } from "react-intl";
interface PriceProps {
value: number;
currency: string;
}
export function Price({ value, currency }: PriceProps) {
const intl = useIntl();
const formattedPrice = intl.formatNumber(value, {
style: "currency",
currency: currency,
});
return <span>{formattedPrice}</span>;
}
useIntl hook 提供了格式化 API 的访问能力。结合 formatNumber 方法和 style: 'currency',可以同时应用货币符号和本地数字格式。
2. 在不同货币下使用该组件
在应用中传入数值和货币代码,即可在各处显示价格。
export default function ProductCard() {
return (
<div>
<h2>Premium Plan</h2>
<Price value={1200.5} currency="USD" />
</div>
);
}
该组件会根据用户的本地化设置自动格式化价格。美国用户会看到 "$1,200.50",而德国用户会看到 "1.200,50 $"。
3. 使用自定义小数精度格式化价格
通过添加 minimumFractionDigits 和 maximumFractionDigits 选项,可以控制显示的小数位数。
export function PriceWithPrecision({ value, currency }: PriceProps) {
const intl = useIntl();
const formattedPrice = intl.formatNumber(value, {
style: "currency",
currency: currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
return <span>{formattedPrice}</span>;
}
这样可以确保所有价格的小数显示保持一致,即使数值为 100 这样的整数也不例外。
4. 创建内联格式化辅助函数
在不需要组件包装器的情况下,可以创建一个格式化辅助函数。
import { useIntl } from "react-intl";
export function useFormatCurrency() {
const intl = useIntl();
return (value: number, currency: string) => {
return intl.formatNumber(value, {
style: "currency",
currency: currency,
});
};
}
当你需要在属性、计算值或其他非 JSX 场景下获取格式化价格时,可以使用这个 hook。
export function CheckoutSummary({ total }: { total: number }) {
const formatCurrency = useFormatCurrency();
return (
<button aria-label={`Pay ${formatCurrency(total, "USD")}`}>Checkout</button>
);
}
该辅助函数返回一个普通字符串,适用于无法使用 JSX 组件的任何场景。