API Intl.NumberFormat

Formatez des nombres pour n'importe quelle locale avec l'API d'internationalisation intégrée à JavaScript

Introduction

Considérez l'affichage du nombre 1234567.89 dans votre application. L'utilisation de toString() produit "1234567.89", ce qui est difficile à lire et présuppose que tout le monde utilise des points pour les décimales et lit les nombres de gauche à droite. Les Américains s'attendent à "1,234,567.89", les Allemands à "1.234.567,89", et les utilisateurs en Inde à "12,34,567.89" avec des règles de regroupement différentes.

L'API Intl.NumberFormat résout ce problème en formatant les nombres selon les conventions spécifiques à chaque locale. Elle gère les séparateurs de milliers, les points décimaux, le regroupement des chiffres, les symboles monétaires, les signes de pourcentage, les unités de mesure et les systèmes de numération. Cela élimine le besoin de manipulation manuelle de chaînes ou de bibliothèques tierces.

Ce guide explique comment utiliser Intl.NumberFormat pour formater correctement les nombres pour les utilisateurs du monde entier, en commençant par l'utilisation de base et en progressant vers des fonctionnalités avancées comme le formatage des devises, la notation compacte et les modes d'arrondi personnalisés.

Formater un nombre avec les paramètres par défaut

Créez un formateur en appelant new Intl.NumberFormat() avec une chaîne de locale, puis appelez sa méthode format() avec un nombre.

const formatter = new Intl.NumberFormat('en-US');
formatter.format(1234567.89);
// "1,234,567.89"

Le formateur ajoute des séparateurs de milliers et formate le point décimal selon la locale. Sans spécifier de locale, le formateur utilise la locale par défaut de l'environnement d'exécution, généralement basée sur les paramètres système de l'utilisateur.

const formatter = new Intl.NumberFormat('de-DE');
formatter.format(1234567.89);
// "1.234.567,89"

Les conventions allemandes utilisent des points pour les séparateurs de milliers et des virgules pour les points décimaux, à l'inverse des conventions américaines. Le formateur gère automatiquement ces différences.

Comprendre les codes de locale

Un code de locale identifie une langue et éventuellement une région, écrit comme langue-REGION. La langue utilise un code ISO 639-1 à deux lettres comme en ou es. La région utilise un code ISO 3166-1 à deux lettres comme US ou MX.

new Intl.NumberFormat('en-US').format(1234.56);
// "1,234.56" (anglais américain)

new Intl.NumberFormat('en-GB').format(1234.56);
// "1,234.56" (anglais britannique)

new Intl.NumberFormat('es-ES').format(1234.56);
// "1234,56" (espagnol européen)

new Intl.NumberFormat('es-MX').format(1234.56);
// "1,234.56" (espagnol mexicain)

Les deux variantes de l'anglais utilisent le même formatage, mais les variantes espagnoles diffèrent. L'espagnol européen omet les séparateurs de milliers pour les nombres à quatre chiffres et utilise des virgules pour les décimales, tandis que l'espagnol mexicain suit les conventions américaines.

Choisissez les locales en fonction de l'emplacement de vos utilisateurs ou de leurs préférences linguistiques. Les applications déterminent généralement la locale à partir des paramètres utilisateur, de la langue du navigateur ou de la géolocalisation IP.

Choisir un style de formatage

L'option style détermine la catégorie de formatage. Passez un objet d'options comme second argument au constructeur.

new Intl.NumberFormat('en-US', {
  style: 'decimal'
}).format(1234.56);
// "1,234.56"

Le style decimal est celui par défaut. Les autres styles sont currency, percent, et unit.

Formater les devises avec symboles et codes

Le style currency nécessite une option currency avec un code de devise ISO 4217.

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(1234.56);
// "$1,234.56"

Le formateur ajoute le symbole dollar et formate par défaut avec deux décimales, le standard pour la plupart des devises. Les différentes locales positionnent le symbole différemment.

