Kodokon kodokon.com

Internationalisierung: lang, dir, charset und Unicode-Fallen

Setze lang, dir und die Kodierungsdeklaration klug ein und überwinde die Fallen von Unicode-Normalisierung und Schreibrichtung.

9 Min. · 3 Fragen

Diese Lektion in Kodokon öffnen

Das lang-Attribut ist weit mehr als Metadaten: Es steuert die Stimmen von Screenreadern, die Silbentrennung (hyphens: auto funktioniert ohne es nicht), die Auswahl der CJK-Glyphen (dasselbe Ideogramm wird im Japanischen und im Chinesischen unterschiedlich gezeichnet), die von <q> erzeugten Anführungszeichen und den CSS-Selektor :lang(). Es wird vererbt: Deklariere es auf <html> mit einem BCP-47-Tag (en, en-GB, ja) und überschreibe es lokal bei jedem Sprachwechsel.

HTML
<html lang="en">
  <p>She said: <q>hello</q>.</p>
  <p lang="fr">Elle a dit : <q>bonjour</q>.</p>
</html>
Die Anführungszeichen von q folgen der Sprache: “hello”, dann « bonjour ».

dir=rtl kehrt die Standardausrichtung und die visuelle Reihenfolge von Zeichen mit neutraler Schreibrichtung um. Für unvorhersehbaren Nutzerinhalt wählt dir=auto die Richtung anhand des ersten Zeichens mit starker Richtung. Das <bdi>-Element isoliert ein Fragment vom bidirektionalen Algorithmus: Ohne es wird bei einem arabischen Benutzernamen, gefolgt von „: 12 Punkte“, die Interpunktion zu Kauderwelsch umgeordnet.

HTML
<p dir="auto">مرحبا - inferred direction: RTL</p>
<ul>
  <li><bdi>مستخدم</bdi>: 12 points</li>
  <li><bdi>Alice</bdi>: 8 points</li>
</ul>
bdi schützt das Layout vor bidirektionalen Benutzernamen.

Die Deklaration <meta charset=utf-8> muss innerhalb der ersten 1024 Bytes des Dokuments erscheinen: Der Browser führt einen auf dieses Fenster begrenzten Vorabscan durch, bevor er eine Kodierung wählt. Ohne Deklaration und ohne HTTP-Header hängt die Standardkodierung von der Locale des Nutzers ab (oft windows-1252 in Westeuropa) - niemals UTF-8. Ein BOM am Anfang der Datei überschreibt jedoch alles andere, einschließlich des HTTP-Headers.

JAVASCRIPT
const composed = "\u00e9";
const decomposed = "e\u0301";
console.log(composed === decomposed); // false
const nfc = decomposed.normalize("NFC");
console.log(composed === nfc);        // true
Zwei visuell identische “é”, die im Speicher dennoch verschieden sind.

macOS speichert manche Dateinamen in zerlegter Form (NFD): Ein „é“ aus einem Upload kann sich daher von dem auf einer Tastatur getippten unterscheiden. Normalisiere jede Nutzereingabe systematisch auf NFC, bevor du sie speicherst oder vergleichst. Schließlich zählt .length UTF-16-Code-Units, nicht wahrgenommene Zeichen: Ein Familien-Emoji setzt sich aus mehr als sieben davon zusammen; nutze Intl.Segmenter, um echte Grapheme zu zählen.

Wissenscheck

Stelle sicher, dass du die wichtigsten Punkte dieser Lektion behalten hast.

  1. Wo muss die Deklaration <meta charset=utf-8> zwingend stehen?
    • Irgendwo im <head>
    • Innerhalb der ersten 1024 Bytes des Dokuments
    • Vor der DOCTYPE-Deklaration
    • Innerhalb der ersten 512 Bytes des <body>
  2. Wie bestimmt dir=auto die Richtung eines Elements?
    • Es untersucht das erste Zeichen mit starker Richtung im Inhalt
    • Es wendet die auf dem <html>-Element deklarierte Richtung an
    • Es zählt RTL- und LTR-Zeichen und behält die Mehrheit
  3. Warum können zwei Zeichenketten, die beide „é“ anzeigen, für === verschieden sein?
    • Weil eine in UTF-8 und die andere in UTF-16 kodiert ist
    • Weil die Unicode-Groß-/Kleinschreibung je nach Locale unterschiedlich ist
    • Weil eine das vorkomponierte Zeichen U+00E9 verwendet und die andere die zerlegte Sequenz e + U+0301