Kodokon kodokon.com

Internacionalización: lang, dir, charset y trampas de Unicode

Usa lang, dir y la declaración de codificación con criterio, y vence las trampas de normalización y direccionalidad de Unicode.

9 min · 3 preguntas

Abrir esta lección en Kodokon

El atributo lang es mucho más que metadatos: dirige las voces de los lectores de pantalla, la separación silábica (hyphens: auto no funciona sin él), la selección de glifos CJK (el mismo ideograma se dibuja de forma diferente en japonés y en chino), las comillas generadas por <q> y el selector CSS :lang(). Se hereda: decláralo en <html> con una etiqueta BCP 47 (en, en-GB, ja) y anúlalo localmente en cada cambio de idioma.

HTML
<html lang="en">
  <p>She said: <q>hello</q>.</p>
  <p lang="fr">Elle a dit : <q>bonjour</q>.</p>
</html>
Las comillas de q siguen al idioma: “hello” y luego « bonjour ».

dir=rtl invierte la alineación por defecto y el orden visual de los caracteres con direccionalidad neutra. Para contenido de usuario impredecible, dir=auto elige la dirección según el primer carácter fuertemente direccional. El elemento <bdi> aísla un fragmento del algoritmo bidireccional: sin él, un nombre de usuario en árabe seguido de ": 12 points" ve su puntuación reordenada de forma ininteligible.

HTML
<p dir="auto">مرحبا - inferred direction: RTL</p>
<ul>
  <li><bdi>مستخدم</bdi>: 12 points</li>
  <li><bdi>Alice</bdi>: 8 points</li>
</ul>
bdi protege el diseño de nombres de usuario bidireccionales.

La declaración <meta charset=utf-8> debe aparecer dentro de los primeros 1024 bytes del documento: el navegador ejecuta un preanálisis limitado a esa ventana antes de elegir una codificación. Sin declaración y sin cabecera HTTP, la codificación por defecto depende de la configuración regional del usuario (a menudo windows-1252 en Europa Occidental) - nunca UTF-8. Un BOM al inicio del archivo, en cambio, anula todo lo demás, incluida la cabecera HTTP.

JAVASCRIPT
const composed = "\u00e9";
const decomposed = "e\u0301";
console.log(composed === decomposed); // false
const nfc = decomposed.normalize("NFC");
console.log(composed === nfc);        // true
Dos “é” visualmente idénticas, pero diferentes en memoria.

macOS almacena algunos nombres de archivo en forma descompuesta (NFD): una "é" proveniente de una subida puede por tanto diferir de la escrita en un teclado. Normaliza sistemáticamente toda entrada de usuario a NFC antes de almacenarla o compararla. Por último, .length cuenta unidades de código UTF-16, no caracteres percibidos: un emoji de familia combina más de siete de ellas; usa Intl.Segmenter para contar grafemas reales.

Prueba de conocimientos

Comprueba que has retenido los puntos clave de esta lección.

  1. ¿Dónde debe ubicarse imperativamente la declaración <meta charset=utf-8>?
    • En cualquier parte del <head>
    • Dentro de los primeros 1024 bytes del documento
    • Antes de la declaración DOCTYPE
    • Dentro de los primeros 512 bytes del <body>
  2. ¿Cómo determina dir=auto la dirección de un elemento?
    • Examina el primer carácter fuertemente direccional del contenido
    • Aplica la dirección declarada en el elemento <html>
    • Cuenta los caracteres RTL y LTR y conserva la mayoría
  3. ¿Por qué dos cadenas que ambas muestran “é” pueden ser diferentes para ===?
    • Porque una está codificada en UTF-8 y la otra en UTF-16
    • Porque el manejo de mayúsculas/minúsculas de Unicode difiere según la configuración regional
    • Porque una usa el carácter precompuesto U+00E9 y la otra la secuencia descompuesta e + U+0301