Comment formater des listes comme A, B et C en JavaScript ?

Utilisez Intl.ListFormat pour formater des tableaux avec des conjonctions et des séparateurs spécifiques à la locale.

Introduction

Lorsque vous affichez une liste d'éléments aux utilisateurs, vous devez les joindre avec des virgules et une conjonction comme « et ». Différentes langues ont différentes conventions pour le formatage des listes. L'anglais utilise des virgules et « and », l'espagnol utilise « y », le français utilise « et », et le chinois utilise une ponctuation entièrement différente.

L'API Intl.ListFormat formate les tableaux en chaînes appropriées à la locale avec les séparateurs et conjonctions corrects. Cela gère automatiquement les différences culturelles dans le formatage des listes.

Le problème du formatage manuel des listes

Vous pouvez joindre les éléments d'un tableau avec des virgules en utilisant la méthode join().

const fruits = ["apples", "oranges", "bananas"];
const list = fruits.join(", ");
console.log(list);
// "apples, oranges, bananas"

Cette approche présente deux problèmes. Premièrement, elle n'ajoute pas de conjonction avant le dernier élément. Deuxièmement, elle utilise une ponctuation anglaise qui ne fonctionne pas pour d'autres langues.

Vous pourriez ajouter manuellement « et » avant le dernier élément.

const fruits = ["apples", "oranges", "bananas"];
const lastFruit = fruits[fruits.length - 1];
const otherFruits = fruits.slice(0, -1);
const list = otherFruits.join(", ") + ", and " + lastFruit;
console.log(list);
// "apples, oranges, and bananas"

Ce code ne fonctionne que pour l'anglais. Les utilisateurs espagnols verraient « apples, oranges, and bananas » au lieu de « apples, oranges y bananas ». Les utilisateurs français verraient « and » au lieu de « et ». Les règles de ponctuation et de conjonction varient selon la langue.

Utiliser Intl.ListFormat pour formater des listes

Le constructeur Intl.ListFormat crée un formateur qui convertit les tableaux en chaînes de liste appropriées à la locale.

const formatter = new Intl.ListFormat("en");
const fruits = ["apples", "oranges", "bananas"];
console.log(formatter.format(fruits));
// "apples, oranges, and bananas"

Le formateur utilise les séparateurs et la conjonction corrects pour la locale spécifiée. Vous passez la locale comme premier argument au constructeur.

const enFormatter = new Intl.ListFormat("en");
const esFormatter = new Intl.ListFormat("es");
const frFormatter = new Intl.ListFormat("fr");

const fruits = ["apples", "oranges", "bananas"];

console.log(enFormatter.format(fruits));
// "apples, oranges, and bananas"

console.log(esFormatter.format(fruits));
// "apples, oranges y bananas"

console.log(frFormatter.format(fruits));
// "apples, oranges et bananas"

Le formateur applique automatiquement les règles de ponctuation et de conjonction pour chaque locale.

Formatage des listes avec « et »

Le comportement par défaut de Intl.ListFormat utilise la conjonction « et » ou son équivalent dans d'autres langues. C'est ce qu'on appelle le formatage par conjonction.

const formatter = new Intl.ListFormat("en", { type: "conjunction" });
const items = ["bread", "milk", "eggs"];
console.log(formatter.format(items));
// "bread, milk, and eggs"

L'option type contrôle quel connecteur apparaît entre les éléments. La valeur "conjunction" produit des listes qui utilisent « et ». C'est la valeur par défaut, vous pouvez donc l'omettre.

Comprendre les options de type de liste

L'option type accepte trois valeurs qui contrôlent la façon dont les éléments se connectent.

Le type "conjunction" utilise « et » ou son équivalent.

const formatter = new Intl.ListFormat("en", { type: "conjunction" });
console.log(formatter.format(["red", "green", "blue"]));
// "red, green, and blue"

Le type "disjunction" utilise « ou » ou son équivalent.

const formatter = new Intl.ListFormat("en", { type: "disjunction" });
console.log(formatter.format(["red", "green", "blue"]));
// "red, green, or blue"

Le type "unit" formate les listes de mesures ou de quantités sans conjonction.

const formatter = new Intl.ListFormat("en", { type: "unit" });
console.log(formatter.format(["5 pounds", "12 ounces"]));
// "5 pounds, 12 ounces"

Le type unit utilise une ponctuation minimale appropriée pour les données techniques ou de mesure.

Comprendre les options de style

L'option style contrôle la longueur et la formalité de la sortie formatée. Elle accepte trois valeurs.

