JavaScript/Objekte/Intl/Collator

Aus SELFHTML-Wiki
< JavaScript‎ | Objekte‎ | Intl
Wechseln zu: Navigation, Suche

Ein Intl.Collator-Objekt dient dazu, Stringvergleiche im Kontext einer bestimmten Kultur durchzuführen. Über das Optionen-Objekt, das der Konstruktor übergeben bekommt, sind etliche Varianten möglich.

Viele Locales bieten zum Sortieren unterschiedliche Zeichenordnungen (collation) an. Welche von einem Locale unterstützt werden, findest du heraus, indem du ein Locale-Objekt erzeugst und darauf die getCollations()-Methode aufrufst. Eine von diesen ist die Default-Collation des Locale, uns fehlt allerdings die Information, wie man für ein konkretes Locale ermittelt, welche Collation die Default-Collation ist. Für das de-DE Locale ist die Default-Collation jedenfalls eor (european ordering rules). Eine Liste aller Collations wird vom Unicode-Konsortium im CLDR Repository angeboten.

Beachte: In der ECMA-402 Spezifikation steht getCollations(). Im Firefox fehlt diese Abfragemöglichkeit allerdings bisher (Nov. 2023) ganz, und die Chromium- und Safaro-Browser implementieren statt dessen eine Eigenschaft namens collations. Um mit Realität und Spezifikation kompatibel zu sein, muss man deshalb prüfen, ob es die Methode gibt und sie benutzen, wenn sie vorhanden ist.

Zentrale Funktionalität

Konstruktor

Der Konstruktor kann mit oder ohne new-Operator aufgerufen werden:

Syntax:

 const collator = new Intl.Collator(locale, optionen);
 const collator = Intl.Collator(locale, optionen);
locale
Eine einzelne Locale-Angabe oder ein Array von Locale-Angaben. Die Locale-Angabe kann aus einem Sprachkürzel oder einem Intl.Locale-Objekt bestehen.
optionen
Ein Objekt mit Optionen für den erzeugten Collator

Mögliche Optionen sind:

usage
Der Anwendungszweck für den Collator. Diese Werte sind möglich:
"sort"
(Defaultwert) Der Collator liefert Ordnungsinformationen und kann zum Sortieren verwendet werden
"search"
Der Collator soll zum Suchen verwendet werden - die Rückgabe darf nur auf „0“ oder „nicht 0“ getestet werden, d. h. der Einsatz eines search-Collators zum Sortieren ist nicht zulässig. Dadurch, dass die "search" Variante auf die Bestimmung der Reihenfolge verzichtet, ist sie etwas schneller.
collation
Festlegen der verwendeten Vergleichstabelle (siehe Einleitung)
numeric
Mögliche Werte sind die booleschen Werte false (als Default) oder true. Wichtig: keinen String übergeben, das wird immer als true interpretiert. Mit numeric:true schaltet man einen numerischen Vergleich ein. Die genaue Vorgehensweise für einen solchen Vergleich ist in ECMA-402 nicht definiert, man verweist auf den Unicode Collation-Algorithmus, der wiederum nur sagt, dass die Identifikation von Zahlen in Strings zu Mehrdeutigkeiten führen könne. Das Ziel ist aber, dass "12" > "2" erfüllt ist und auch "Test-17" > "Test-5".
caseFirst
Mögliche Werte sind "false" (der Defaultwert, es wird der Defaultwert des Locale verwendet) sowie "lower" und "upper". Diese Option steuert, ob Kleinbuchstaben vor Großbuchstaben einsortiert werden. Diese Regel greift aber nur dann, wenn die beiden Zeichenketten ansonsten identisch sind, d. h. "haus" wird immer vor "Haut" eingeordnet, ganz gleich, ob caseFirst auf "lower" oder "upper" steht.
sensitivity
Gibt an, wie stark beim Vergleich auf Groß- und Kleinschreibung sowie auf Akzentzeichen geachtet wird. Es gibt diese Werte:
"base"
Der Vergleich ignoriert Groß- und Kleinschreibung sowie Akzentzeichen. "a" = "A", "e" = "é", "a" ≠ "b"
"accent"
Der Vergleich ignoriert Groß- und Kleinschreibung, unterscheidet aber Akzentzeichen. "a" = "A", "e" ≠ "é", "a" ≠ "b"
"case"
Der Vergleich beachtet Groß- und Kleinschreibung, ignoriert aber Akzentzeichen. "a" ≠ "A", "e" = "é", "a" ≠ "b"
"variant"
Der Vergleich beachtet Groß- und Kleinschreibung und Akzentzeichen. "a" ≠ "A", "e" ≠ "é", "a" ≠ "b"
Beachte: Diese Unterscheidung ist nur relevant, wenn die verglichenen Zeichenketten mit sensitivity:"base" als gleich erkannt werden. Ergibt der base-Vergleich einen Unterschied, werden Akzentzeichen oder Schreibung beim Sortieren nicht beachtet. "roh" ist immer kleiner als "rot", ganz gleich, wo man Großschrift oder Akzente setzt.
localeMatcher
Im Einleitungsartikel beschrieben.

Das folgende Beispiel erzeugt einen Collator, der Groß- und Kleinschreibung sowie Akzente nicht beachtet und eine Sortierung nach den Regeln für österreichische Telefonbücher erzeugt:

Erzeugen eines Collators
const collator = Intl.Collator("de-AT", 
                     {
                        collation: "phonebk",
                        sensitivity: "base"
                     });

["Muelhens", "Müller", "Mulan", "Mond", "Mykonos"].toSorted(collator.compare);
// Ausgabe: ['Mond', 'Muelhens', 'Mulan', 'Müller', 'Mykonos']

Würde man "de-DE" angeben, wären Mulan und Müller übrigens andersherum sortiert worden. Deutschland und Österreich, zwei Länder, die durch eine gemeinsame Sprache getrennt sind...

Die compare-Methode

Die in Intl.Collator.prototype implementierte Collator-Schnittstelle besitzt eine einzige relevante Methode, nämlich compare. Hierbei handelt es sich um eine gebundene Methode, das bedeutet, du kannst sie einfach irgendwohin als Argument übergeben, ohne dass sie die Verbindung zu ihrem Collator-Objekt verliert. Das Beispiel am Ende des Konstruktor-Abschnitts zeigt das.

Syntax:

  ergebnis = collator.compare(zeichenkette 1, zeichenkette 2);

Das Ergebnis ist 0, wenn die verglichenen Zeichenketten nach den Regeln des Collators gleich sind, und ungleich 0, wenn sie verschieden sind. Wenn du den Collator mit usage:"search" erzeugt hast, kann weiter nichts geprüft werden. Bei einem Collator mit usage:"sort" gibt ein negatives Ergebnis an, dass die Zeichenkette 1 vor Zeichenkette 2 einzusortieren ist, und ein positives Ergebnis, dass sie dahinter einsortiert werden muss.

Beachte: Die Optionen caseFirst und sensitivity haben nur Einfluss auf ein positives oder negatives Ergebnis, wenn die verglichenen Zeichenketten in einem sensitivity:"base"-Vergleich als gleich erkannt werden. Sind sie im base-Vergleich unterschiedlich, wird ihre Reihenfolge durch das Ergebnis des base-Vergleichs bestimmt. "roh" ist immer kleiner als "rot", ganz gleich, ob man "roh", "ROH", "Rot" oder vielleicht "rôt" vergleicht.

Weitere Methoden

Intl.Collator.supportedLocalesOf()

Hierbei handelt es sich um eine Methode der Konstruktorfunktion, nicht des Collators. Du kannst ihr ein Array mit Locales übergeben und sie filtert dieses Array auf diejenigen Locales, für die dein Computer einen Collator unterstützt, ohne auf das Default-Locale der JavaScript-Runtime zurückfallen zu müssen.

Syntax:

 Intl.Collator.supportedLocalesOf(locales, options)
locales
Hier kann ein Locale oder ein Array von Locales in Form eines Sprachkürzels übergeben werden. Die Übergabe von Locale-Objekten ist nicht möglich (und auch nicht sinnvoll, weil ein Locale-Objekt nur für ein unterstütztes Locale erstellt werden kann).
options
Ein Objekt mit Optionen. Die einzige Option, die hier möglich ist, ist localeMatcher. Diese Option ist auf der Intl-Übersichtsseite beschrieben.
Ermitteln von unterstützten Locales
console.log(Intl.Collator.supportedLocalesOf( [
   "de-DE", "tlh", "en-RU" ], { localeMatcher: 'lookup' });

Die Ausgabe auf dem PC des Autors ist [ 'de-DE', 'en-RU' ] – schade eigentlich, dass eine verbreitete Sprache wie Klingonisch (tlh) unbekannt ist, während die Merkwürdigkeit „in Russland gesprochenes Englisch“ scheinbar unterstützt wird.

resolvedOptions()

Mit dieser Methode von Intl.Collator.prototype kannst du ermitteln, welche Optionen ein vom Konstruktor erzeugtes Collator-Objekt tatsächlich verwendet und welche Anforderungen, die du dem Konstruktor mitgeteilt hast, nicht realisierbar waren.

Beispiel

Ergebnis von resolvedOptions()

Das Ergebnis zeigt leider, dass Klingonisch nicht unterstützt wird. Es zeigt aber auch, dass das englische Locale vorgezogen wird, weil es zuerst gelistet wurde, obwohl die Collation phonebk angefordert wurde, die nur vom Deutschen unterstützt wird.

{ 
  caseFirst: "false"
  collation: "default"
  ignorePunctuation: false
  locale: "en"
  numeric: false
  sensitivity: "variant"
  usage: "sort"
  Prototype: Object
}

Im folgenden Beispiel zeigt sich noch etwas anderes:

locale mit Optionen in resolvedOptions()
const collator = new Intl.Collator("de", { collation:'phonebk'});
console.log(collator.resolvedOptions());
// Ausgabe (gekürzt): {locale: 'de-u-co-phonebk', ..., collation: 'phonebk', ... }
console.log(new Intl.Locale(collator.locale));
// Ausgabe: { language: 'de', baseName: 'de', collation: 'phonebk', region: undefined, ... }

Das Locale, das sich in den resolvedOptions zeigt, enthält das Suffix "u-co-phonebk". Hierbei handelt es sich um eine Erweiterungssyntax von Locales, um Optionen direkt im Sprachkürzel unterzubringen. Passe daher auf, wenn Du in den resolvedOptions den Wert von locale mit irgendetwas vergleichen möchtest. Die Intl.Locale Klasse ermöglicht es, einen erweiterten Locale-String in seine Komponenten zu zerlegen.