Como desarrollador front-end que trabaja para clientes de todo el mundo, siempre he tenido problemas para lidiar con sitios web multilingües, especialmente en los casos en los que se utilizan tanto de derecha a izquierda (RTL) como de izquierda a derecha (LTR). Dicho esto, he aprendido algunas cosas a lo largo del camino y voy a compartir algunos consejos en esta publicación.
Trabajemos en árabe e inglés, no solo porque el árabe es mi lengua materna, sino porque es un ejemplo clásico de RTL en uso.
Agregar soporte RTL a un sitio
Sin embargo, antes de esto, queremos agregar soporte para un lenguaje RTL en nuestro sitio. Hay dos formas en que podemos hacer esto, y ambas no son exactamente ideales.
No es ideal: use una fuente específica para cada dirección
La primera forma en que podríamos hacer esto es confiar en el atributo direction (dir) en cualquier elemento dado (que generalmente es el elemento , por lo que establece la dirección globalmente):
/* For LTR, use Roboto */
[dir=ltr] body {
font-family: "Roboto", sans-serif;
}
/* For RTL, use Amiri */
[dir=rtl] body {
font-family: "Amiri", sans-serif;
}
PostCSS-RTL hace que sea aún más fácil generar estilos para cada dirección, pero el problema con este método es que solo está usando una fuente, lo cual no es ideal si tiene varios idiomas en un párrafo.
Este es el por qué. Descubrirá que los párrafos multilingües estropean la interfaz de usuario porque los glifos árabes tienen una fuente predeterminada que no se alinea con el elemento.
Puede ser peor en algunos navegadores que en otros.
Tampoco es ideal: use una sola fuente que admita ambos idiomas
La segunda opción podría ser usar fuentes que ofrezcan soporte para ambas direcciones. Sin embargo, en mi experiencia personal, usar solo una fuente para ambos idiomas limita la creatividad y la libertad de usar una fuente diferente para cada dirección. Puede que no sea tan malo, dependiendo de los requisitos de diseño. Pero definitivamente he trabajado en proyectos en los que marca la diferencia.
OK, ¿y entonces qué?
Necesitamos una solución más sencilla. Según MDN:
La selección de fuentes no se detiene simplemente en la primera fuente de la lista que se encuentra en el sistema del usuario. Más bien, la selección de fuentes se realiza un carácter a la vez, de modo que si una fuente disponible no tiene un glifo para un carácter necesario, se prueban las últimas fuentes.
Es decir, todavía podemos usar la propiedad font-family pero usando un respaldo en los casos en que la primera fuente no tenga un glifo para un carácter. En realidad, esto resuelve los dos problemas anteriores, ¡dos pájaros de un tiro!
body {
font-family: 'Roboto', 'Amiri', 'Galada', sans-serif;
}
¿Por qué funciona esto?
Al igual que la forma en que flexbox y la cuadrícula CSS, hacen que los diseños CSS sean mucho más flexibles, el algoritmo de coincidencia de fuentes hace que sea aún más fácil trabajar con contenido en diferentes idiomas. Esto es lo que dice el W3C sobre cómo hacer coincidir caracteres con fuentes:
Cuando el texto contiene caracteres como marcas de combinación, lo ideal es que el carácter base se renderice utilizando la misma fuente que la marca, esto asegura la ubicación adecuada de la marca. Por esta razón, el algoritmo de coincidencia de fuentes para grupos es más especializado que el caso general de hacer coincidir un solo carácter por sí mismo. Para las secuencias que contienen selectores de variación, que indican el glifo exacto que se utilizará para un carácter determinado, los agentes de usuario siempre intentan la reserva de fuentes del sistema para encontrar el glifo apropiado antes de usar el glifo predeterminado del carácter base.
(Énfasis mío)
¿Y cómo se combinan las fuentes? La especificación describe los pasos que toma el algoritmo, que parafrasearé aquí.
- El navegador mira un grupo de texto e intenta hacer coincidirlo con la lista de fuentes declaradas en CSS.
- Si encuentra una fuente que admita todos los caracteres, ¡genial! Eso es lo que se usa.
- Si el navegador no encuentra una fuente que admita todos los caracteres, vuelve a leer la lista de fuentes para encontrar una que admita los caracteres no coincidentes y la aplica a esos caracteres específicos.
- Si el navegador no encuentra una fuente en la lista que no coincida ni con todos los caracteres del grupo ni con los individuales, entonces busca la fuente predeterminada del sistema y verifica que sea compatible con todos los caracteres.
- Si la fuente predeterminada del sistema coincide, de nuevo, ¡genial! Eso es lo que se usa.
- Si la fuente del sistema no funciona, ahí es donde el navegador muestra un glifo roto.
Hablemos de rendimiento
La secuencia que acabamos de ver podría ser una carga para el rendimiento de un sitio. Imagine que el navegador tiene que recorrer cada respaldo definido, hacer coincidir caracteres específicos con glifos y descargar archivos de fuentes según lo que encuentre. Eso puede sumar mucho trabajo, sin mencionar FOUT y otras rarezas de renderizado.
El objetivo es permitir que el algoritmo de coincidencia de fuentes decida qué fuente aplicar a cada texto en lugar de depender de una fuente para ambos idiomas o agregar CSS adicional para manejar diferentes direcciones. Si una fuente nunca se aplica a nada (digamos que una página en particular está en RTL y resulta que no tiene ningún texto LTR, o viceversa), la fuente más abajo de la pila que no se usa nunca se descarga.
Hacer que eso suceda requiere seleccionar buenas fuentes multilingües. Las buenas fuentes multilingües son aquellas que tienen glifos para tantos caracteres que anticipa usar en una página. Y si no puede encontrar uno que los admita todos, usar uno que admita la mayoría de ellos y luego recurrir a otra fuente que sí los admita es una forma eficiente de hacerlo. Si esa es la fuente predeterminada del sistema, es igual de genial porque es un archivo de fuente menos descargado.
Lo bueno de dejar que la propiedad de la familia de fuentes decida la fuente para cada glifo (en lugar de hacer selectores de CSS adicionales para cada dirección) es que el comportamiento ya está ahí como lo describimos anteriormente; simplemente necesitamos hacer uso de él.