new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
}).format(1234.56);
// "1.234,56 €"

Le formatage allemand place le symbole euro après le montant avec un espace. L'option currency détermine quelle devise afficher, et non quelles conventions de locale suivre. La locale détermine les conventions de formatage, tandis que la devise détermine le symbole.

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'EUR'
}).format(1234.56);
// "€1,234.56"

Les conventions de formatage américaines avec le symbole euro produisent un signe euro avant le montant, suivant les conventions de placement américaines plutôt qu'européennes.

Contrôler le format d'affichage des devises

L'option currencyDisplay modifie la façon dont la devise apparaît dans la chaîne formatée.

const amount = 1234.56;

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'symbol'
}).format(amount);
// "$1,234.56"

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'code'
}).format(amount);
// "USD 1,234.56"

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'name'
}).format(amount);
// "1,234.56 US dollars"

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'narrowSymbol'
}).format(amount);
// "$1,234.56"

L'option symbol est celle par défaut et affiche le symbole de devise comme $ ou . L'option code affiche le code de devise à trois lettres. L'option name écrit le nom de la devise en toutes lettres. L'option narrowSymbol utilise le symbole de devise étroit d'une locale, qui peut être ambigu mais économise de l'espace.

La différence entre symbol et narrowSymbol devient évidente avec les devises qui partagent des symboles.

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'CAD',
  currencyDisplay: 'symbol'
}).format(100);
// "CA$100.00"

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'CAD',
  currencyDisplay: 'narrowSymbol'
}).format(100);
// "$100.00"

Les dollars canadiens s'affichent comme CA$ avec l'option symbol pour les distinguer des dollars américains, mais s'affichent simplement comme $ avec narrowSymbol.

Formater les montants négatifs en devise avec la notation comptable

L'option currencySign contrôle l'apparence des montants négatifs.

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'standard'
}).format(-1234.56);
// "-$1,234.56"

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting'
}).format(-1234.56);
// "($1,234.56)"

L'option standard est celle par défaut et utilise un signe moins. L'option accounting entoure les montants négatifs de parenthèses, suivant les conventions comptables. Cela rend les nombres négatifs visuellement plus distincts dans les rapports financiers.

Formater les pourcentages

Le style percent multiplie le nombre par 100 et ajoute un signe de pourcentage.

new Intl.NumberFormat('en-US', {
  style: 'percent'
}).format(0.1234);
// "12%"

new Intl.NumberFormat('en-US', {
  style: 'percent'
}).format(0.1256);
// "13%"

Le formateur arrondit à l'entier le plus proche par défaut. Contrôlez les décimales avec les options de chiffres.

new Intl.NumberFormat('en-US', {
  style: 'percent',
  minimumFractionDigits: 2
}).format(0.1234);
// "12.34%"

Passez la forme décimale du pourcentage, pas la forme multipliée. Le formateur gère la multiplication.

Formater les mesures avec des unités

Le style unit nécessite une option unit avec un identifiant d'unité.

new Intl.NumberFormat('en-US', {
  style: 'unit',
  unit: 'kilometer-per-hour'
}).format(100);
// "100 km/h"

new Intl.NumberFormat('en-GB', {
  style: 'unit',
  unit: 'mile-per-hour'
}).format(100);
// "100 mph"

Les unités disponibles comprennent les mesures de longueur (meter, kilometer, mile), les durées (second, minute, hour), le stockage numérique (byte, kilobyte, megabyte), les températures (celsius, fahrenheit), et bien d'autres. Les unités composées comme kilometer-per-hour combinent des unités simples avec des traits d'union.

L'option unitDisplay contrôle le format de l'unité.

const distance = 1234.5;

new Intl.NumberFormat('en-US', {
  style: 'unit',
  unit: 'kilometer',
  unitDisplay: 'long'
}).format(distance);
// "1,234.5 kilometers"

