Intl.Collator API
Zeichenketten sprachübergreifend korrekt sortieren und vergleichen
Einführung
Das Sortieren von Zeichenketten in JavaScript scheint unkompliziert, bis man auf internationalen Text stößt. Der standardmäßige Zeichenkettenvergleich verwendet Unicode-Codepunktwerte, was für viele Sprachen zu falschen Ergebnissen führt. Die Intl.Collator API bietet einen sprachbewussten Zeichenkettenvergleich, der kulturelle Sortierregeln respektiert und Sonderzeichen korrekt behandelt.
Warum die Standardsortierung versagt
Betrachten Sie das Sortieren einer Liste deutscher Namen:
const names = ["Zoe", "Ava", "Ärzte", "Änder"];
console.log(names.sort());
// ["Ava", "Zoe", "Änder", "Ärzte"]
Diese Ausgabe ist für deutschsprachige Personen falsch. Im Deutschen sollten Zeichen mit Umlauten wie ä in der Nähe ihres Grundbuchstabens a sortiert werden, nicht am Ende. Das Problem liegt darin, dass JavaScript Unicode-Codepunktwerte vergleicht, wobei Ä (U+00C4) nach Z (U+005A) kommt.
Verschiedene Sprachen haben unterschiedliche Sortierregeln. Schwedisch sortiert ä am Ende des Alphabets, Deutsch sortiert es in der Nähe von a, und Französisch behandelt akzentuierte Zeichen anders. Der binäre Vergleich ignoriert diese kulturellen Konventionen.
Wie Zeichenketten-Kollation funktioniert
Kollation ist der Prozess des Vergleichens und Ordnens von Zeichenketten nach sprachspezifischen Regeln. Der Unicode Collation Algorithm definiert, wie Zeichenketten verglichen werden, indem Zeichen, Diakritika, Groß-/Kleinschreibung und Interpunktion separat analysiert werden.
Beim Vergleichen zweier Zeichenketten gibt eine Kollationsfunktion eine Zahl zurück:
- Negativer Wert: erste Zeichenkette kommt vor der zweiten
- Null: Zeichenketten sind für die aktuelle Empfindlichkeitsstufe äquivalent
- Positiver Wert: erste Zeichenkette kommt nach der zweiten
Dieses dreiwertige Vergleichsmuster funktioniert mit Array.sort und ermöglicht präzise Kontrolle darüber, welche Unterschiede relevant sind.
Verwendung von localeCompare für grundlegende sprachbewusste Sortierung
Die localeCompare-Methode bietet sprachbewussten Zeichenkettenvergleich:
const names = ["Zoe", "Ava", "Ärzte", "Änder"];
console.log(names.sort((a, b) => a.localeCompare(b, "de")));
// ["Ava", "Änder", "Ärzte", "Zoe"]
Dies erzeugt eine korrekte deutsche Sortierung. Der erste Parameter gibt das Gebietsschema an, und localeCompare behandelt die kulturellen Regeln automatisch.
Sie können Optionen als dritten Parameter übergeben:
const items = ["File10", "File2", "File1"];
console.log(items.sort((a, b) =>
a.localeCompare(b, "en", { numeric: true })
));
// ["File1", "File2", "File10"]
Die numeric-Option ermöglicht eine natürliche Sortierung, bei der "2" vor "10" kommt. Ohne diese Option würde "10" vor "2" sortiert werden, da "1" vor "2" kommt.
Das Performance-Problem bei wiederholtem localeCompare
Jeder localeCompare-Aufruf verarbeitet die Gebietsschema-Einstellungen von Grund auf neu. Beim Sortieren großer Arrays entsteht dadurch ein erheblicher Overhead:
// Inefficient: processes locale for every comparison
const sorted = items.sort((a, b) => a.localeCompare(b, "de"));
Das Sortieren von 1000 Elementen erfordert etwa 10000 Vergleiche. Jeder Vergleich erstellt die Gebietsschema-Konfiguration neu, wodurch sich die Performance-Kosten multiplizieren. Dieser Overhead wird in Benutzeroberflächen mit großen Datensätzen spürbar.
Verwendung von Intl.Collator für effizienten String-Vergleich
Intl.Collator erstellt ein wiederverwendbares Vergleichsobjekt, das die Gebietsschema-Einstellungen einmalig verarbeitet:
const collator = new Intl.Collator("de");
const sorted = items.sort((a, b) => collator.compare(a, b));
Die Collator-Instanz speichert die Gebietsschema-Konfiguration und Vergleichsregeln. Die compare-Methode verwendet diese vorberechneten Regeln für jeden Vergleich und eliminiert so den wiederholten Initialisierungs-Overhead.
Performance-Verbesserungen liegen beim Sortieren großer Arrays zwischen 60% und 80% im Vergleich zu wiederholten localeCompare-Aufrufen.
Direkter Zugriff auf die compare-Methode
Sie können die compare-Methode direkt an sort übergeben:
const collator = new Intl.Collator("de");
const sorted = items.sort(collator.compare);
Dies funktioniert, weil compare an die Collator-Instanz gebunden ist. Die Methode empfängt zwei Strings und gibt das Vergleichsergebnis zurück, was der Signatur entspricht, die Array.sort erwartet.
Verständnis der Sensitivity-Stufen
Die sensitivity-Option steuert, welche Zeichenunterschiede beim Vergleich relevant sind. Es gibt vier Stufen:
Base-Sensitivity
Base-Sensitivity ignoriert Akzente und Groß-/Kleinschreibung:
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
Nur Grundbuchstaben unterscheiden sich. Diese Stufe eignet sich gut für Fuzzy-Suchen, bei denen Benutzer möglicherweise keine Akzente korrekt eingeben.
Akzentsensitivität
Akzentsensitivität berücksichtigt Akzente, ignoriert jedoch Groß-/Kleinschreibung:
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
Akzentuierte und nicht akzentuierte Zeichen unterscheiden sich. Groß- und Kleinbuchstaben desselben Buchstabens stimmen überein.
Groß-/Kleinschreibungssensitivität
Groß-/Kleinschreibungssensitivität berücksichtigt Groß-/Kleinschreibung, ignoriert jedoch Akzente:
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
Unterschiede in der Groß-/Kleinschreibung sind relevant, Akzente werden jedoch ignoriert. Diese Stufe ist in der Praxis weniger verbreitet.
Variantensensitivität
Variantensensitivität berücksichtigt alle Unterschiede:
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
Dies ist die Standardeinstellung für die Sortierung. Jeder Zeichenunterschied führt zu einem unterschiedlichen Vergleichsergebnis.
Auswahl der Sensitivität basierend auf dem Anwendungsfall
Verschiedene Szenarien erfordern unterschiedliche Sensitivitätsstufen:
- Sortieren von Listen: Verwenden Sie Variantensensitivität, um eine strikte Reihenfolge beizubehalten
- Durchsuchen von Inhalten: Verwenden Sie Basissensitivität, um unabhängig von Akzenten oder Groß-/Kleinschreibung zu suchen
- Filtern von Optionen: Verwenden Sie Akzentsensitivität, wenn Groß-/Kleinschreibung keine Rolle spielen soll
- Groß-/Kleinschreibungssensitive Suche: Verwenden Sie Groß-/Kleinschreibungssensitivität, wenn Akzente keine Rolle spielen sollen
Die usage-Option bietet Standard-Sensitivitätseinstellungen für gängige Szenarien.
Verwendung von usage für Sortier- und Suchmodi
Die usage-Option optimiert das Collator-Verhalten für Sortierung oder Suche:
// Optimized for sorting
const sortCollator = new Intl.Collator("en", { usage: "sort" });
// Optimized for searching
const searchCollator = new Intl.Collator("en", { usage: "search" });
Sort-usage verwendet standardmäßig Variantensensitivität und stellt sicher, dass jeder Unterschied eine konsistente Reihenfolge erzeugt. Search-usage optimiert das Auffinden von Übereinstimmungen und verwendet typischerweise eine lockerere Sensitivität.
Für Groß-/Kleinschreibungs- und akzentunabhängige Suche:
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"]
Dieses Muster ermöglicht Fuzzy-Matching, bei dem Benutzer keine exakten Zeichen eingeben müssen.
Aktivierung der numerischen Sortierung für natürliche Reihenfolge
Die numeric-Option behandelt eingebettete Zahlen als numerische Werte:
const collator = new Intl.Collator("en", { numeric: true });
const files = ["File1", "File10", "File2"];
console.log(files.sort(collator.compare));
// ["File1", "File2", "File10"]
Ohne numerische Sortierung würde "File10" vor "File2" sortiert werden, da die Zeichenkette "10" mit "1" beginnt. Die numerische Sortierung analysiert Zahlenfolgen und vergleicht sie mathematisch.
Dies erzeugt eine natürliche Reihenfolge, die den menschlichen Erwartungen für Dateinamen, Versionsnummern und nummerierte Listen entspricht.
Umgang mit Dezimalzahlen bei numerischer Sortierung
Die numerische Sortierung hat eine Einschränkung bei Dezimalzahlen:
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"]
Der Dezimalpunkt wird als Satzzeichen behandelt, nicht als Teil der Zahl. Jedes Segment zwischen Satzzeichen wird separat sortiert. Für die Sortierung von Dezimalzahlen sollten Werte in Zahlen geparst und numerisch verglichen werden.
Steuerung der Groß-/Kleinschreibungsreihenfolge mit caseFirst
Die Option caseFirst bestimmt, ob Groß- oder Kleinbuchstaben zuerst sortiert werden:
// 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"]
Der Standardwert ist false, wodurch die Standard-Reihenfolge der Locale verwendet wird. Diese Option hat keine Auswirkung, wenn sensitivity auf base oder accent gesetzt ist, da diese Ebenen die Groß-/Kleinschreibung ignorieren.
Ignorieren von Satzzeichen beim Vergleich
Die Option ignorePunctuation überspringt Satzzeichen beim Vergleich:
const collator = new Intl.Collator("en", { ignorePunctuation: true });
console.log(collator.compare("hello", "he-llo")); // 0
console.log(collator.compare("hello", "hello!")); // 0
Diese Option ist standardmäßig true für Thai und false für andere Sprachen. Verwenden Sie sie, wenn Satzzeichen die Reihenfolge oder den Abgleich von Zeichenketten nicht beeinflussen sollen.
Angabe von Collation-Typen für sprachspezifische Regeln
Einige Locales unterstützen mehrere Collation-Typen für spezialisierte Sortierung:
// 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");
Der Collation-Typ wird in der Locale-Zeichenkette mithilfe der Unicode-Erweiterungssyntax angegeben. Gängige Typen umfassen:
pinyin: Chinesische Sortierung nach romanisierter Aussprachestroke: Chinesische Sortierung nach Strichanzahlphonebk: Deutsche Telefonbuch-Reihenfolgetrad: Traditionelle Sortierregeln für bestimmte Sprachenemoji: Gruppiert Emojis nach Kategorie
Prüfen Sie Intl.supportedValuesOf für verfügbare Sortierungstypen in Ihrer Umgebung.
Wiederverwendung von Collator-Instanzen in Ihrer Anwendung
Erstellen Sie Collator-Instanzen einmal und verwenden Sie diese in Ihrer gesamten Anwendung wieder:
// 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);
Dieses Muster maximiert die Performance und gewährleistet ein konsistentes Vergleichsverhalten in Ihrer gesamten Codebasis.
Sortierung von Objekt-Arrays nach Eigenschaft
Verwenden Sie den Collator in einer Vergleichsfunktion, die auf Objekteigenschaften zugreift:
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)
);
Dieser Ansatz funktioniert für jede Objektstruktur. Extrahieren Sie die zu vergleichenden Strings und übergeben Sie diese an den Collator.
Vergleich der Performance von Intl.Collator mit localeCompare
Intl.Collator bietet eine bessere Performance beim Sortieren großer Datensätze:
// 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);
Bei kleinen Arrays (unter 100 Elementen) ist der Unterschied vernachlässigbar. Bei großen Arrays (Tausende von Elementen) kann Intl.Collator 60–80 % schneller sein.
Eine Ausnahme besteht in V8-basierten Browsern wie Chrome. localeCompare verfügt über eine Optimierung für reine ASCII-Strings mittels Lookup-Tabellen. Beim Sortieren reiner ASCII-Strings kann localeCompare eine vergleichbare Performance wie Intl.Collator aufweisen.
Wann Intl.Collator versus localeCompare verwendet werden sollte
Verwenden Sie Intl.Collator, wenn:
- Sie große Arrays sortieren (Hunderte oder Tausende von Elementen)
- Sie wiederholt sortieren (Benutzer wechselt Sortierreihenfolge, virtuelle Listen)
- Sie wiederverwendbare Vergleichs-Utilities erstellen
- Performance für Ihren Anwendungsfall wichtig ist
Verwenden Sie localeCompare, wenn:
- Sie einmalige Vergleiche durchführen
- Sie kleine Arrays sortieren (unter 100 Elementen)
- Einfachheit wichtiger als Performance-Aspekte ist
- Sie einen Inline-Vergleich ohne Setup benötigen
Beide APIs unterstützen dieselben Optionen und liefern identische Ergebnisse. Der Unterschied liegt ausschließlich in Performance und Code-Organisation.
Überprüfung aufgelöster Optionen
Die Methode resolvedOptions gibt die tatsächlich vom Collator verwendeten Optionen zurück:
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"
// }
Dies hilft beim Debuggen des Sortierungsverhaltens und beim Verstehen der Standardwerte. Das aufgelöste Gebietsschema kann vom angeforderten Gebietsschema abweichen, wenn das System das exakte Gebietsschema nicht unterstützt.
Unterstützung von Gebietsschemata überprüfen
Prüfen Sie, welche Gebietsschemata in der aktuellen Umgebung unterstützt werden:
const supported = Intl.Collator.supportedLocalesOf(["de", "fr", "xx"]);
console.log(supported); // ["de", "fr"]
Nicht unterstützte Gebietsschemata fallen auf die Systemstandardeinstellung zurück. Diese Methode hilft zu erkennen, wenn Ihr angefordertes Gebietsschema nicht verfügbar ist.
Browser- und Umgebungsunterstützung
Intl.Collator wird seit September 2017 weitgehend unterstützt. Alle modernen Browser und Node.js-Versionen unterstützen es. Die API funktioniert konsistent über alle Umgebungen hinweg.
Einige Sortierungstypen und Optionen haben möglicherweise eingeschränkte Unterstützung in älteren Browsern. Testen Sie kritische Funktionalität oder prüfen Sie die MDN-Kompatibilitätstabellen, wenn Sie ältere Umgebungen unterstützen.
Häufige Fehler, die vermieden werden sollten
Erstellen Sie nicht für jeden Vergleich einen neuen Collator:
// 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);
Gehen Sie nicht davon aus, dass die Standardsortierung für internationalen Text funktioniert:
// Wrong: breaks for non-ASCII characters
names.sort();
// Right: use locale-aware sorting
names.sort(new Intl.Collator("de").compare);
Vergessen Sie nicht, die Sensitivität für die Suche anzugeben:
// 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);
Praktische Anwendungsfälle
Verwenden Sie Intl.Collator für:
- Sortierung von benutzergenerierten Inhalten (Namen, Titel, Adressen)
- Implementierung von Such- und Autocomplete-Funktionen
- Erstellung von Datentabellen mit sortierbaren Spalten
- Erstellung gefilterter Listen und Dropdown-Optionen
- Sortierung von Dateinamen und Versionsnummern
- Alphabetische Navigation in Kontaktlisten
- Mehrsprachige Anwendungsoberflächen
Jede Oberfläche, die Benutzern sortierten Text anzeigt, profitiert von gebietsschemabewusster Sortierung. Dies stellt sicher, dass Ihre Anwendung unabhängig von der Sprache des Benutzers nativ und korrekt wirkt.