Comment formater les nombres ordinaux comme 1er, 2e, 3e

Utiliser JavaScript pour afficher les nombres ordinaux avec des suffixes et un formatage adaptés à la locale

Introduction

Les nombres ordinaux indiquent la position ou le rang dans une séquence. En anglais, on écrit 1st, 2nd, 3rd, 4th pour décrire les positions d'arrivée dans une course ou les éléments d'une liste. Ces suffixes aident à distinguer les nombres ordinaux des nombres cardinaux ordinaires.

Différentes langues utilisent des conventions complètement différentes pour les ordinaux. L'anglais ajoute des suffixes comme st, nd, rd et th. Le français utilise des lettres en exposant comme 1er et 2e. L'allemand ajoute un point après le nombre comme 1. et 2. Le japonais préfixe les nombres avec le caractère 第. Lorsque vous codez en dur les suffixes ordinaux anglais, vous supposez que tous les utilisateurs suivent la même convention.

JavaScript fournit l'API Intl.PluralRules avec un type ordinal pour gérer ces différences automatiquement. Cette leçon explique ce que sont les nombres ordinaux, pourquoi leur formatage varie selon les langues et comment les formater correctement pour n'importe quelle locale.

Ce que sont les nombres ordinaux

Les nombres ordinaux expriment la position, le rang ou l'ordre dans une séquence. Ils répondent à la question "lequel" plutôt que "combien". Les nombres 1er, 2e, 3e décrivent des positions dans une course. Premier, deuxième, troisième décrivent des éléments dans une liste.

Les nombres cardinaux expriment une quantité ou un montant. Ils répondent à la question "combien". Les nombres 1, 2, 3 décrivent des comptages d'objets. Un, deux, trois décrivent des quantités.

La même valeur numérique sert les deux objectifs selon le contexte. Le nombre 5 est cardinal dans "5 pommes" mais ordinal dans "5e place". La distinction est importante car de nombreuses langues formatent les ordinaux différemment des cardinaux.

En français, les ordinaux ont des formes de mots uniques. Premier, deuxième, troisième, quatrième, cinquième sont des mots distincts. Au-dessus de 10, le français forme les ordinaux en ajoutant des suffixes. Onzième, douzième, vingtième, vingt et unième suivent des modèles mais nécessitent des suffixes.

Lorsqu'on écrit des ordinaux sous forme de chiffres plutôt que de mots, le français ajoute des suffixes er, e, ème. Ces suffixes suivent des règles spécifiques basées sur le nombre.

Pourquoi le formatage ordinal varie selon la locale

Différentes langues ont développé différents systèmes pour exprimer les nombres ordinaux. Ces conventions reflètent les règles grammaticales, les systèmes d'écriture et les pratiques culturelles propres à chaque langue.

En anglais, les ordinaux utilisent quatre suffixes différents. Les nombres se terminant par 1 utilisent st, ceux se terminant par 2 utilisent nd, ceux se terminant par 3 utilisent rd, et tous les autres nombres utilisent th. Cependant, les nombres se terminant par 11, 12 ou 13 utilisent tous th. Cela donne 1st, 2nd, 3rd, 4th, 11th, 12th, 13th, 21st, 22nd, 23rd.

En français, les ordinaux utilisent des abréviations en exposant. Le premier élément utilise 1er pour le masculin ou 1re pour le féminin. Tous les autres ordinaux utilisent e en exposant, comme 2e, 3e, 4e. Le formatage inclut la typographie en exposant, pas seulement les lettres du suffixe.

En allemand, les ordinaux utilisent un point après le nombre. La notation 1., 2., 3. représente premier, deuxième, troisième. Ce point indique que le lecteur doit mentalement ajouter la terminaison grammaticale appropriée lors de la lecture à haute voix.

En espagnol, les ordinaux utilisent des indicateurs genrés en exposant. Les ordinaux masculins utilisent 1.º, 2.º, 3.º tandis que les ordinaux féminins utilisent 1.ª, 2.ª, 3.ª. Le point sépare le nombre de l'indicateur.

