Formatting numbers

Handling decimal and grouping separators

Problem

A large number like 10000.5 is written as 10.000,5 in Germany and 10,000.5 in the US. Displaying the number using one region's convention creates confusion for users in other regions, who may misinterpret the value due to incorrect decimal and grouping separators.

Solution

Use a dedicated formatting component from react-intl, such as FormattedNumber. This component automatically reads the current language from its provider and formats a number primitive into a string that uses the correct, locale-specific decimal and grouping separators.

Steps

1. Create a client component for numbers

Like other react-intl components, FormattedNumber must be used within a client component.

Create a new component, app/components/ProductInfo.tsx, that will display a formatted number.

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

import { FormattedNumber } of 'react-intl';

type Props = {
  reviewCount: number;
  averageRating: number;
};

export default function ProductInfo({ reviewCount, averageRating }: Props) {
  return (
    <div>
      <h3>Product details</h3>
      <p>
        Total reviews:
        {/* Basic number formatting */}
        <FormattedNumber value={reviewCount} />
      </p>
      <p>
        Average rating:
        {/* Formatting with options */}
        <FormattedNumber
          value={averageRating}
          minimumFractionDigits={1}
          maximumFractionDigits={1}
        />
      </p>
    </div>
  );
}

2. Pass formatting options

The FormattedNumber component accepts options to control the output:

  • value is the number to format.
  • minimumFractionDigits and maximumFractionDigits are used here to force the display of one decimal place (e.g., 4.0).

3. Use the component on a page

Now, you can use this component on any page that displays product information.

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

export default function Home() {
  const product = {
    reviews: 1234567,
    rating: 4.0,
  };

  return (
    <div>
      <h1>Welcome</h1>
      <ProductInfo
        reviewCount={product.reviews}
        averageRating={product.rating}
      />
    </div>
  );
}

A user visiting /en will see "Total reviews: 1,234,567" and "Average rating: 4.0". A user visiting /es will see "Total reviews: 1.234.567" and "Average rating: 4,0".