API Intl.Collator
Trier et comparer des chaînes correctement dans toutes les langues
Introduction
Trier des chaînes en JavaScript semble simple jusqu'à ce que vous rencontriez du texte international. La comparaison de chaînes par défaut utilise les valeurs de points de code Unicode, produisant des résultats incorrects pour de nombreuses langues. L'API Intl.Collator fournit une comparaison de chaînes sensible aux paramètres régionaux qui respecte les règles de tri culturelles et gère correctement les caractères spéciaux.
Pourquoi le tri par défaut échoue
Considérez le tri d'une liste de noms allemands :
const names = ["Zoe", "Ava", "Ärzte", "Änder"];
console.log(names.sort());
// ["Ava", "Zoe", "Änder", "Ärzte"]
Ce résultat est incorrect pour les germanophones. En allemand, les caractères avec trémas comme ä doivent être triés près de leur lettre de base a, et non à la fin. Le problème vient du fait que JavaScript compare les valeurs de points de code Unicode, où Ä (U+00C4) vient après Z (U+005A).
Différentes langues ont différentes règles de tri. Le suédois trie ä à la fin de l'alphabet, l'allemand le trie près de a, et le français traite les caractères accentués différemment. La comparaison binaire ignore ces conventions culturelles.
Comment fonctionne la collation de chaînes
La collation est le processus de comparaison et d'ordonnancement des chaînes selon des règles spécifiques à la langue. L'algorithme de collation Unicode définit comment comparer les chaînes en analysant séparément les caractères, les signes diacritiques, la casse et la ponctuation.
Lors de la comparaison de deux chaînes, une fonction de collation renvoie un nombre :
- Valeur négative : la première chaîne vient avant la seconde
- Zéro : les chaînes sont équivalentes pour le niveau de sensibilité actuel
- Valeur positive : la première chaîne vient après la seconde
Ce modèle de comparaison à trois voies fonctionne avec Array.sort et permet un contrôle précis sur les différences qui comptent.
Utiliser localeCompare pour un tri de base sensible aux paramètres régionaux
La méthode localeCompare fournit une comparaison de chaînes sensible aux paramètres régionaux :
const names = ["Zoe", "Ava", "Ärzte", "Änder"];
console.log(names.sort((a, b) => a.localeCompare(b, "de")));
// ["Ava", "Änder", "Ärzte", "Zoe"]
Cela produit un tri allemand correct. Le premier paramètre spécifie la locale, et localeCompare gère automatiquement les règles culturelles.
Vous pouvez passer des options comme troisième paramètre :
const items = ["File10", "File2", "File1"];
console.log(items.sort((a, b) =>
a.localeCompare(b, "en", { numeric: true })
));
// ["File1", "File2", "File10"]
L'option numeric active le tri naturel où "2" vient avant "10". Sans elle, "10" serait trié avant "2" car "1" vient avant "2".
Le problème de performance avec localeCompare répété
Chaque appel à localeCompare traite les paramètres de locale depuis le début. Lors du tri de grands tableaux, cela crée une surcharge significative :
// Inefficient: processes locale for every comparison
const sorted = items.sort((a, b) => a.localeCompare(b, "de"));
Trier 1000 éléments nécessite environ 10000 comparaisons. Chaque comparaison recrée la configuration de locale, multipliant le coût en performance. Cette surcharge devient perceptible dans les interfaces utilisateur avec de grands ensembles de données.
Utiliser Intl.Collator pour une comparaison de chaînes efficace
Intl.Collator crée un objet de comparaison réutilisable qui traite les paramètres de locale une seule fois :
const collator = new Intl.Collator("de");
const sorted = items.sort((a, b) => collator.compare(a, b));
L'instance du collator stocke la configuration de locale et les règles de comparaison. La méthode compare utilise ces règles précalculées pour chaque comparaison, éliminant la surcharge d'initialisation répétée.
Les améliorations de performance varient de 60 % à 80 % lors du tri de grands tableaux par rapport aux appels répétés à localeCompare.
Accéder directement à la méthode compare
Vous pouvez passer la méthode compare directement à sort :
const collator = new Intl.Collator("de");
const sorted = items.sort(collator.compare);
Cela fonctionne car compare est lié à l'instance du collator. La méthode reçoit deux chaînes et retourne le résultat de la comparaison, correspondant à la signature attendue par Array.sort.
Comprendre les niveaux de sensibilité
L'option sensitivity contrôle quelles différences de caractères comptent lors de la comparaison. Il existe quatre niveaux :
Sensibilité de base
La sensibilité de base ignore les accents et la casse :
const collator = new Intl.Collator("en", { sensitivity: "base" });
console.log(collator.compare("a", "a")); // 0
console.log(collator.compare("a", "á")); // 0
console.log(collator.compare("a", "A")); // 0
console.log(collator.compare("a", "b")); // -1
Seules les lettres de base diffèrent. Ce niveau fonctionne bien pour la recherche floue où les utilisateurs peuvent ne pas saisir correctement les accents.
Sensibilité aux accents
La sensibilité aux accents prend en compte les accents mais ignore la casse :
const collator = new Intl.Collator("en", { sensitivity: "accent" });
console.log(collator.compare("a", "a")); // 0
console.log(collator.compare("a", "á")); // -1
console.log(collator.compare("a", "A")); // 0
console.log(collator.compare("á", "A")); // 1
Les caractères accentués et non accentués diffèrent. Les versions majuscules et minuscules de la même lettre correspondent.
Sensibilité à la casse
La sensibilité à la casse prend en compte la casse mais ignore les accents :
const collator = new Intl.Collator("en", { sensitivity: "case" });
console.log(collator.compare("a", "a")); // 0
console.log(collator.compare("a", "á")); // 0
console.log(collator.compare("a", "A")); // -1
console.log(collator.compare("á", "Á")); // -1
Les différences de casse comptent mais les accents sont ignorés. Ce niveau est moins courant en pratique.
Sensibilité aux variantes
La sensibilité aux variantes prend en compte toutes les différences :
const collator = new Intl.Collator("en", { sensitivity: "variant" });
console.log(collator.compare("a", "a")); // 0
console.log(collator.compare("a", "á")); // -1
console.log(collator.compare("a", "A")); // -1
console.log(collator.compare("á", "Á")); // -1
C'est le paramètre par défaut pour le tri. Chaque différence de caractère produit un résultat de comparaison distinct.
Choisir la sensibilité en fonction du cas d'usage
Différents scénarios nécessitent différents niveaux de sensibilité :
- Tri de listes : utilisez la sensibilité aux variantes pour maintenir un ordre strict
- Recherche de contenu : utilisez la sensibilité de base pour correspondre indépendamment des accents ou de la casse
- Filtrage d'options : utilisez la sensibilité aux accents lorsque la casse ne doit pas compter
- Recherche sensible à la casse : utilisez la sensibilité à la casse lorsque les accents ne doivent pas compter
L'option usage fournit des paramètres de sensibilité par défaut pour les scénarios courants.
Utiliser usage pour les modes tri et recherche
L'option usage optimise le comportement du collator pour le tri ou la recherche :
// Optimized for sorting
const sortCollator = new Intl.Collator("en", { usage: "sort" });
// Optimized for searching
const searchCollator = new Intl.Collator("en", { usage: "search" });
L'usage sort utilise par défaut la sensibilité aux variantes, garantissant que chaque différence produit un ordre cohérent. L'usage search optimise la recherche de correspondances, utilisant généralement une sensibilité plus souple.
Pour une recherche insensible à la casse et aux accents :
const collator = new Intl.Collator("en", {
usage: "search",
sensitivity: "base"
});
const items = ["Apple", "Äpfel", "Banana"];
const matches = items.filter(item =>
collator.compare(item, "apple") === 0
);
console.log(matches); // ["Apple"]
Ce modèle permet une correspondance approximative où les utilisateurs n'ont pas besoin de saisir les caractères exacts.
Activer le tri numérique pour un ordre naturel
L'option numeric traite les nombres intégrés comme des valeurs numériques :
const collator = new Intl.Collator("en", { numeric: true });
const files = ["File1", "File10", "File2"];
console.log(files.sort(collator.compare));
// ["File1", "File2", "File10"]
Sans tri numérique, "Fichier10" serait trié avant "Fichier2" car la chaîne "10" commence par "1". Le tri numérique analyse les séquences de nombres et les compare mathématiquement.
Cela produit un ordre naturel qui correspond aux attentes humaines pour les noms de fichiers, les numéros de version et les listes numérotées.
Gestion des nombres décimaux avec le tri numérique
Le tri numérique présente une limitation avec les nombres décimaux :
const collator = new Intl.Collator("en", { numeric: true });
const values = ["1.5", "1.10", "1.2"];
console.log(values.sort(collator.compare));
// ["1.2", "1.5", "1.10"]
Le point décimal est traité comme une ponctuation, et non comme une partie du nombre. Chaque segment entre les signes de ponctuation est trié séparément. Pour le tri des nombres décimaux, analysez les valeurs en nombres et utilisez la comparaison numérique.
Contrôle de l'ordre de casse avec caseFirst
L'option caseFirst détermine si les lettres majuscules ou minuscules sont triées en premier :
// Uppercase first
const upperFirst = new Intl.Collator("en", { caseFirst: "upper" });
console.log(["a", "A", "b", "B"].sort(upperFirst.compare));
// ["A", "a", "B", "b"]
// Lowercase first
const lowerFirst = new Intl.Collator("en", { caseFirst: "lower" });
console.log(["a", "A", "b", "B"].sort(lowerFirst.compare));
// ["a", "A", "b", "B"]
La valeur par défaut est false, ce qui utilise l'ordre par défaut de la locale. Cette option n'a aucun effet lorsque la sensibilité est base ou accent, car ces niveaux ignorent la casse.
Ignorer la ponctuation lors de la comparaison
L'option ignorePunctuation ignore les signes de ponctuation lors de la comparaison :
const collator = new Intl.Collator("en", { ignorePunctuation: true });
console.log(collator.compare("hello", "he-llo")); // 0
console.log(collator.compare("hello", "hello!")); // 0
Cette option est définie par défaut sur true pour le thaï et false pour les autres langues. Utilisez-la lorsque la ponctuation ne doit pas affecter l'ordre ou la correspondance des chaînes.
Spécification des types de collation pour les règles spécifiques à une langue
Certaines locales prennent en charge plusieurs types de collation pour un tri spécialisé :
// Chinese pinyin ordering
const pinyin = new Intl.Collator("zh-CN-u-co-pinyin");
// German phonebook ordering
const phonebook = new Intl.Collator("de-DE-u-co-phonebk");
// Emoji grouping
const emoji = new Intl.Collator("en-u-co-emoji");
Le type de collation est spécifié dans la chaîne de locale en utilisant la syntaxe d'extension Unicode. Les types courants incluent :
pinyin: tri chinois par prononciation romaniséestroke: tri chinois par nombre de traitsphonebk: ordre de l'annuaire téléphonique allemandtrad: règles de tri traditionnelles pour certaines languesemoji: regroupe les emoji par catégorie
Vérifiez Intl.supportedValuesOf pour connaître les types de collation disponibles dans votre environnement.
Réutilisation des instances de collator dans votre application
Créez les instances de collator une seule fois et réutilisez-les dans toute votre application :
// utils/collation.js
export const germanCollator = new Intl.Collator("de");
export const searchCollator = new Intl.Collator("en", {
sensitivity: "base"
});
export const numericCollator = new Intl.Collator("en", {
numeric: true
});
// In your components
import { germanCollator } from "./utils/collation";
const sorted = names.sort(germanCollator.compare);
Ce modèle maximise les performances et garantit un comportement de comparaison cohérent dans l’ensemble de votre code.
Trier des tableaux d’objets par propriété
Utilisez le collator dans une fonction de comparaison qui accède aux propriétés des objets :
const collator = new Intl.Collator("de");
const users = [
{ name: "Zoe" },
{ name: "Änder" },
{ name: "Ava" }
];
const sorted = users.sort((a, b) =>
collator.compare(a.name, b.name)
);
Cette approche fonctionne pour toute structure d’objet. Extrayez les chaînes à comparer et transmettez-les au collator.
Comparaison des performances entre Intl.Collator et localeCompare
Intl.Collator offre de meilleures performances lors du tri de grands ensembles de données :
// Slower: recreates locale settings for each comparison
const slow = items.sort((a, b) => a.localeCompare(b, "de"));
// Faster: reuses precomputed locale settings
const collator = new Intl.Collator("de");
const fast = items.sort(collator.compare);
Pour les petits tableaux (moins de 100 éléments), la différence est négligeable. Pour les grands tableaux (plusieurs milliers d’éléments), Intl.Collator peut être 60 à 80 % plus rapide.
Il existe une exception dans les navigateurs basés sur V8 comme Chrome. localeCompare dispose d’une optimisation pour les chaînes ASCII uniquement via des tables de correspondance. Lors du tri de chaînes purement ASCII, localeCompare peut offrir des performances comparables à Intl.Collator.
Savoir quand utiliser Intl.Collator ou localeCompare
Utilisez Intl.Collator lorsque :
- Vous triez de grands tableaux (centaines ou milliers d’éléments)
- Vous effectuez des tris répétés (l’utilisateur change l’ordre, listes virtuelles)
- Vous développez des utilitaires de comparaison réutilisables
- Les performances sont importantes pour votre cas d’utilisation
Utilisez localeCompare lorsque :
- Vous effectuez des comparaisons ponctuelles
- Vous triez de petits tableaux (moins de 100 éléments)
- La simplicité prime sur les performances
- Vous avez besoin d’une comparaison en ligne sans configuration
Les deux API prennent en charge les mêmes options et produisent des résultats identiques. La différence concerne uniquement les performances et l’organisation du code.
Vérification des options résolues
La méthode resolvedOptions retourne les options effectivement utilisées par le collator :
const collator = new Intl.Collator("de", { sensitivity: "base" });
console.log(collator.resolvedOptions());
// {
// locale: "de",
// usage: "sort",
// sensitivity: "base",
// ignorePunctuation: false,
// collation: "default",
// numeric: false,
// caseFirst: "false"
// }
Cela aide à déboguer le comportement de la collation et à comprendre les valeurs par défaut. La locale résolue peut différer de la locale demandée si le système ne prend pas en charge la locale exacte.
Vérification de la prise en charge des locales
Vérifiez quelles locales sont prises en charge dans l'environnement actuel :
const supported = Intl.Collator.supportedLocalesOf(["de", "fr", "xx"]);
console.log(supported); // ["de", "fr"]
Les locales non prises en charge reviennent à la valeur par défaut du système. Cette méthode aide à détecter quand votre locale demandée n'est pas disponible.
Prise en charge des navigateurs et des environnements
Intl.Collator est largement pris en charge depuis septembre 2017. Tous les navigateurs modernes et les versions de Node.js le prennent en charge. L'API fonctionne de manière cohérente dans tous les environnements.
Certains types de collation et options peuvent avoir une prise en charge limitée dans les navigateurs plus anciens. Testez les fonctionnalités critiques ou consultez les tableaux de compatibilité MDN si vous prenez en charge des environnements plus anciens.
Erreurs courantes à éviter
Ne créez pas un nouveau collator pour chaque comparaison :
// Wrong: creates collator repeatedly
items.sort((a, b) => new Intl.Collator("de").compare(a, b));
// Right: create once, reuse
const collator = new Intl.Collator("de");
items.sort(collator.compare);
Ne supposez pas que le tri par défaut fonctionne pour le texte international :
// Wrong: breaks for non-ASCII characters
names.sort();
// Right: use locale-aware sorting
names.sort(new Intl.Collator("de").compare);
N'oubliez pas de spécifier la sensibilité pour la recherche :
// Wrong: variant sensitivity requires exact match
const collator = new Intl.Collator("en");
items.filter(item => collator.compare(item, "apple") === 0);
// Right: base sensitivity for fuzzy matching
const collator = new Intl.Collator("en", { sensitivity: "base" });
items.filter(item => collator.compare(item, "apple") === 0);
Cas d'usage pratiques
Utilisez Intl.Collator pour :
- Trier le contenu généré par les utilisateurs (noms, titres, adresses)
- Implémenter des fonctionnalités de recherche et d'autocomplétion
- Créer des tableaux de données avec des colonnes triables
- Créer des listes filtrées et des options de menu déroulant
- Trier les noms de fichiers et les numéros de version
- Navigation alphabétique dans les listes de contacts
- Interfaces d'application multilingues
Toute interface qui affiche du texte trié aux utilisateurs bénéficie d'une collation tenant compte de la locale. Cela garantit que votre application semble native et correcte quelle que soit la langue de l'utilisateur.