Kodokon kodokon.com

国際化: lang、dir、charsetとUnicodeの罠

lang、dir、そして文字エンコーディング宣言を賢く使い、Unicodeの正規化と方向性の罠を打ち破ります。

9 分 · 3 問

このレッスンを Kodokon で開く

lang属性はメタデータをはるかに超えるものです。スクリーンリーダーの音声、ハイフネーション(hyphens: autoはこれなしでは機能しません)、CJKグリフの選択(同じ表意文字が日本語と中国語では異なって描画されます)、<q>が生成する引用符、そしてCSSの:lang()セレクターを駆動します。これは継承されます。<html>にBCP 47タグ(enen-GBja)で宣言し、言語が変わるたびにローカルに上書きしましょう。

HTML
<html lang="en">
  <p>She said: <q>hello</q>.</p>
  <p lang="fr">Elle a dit : <q>bonjour</q>.</p>
</html>
qの引用符は言語に従います: “hello” そして « bonjour »。

dir=rtlはデフォルトの配置と、方向性が中立な文字の視覚的な順序を反転させます。予測できないユーザーコンテンツには、dir=auto最初の強い方向性を持つ文字に基づいて方向を選びます。<bdi>要素はフラグメントを双方向アルゴリズムから隔離します。これがないと、アラビア語のユーザー名の後に「: 12ポイント」が続くと、その句読点が並べ替えられて意味不明になります。

HTML
<p dir="auto">مرحبا - inferred direction: RTL</p>
<ul>
  <li><bdi>مستخدم</bdi>: 12 points</li>
  <li><bdi>Alice</bdi>: 8 points</li>
</ul>
bdiはレイアウトを双方向のユーザー名から守ります。

<meta charset=utf-8>宣言はドキュメントの最初の1024バイト以内に現れなければなりません。ブラウザはエンコーディングを選ぶ前に、そのウィンドウに限定された事前スキャンを実行するからです。宣言もHTTPヘッダーもない場合、デフォルトのエンコーディングはユーザーのロケールに依存し(西ヨーロッパではしばしばwindows-1252)、UTF-8ではありません。ただし、ファイルの先頭にあるBOMは、HTTPヘッダーを含む他のすべてを上書きします。

JAVASCRIPT
const composed = "\u00e9";
const decomposed = "e\u0301";
console.log(composed === decomposed); // false
const nfc = decomposed.normalize("NFC");
console.log(composed === nfc);        // true
見た目は同一の2つの「é」、しかしメモリ上では異なります。

macOSは一部のファイル名を分解形式(NFD)で保存します。したがってアップロードから来た「é」は、キーボードで入力されたものと異なる場合があります。保存や比較の前に、すべてのユーザー入力を体系的にNFCに正規化しましょう。最後に、.lengthはUTF-16コードユニットを数えるのであって、知覚される文字を数えるのではありません。家族の絵文字は7つ以上を組み合わせています。実際の書記素を数えるにはIntl.Segmenterを使いましょう。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. <meta charset=utf-8>宣言は必ずどこに配置しなければなりませんか?
    • <head>内のどこでも
    • ドキュメントの最初の1024バイト以内
    • DOCTYPE宣言の前
    • <body>の最初の512バイト以内
  2. dir=autoはどのようにして要素の方向を決定しますか?
    • コンテンツの最初の強い方向性を持つ文字を調べる
    • <html>要素に宣言された方向を適用する
    • RTLとLTRの文字を数えて多数派を採用する
  3. どちらも「é」を表示する2つの文字列が、なぜ===で異なることがあるのですか?
    • 一方はUTF-8で、もう一方はUTF-16でエンコードされているから
    • Unicodeの大文字小文字変換がロケールによって異なるから
    • 一方は合成済み文字U+00E9を使い、もう一方は分解シーケンス e + U+0301 を使うから