- La tipografía web en árabe es un problema de infraestructura de renderizado donde se entrelazan la conexión entre letras, el texto bidireccional, el manejo de números y signos de puntuación, y la justificación de líneas; no es algo fácil de tratar como un simple bug de CSS
- La composición clásica en árabe lograba la justificación no ampliando los espacios entre palabras, sino con la kashida, alargando trazos dentro de las letras; en cambio, el
text-align: justifyde los navegadores modernos suele ampliar los espacios entre palabras - En árabe, un mismo code point almacenado cambia según el contexto a forma aislada, inicial, medial o final, y sin funciones OpenType ni un motor de shaping las letras se renderizan separadas
- Las Arabic Presentation Forms de Unicode, los sistemas numéricos, el algoritmo bidireccional UAX #9 y los caracteres de control invisibles terminan causando problemas reales de producto, como fallas de búsqueda, números telefónicos invertidos y confusión al mover el cursor
- Ya existen bases clave como HarfBuzz, Amiri y los W3C Arabic Layout Requirements, pero la justificación árabe en navegadores y el uso de
jstfsiguen siendo vacíos de implementación
Punto de partida: un problema de composición árabe que parecía un “bug de CSS”
- En un dashboard para clientes, un párrafo en árabe con contenido mixto no se renderizaba justificado como en el diseño, y el borde izquierdo quedaba irregular
- La versión en letras latinas del mismo bloque se veía “fine”, pero en árabe las líneas comienzan desde la derecha, así que el borde irregular aparecía a la izquierda
- Incluso aplicando
text-align: justify, no se lograba rellenar la línea alargando trazos dentro de las palabras como en la versión aprobada por el equipo de diseño - En el mismo producto ya habían aparecido antes otros problemas con árabe, como separación de letras en nombres dentro de PDFs, fallas en el índice de búsqueda y problemas con code points Unicode heredados
- La esencia del problema no estaba en una hoja de estilos específica, sino en el estado de la tipografía árabe en la web
El problema que resolvía la tradición manuscrita
- La tradición clásica de copia manuscrita en árabe justificaba las líneas sin aumentar los espacios entre palabras, sino alargando los trazos de conexión dentro de las formas de las letras
- Este método se conoce como taṭwīl o, en terminología técnica moderna, kashida, y consiste en extender el trazo de conexión entre ciertos pares de letras
- Una página bien compuesta en estilo Naskh del siglo XVII alinea ambos márgenes y no expande el espacio entre palabras, creando una textura densa y regular
- El al-khaṭṭ al-mansūb sistematizado por Ibn Muqla organizó las formas de las letras mediante el punto romboidal de la punta de caña, la altura del alif y las proporciones de arcos
- En esa tradición, la justificación no era un problema de repartir espacios, sino un problema de shaping de formas de letras y selección de glifos alternativos
Una letra, cuatro formas
- El árabe es una escritura siempre conectada, como si fuera cursiva permanente, y no existe una distinción entre letra de imprenta y letra manuscrita tipo bloque
- Cada letra cambia según sus vecinas a forma aislada, inicial, medial o final, y seis letras no se conectan hacia adelante, interrumpiendo el flujo dentro de la palabra
- Unicode almacena letras abstractas, la fuente aporta glifos según posición, y el motor de shaping aplica funciones OpenType como
isol,init,medi,fina,rlig,mark,mkmk - Una palabra como
محمدocupa cuatro code points al almacenarse, pero al renderizarse pasa por selección de varios glifos y búsquedas OpenType para verse como un trazo continuo - Si falta un motor de shaping como HarfBuzz o un generador de PDF no pasa por ese proceso, esos mismos code points se renderizan como letras aisladas y separadas entre sí
El fósil de Unicode: Arabic Presentation Forms
- En la época de DOS y las primeras versiones de Windows, las code pages de 8 bits codificaban no letras abstractas sino las formas mismas, como iniciales y mediales, como caracteres separados
- Unicode las aceptó por compatibilidad de ida y vuelta, y por eso siguen presentes en los bloques Arabic Presentation Forms entre U+FB50 y U+FEFF
- Esos code points no deberían aparecer en documentos nuevos, pero los extractores de texto de PDF todavía pueden emitirlos hoy
- Si un mismo nombre se guarda una vez con Unicode moderno y otra con Presentation Forms, en pantalla puede verse igual, pero en comparación de strings y búsquedas se trata como distinto
- Aplicar normalización NFKC puede reducir omisiones en búsquedas al plegar las Presentation Forms hacia letras abstractas
Software que se salta el shaping y el manejo bidireccional
- El software que se salta el motor de shaping y el algoritmo bidireccional dibuja las letras una por una en forma aislada y distribuye la línea de izquierda a derecha
- Ese tipo de salida es algo con lo que lectores de árabe realmente se topan en letreros de tiendas, pases de abordar, marcas de agua y rotulación árabe en películas antiguas
- Versiones viejas de Photoshop, la configuración por defecto de matplotlib, varios generadores de PDF en npm y las impresoras de recibos pueden producir estos problemas
- Los atajos comunes en Python,
arabic_reshaperypython-bidi, usan el bloque Presentation Forms para hornear en el string una forma ya pre-shapeada - Ese atajo adelanta al string un trabajo que debería hacer el renderizador y, en el fondo, expone una falla del stack de texto
Tres tipos de números y el problema de la puntuación
- Los dígitos 0–9 que el mundo llama “Arabic numerals” no son la forma de números que la mayoría de los lectores de árabe usa en la vida diaria
- Egipto, Sudán, el Levante, Irak y la región del Golfo usan los ARABIC-INDIC DIGITS de Unicode:
٠١٢٣٤٥٦٧٨٩ - El Magreb usa glifos de números latinos, mientras que Irán, Afganistán y Pakistán usan los EXTENDED ARABIC-INDIC DIGITS:
۰۱۲۳۴۵۶۷۸۹ - En UAX #9, los números no se tratan como caracteres fuertes sino débiles, y se reclasifican como números europeos o árabes según la direccionalidad del carácter fuerte previo
- Un número telefónico como
010-1234-5678después de una palabra árabe puede terminar viéndose como5678-1234-010en pantalla porque los guiones se interpretan como neutrales - La solución que ofrecen las plataformas es aislar la direccionalidad envolviendo el número con
o<bdi> - Los separadores decimal y de miles en el mundo árabe son U+066B
٫y U+066C٬; visualmente se parecen mucho al ASCII.y,, pero sus code points y propiedades bidireccionales son distintas
Atajos y simplificaciones desde la imprenta hasta la web
- Kitāb Ṣalāt al-Sawāʿī, impreso en 1514 en Fano, fue el primer libro árabe en tipos móviles, y muestra separación de conexiones entre letras y errores en la colocación de puntos
- El Qurʾān de Paganini, impreso en 1537 en Venecia, combinó errores tipográficos y errores textuales, fracasó comercialmente, y un ejemplar fue hallado en 1987 en la biblioteca de un monasterio en Venecia
- La historia de una prohibición otomana de imprimir tiene el problema de que no se conservan los decretos originales de Bayezid II y Selim I, y depende de relatos de viajeros europeos
- La imprenta Bulaq de El Cairo fue fundada por Muhammad Ali en 1820 y mejoró la calidad del tipo metálico árabe con cientos de piezas y mucha paciencia
- El Qurʾān de El Cairo de 1924 fue producido en Amiria Press con tipo metálico y contribuyó a la estandarización textual y tipográfica del siglo XX
- A finales de los años 1950, Kamel Mrowa y Linotype crearon Simplified Arabic para ajustarse a revistas de 90 canales, fusionando formas iniciales con mediales y finales con aisladas, y reduciendo ligaduras
- Simplified Arabic hizo posible una producción periodística más rápida y barata, y en una generación pasó a dominar las redacciones en árabe
La kashida que la web todavía no sabe dibujar
- En los primeros borradores de CSS Text Module Level 3 existía el valor kashida para
text-justify, e Internet Explorer 5.5 lo implementó en 2000 - IE 5.5 también ofrecía la propiedad
text-kashida-space, pero como otros navegadores no la implementaron, ese valor desapareció de la especificación - En Chrome, Firefox y Safari modernos,
text-align: justifyen árabe funciona ampliando el espacio entre palabras - El issue de la justificación árabe en el CSS Working Group lleva abierto al menos desde 2015, y el trabajo de W3C Arabic Layout Requirements también comenzó ese mismo año
- La justificación con kashida exige que shaping y layout renegocien línea por línea, porque al estirar glifos cambia el ancho, y ese cambio de ancho vuelve a alterar los saltos de línea y la cantidad de estiramiento necesaria
- OpenType tiene desde los años 1990 la tabla
jstf, con la que una fuente puede indicar prioridades de justificación, pero casi ningún motor de shaping la lee y casi ningún diseñador tipográfico la provee - Microsoft Word e InDesign Middle East Edition ofrecen justificación con kashida, pero el conjunto de renderizadores de navegador donde la gente más lee sigue sin poder alargar las letras
Hacks con Tatweel y problemas de ligaduras y vocales
- Un atajo común en la web es insertar en el propio texto el carácter U+0640 TATWEEL para que parezca un trazo estirado
- Tatweel modifica el contenido, así que causa problemas en coincidencia de búsquedas, copiar y pegar, lectores de pantalla y reflujo de columnas
- El trazo que dibuja Tatweel no es una kashida colocada según reglas de fuente y carácter, sino una barra estilo máquina de escribir insertada por quien escribe a ojo
- Las ligaduras OpenType se dividen en
rlig,ligaydlig, y si se rompe una ligadura obligatoria comolām-alif, el texto deja de estar simplemente feo: pasa a estar incorrecto - Si se inserta U+200C ZERO WIDTH NON-JOINER entre letras, las letras almacenadas se conservan, pero el renderizado fuerza a cada una a aparecer en forma aislada
- Safari ignora
"rlig" 0y"liga" 0, así que las demos para desactivar ligaduras obligatorias no tienen efecto ahí - Amiri es una fuente Naskh publicada por Khaled Hosny en 2011 bajo SIL Open Font License, y tras una reescritura 1.0 en 2022 ofrece kashida curva y un apilado de vocales refinado
- Un componente de tarjeta con
line-height: 1yoverflow: hiddenpuede recortar las marcas vocálicas superiores del árabe completamente vocalizado
El algoritmo bidireccional y el cursor que miente
- Dentro de un párrafo en árabe, números de versión, identificadores en inglés, URLs y palabras en francés activan el UAX #9, el Unicode Bidirectional Algorithm
- Las letras árabes se tratan como caracteres fuertes de derecha a izquierda, las letras latinas como fuertes de izquierda a derecha, los números como caracteres débiles que siguen el contexto, y los espacios y signos de puntuación como neutrales
- El algoritmo asigna una clase direccional a cada carácter, interpreta paso a paso los caracteres débiles y neutrales, luego asigna niveles de embedding e invierte las runs del mismo nivel
- Como el orden visual en pantalla difiere del orden lógico en memoria, mover el cursor, hacer clic con el mouse y seleccionar texto exige traducir constantemente entre ambos órdenes
- En los límites entre runs hay dos posiciones de cursor legítimas, una lógica y otra visual, y Chrome, Firefox, Qt y Outlook pueden manejarlas de formas distintas
- Escribir texto mixto árabe-inglés sigue siendo, incluso en 2026, una experiencia con alto costo cognitivo por defecto en los principales editores, clientes de correo y aplicaciones de chat
- Rangos como
الصفحات 10-20pueden verse como “de 20 a 10” por la regla W2 y el tratamiento neutral del guion, y se pueden corregir poniendo antes U+200E LEFT-TO-RIGHT MARK
La base que sí funciona y los vacíos que siguen ahí
- Khaled Hosny creó Amiri, escribió la herramienta de línea de comandos
hb-shapepara HarfBuzz y también actúa como co-mantenedor de HarfBuzz - Behdad Esfahbod escribió gran parte de HarfBuzz antes de Hosny y contribuye al motor de shaping que hoy permite que los navegadores dibujen correctamente las letras árabes
- Brill encargó a John Hudson la tipografía Brill para incluir todos los caracteres de transliteración necesarios en su catálogo de estudios semíticos, y la publicó gratis para uso no comercial en 2011
- Sakhr AX-170 fue una computadora MSX saudí-kuwaití de alrededor de 1984 que mostraba árabe desde ROM y soportaba identificadores Arabic BASIC escritos de derecha a izquierda
- HarfBuzz, Amiri, Scheherazade, el soporte de Presentation Forms en GNU Unifont, Noto Arabic y la documentación de W3C Arabic Layout dependen en gran medida del esfuerzo de unas pocas personas, organizaciones y voluntarios
- Los fabricantes de navegadores adoptaron HarfBuzz cuando ya estaba terminado y disponible gratis, pero casi no han contribuido al loop de layout necesario para implementar en pantalla la justificación heredada de la tradición manuscrita
- La brecha restante consiste en algoritmos bien entendidos que algunos motores de layout todavía deben implementar, y el margen izquierdo irregular en un dashboard para clientes es la forma visible para el usuario de esa falta de inversión
1 comentarios
Comentarios de Lobste.rs
De verdad es un artículo increíble.
Y me encanta que este carácter
﷽sea un solo code point. Es curioso copiarlo y probarlo.Significa “En el nombre de Alá, el más misericordioso, el más compasivo”.
﷽es poética:“Un monumento a una época en la que nadie confiaba en los motores de renderizado, así que el renderizado venía horneado en la codificación. Como una mosca recitando preservada para siempre dentro del ámbar”.
Fue divertido seguir las referencias del enlace de Wikipedia citado ahí: https://lobste.rs/c/dq2ucz
En resumen, este carácter entró en Unicode porque estaba en una code page de Pakistán, y terminó ahí porque existía un requisito legal de incluir esa frase en documentos jurídicos. Como el urdu es una lengua indoeuropea, con la tecnología de ese momento seguramente habría sido difícil “hacer una llamada externa” a una code page árabe para escribir la basmala.
Lamentablemente, no todos los comentarios muestran las virtudes de esa comunidad.
Meta: este es otro gran ejemplo de por qué a artículos así les hace falta una etiqueta
typography.En lobste.rs, las etiquetas se usan principalmente para filtrar.
La propiedad
text-justifyde IE... en esa época había cosas muy interesantes. También existíatext-justify: newspaper, y aunque décadas después algunas personas lo explicaron como Knuth-Plass o algo parecido, no creo que realmente lo fuera.https://mediumwell.com/wp-content/uploads/… muestra un comportamiento que en su momento se atribuía a
text-justify: newspaper, y que coincide con eltext-justify: inter-characterde las especificaciones actuales.IE de verdad tenía muchas funciones geniales desde bastante temprano, y otros navegadores las dejaron abandonadas en la canasta de “demasiado difícil”. Al final, algunas nunca volvieron, y otras no regresaron sino hasta 15 o 30 años después. Firefox obtuvo
text-justify: inter-characteren 2017, Chromium apenas implementó esa parte hace unos meses, y Safari todavía no lo tiene.Un artículo increíblemente bueno y útil. Me gustó especialmente el contexto histórico, que le da un marco más amplio a toda la historia.
Como alguien con un título relacionado con historia y también una carrera en TI, este artículo tocó perfectamente mis dos intereses.
Hay algo en el artículo que activa mi detector de LLM, lo cual es una lástima. Tiene profundidad y además trata partes poco documentadas del stack tecnológico moderno.
Un ejemplo de ese tono como de LLM sería este pasaje, aunque esa sensación aparece a lo largo de todo el texto:
“La razón por la que ningún navegador ofrece esto es estructural, y como obstáculo esa estructura es bastante elegante. La justificación en escritura latina trata el texto ya conformado como algo fijo, mide las palabras, vierte el espacio sobrante en los espaciados y termina. El shaping y el layout permanecen cada uno en su propia caja, y todos los stacks de texto en producción están diseñados alrededor de esa separación. La justificación con kashida abre esa caja de golpe”.
Me gustaría preguntarle a @lr0 si el cuerpo de este artículo fue generado, pulido o traducido con un LLM. Si fue así, quizá convendría ajustar el nivel de control que el LLM tiene sobre el resultado final. Entradas viejas del blog, por ejemplo https://lr0.org/blog/p/gpt/ y https://lr0.org/blog/p/linux_new_users/ , se sentían mucho más humanas.