Formatting prices

Displaying localized currency and number formats

Problem

Displaying a price involves both a number and a currency. A US price is $1,200.50, while the same value in Euros might be 1 200,50 € in Germany. The currency symbol's position, the decimal separator, and the grouping separator all change, and hard-coding these rules for every language is unmanageable.

Solution

Use the FormattedNumber component from react-intl with the style: 'currency' option. This component reads the current locale from its provider and formats a number as a price, automatically handling symbol placement, decimal separators, and grouping for that locale and specified currency.

Steps

1. Create a client component for prices

Formatting components from react-intl must be used within client components.

Create a new component, 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. Pass formatting options

The FormattedNumber component is controlled by these props:

  • value: The numeric value of the price.
  • style: 'currency': This tells the component to format the number as a currency, not a standard decimal.
  • currency: The three-letter ISO currency code (e.g., 'USD', 'EUR'). This is required when using style: 'currency'.

3. Use the component on a page

You can now use this component in your server or client components to display prices.

// 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>
  );
}

A user visiting /en will see "Price (USD): $1,299.99" and "Price (EUR): €1,199.50". A user visiting /es will see "Price (USD): 1299,99 US$" and "Price (EUR): 1199,50 €".