new Intl.NumberFormat('en-US', {
  style: 'unit',
  unit: 'kilometer',
  unitDisplay: 'short'
}).format(distance);
// "1,234.5 km"

new Intl.NumberFormat('en-US', {
  style: 'unit',
  unit: 'kilometer',
  unitDisplay: 'narrow'
}).format(distance);
// "1,234.5km"

L'option long écrit le nom complet de l'unité. L'option short utilise des abréviations. L'option narrow utilise la forme la plus compacte, qui peut être ambiguë.

Afficher les grands nombres avec une notation compacte

L'option notation modifie la façon dont les nombres sont exprimés. La valeur compact utilise des formes abrégées spécifiques à la locale pour les grands nombres.

new Intl.NumberFormat('en-US', {
  notation: 'compact'
}).format(1234567);
// "1.2M"

new Intl.NumberFormat('en-US', {
  notation: 'compact'
}).format(987654321);
// "988M"

La notation compacte arrondit à une décimale par défaut et ajoute des suffixes comme K pour les milliers, M pour les millions et B pour les milliards. Ce format apparaît dans les compteurs d'abonnés sur les réseaux sociaux, les compteurs de vues de vidéos et les tableaux de bord d'analyse.

L'option compactDisplay contrôle la longueur du suffixe.

new Intl.NumberFormat('en-US', {
  notation: 'compact',
  compactDisplay: 'short'
}).format(1234567);
// "1.2M"

new Intl.NumberFormat('en-US', {
  notation: 'compact',
  compactDisplay: 'long'
}).format(1234567);
// "1.2 million"

L'option short est celle par défaut et utilise des symboles. L'option long écrit le mot de magnitude en toutes lettres. Différentes locales utilisent différents suffixes.

new Intl.NumberFormat('zh-CN', {
  notation: 'compact'
}).format(123456789);
// "1.2亿"

Le chinois utilise 亿 pour les centaines de millions, reflétant le système de regroupement numérique de la langue.

Exprimer des nombres très grands ou très petits en notation scientifique

La notation scientific exprime les nombres comme un coefficient multiplié par une puissance de dix.

new Intl.NumberFormat('en-US', {
  notation: 'scientific'
}).format(123456789);
// "1.235E8"

new Intl.NumberFormat('en-US', {
  notation: 'scientific'
}).format(0.00000123);
// "1.23E-6"

Ce format convient bien aux très grands nombres (distances astronomiques, comptages moléculaires) et aux très petits nombres (masses de particules, mesures à l'échelle nanométrique). L'exposant apparaît toujours comme un multiple de un.

Utiliser la notation d'ingénierie pour les applications techniques

La notation engineering est similaire à la notation scientifique mais limite les exposants à des multiples de trois.

new Intl.NumberFormat('en-US', {
  notation: 'engineering'
}).format(123456789);
// "123.457E6"

new Intl.NumberFormat('en-US', {
  notation: 'engineering'
}).format(1234);
// "1.234E3"

La notation d'ingénierie s'aligne sur les préfixes d'unités SI (kilo, mega, giga), ce qui en fait une norme dans les contextes d'ingénierie et de physique. Le coefficient varie de 1 à 999.

Contrôler les décimales avec les chiffres fractionnaires

Les options minimumFractionDigits et maximumFractionDigits contrôlent le nombre de chiffres qui apparaissent après la virgule.

new Intl.NumberFormat('en-US', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
}).format(1234.5);
// "1,234.50"

new Intl.NumberFormat('en-US', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
}).format(1234.567);
// "1,234.57"

Le minimum garantit l'apparition des zéros finaux lorsque nécessaire. Le maximum arrondit les décimales plus longues. Les formateurs de devises utilisent par défaut deux décimales. Les formateurs décimaux utilisent par défaut zéro comme minimum et trois comme maximum.

