Comment formater les nombres pour différentes locales dans Next.js (Pages Router) v16
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, des significations opposées.
Lorsque les applications affichent des nombres sans formatage adapté à la locale, elles risquent de confondre les utilisateurs ou de transmettre des informations incorrectes. Les montants monétaires, les pourcentages, les mesures et les statistiques dépendent tous de conventions régionales que les utilisateurs ont apprises depuis l'enfance.
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 propose deux approches : le composant <FormattedNumber> pour un formatage déclaratif dans JSX, et la méthode formatNumber du hook useIntl pour un formatage impératif. Les deux s'appuient sur l'API Intl.NumberFormat du navigateur et appliquent automatiquement la locale configurée dans votre IntlProvider. La sortie formatée respecte les conventions régionales pour les séparateurs de milliers, les points décimaux et le groupement des chiffres.
Étapes
1. Créer un composant qui formate les nombres de manière déclarative
Le composant <FormattedNumber> utilise les API formatNumber et Intl.NumberFormat et accepte une prop value ainsi que des options qui correspondent à Intl.NumberFormatOptions.
import { FormattedNumber } from "react-intl";
export default function ProductPrice({ price }: { price: number }) {
return (
<div>
<FormattedNumber value={price} />
</div>
);
}
Par défaut, <FormattedNumber> affiche le nombre formaté dans un React.Fragment. Le composant lit la locale depuis le IntlProvider le plus proche et applique les règles de formatage appropriées.
2. Formater les nombres avec des options spécifiques
Passez des options de formatage pour contrôler l'apparence des nombres. Les options courantes incluent minimumFractionDigits, maximumFractionDigits et style.
import { FormattedNumber } from "react-intl";
export default function Statistics({ value }: { value: number }) {
return (
<dl>
<dt>Total Users</dt>
<dd>
<FormattedNumber
value={value}
minimumFractionDigits={0}
maximumFractionDigits={0}
/>
</dd>
<dt>Conversion Rate</dt>
<dd>
<FormattedNumber
value={value / 100}
style="percent"
minimumFractionDigits={2}
/>
</dd>
</dl>
);
}
Ces props correspondent à Intl.NumberFormatOptions, vous donnant le contrôle sur la précision et la présentation tout en conservant les séparateurs spécifiques à la locale.
3. Formater les nombres de manière impérative avec le hook useIntl
Lorsqu'un composant peut être exprimé comme un composant fonction, le hook useIntl fournit un accès à l'objet intl, qui inclut une méthode formatNumber.
import { useIntl } from "react-intl";
export default function DataTable({ rows }: { rows: number[] }) {
const intl = useIntl();
return (
<table>
<tbody>
{rows.map((value, index) => (
<tr key={index}>
<td>{intl.formatNumber(value)}</td>
</tr>
))}
</tbody>
</table>
);
}
La fonction formatNumber retourne une chaîne de caractères représentant le nombre formaté et accepte une valeur qui peut être analysée comme un nombre, ainsi que des options conformes à NumberFormatOptions.
4. Formater les nombres dans des contextes non-JSX
Utilisez formatNumber lorsque vous avez besoin de nombres formatés dans des attributs, des variables ou d'autres contextes où les composants ne peuvent pas être utilisés.
import { useIntl } from "react-intl";
export default function Chart({ dataPoints }: { dataPoints: number[] }) {
const intl = useIntl();
const formattedLabel = intl.formatNumber(dataPoints[0], {
notation: "compact",
maximumFractionDigits: 1,
});
return (
<div>
<img
src="/chart.png"
alt={`Chart showing ${formattedLabel} items`}
title={formattedLabel}
/>
</div>
);
}
L'API impérative est essentielle pour définir des attributs de texte tels que title, aria-label ou alt, où les composants React ne peuvent pas être rendus.