Implémenter le formatage des devises avec Claude Code
Découvrez l'implémentation du formatage des devises avec Claude Code. Exemples de code pratiques inclus.
Implémenter correctement le formatage des devises avec Claude Code
Pour les sites e-commerce, les applications comptables et les services internationaux, un formatage précis des devises est indispensable. Les règles de séparateur décimal, de séparateur de milliers et de symbole de devise varient selon les pays et les devises. Claude Code vous permet de construire efficacement une implémentation robuste utilisant Intl.NumberFormat ou des bibliothèques dédiées.
Utilisation de Intl.NumberFormat
> Crée un utilitaire de formatage de devises multidevises.
> Supporte le yen japonais, le dollar américain et l'euro.
> Inclus l'affichage par locale, la conversion de taux de change et la validation des montants.
// src/lib/currency.ts
export type CurrencyCode = 'JPY' | 'USD' | 'EUR' | 'GBP' | 'CNY' | 'KRW';
interface FormatOptions {
currency: CurrencyCode;
locale?: string;
compact?: boolean; // Affichage abrégé comme "1,2M"
showSign?: boolean; // Afficher le signe +/-
}
/**
* Formater une devise
*/
export function formatCurrency(
amount: number,
options: FormatOptions
): string {
const { currency, locale = 'fr-FR', compact = false, showSign = false } = options;
const formatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency,
notation: compact ? 'compact' : 'standard',
signDisplay: showSign ? 'exceptZero' : 'auto',
// Les devises sans décimales (JPY/KRW) sont automatiquement détectées
});
return formatter.format(amount);
}
// Exemples d'utilisation
formatCurrency(1234567, { currency: 'JPY' }); // "1 234 567 JPY"
formatCurrency(1234.56, { currency: 'USD' }); // "1 234,56 $US"
formatCurrency(1234.56, { currency: 'EUR', locale: 'fr-FR' }); // "1 234,56 €"
formatCurrency(1234567, { currency: 'JPY', compact: true }); // "1 M JPY"
Précautions pour les calculs de devises
// src/lib/currency-math.ts
/**
* Pour éviter les erreurs de virgule flottante, calculer en entiers (unité minimale de devise)
* JPY : 1 yen = 1 | USD : 1 cent = 1 | EUR : 1 centime = 1
*/
export class Money {
constructor(
private readonly amountInMinorUnit: number,
private readonly currency: CurrencyCode
) {}
// Nombre de décimales en centimes/yens
private static decimals(currency: CurrencyCode): number {
return ['JPY', 'KRW'].includes(currency) ? 0 : 2;
}
static fromMajorUnit(amount: number, currency: CurrencyCode): Money {
const decimals = Money.decimals(currency);
const minor = Math.round(amount * Math.pow(10, decimals));
return new Money(minor, currency);
}
toMajorUnit(): number {
const decimals = Money.decimals(this.currency);
return this.amountInMinorUnit / Math.pow(10, decimals);
}
add(other: Money): Money {
this.assertSameCurrency(other);
return new Money(this.amountInMinorUnit + other.amountInMinorUnit, this.currency);
}
subtract(other: Money): Money {
this.assertSameCurrency(other);
return new Money(this.amountInMinorUnit - other.amountInMinorUnit, this.currency);
}
multiply(factor: number): Money {
return new Money(Math.round(this.amountInMinorUnit * factor), this.currency);
}
format(locale?: string): string {
return formatCurrency(this.toMajorUnit(), { currency: this.currency, locale });
}
private assertSameCurrency(other: Money) {
if (this.currency !== other.currency) {
throw new Error(`Devises différentes : ${this.currency} et ${other.currency}`);
}
}
}
// Exemple d'utilisation
const price = Money.fromMajorUnit(19.80, 'EUR');
const tax = price.multiply(0.2);
const total = price.add(tax);
console.log(total.format()); // "23,76 €"
Conversion de taux de change
// src/lib/exchange.ts
interface ExchangeRates {
base: CurrencyCode;
rates: Record<CurrencyCode, number>;
updatedAt: string;
}
let cachedRates: ExchangeRates | null = null;
export async function getExchangeRates(base: CurrencyCode = 'EUR'): Promise<ExchangeRates> {
// Réutiliser le cache s'il a moins d'une heure
if (cachedRates && Date.now() - new Date(cachedRates.updatedAt).getTime() < 3600000) {
return cachedRates;
}
const res = await fetch(`https://api.exchangerate-api.com/v4/latest/${base}`);
const data = await res.json();
cachedRates = {
base,
rates: data.rates,
updatedAt: new Date().toISOString(),
};
return cachedRates;
}
export async function convertCurrency(
amount: number,
from: CurrencyCode,
to: CurrencyCode
): Promise<{ converted: number; rate: number }> {
const rates = await getExchangeRates(from);
const rate = rates.rates[to];
return {
converted: Math.round(amount * rate * 100) / 100,
rate,
};
}
Composant de saisie de devise
// src/components/CurrencyInput.tsx
'use client';
import { useState } from 'react';
interface Props {
value: number;
currency: CurrencyCode;
onChange: (value: number) => void;
}
export function CurrencyInput({ value, currency, onChange }: Props) {
const [displayValue, setDisplayValue] = useState(value.toLocaleString());
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const raw = e.target.value.replace(/[^0-9.-]/g, '');
setDisplayValue(e.target.value);
const num = parseFloat(raw);
if (!isNaN(num)) onChange(num);
};
const handleBlur = () => {
setDisplayValue(value.toLocaleString());
};
const symbol = new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency,
currencyDisplay: 'narrowSymbol',
}).formatToParts(0).find((p) => p.type === 'currency')?.value || '';
return (
<div className="relative">
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">{symbol}</span>
<input
type="text"
value={displayValue}
onChange={handleChange}
onBlur={handleBlur}
className="w-full border rounded-lg pl-8 pr-4 py-2 text-right"
inputMode="decimal"
/>
</div>
);
}
Le piège de la virgule flottante
Le problème bien connu en JavaScript où 0.1 + 0.2 === 0.30000000000000004 est critique pour les calculs de devises. La règle d’or est de toujours travailler en entiers (centimes/yens) et de ne convertir en décimaux qu’à l’affichage.
Articles connexes
Pour le formatage des dates, consultez Gestion des dates et heures, et pour l’internationalisation en général, consultez le guide d’implémentation i18n.
Les spécifications détaillées de Intl.NumberFormat sont disponibles sur MDN (developer.mozilla.org/Intl/NumberFormat).
Related Posts
Comment booster vos projets personnels avec Claude Code [Avec exemples]
Apprenez à accélérer considérablement vos projets de développement personnels avec Claude Code. Inclut des exemples concrets et un workflow pratique de l'idée au déploiement.
Comment automatiser le refactoring avec Claude Code
Apprenez à automatiser efficacement le refactoring de code avec Claude Code. Inclut des prompts pratiques et des patterns de refactoring concrets pour des projets réels.
Guide complet de configuration CORS avec Claude Code
Découvrez le guide complet de configuration CORS avec Claude Code. Conseils pratiques et exemples de code inclus.