new Intl.NumberFormat('en-US', {
  minimumFractionDigits: 0,
  maximumFractionDigits: 0
}).format(1234.567);
// "1,235"

Définir les deux à zéro arrondit à l'entier le plus proche.

Contrôler la précision globale avec les chiffres significatifs

Les options minimumSignificantDigits et maximumSignificantDigits contrôlent la précision totale indépendamment de la position de la virgule décimale.

new Intl.NumberFormat('en-US', {
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 3
}).format(1234.567);
// "1,230"

new Intl.NumberFormat('en-US', {
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 3
}).format(0.001234);
// "0.00123"

Les chiffres significatifs comptent tous les chiffres à l'exception des zéros non significatifs. Le premier exemple arrondit à trois chiffres, produisant 1230. Le second exemple conserve trois chiffres après les zéros non significatifs, produisant 0.00123.

Les options de chiffres significatifs remplacent les options de chiffres fractionnaires lorsque les deux sont spécifiées.

Choisir une stratégie d'arrondi avec les modes d'arrondi

L'option roundingMode détermine comment les nombres sont arrondis lorsqu'une troncature est nécessaire.

const value = 1.5;

new Intl.NumberFormat('en-US', {
  maximumFractionDigits: 0,
  roundingMode: 'halfExpand'
}).format(value);
// "2"

new Intl.NumberFormat('en-US', {
  maximumFractionDigits: 0,
  roundingMode: 'halfTrunc'
}).format(value);
// "1"

Le mode halfExpand est le mode par défaut et arrondit 0,5 en s'éloignant de zéro, une stratégie d'arrondi courante enseignée dans les écoles. Le mode halfTrunc arrondit 0,5 vers zéro.

Les autres modes comprennent :

  • ceil : Toujours arrondir vers l'infini positif
  • floor : Toujours arrondir vers l'infini négatif
  • expand : Toujours arrondir en s'éloignant de zéro
  • trunc : Toujours arrondir vers zéro
  • halfCeil : Arrondir 0,5 vers l'infini positif
  • halfFloor : Arrondir 0,5 vers l'infini négatif
  • halfEven : Arrondir 0,5 vers le nombre pair le plus proche
const prices = [1.5, 2.5, 3.5];

prices.map(price =>
  new Intl.NumberFormat('en-US', {
    maximumFractionDigits: 0,
    roundingMode: 'halfEven'
  }).format(price)
);
// ["2", "2", "4"]

Le mode halfEven, également appelé arrondi bancaire, réduit le biais d'arrondi dans les calculs répétés. Lors de l'arrondi de 0,5, il choisit le nombre pair le plus proche. Cela produit 2 pour 1,5 et 2,5, mais 4 pour 3,5.

Les applications financières utilisent ceil pour arrondir les frais à la hausse et floor pour arrondir les remboursements à la baisse. Les applications statistiques utilisent halfEven pour minimiser les erreurs d'arrondi cumulatives.

Contrôler les séparateurs de milliers avec les options de regroupement

L'option useGrouping contrôle l'affichage des séparateurs de milliers.

new Intl.NumberFormat('en-US', {
  useGrouping: true
}).format(123456);
// "123,456"

new Intl.NumberFormat('en-US', {
  useGrouping: false
}).format(123456);
// "123456"

La valeur true est celle par défaut. La valeur false supprime tous les séparateurs. Les valeurs de type chaîne offrent un contrôle plus précis.

new Intl.NumberFormat('en-US', {
  useGrouping: 'always'
}).format(1234);
// "1,234"

new Intl.NumberFormat('en-US', {
  useGrouping: 'min2'
}).format(1234);
// "1234"

La valeur always utilise des séparateurs dans tous les cas. La valeur min2 omet les séparateurs pour les nombres à quatre chiffres. La valeur auto suit les préférences de la locale, qui correspondent généralement au comportement de min2.

La notation compacte utilise min2 par défaut car les nombres compacts nécessitent rarement des séparateurs internes.