Le style "long" utilise des mots complets et une ponctuation standard. C'est le style par défaut.

const formatter = new Intl.ListFormat("en", { style: "long" });
console.log(formatter.format(["Alice", "Bob", "Carol"]));
// "Alice, Bob, and Carol"

Le style "short" utilise des formes abrégées lorsqu'elles sont disponibles.

const formatter = new Intl.ListFormat("en", { style: "short" });
console.log(formatter.format(["Alice", "Bob", "Carol"]));
// "Alice, Bob, & Carol"

Le style "narrow" utilise la forme la plus compacte possible.

const formatter = new Intl.ListFormat("en", { style: "narrow" });
console.log(formatter.format(["Alice", "Bob", "Carol"]));
// "Alice, Bob, Carol"

Le style narrow omet souvent entièrement la conjonction. La sortie exacte dépend de la locale.

Comment les différentes locales formatent les listes

Chaque locale a ses propres règles pour le formatage des listes. Le formateur applique ces règles automatiquement.

L'anglais utilise des virgules et inclut la virgule d'Oxford avant « and ».

const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["coffee", "tea", "juice"]));
// "coffee, tea, and juice"

L'espagnol utilise des virgules et la conjonction "y".

const formatter = new Intl.ListFormat("es");
console.log(formatter.format(["café", "té", "jugo"]));
// "café, té y jugo"

Le français utilise des virgules et la conjonction "et".

const formatter = new Intl.ListFormat("fr");
console.log(formatter.format(["café", "thé", "jus"]));
// "café, thé et jus"

Le chinois utilise le caractère 和 pour "et" et la virgule d'énumération 、 comme séparateur.

const formatter = new Intl.ListFormat("zh");
console.log(formatter.format(["咖啡", "茶", "可乐"]));
// "咖啡、茶和可乐"

L'allemand utilise des virgules et la conjonction "und".

const formatter = new Intl.ListFormat("de");
console.log(formatter.format(["Kaffee", "Tee", "Saft"]));
// "Kaffee, Tee und Saft"

Le formateur gère ces différences sans que vous ayez besoin de connaître les règles de chaque langue.

Obtenir les parties individuelles avec formatToParts

La méthode formatToParts() renvoie un tableau d'objets représentant chaque partie de la liste formatée. Cela est utile lorsque vous devez styliser différentes parties séparément.

const formatter = new Intl.ListFormat("en");
const parts = formatter.formatToParts(["red", "green", "blue"]);
console.log(parts);

Le résultat est un tableau d'objets avec les propriétés type et value.

[
  { type: "element", value: "red" },
  { type: "literal", value: ", " },
  { type: "element", value: "green" },
  { type: "literal", value: ", and " },
  { type: "element", value: "blue" }
]

Chaque élément de liste a le type "element". Les séparateurs et conjonctions ont le type "literal". Vous pouvez utiliser cela pour appliquer un style personnalisé.

const formatter = new Intl.ListFormat("en");
const parts = formatter.formatToParts(["red", "green", "blue"]);

const html = parts
  .map((part) => {
    if (part.type === "element") {
      return `<strong>${part.value}</strong>`;
    }
    return part.value;
  })
  .join("");

console.log(html);
// "<strong>red</strong>, <strong>green</strong>, and <strong>blue</strong>"

Cette approche vous donne un contrôle précis sur le formatage tout en conservant les séparateurs et conjonctions appropriés à la locale.

Compatibilité des navigateurs

L'API Intl.ListFormat est disponible dans tous les navigateurs modernes. Elle est prise en charge depuis avril 2021 dans les principaux navigateurs, notamment Chrome, Firefox, Safari et Edge.

Vous pouvez vérifier si l'API est disponible avant de l'utiliser.

if (typeof Intl.ListFormat !== "undefined") {
  const formatter = new Intl.ListFormat("en");
  console.log(formatter.format(["a", "b", "c"]));
} else {
  console.log("Intl.ListFormat is not supported");
}

Pour les navigateurs plus anciens, vous devez fournir une solution de repli ou utiliser un polyfill. La solution de repli peut utiliser la méthode simple join().

function formatList(items, locale) {
  if (typeof Intl.ListFormat !== "undefined") {
    const formatter = new Intl.ListFormat(locale);
    return formatter.format(items);
  }
  return items.join(", ");
}

console.log(formatList(["red", "green", "blue"], "en"));
// "red, green, and blue" (or "red, green, blue" in older browsers)

Cela garantit que votre code fonctionne même dans les navigateurs sans prise en charge de Intl.ListFormat.