Comment formater les nombres pour différentes locales dans React Router v7

Afficher les nombres avec des séparateurs spécifiques à la locale

Problème

Les nombres s'écrivent différemment à travers le monde. Ce qui apparaît comme 10,000.5 aux États-Unis devient 10.000,5 en Allemagne — les virgules et les points échangent complètement leurs rôles. Ce n'est pas une question de préférence ou de style, mais de lisibilité. Un utilisateur allemand voyant 10,000.5 pourrait le lire comme dix, en ignorant les séparateurs de groupement. Un utilisateur américain voyant 10.000,5 pourrait le lire comme dix mille, en ignorant le séparateur décimal.

Les mêmes chiffres peuvent transmettre des significations opposées selon les conventions régionales du lecteur. Lorsque les applications affichent des valeurs numériques brutes sans formatage adapté à la locale, elles risquent de confondre les utilisateurs et de compromettre la confiance dans les données présentées.

Solution

Formater les nombres en fonction de la locale de l'utilisateur, en utilisant les règles régionales pour les séparateurs décimaux et de groupement. Cela transforme les valeurs numériques en chaînes qui suivent les règles de formatage familières aux utilisateurs de leur région.

React-intl fournit des méthodes de formatage qui exploitent l'API Intl.NumberFormat intégrée au navigateur, qui gère la complexité des conventions numériques régionales. En passant les valeurs numériques à travers ces formateurs, l'application produit un résultat qui correspond aux attentes des utilisateurs sans logique manuelle de séparateurs.

Étapes

1. Créer un composant qui formate les nombres avec useIntl

Le hook useIntl donne accès aux méthodes de formatage, y compris formatNumber, qui accepte une valeur numérique et retourne une chaîne formatée selon la locale.

import { useIntl } from "react-intl";

export default function ProductPrice() {
  const intl = useIntl();
  const price = 1234.56;

  return (
    <div>
      <p>Price: {intl.formatNumber(price)}</p>
    </div>
  );
}

La méthode formatNumber applique automatiquement les séparateurs corrects pour la locale actuelle. Un utilisateur avec la locale en-US voit "1,234.56" tandis qu'un utilisateur avec la locale de-DE voit "1.234,56".

2. Formater les valeurs monétaires avec des options de style

La méthode formatNumber accepte des options conformes à Intl.NumberFormatOptions, y compris le formatage des devises.

import { useIntl } from "react-intl";

export default function ProductPrice() {
  const intl = useIntl();
  const price = 1234.56;

  return (
    <div>
      <p>
        {intl.formatNumber(price, {
          style: "currency",
          currency: "USD",
        })}
      </p>
    </div>
  );
}

Cela produit "$1,234.56" pour en-US et "1.234,56 $" pour de-DE, en appliquant à la fois les conventions de séparateur et de symbole monétaire.

3. Utiliser FormattedNumber pour un formatage déclaratif

Le composant FormattedNumber fournit une alternative déclarative qui accepte les mêmes options en tant que props.

import { FormattedNumber } from "react-intl";

export default function Statistics() {
  const totalUsers = 1500000;
  const growthRate = 0.23;

  return (
    <div>
      <p>
        Total users: <FormattedNumber value={totalUsers} />
      </p>
      <p>
        Growth rate: <FormattedNumber value={growthRate} style="percent" />
      </p>
    </div>
  );
}

Le composant affiche le nombre formaté directement dans le DOM. Pour en-US, cela affiche "1,500,000" et "23%". Pour de-DE, cela affiche "1.500.000" et "23 %".

4. Formater les nombres à partir des données du loader

Dans React Router 7, les composants de route accèdent aux données du loader via le hook useLoaderData. Combinez cela avec le formatage des nombres pour afficher les valeurs fournies par le serveur.

import { useLoaderData } from "react-router";
import { FormattedNumber } from "react-intl";

export async function loader() {
  return {
    revenue: 45678.9,
    units: 12500,
  };
}

export default function Dashboard() {
  const { revenue, units } = useLoaderData<typeof loader>();

  return (
    <div>
      <h1>Dashboard</h1>
      <p>
        Revenue:{" "}
        <FormattedNumber value={revenue} style="currency" currency="USD" />
      </p>
      <p>
        Units sold: <FormattedNumber value={units} />
      </p>
    </div>
  );
}

Le loader fournit des données numériques brutes, et le composant les formate selon la locale de l'utilisateur. Cette séparation maintient la récupération des données indépendante des préoccupations de présentation.