API Intl.NumberFormat

Formatez les nombres pour n'importe quelle locale avec l'API d'internationalisation intégrée de 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 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 s'attendent à "1.234.567,89", et les utilisateurs en Inde s'attendent à "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 ces différences automatiquement.

Comprendre les codes de locale

Un code de locale identifie une langue et éventuellement une région, écrit sous la forme language-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" (American English)

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

new Intl.NumberFormat('es-ES').format(1234.56);
// "1234,56" (European Spanish)

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

Les deux variantes anglaises 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 ou des préférences linguistiques de vos utilisateurs. 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 deuxième argument au constructeur.

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

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

Formater la devise avec des symboles et des 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 à deux décimales, la norme pour la plupart des devises. 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 de la devise

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 l'option par défaut et affiche le symbole de la devise comme $ ou . L'option code affiche le code de devise à trois lettres. L'option name écrit le nom complet de la devise. 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 les mêmes 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 avec la notation comptable

L'option currencySign contrôle l'affichage 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 encadre les montants négatifs entre parenthèses, suivant les conventions comptables. Cela rend les nombres négatifs plus visuellement 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 incluent 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 de l'unité en toutes lettres. 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 la notation compacte

L'option notation modifie la façon dont les nombres sont exprimés. La valeur compact utilise des formes courtes 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 analytiques.

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 la valeur 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 fonctionne bien pour les très grands nombres (distances astronomiques, comptages moléculaires) et les 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 contraint 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 avec les préfixes d'unités SI (kilo, méga, giga), ce qui en fait la 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 de zéros de fin 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 minimum et trois maximum.

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

Définir les deux à zéro arrondit au nombre 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.

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 sauf les zéros de tête. Le premier exemple arrondit à trois chiffres, produisant 1230. Le second exemple conserve trois chiffres après les zéros de tête, 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 s'arrondissent lorsque la 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 incluent :

  • 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 la valeur par défaut. La valeur false supprime tous les séparateurs. Les valeurs de 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 omit les séparateurs pour les nombres à quatre chiffres. La valeur auto suit les préférences locales, qui correspondent généralement au comportement min2.

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

Afficher les signes explicitement avec les options d'affichage des signes

L'option signDisplay contrôle l'affichage des signes positifs et négatifs.

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

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

La valeur auto est la valeur 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 les affichages déroutants +0 et -0.

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

La valeur never supprime entièrement 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 la sortie formatée 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 d'appliquer un style personnalisé aux composants individuels.

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 monétaires 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 demi-cadratin en français) et inclut les deux symboles monétaires. Si les valeurs se formatent en la même chaîne, le formateur renvoie une valeur unique avec un tilde.

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

1200 et 1800 se formatent tous deux comme 1K en notation compacte, donc le formateur affiche environ 1K.

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

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

Cela retourne :

[
  { 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 aux paramètres régionaux.

Inspecter les options résolues

La méthode resolvedOptions() retourne 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 retourne :

{
  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. Le locale peut différer des paramètres régionaux demandés si le système a résolu vers des paramètres régionaux différents mais compatibles. 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 des données de paramètres régionaux et le traitement des options. Réutilisez les instances lors du formatage de plusieurs valeurs avec les mêmes paramètres.

// Inefficient: creates new formatter for each value
prices.map(price =>
  new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD'
  }).format(price)
);

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

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

La deuxième approche est nettement 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 telles que formatRange(), formatRangeToParts() et les options roundingMode étendues ont obtenu une prise en charge plus récemment mais sont désormais disponibles dans les versions actuelles des navigateurs.

Vérifiez la prise en charge en utilisant :

if (typeof Intl !== 'undefined' && Intl.NumberFormat) {
  // NumberFormat is supported
  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 is supported
}

Les applications nécessitant la prise en charge de 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 devises dans les applications e-commerce
  • Afficher des pourcentages dans les tableaux de bord analytiques
  • Afficher le nombre d'abonnés, de vues et autres métriques sociales
  • Formater des mesures et des valeurs scientifiques
  • Créer des applications internationalisées prenant 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 dans les calculs et le stockage, en appliquant le formatage uniquement lors de l'affichage des valeurs aux utilisateurs.