En japonais, les ordinaux ajoutent le préfixe 第 avant le nombre. Premier, deuxième, troisième apparaissent comme 第一, 第二, 第三. Ce préfixe change la signification de cardinal à ordinal.

Lorsque vous construisez des chaînes ordinales en concaténant des nombres avec des suffixes codés en dur, vous forcez tous les utilisateurs à interpréter les conventions anglaises. Cela rend votre application plus difficile à utiliser pour les personnes qui s'attendent à des formats différents.

Comprendre Intl.PluralRules avec le type ordinal

L'API Intl.PluralRules détermine à quelle catégorie de pluriel appartient un nombre pour une locale donnée. Bien que cette API soit couramment utilisée pour choisir entre les formes singulières et plurielles des mots, elle gère également les nombres ordinaux.

Le constructeur accepte un identifiant de locale et un objet d'options. Définissez l'option type sur "ordinal" pour travailler avec des nombres ordinaux au lieu de nombres cardinaux.

const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });

Cela crée un objet de règles qui comprend les modèles ordinaux anglais. La méthode select() renvoie un nom de catégorie pour n'importe quel nombre que vous lui transmettez.

const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });

console.log(rules.select(1));
// Sortie : "one"

console.log(rules.select(2));
// Sortie : "two"

console.log(rules.select(3));
// Sortie : "few"

console.log(rules.select(4));
// Sortie : "other"

Les catégories renvoyées sont des termes linguistiques, pas les suffixes réels. La catégorie "one" correspond aux nombres qui prennent le suffixe st en anglais. La catégorie "two" correspond aux suffixes nd. La catégorie "few" correspond aux suffixes rd. La catégorie "other" correspond aux suffixes th.

Vous associez ces noms de catégories aux suffixes appropriés pour votre locale. L'API gère les règles complexes pour déterminer à quelle catégorie appartient chaque nombre.

Construction d'une fonction de formatage ordinal

Pour formater les nombres ordinaux, vous combinez Intl.PluralRules avec une correspondance entre les catégories de pluriel et les suffixes. Créez une fonction de formatage qui prend un nombre et renvoie la chaîne formatée.

function formatOrdinal(number, locale) {
  const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
  const category = rules.select(number);

  const suffixes = {
    one: 'st',
    two: 'nd',
    few: 'rd',
    other: 'th'
  };

  const suffix = suffixes[category];
  return `${number}${suffix}`;
}

console.log(formatOrdinal(1, 'en-US'));
// Sortie : "1st"

console.log(formatOrdinal(2, 'en-US'));
// Sortie : "2nd"

console.log(formatOrdinal(3, 'en-US'));
// Sortie : "3rd"

console.log(formatOrdinal(4, 'en-US'));
// Sortie : "4th"

Cette fonction crée une nouvelle instance de PluralRules chaque fois qu'elle s'exécute. Pour de meilleures performances, créez l'objet rules une seule fois et réutilisez-le pour plusieurs nombres.

const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });

const suffixes = {
  one: 'st',
  two: 'nd',
  few: 'rd',
  other: 'th'
};

function formatOrdinal(number) {
  const category = rules.select(number);
  const suffix = suffixes[category];
  return `${number}${suffix}`;
}

console.log(formatOrdinal(1));
// Sortie : "1st"

console.log(formatOrdinal(21));
// Sortie : "21st"

console.log(formatOrdinal(22));
// Sortie : "22nd"

console.log(formatOrdinal(23));
// Sortie : "23rd"

L'API gère correctement les nombres comme 11, 12 et 13, qui utilisent tous "th" malgré leurs chiffres finaux.

console.log(formatOrdinal(11));
// Sortie : "11th"

console.log(formatOrdinal(12));
// Sortie : "12th"

console.log(formatOrdinal(13));
// Sortie : "13th"

Les règles de pluriel encodent tous les cas spéciaux et les exceptions pour la locale. Vous n'avez pas besoin d'écrire une logique conditionnelle pour gérer ces cas particuliers.

Formatage des nombres ordinaux pour différentes locales

