Форматирование цен

Отображение локализованных форматов валют и чисел

Проблема

Отображение цены включает как число, так и валюту. Цена в США выглядит как $1,200.50, в то время как та же сумма в евро в Германии может быть представлена как 1 200,50 €. Позиция символа валюты, десятичный разделитель и разделитель групп меняются, и жестко задавать эти правила для каждого языка невозможно.

Решение

Используйте компонент FormattedNumber из библиотеки react-intl с опцией style: 'currency'. Этот компонент считывает текущую локаль из своего провайдера и форматирует число как цену, автоматически обрабатывая расположение символа, десятичные разделители и группировку для данной локали и указанной валюты.

Шаги

1. Создайте клиентский компонент для цен

Форматирующие компоненты из react-intl должны использоваться внутри клиентских компонентов.

Создайте новый компонент app/components/ProductPrice.tsx.

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

import { FormattedNumber } from 'react-intl';

type Props = {
  price: number;
  currencyCode: string; // например, "USD", "EUR", "JPY"
};

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

2. Передайте параметры форматирования

Компонент FormattedNumber управляется следующими свойствами:

  • 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>Продукт</h1>
      <p>
        Цена (USD): <ProductPrice price={product.price} currencyCode={product.currency} />
      </p>
      <p>
        Цена (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 €".