如何在 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 钩子提供了访问格式化 API 的能力。使用 style: 'currency'formatNumber 方法可以同时应用货币符号和特定语言环境的数字格式规则。

2. 使用组件处理不同的货币

通过传递数值金额和货币代码,在您的应用程序中显示价格。

export default function ProductCard() {
  return (
    <div>
      <h2>高级计划</h2>
      <Price value={1200.5} currency="USD" />
    </div>
  );
}

该组件会根据用户的区域设置自动格式化价格。美国用户会看到 "$1,200.50",而德国用户会看到 "1.200,50 $"。

3. 使用自定义小数精度格式化价格

通过添加 minimumFractionDigitsmaximumFractionDigits 选项,控制显示的小数位数。

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 上下文中使用格式化价格时,可以使用此钩子。

export function CheckoutSummary({ total }: { total: number }) {
  const formatCurrency = useFormatCurrency();

  return (
    <button aria-label={`支付 ${formatCurrency(total, "USD")}`}>结算</button>
  );
}

该辅助工具返回一个适用于任何无法使用 JSX 组件的上下文的纯字符串。