Les catégories de pluriel et leurs significations changent selon les locales. Certaines langues ont moins de catégories que l'anglais. D'autres ont des règles différentes pour déterminer quels nombres appartiennent à chaque catégorie.

Le gallois utilise un système de catégorisation différent. Les règles identifient plus de catégories, chacune correspondant à différentes formes ordinales en gallois.

const enRules = new Intl.PluralRules('en-US', { type: 'ordinal' });
const cyRules = new Intl.PluralRules('cy', { type: 'ordinal' });

console.log(enRules.select(1));
// Sortie : "one"

console.log(cyRules.select(1));
// Sortie : "one"

console.log(enRules.select(2));
// Sortie : "two"

console.log(cyRules.select(2));
// Sortie : "two"

console.log(enRules.select(5));
// Sortie : "other"

console.log(cyRules.select(5));
// Sortie : "many"

Pour prendre en charge plusieurs locales, vous avez besoin de différentes correspondances de suffixes pour chaque locale. Les catégories restent les mêmes, mais les suffixes changent.

const ordinalSuffixes = {
  'en-US': {
    one: 'st',
    two: 'nd',
    few: 'rd',
    other: 'th'
  },
  'fr-FR': {
    one: 'er',
    other: 'e'
  }
};

function formatOrdinal(number, locale) {
  const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
  const category = rules.select(number);
  const suffixes = ordinalSuffixes[locale];
  const suffix = suffixes[category] || suffixes.other;
  return `${number}${suffix}`;
}

console.log(formatOrdinal(1, 'en-US'));
// Sortie : "1st"

console.log(formatOrdinal(1, 'fr-FR'));
// Sortie : "1er"

console.log(formatOrdinal(2, 'en-US'));
// Sortie : "2nd"

console.log(formatOrdinal(2, 'fr-FR'));
// Sortie : "2e"

Cette approche fonctionne bien lorsque vous contrôlez les chaînes de suffixes pour chaque locale. Cependant, elle nécessite de maintenir des données de suffixes pour chaque locale que vous prenez en charge.

Comprendre les catégories de pluriels ordinaux

L'API Intl.PluralRules utilise six noms de catégories possibles. Différentes locales utilisent différents sous-ensembles de ces catégories.

Les catégories sont zero, one, two, few, many, et other. Toutes les langues ne distinguent pas les six catégories. Les ordinaux anglais n'utilisent que quatre catégories : one, two, few, et other.

Les noms des catégories ne correspondent pas directement aux valeurs numériques. La catégorie "one" inclut 1, 21, 31, 41, et tous les nombres se terminant par 1 sauf 11. La catégorie "two" inclut 2, 22, 32, 42, et tous les nombres se terminant par 2 sauf 12.

Vous pouvez vérifier quelles catégories une locale utilise en appelant la méthode resolvedOptions() et en examinant la propriété pluralCategories.

const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });
const options = rules.resolvedOptions();

console.log(options.pluralCategories);
// Sortie : ["one", "two", "few", "other"]

Cela montre que les ordinaux anglais utilisent quatre catégories. D'autres locales utilisent différents ensembles de catégories.

const rules = new Intl.PluralRules('fr-FR', { type: 'ordinal' });
const options = rules.resolvedOptions();

console.log(options.pluralCategories);
// Sortie : ["one", "other"]

Les ordinaux français ne distinguent qu'entre one et other. Cette catégorisation plus simple reflète les règles de suffixe plus simples en français.

Formater les nombres ordinaux pour la locale de l'utilisateur

Au lieu de coder en dur une locale spécifique, vous pouvez utiliser la langue préférée de l'utilisateur depuis le navigateur. La propriété navigator.language renvoie la préférence linguistique principale de l'utilisateur.

const userLocale = navigator.language;
const rules = new Intl.PluralRules(userLocale, { type: 'ordinal' });

const suffixes = {
  one: 'st',
  two: 'nd',
  few: 'rd',
  other: 'th'
};

function formatOrdinal(number) {
  const category = rules.select(number);
  const suffix = suffixes[category] || suffixes.other;
  return `${number}${suffix}`;
}

