Comment formater les montants de devises dans React Router v7
Afficher les prix avec symboles de devise et séparateurs
Problème
L'affichage des prix dans les applications web nécessite de gérer deux préoccupations de localisation interdépendantes : la devise utilisée et les conventions régionales pour présenter les valeurs monétaires. Un prix de 1200.50 dollars américains apparaît comme "$1,200.50" pour les utilisateurs aux États-Unis mais comme "1 200,50 $US" en France. La position du symbole monétaire, le séparateur décimal, le regroupement des milliers et l'espacement varient tous selon la locale. Lorsque ces conventions ne sont pas respectées, les utilisateurs peuvent mal interpréter les montants ou remettre en question l'exactitude du prix, ce qui mine la confiance dans l'application.
Le défi est amplifié lorsqu'une application dessert plusieurs régions ou permet aux utilisateurs de visualiser les prix dans différentes devises. Coder en dur des chaînes de format ou placer manuellement des symboles crée un code fragile qui se brise lorsque de nouvelles locales ou devises sont ajoutées. Sans une approche systématique, maintenir un affichage de prix cohérent et correct dans toute l'application devient sujet aux erreurs.
Solution
Formatez les valeurs monétaires en utilisant à la fois le code de devise cible et la locale active de l'utilisateur. Cette approche délègue les règles complexes de présentation des devises aux API d'internationalisation du navigateur, qui encodent déjà les conventions de formatage pour des centaines de combinaisons locale-devise.
En transmettant un montant numérique, un code de devise et la locale actuelle à une fonction de formatage, le système applique automatiquement le symbole, les séparateurs et la mise en page corrects. Cela garantit que les prix apparaissent toujours dans un format familier à l'utilisateur, quelle que soit la devise affichée ou la région où se trouve l'utilisateur.
Étapes
1. Créer un composant réutilisable de formatage de devise
Construisez un composant qui utilise FormattedNumber de react-intl avec les props style et currency pour formater les valeurs monétaires.
import { FormattedNumber } from "react-intl";
interface PriceProps {
amount: number;
currency: string;
}
export function Price({ amount, currency }: PriceProps) {
return (
<FormattedNumber value={amount} style="currency" currency={currency} />
);
}
Le composant FormattedNumber utilise l'API formatNumber et accepte Intl.NumberFormatOptions. L'option style="currency" indique au formateur d'inclure les symboles monétaires, et la prop currency spécifie quelle devise afficher.
2. Utiliser le composant Price dans les composants de route
Affichez les prix dans n'importe quel composant de route React Router en passant la valeur numérique et le code de devise.
import { Price } from "~/components/Price";
export default function ProductPage() {
const product = {
name: "Casque sans fil",
price: 129.99,
currency: "USD",
};
return (
<div>
<h1>{product.name}</h1>
<p>
<Price amount={product.price} currency={product.currency} />
</p>
</div>
);
}
Le composant Price formate automatiquement le montant selon les paramètres régionaux configurés dans l'IntlProvider. Pour les paramètres régionaux américains, cela affiche "$129.99" ; pour les paramètres régionaux allemands avec la même devise USD, cela affiche "129,99 $".
3. Formater la devise de manière impérative lorsque nécessaire
Pour les scénarios où vous avez besoin directement de la chaîne formatée, utilisez le hook useIntl pour accéder à la méthode formatNumber.
import { useIntl } from "react-intl";
export default function CheckoutSummary() {
const intl = useIntl();
const subtotal = 89.99;
const tax = 7.2;
const total = subtotal + tax;
const formattedTotal = intl.formatNumber(total, {
style: "currency",
currency: "EUR",
});
return (
<div>
<h2>Récapitulatif de commande</h2>
<dl>
<dt>Sous-total</dt>
<dd>
{intl.formatNumber(subtotal, {
style: "currency",
currency: "EUR",
})}
</dd>
<dt>Taxe</dt>
<dd>
{intl.formatNumber(tax, {
style: "currency",
currency: "EUR",
})}
</dd>
<dt>Total</dt>
<dd aria-label={`Total : ${formattedTotal}`}>
<strong>{formattedTotal}</strong>
</dd>
</dl>
</div>
);
}
La méthode formatNumber accepte une valeur et un objet d'options avec FormatNumberOptions. C'est utile lorsque vous avez besoin de la chaîne formatée pour des attributs, des journaux ou des contextes non-JSX.
4. Contrôler la précision décimale pour les devises à nombres entiers
Certaines devises n'utilisent pas d'unités fractionnaires. Ajustez le nombre de décimales pour correspondre aux conventions monétaires.
import { FormattedNumber } from "react-intl";
interface PriceProps {
amount: number;
currency: string;
}
export function Price({ amount, currency }: PriceProps) {
const isWholeNumberCurrency = currency === "JPY" || currency === "KRW";
return (
<FormattedNumber
value={amount}
style="currency"
currency={currency}
minimumFractionDigits={isWholeNumberCurrency ? 0 : 2}
maximumFractionDigits={isWholeNumberCurrency ? 0 : 2}
/>
);
}
Le yen japonais n'utilise pas d'unité mineure, donc les montants sont affichés sans décimales. Les options minimumFractionDigits et maximumFractionDigits remplacent le comportement décimal par défaut lorsque nécessaire.