价格格式化

显示本地化的货币和数字格式

问题

显示价格时既涉及数字也涉及货币。例如,美国的价格是 $1,200.50,而在德国,相同数值的欧元价格可能是 1 200,50 €。货币符号的位置、小数点分隔符和千位分隔符都会变化,为每种语言手动编写这些规则几乎无法管理。

解决方案

使用 FormattedNumber 组件(来自 react-intl),并配合 style: 'currency' 选项。该组件会从其 provider 读取当前 locale,并将数字格式化为价格,自动处理该 locale 和指定货币的符号位置、小数点分隔符和分组方式。

步骤

1. 创建价格的客户端组件

来自 react-intl 的格式化组件必须在客户端组件中使用。

新建一个组件 app/components/ProductPrice.tsx

// app/components/ProductPrice.tsx
'use client';

import { FormattedNumber } from 'react-intl';

type Props = {
  price: number;
  currencyCode: string; // e.g., "USD", "EUR", "JPY"
};

export default function ProductPrice({ price, currencyCode }: Props) {
  return (
    <FormattedNumber
      value={price}
      style="currency"
      currency={currencyCode}
    />
  );
}

2. 传递格式化选项

FormattedNumber 组件通过以下 props 控制:

  • value:价格的数值。
  • style: 'currency':指示组件将数字格式化为货币,而不是普通小数。
  • currency:三位字母的 ISO 货币代码(如 'USD'、'EUR')。当使用 style: 'currency' 时必填。

3. 在页面中使用该组件

现在可以在服务端或客户端组件中使用该组件来显示价格。

// app/[lang]/page.tsx
import ProductPrice from '@/app/components/ProductPrice';

export default function Home() {
  const product = {
    price: 1299.99,
    currency: 'USD',
  };

  const productInEuros = {
    price: 1199.5,
    currency: 'EUR',
  };

  return (
    <div>
      <h1>Product</h1>
      <p>
        Price (USD): <ProductPrice price={product.price} currencyCode={product.currency} />
      </p>
      <p>
        Price (EUR): <ProductPrice price={productInEuros.price} currencyCode={productInEuros.currency} />
      </p>
    </div>
  );
}

访问 /en 的用户会看到“价格 (USD):$1,299.99”和“价格 (EUR):€1,199.50”。访问 /es 的用户会看到“价格 (USD):1299,99 US$”和“价格 (EUR):1199,50 €”。