console.log(formatOrdinal(1));
// La sortie varie selon la locale de l'utilisateur

Cette approche s'adapte automatiquement à la préférence linguistique de l'utilisateur. Cependant, vous devez toujours fournir des mappages de suffixes appropriés pour chaque locale que votre application prend en charge.

Pour les locales sans mappages de suffixes spécifiques, vous pouvez revenir à un comportement par défaut ou afficher le nombre sans suffixe.

function formatOrdinal(number, locale = navigator.language) {
  const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
  const category = rules.select(number);

  const localeMapping = ordinalSuffixes[locale];

  if (!localeMapping) {
    return String(number);
  }

  const suffix = localeMapping[category] || localeMapping.other || '';
  return `${number}${suffix}`;
}

Cette fonction renvoie simplement le nombre lorsqu'aucun mappage de suffixe n'existe pour la locale.

Cas d'utilisation courants pour les nombres ordinaux

Les nombres ordinaux apparaissent dans plusieurs contextes courants dans les interfaces utilisateur. Comprendre ces cas d'utilisation vous aide à décider quand formater les nombres en ordinaux.

Les classements et tableaux de leaders affichent les positions des utilisateurs. Une application de jeu affiche "1er place", "2e place", "3e place" au lieu de "place 1", "place 2", "place 3".

function formatRanking(position) {
  const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });
  const category = rules.select(position);

  const suffixes = {
    one: 'st',
    two: 'nd',
    few: 'rd',
    other: 'th'
  };

  const suffix = suffixes[category];
  return `${position}${suffix} place`;
}

console.log(formatRanking(1));
// Output: "1st place"

console.log(formatRanking(42));
// Output: "42nd place"

Le formatage des dates utilise parfois des ordinaux pour le jour du mois. Certaines locales écrivent "1er janvier" au lieu de "1 janvier".

Les instructions étape par étape utilisent des ordinaux pour numéroter chaque étape. Un tutoriel affiche "1ère étape : Installer le logiciel", "2e étape : Configurer les paramètres", "3e étape : Démarrer l'application".

Les éléments de liste dans de longues séquences bénéficient du formatage ordinal lorsque l'accent mis sur la position importe plus que la simple énumération.

Réutilisation des objets de règles pour la performance

La création d'une nouvelle instance Intl.PluralRules implique le chargement des données de locale et le traitement des options. Lorsque vous formatez plusieurs nombres ordinaux avec la même locale, créez l'objet de règles une seule fois et réutilisez-le.

const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });

const suffixes = {
  one: 'st',
  two: 'nd',
  few: 'rd',
  other: 'th'
};

function formatOrdinal(number) {
  const category = rules.select(number);
  const suffix = suffixes[category];
  return `${number}${suffix}`;
}

const positions = [1, 2, 3, 4, 5];

positions.forEach(position => {
  console.log(formatOrdinal(position));
});
// Output:
// "1st"
// "2nd"
// "3rd"
// "4th"
// "5th"

Cette approche est plus efficace que de créer un nouvel objet de règles pour chaque nombre. La différence de performance devient significative lors du formatage de tableaux contenant des centaines ou des milliers de valeurs.

Vous pouvez également créer une fabrique de formateur qui renvoie une fonction configurée pour une locale spécifique.

function createOrdinalFormatter(locale, suffixMapping) {
  const rules = new Intl.PluralRules(locale, { type: 'ordinal' });

  return function(number) {
    const category = rules.select(number);
    const suffix = suffixMapping[category] || suffixMapping.other || '';
    return `${number}${suffix}`;
  };
}

const formatEnglishOrdinal = createOrdinalFormatter('en-US', {
  one: 'st',
  two: 'nd',
  few: 'rd',
  other: 'th'
});

console.log(formatEnglishOrdinal(1));
// Output: "1st"

console.log(formatEnglishOrdinal(2));
// Output: "2nd"

Ce modèle encapsule l'objet de règles et le mappage des suffixes ensemble, rendant le formateur facile à réutiliser dans votre application.