Afficher explicitement les signes avec les options d'affichage de signe

L'option signDisplay contrôle quand les signes positifs et négatifs apparaissent.

new Intl.NumberFormat('en-US', {
  signDisplay: 'auto'
}).format(100);
// "100"

new Intl.NumberFormat('en-US', {
  signDisplay: 'always'
}).format(100);
// "+100"

La valeur auto est celle par défaut et affiche les signes moins pour les nombres négatifs mais pas les signes plus pour les nombres positifs. La valeur always affiche les deux.

new Intl.NumberFormat('en-US', {
  signDisplay: 'exceptZero'
}).format(0);
// "0"

new Intl.NumberFormat('en-US', {
  signDisplay: 'always'
}).format(0);
// "+0"

La valeur exceptZero omet les signes pour les valeurs zéro même avec le comportement always. Cela évite d'afficher de façon confuse +0 et -0.

new Intl.NumberFormat('en-US', {
  signDisplay: 'never'
}).format(-100);
// "100"

La valeur never supprime complètement les signes, n'affichant que la valeur absolue.

Les applications financières utilisent always pour mettre en évidence les gains avec des signes plus. Les affichages de température utilisent exceptZero pour éviter d'afficher +0° ou -0°.

Décomposer le résultat formaté en parties

La méthode formatToParts() renvoie un tableau d'objets représentant chaque composant de la chaîne formatée.

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).formatToParts(1234.56);

Cela renvoie :

[
  { type: 'currency', value: '$' },
  { type: 'integer', value: '1' },
  { type: 'group', value: ',' },
  { type: 'integer', value: '234' },
  { type: 'decimal', value: '.' },
  { type: 'fraction', value: '56' }
]

Chaque objet possède un type identifiant le composant et une value contenant la chaîne. Le type peut être currency, integer, group, decimal, fraction, literal, minusSign, plusSign, percentSign, ou autres.

Cela permet une personnalisation du style de chaque composant.

const parts = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).formatToParts(1234.56);

const formatted = parts.map(part => {
  if (part.type === 'currency') {
    return `<span class="currency">${part.value}</span>`;
  }
  if (part.type === 'integer') {
    return `<span class="integer">${part.value}</span>`;
  }
  return part.value;
}).join('');

// <span class="currency">$</span><span class="integer">1</span>,<span class="integer">234</span>.56

Cela produit du HTML avec des composants stylisés. La même approche fonctionne pour appliquer différentes couleurs aux montants négatifs, agrandir les symboles de devise ou animer des chiffres individuels.

Formater des plages de nombres

La méthode formatRange() formate deux nombres sous forme de plage.

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).formatRange(100, 200);
// "$100.00 – $200.00"

Le formateur utilise un séparateur de plage spécifique à la locale (un tiret cadratin en français) et inclut les deux symboles de devise. Si les valeurs se formatent en une même chaîne, le formateur renvoie une valeur unique avec un tilde.

new Intl.NumberFormat('en-US', {
  notation: 'compact'
}).formatRange(1200, 1800);
// "~1K"

Les valeurs 1200 et 1800 sont formatées comme 1K en notation compacte, donc le formateur affiche approximativement 1K.

La méthode formatRangeToParts() renvoie les parties de la plage.

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).formatRangeToParts(100, 200);

Cela renvoie :

[
  { type: 'currency', value: '$', source: 'startRange' },
  { type: 'integer', value: '100', source: 'startRange' },
  { type: 'decimal', value: '.', source: 'startRange' },
  { type: 'fraction', value: '00', source: 'startRange' },
  { type: 'literal', value: ' – ', source: 'shared' },
  { type: 'currency', value: '$', source: 'endRange' },
  { type: 'integer', value: '200', source: 'endRange' },
  { type: 'decimal', value: '.', source: 'endRange' },
  { type: 'fraction', value: '00', source: 'endRange' }
]

