Exploitez lang, dir et la déclaration d'encodage à bon escient, et déjouez les pièges de normalisation et de directionnalité Unicode.
Ouvrir cette leçon dans KodokonL'attribut lang est bien plus qu'une métadonnée : il pilote la voix des lecteurs d'écran, la césure (hyphens: auto ne fonctionne pas sans lui), la sélection des glyphes CJK (un même idéogramme se dessine différemment en japonais et en chinois), les guillemets générés par <q> et le sélecteur CSS :lang(). Il s'hérite : déclarez-le sur <html> avec une étiquette BCP 47 (fr, fr-CA, ja) et surchargez-le localement à chaque changement de langue.
<html lang="fr">
<p>Elle a dit : <q>bonjour</q>.</p>
<p lang="en">She said: <q>hello</q>.</p>
</html>dir=rtl inverse l'alignement par défaut et l'ordre visuel des caractères à directionnalité neutre. Pour du contenu utilisateur imprévisible, dir=auto choisit la direction d'après le premier caractère fortement directionnel. L'élément <bdi> isole un fragment de l'algorithme bidirectionnel : sans lui, un pseudo arabe suivi de « : 12 points » voit sa ponctuation se réordonner de façon illisible.
<p dir="auto">مرحبا - direction déduite : RTL</p>
<ul>
<li><bdi>مستخدم</bdi> : 12 points</li>
<li><bdi>Alice</bdi> : 8 points</li>
</ul>La déclaration <meta charset=utf-8> doit apparaître dans les 1024 premiers octets du document : le navigateur effectue un prescan limité à cette fenêtre avant de choisir un encodage. Sans déclaration ni en-tête HTTP, l'encodage par défaut dépend de la locale de l'utilisateur (souvent windows-1252 en Europe de l'Ouest) - jamais UTF-8. Un BOM en tête de fichier, lui, prime sur tout le reste, y compris l'en-tête HTTP.
const composed = "\u00e9";
const decomposed = "e\u0301";
console.log(composed === decomposed); // false
const nfc = decomposed.normalize("NFC");
console.log(composed === nfc); // truemacOS enregistre certains noms de fichiers en forme décomposée (NFD) : un « é » venu d'un upload peut donc différer de celui saisi au clavier. Normalisez systématiquement en NFC toute saisie utilisateur avant stockage ou comparaison. Enfin, .length compte des unités UTF-16, pas des caractères perçus : un emoji familial en combine plus de sept ; utilisez Intl.Segmenter pour compter de vrais graphèmes.
<meta charset=utf-8> doit-elle impérativement se situer ?<head><body>dir=auto détermine-t-il la direction d'un élément ?<html>=== ?