La propriété source identifie si la partie provient de la valeur de début, de la valeur de fin ou du séparateur de plage.

Les plages de prix, les plages de dates et les plages de mesures utilisent cette méthode pour un formatage approprié et sensible à la locale.

Inspecter les options résolues

La méthode resolvedOptions() renvoie un objet montrant les options réelles utilisées par le formateur.

const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

formatter.resolvedOptions();

Cela renvoie :

{
  locale: 'en-US',
  numberingSystem: 'latn',
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'symbol',
  currencySign: 'standard',
  minimumIntegerDigits: 1,
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
  useGrouping: 'auto',
  notation: 'standard',
  signDisplay: 'auto',
  roundingMode: 'halfExpand'
}

L'objet inclut les options explicitement définies et les valeurs par défaut. La locale peut différer de la locale demandée si le système a résolu vers une locale différente mais compatible. Le numberingSystem indique quels caractères numériques le formateur utilise.

Cette méthode aide à déboguer un formatage inattendu en révélant tous les paramètres actifs.

Réutiliser les formateurs pour de meilleures performances

La création d'une instance NumberFormat implique le chargement de données de locale et le traitement des options. Réutilisez les instances lors du formatage de plusieurs valeurs avec les mêmes paramètres.

// Inefficace : crée un nouveau formateur pour chaque valeur
prices.map(price =>
  new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD'
  }).format(price)
);

// Efficace : crée le formateur une seule fois
const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

prices.map(price => formatter.format(price));

La seconde approche est significativement plus rapide lors du formatage de nombreuses valeurs. Créez les formateurs en dehors des boucles et des fonctions de rendu des composants.

Les moteurs JavaScript modernes mettent en cache les instances NumberFormat en interne, mais la réutilisation explicite offre de meilleures performances et un code plus clair.

Vérifier la compatibilité des navigateurs

L'API Intl.NumberFormat est prise en charge dans tous les navigateurs modernes. Chrome, Firefox, Safari et Edge prennent en charge l'API de base depuis 2016. Les fonctionnalités avancées comme formatRange(), formatRangeToParts() et les options étendues de roundingMode ont été prises en charge plus récemment mais sont maintenant disponibles dans les versions actuelles des navigateurs.

Vérifiez la prise en charge en utilisant :

if (typeof Intl !== 'undefined' && Intl.NumberFormat) {
  // NumberFormat est pris en charge
  const formatter = new Intl.NumberFormat('en-US');
}

Vérifiez les fonctionnalités spécifiques :

const formatter = new Intl.NumberFormat('en-US');

if (typeof formatter.formatRange === 'function') {
  // formatRange est pris en charge
}

Les applications nécessitant une prise en charge des navigateurs plus anciens peuvent utiliser des polyfills comme @formatjs/intl-numberformat, mais la plupart des applications modernes peuvent utiliser l'API native sans solutions de repli.

Quand utiliser NumberFormat

Utilisez Intl.NumberFormat pour :

  • Afficher des nombres aux utilisateurs dans n'importe quel contexte d'interface utilisateur
  • Formater des montants en devise dans les applications de commerce électronique
  • Présenter des pourcentages dans les tableaux de bord d'analyse
  • Afficher le nombre d'abonnés, le nombre de vues et autres métriques sociales
  • Formater des mesures et des valeurs scientifiques
  • Créer des applications internationalisées qui prennent en charge plusieurs locales

N'utilisez pas Intl.NumberFormat pour :

  • Les calculs internes ou le traitement de données
  • Stocker des valeurs dans des bases de données
  • Sérialiser des données pour les API
  • Analyser les entrées utilisateur pour les reconvertir en nombres

NumberFormat est un outil de couche de présentation. Conservez les valeurs numériques brutes pour les calculs et le stockage, en appliquant le formatage uniquement lors de l'affichage des valeurs aux utilisateurs.