Internacionalización: hacer que la web sea accesible para todos

Ecma International, el Comité Técnico 39 o simplemente TC39 es un grupo de desarrolladores de JavaScript, implementadores de tecnología, académicos y otras partes interesadas que, junto con la comunidad, apoyan y desarrollan JavaScript como plataforma.

Los participantes de TC39 generalmente comparten algo interesante usando su profundo conocimiento de JavaScript. Pero algunas personas piensan que se han alejado demasiado de los problemas de los desarrolladores comunes. ¿Dónde está el desarrollador del lenguaje y dónde está la persona que escribe frontends todos los días en la práctica?

Conozcamos el informe, que combina la profundidad de la comprensión y la alta aplicabilidad práctica . Conozca la nueva historia de Romulo Cintra sobre los problemas de internacionalización que abordará la nueva API, que pronto aparecerá en JavaScript.



Rómulo Cintra - delegado TC39, ha estado trabajando en desarrollo y arquitectura durante más de 10 años, especializándose en web, desarrollo móvil y nubes. En este informe, conocerá de primera mano al copresidente del grupo de trabajo MessageFormat , qué opciones ya están disponibles para resolver problemas existentes y en qué forma se resolverán utilizando la nueva API en JavaScript.

Debajo del corte, la transcripción textual completa del informe Rómulo y un enlace al video. Si te gusta leer, este artículo lo tiene todo; no te perderás nada. Si tiene tiempo para comenzar la grabación de video, tendrá aproximadamente una hora de buena grabación de video con diapositivas interesantes e inglés comprensible.

Narración adicional en nombre del orador.


Hay tres cosas que debe saber sobre el estado de internacionalización y localización: todo es muy, muy, muy malo. Mi nombre es Romulo Cintra, y estoy involucrado en aplicaciones de arquitectura financiera. Hablo mucho con personas de TC39 y veo cómo tratan de hacer del mundo JavaScript un lugar mejor. Además, soy un gran defensor del código abierto, y en mi tiempo libre soy profesor en la Escuela de Tecnología de Barcelona.

El tema de la internacionalización es muy importante. Dio la casualidad de que en nuestra Tierra hay muchos pueblos e idiomas diferentes. En el mundo de hoy hay alrededor de 195 países y 6 mil idiomas. Esto hace que nuestra tarea sea extremadamente difícil. Piensa en otra cosa: escribo artículos y leo informes en inglés, no en ruso; Ya tenemos un problema de internacionalización. Si alguien no habla inglés, será excluido de nuestra conversación con usted. Para evitar que esto suceda, se inventó la internacionalización.

La internacionalización inglesa se abrevia como i18n. El número 18 es el número de caracteres entre las letras i y n en esta palabra. En resumen, la internacionalización es el diseño de software para simplificar la localización tanto como sea posible. Gracias a la internacionalización, el software puede admitir configuraciones locales, idioma, moneda, etc. La internacionalización hace que la web sea más accesible para todos. Aquí puede trazar un paralelo con el desarrollo a través de pruebas (desarrollo basado en pruebas): primero se escribe la prueba y luego el código; Con la internacionalización es necesario hacer lo mismo. Por lo general, la gente piensa en la internacionalización después de escribir el código, pero está mal.

Similar a i18n, l10n es la abreviatura de localización, y 10 es el número de caracteres entre el primer l y el último n. La localización es la adaptación de un producto al entorno lingüístico y cultural en el que se distribuye. Es decir, no solo necesita traducir "Hola" a "Hola", sino también usar la moneda local, el separador decimal, etc., es decir, hacer que el software sea más familiar para el usuario. Es más que solo una traducción.

¿Cuántos idiomas soportan sus proyectos web? Muchos tienen más de dos. ¿Hay alguien que tenga más de cinco? ¿Qué hay de 15? Apoyamos alrededor de 25 idiomas. No tenemos muy buen apoyo, porque la internacionalización no está organizada de la mejor manera. En el curso del informe, explicaré cómo mejorar la internacionalización y hablaré sobre las medidas que estamos tomando.

Por lo tanto, repito una vez más: la internacionalización significa simplificar la localización, brindando soporte a nivel de arquitectura. Y la localización es la adaptación del software a las realidades locales. La traducción a menudo no se corresponde con el original; tomemos un ejemplo de la industria cinematográfica, donde el nombre de la película "Pain and Gain" se tradujo como "Blood and Sweat: Anabolics".



O otro ejemplo: un anuncio de un baño ruso, en el que la traducción al inglés dice "crematorio ruso" (crematorio ruso).



Dudo que esto atraiga clientes, al menos vivos. La internacionalización y la localización son tan importantes precisamente porque nos permiten transmitir exactamente lo que queremos decir al usuario. En esencia, la internacionalización es la provisión de accesibilidad, porque si no puede comprender el software con el que trabaja, sus opciones son limitadas. Es beneficioso para todos que el software sea más accesible, ya que proporciona una gama más amplia de usuarios y, por lo tanto, un mayor ingreso; También mejora la web.

Formato de mensaje


Considere los ejemplos de código:

'es-ES': { 
    HELLO_WORLD: '¡Hola mundo!' 
}, 
'en-GB': { 
    HELLO_WORLD: 'Hello world!'

Necesitamos traducir nuestros objetos de cadena. Tenemos una variable HELLO_WORLDcon líneas correspondientes en cada idioma. Para dicha traducción en muchos idiomas (por ejemplo, Java), existe el formato MessageFormat . Tratemos de descubrir qué es. Primero, un poco sobre algunas tecnologías básicas: comencemos con Unicode. Este es un estándar que crea un espacio único para caracteres de diferentes idiomas. Dibujemos una analogía con el ajedrez: cada tipo de piezas puede tener una forma diferente, pero siempre sabemos dónde deben estar exactamente en el tablero. Bueno, por supuesto, hay diferentes formatos Unicode con diferentes números de bytes: UTF-8, UTF-16 y UTF-32. Ahora la metaetiqueta más utilizada es UTF-8. Con Unicode, el navegador puede mostrar caracteres especiales, si esta etiqueta`metaolvide, nadie entenderá qué tipo de símbolos tenemos en la página.

Además de Unicode, otras dos tecnologías importantes son CLDR e ICU. CLDR es un tipo de base de datos de alfabetos, países, monedas, zonas horarias, etc., almacenados en diferentes idiomas del mundo. No están presentes los 6 mil idiomas del mundo, todavía se está trabajando en esta base de datos. La última actualización fue en octubre pasado. Otro proyecto importante es la UCI. Esta es una gran base de datos de palabras, números y símbolos de diferentes idiomas, que se proporcionan en forma de métodos para ordenar, normalizar, formatear, etc. Estas bibliotecas se utilizan en muchos lenguajes de programación. En JavaScript, ICU está en el núcleo de la API Intl. Pero hay tantos materiales diversos en los idiomas del mundo que deben mostrarse en los navegadores que el trabajo de incluirlos en estos estándares está lejos de ser completo.

MessageFormat es un formato que le permite asociar una clave específica con un mensaje específico en un idioma específico. En algunos casos, las variables se pueden pasar a MessageFormat , las define y las ingresa en la línea final. El mismo problema se resolvió de manera ligeramente diferente en otros idiomas. En Android, MessageFormat se implementa en Java. Allí, para trabajar con este formato, no se necesita una biblioteca especial; Android puede interactuar con él mismo. En iOS, hay una API que es muy similar a la de JavaScript. Está integrado en el sistema, no hay necesidad de descargar nada allí, simplemente pase la línea necesaria al método de esta API.

¿Cómo se resolvió este problema en JavaScript? Aún no. Pero tenemos muchas bibliotecas que ofrecen una solución.



Muestra la cantidad de descargas de las más populares (y dos menos populares, fluidas de Mozilla y fbt de Facebook). Se realizan casi dos millones de descargas cada semana, por lo que se necesitan bibliotecas para la internacionalización.

Bibliotecas


Presentaremos brevemente algunas de estas bibliotecas y comenzaremos con i18next. Sus desarrolladores han realizado muchos cambios en MessageFormat , y no sigue completamente la UCI. Sin embargo, es una muy buena biblioteca. Su implementación de MessageFormat tiene muchas ventajas, por ejemplo, la capacidad de utilizar la interpolación de cadenas (que no está disponible en formato ICU). Sin embargo, también hay desventajas, por ejemplo, los mensajes plurales no se pueden colocar en la misma línea que el único, como se puede hacer en la UCI.

Una de las bibliotecas de internacionalización más famosas es intl-messageformat. Cada semana se descarga más de 700 mil veces. Su apoyo es manejado por mi colega, Long Hu. Su popularidad se explica por el hecho de que react-intl se crea encima de él. Entonces, si usa React, lo más probable es que tenga esta biblioteca. Su desarrollador también participa en ECMA-402 y, por lo tanto, intenta cumplir con el estándar de la UCI.

var MESSAGES = { 
    'en-US': { 
        NUM_PHOTOS: 'You have {numPhotos, plural, ' +
            '=0 {no photos.}' +
            '=1 {one photo.}' +
            'other {# photos.}}'
}, 
    'es-MX': {
        NUM_PHOTOS: 'Usted {numPhotos, plural, ' +
            '=0 {no tiene fotos.}' + 
            '=1 {tiene una foto.}' 
            +'other {tiene # fotos.}}' 
    } 
};

Su implementación es muy similar a MessageFormat . Aquí puede pasar variables e indicar la necesidad del plural.

Antes de pasar a los ejemplos de código, hablaré sobre dos bibliotecas nuevas más que ahora están de moda, fueron creadas por Facebook y Mozilla.



La API completa no se puede mostrar como un todo, pero confíe en mi palabra: los desarrolladores de estas bibliotecas hicieron todo lo posible, es exactamente lo que nos falta en este momento. Es cierto que Facebook lo hizo con su propio estilo: su propio marcado, la capacidad de ejecutarse durante el diseño, la extracción de mapas hash de cadenas que se pueden traducir automáticamente. El problema es que todo esto se centra en la escala con la que el programador promedio rara vez trabaja. El proyecto es muy joven y quieren integrarlo con otras bibliotecas conocidas, por ejemplo, con React. En el futuro, es probable que gane popularidad.

Todo lo anterior son bibliotecas que deben descargarse adicionalmente, no están integradas en el navegador. Con un solo navegador, no llegaremos lejos, por lo que todo es malo con la localización. MessageFormat puede ayudarnos a cambiar este estado de cosas . Si bien no podemos usarlo, pero créanme: el futuro recae en él. Ahora estamos trabajando activamente en ello, estableciendo interesados, buscando nuevas ideas para el nuevo MessageFormat . En su versión original, este formato ya está desactualizado, las necesidades de los desarrolladores han evolucionado significativamente desde su inicio. El nuevo formato debe estar hecho con alta calidad y ser fácil de usar.

Intl.DateTimeFormat


Los navegadores ya tienen muchos mecanismos incorporados para la internacionalización y localización, la mayoría de ellos simplemente no los conocen y no los usan. ¿Has oído hablar de Intl.DateTimeFormat? En este proyecto, estamos constantemente creando nuevas API. Es probable que ya no se necesiten Moment.js , Day.js , date-fns .

const myDate = new Date(); 
new Intl.DateTimeFormat('ru', { timeStyle : 'short'}).format(myDate); 
// short → 19:49 
// medium → 19:49:17 
// long → 19:49:17 GMT+2
// full → 19:49:17  ,  

Existe timeStyle, fue creado hace unos meses y le permite formatear la fecha y la hora sin tener que recurrir a Moment.js. Además, hay un método formatRange . Cualquier tarea asociada con la elección de un rango de fechas (como en sitios con una función de reserva) siempre es difícil. Pero el método para esto ya existe en el navegador. Y, lo más importante, este método admite la internacionalización, al tiempo que elimina la necesidad de descargar bibliotecas adicionales.

Int.RelativeTimeFormat


Trabajé en la documentación para la segunda parte de este proyecto, y si también quieres participar, necesitamos ayuda para traducir al ruso y cumplir con los estándares. RelativeTimeFormat es necesario cuando necesita hacer una cuenta regresiva.

const myTime = new Intl.RelativeTimeFormat('ru', { style: 'narrow' }); 
myTime.format(2 , 'quarter'); 
//Style Narrow : +2 . → in 2 qtrs. → dentro de 2 trim. 
//Style Long :  2  → in 2 quarters → dentro de 2 trimestres

Ahora es bastante simple hacer esto, puede especificar el tiempo en dos días, dos semanas, en un trimestre, etc. Anteriormente, dicho formato en la web no existía.

const myTime = new Intl.RelativeTimeFormat('ru', { style: 'narrow' }); 
myTime.format(2 , 'day'); 
//Style Narrow : +2 . → in 2 days → dentro de 2 días 
//Style Long :  2  → dentro de 2 días myTime.format(-1 , 'day');
//Style Narrow : -1 . → 1 day ago → hace 1 día 
//Style Long : 1   → 1 day ago → hace 1 día //Numeric(auto) :  → yesterday → ayer 

Aquí hay un ejemplo en ruso. Usted mismo puede probar el funcionamiento de este código, porque ya está en su navegador.

const myTime = new Intl.RelativeTimeFormat('ru', { style: 'narrow' }); 
myTime.format(20 , 'seconds'); 
//Style Narrow : +20  → in 20 sec. → dentro de 20 s 
//Style Long :  20  → in 20 seconds → dentro de 20 segundos

Este método es muy útil, puede dar tiempo en el formato corto que ves arriba. Enfatizo que para todo esto no necesita usar ninguna biblioteca de terceros.

Intl.NumberFormat


Lo siguiente que quería compartir es Intl.NumberFormat . Hablaré sobre la tercera etapa, pero solo la segunda se presenta en los ejemplos, porque todavía se están discutiendo algunos cambios. Intl.NumberFormat funciona con unidades y formularios de registro. Vale la pena prestar atención a lo que hace con las unidades: te permite trabajar con diferentes estilos.

new Intl.NumberFormat("ru", { 
style: "unit", 
unit: "liter", unitDisplay: "long" 
}).format(16); 
// → 16  → 16 liters → 16 litros

Todas las unidades se toman de UTC 35, y hay muchas de ellas. En total, aquí se presentan unas 140 unidades para formatear. Así que ahora la internacionalización es más fácil que nunca. Solo necesita traducir sus líneas, y toda la dinámica necesaria ya está contenida en el navegador.

const nbr = 987654321; 
new Intl.NumberFormat('ru', { notation: 'scientific' }).format(nbr); 
// → 9,877E8 → 9.877E8 (en-US) 
new Intl.NumberFormat('ru', { notation: 'engineering' }).format(nbr); 
// → 987,654E6 → 987.654E6 (en-US) 
new Intl.NumberFormat('ru', { notation: 'compact' }).format(nbr); 
// → 988  → 988M (en-US) → 9.9亿 (zn-CN) 
new Intl.NumberFormat('ru', { notation: 'compact', compactDisplay: 'long' }).format(nbr); 
// → 988  → 988 millions (fr)

Ahora para las formas de grabación. Para ser honesto, no los uso con demasiada frecuencia, porque no uso la forma de grabar con el exponente (registro científico), y no necesito presentar grandes números. Pero si lo necesita, entonces hay una API correspondiente especialmente para usted.

Intl.ListFormat


Otra API útil es Intl.ListFormat , que ya está en la tercera etapa y le permite formatear listas de dos maneras diferentes. Supongamos que necesito decir la frase "Voy a HolyJS". Podemos hacer una lista que incluya las líneas "Moscú" y "St. Petersburgo ", especifique el parámetro" conjunción ", y las líneas se combinarán mediante la unión del idioma ruso" y ". Esta es una característica completamente nueva y muy útil.



Si especifica "disyunción", obtenemos la unión "o".



Finalmente, la función puede determinar automáticamente el idioma y el alfabeto utilizados y ordenar los elementos de la lista en consecuencia.

Reglas Plurales Internacionales


Otra API importante es Intl.PluralRules . Esta API es la más antigua de todas, pero por alguna razón nadie la usa.



Cuando veo las listas de finalistas en carreras o en fútbol, ​​los números siempre se indican junto a los nombres: "1", "2", "3", etc. Pero esto no corresponde a la forma en que decimos que estaría mucho más cerca para el discurso, escriba "1st", "2nd", "3rd". Y para esto hay API especiales, que no son tan difíciles de usar.



Por ejemplo, podemos escribir las frases "1 gato", "0 gatos", "0.5 gatos", "1.5 gatos", y la API seleccionará automáticamente la terminación plural correcta.

Intl.DisplayNames


Esta es una de las API más populares, porque a menudo tenemos que mostrar listas de países. Supongamos que tenemos una lista de países, por ejemplo, en una base de datos o en JSON. Luego, cada vez que cambie el idioma, necesitamos cargar un JSON separado con una nueva lista de países, monedas, etc. Hay demasiados de estos JSON, y ¿cómo termina? Creamos un microservicio en el que está integrada una base de datos con varios idiomas, y extraemos todos los datos de ella. Por supuesto, en el ejemplo con la lista de países tuvimos suerte y necesitamos actualizar los datos con poca frecuencia, pero no siempre será así, ¿verdad? No podemos resolver todos los problemas a la vez, pero DisplayNames resuelve algunos de ellos. Tiene la API como en el ejemplo a continuación, y puede solicitar solo una lista de monedas o solo una lista de países:

const currencyNames = new Intl.DisplayNames(['en'], {type: 'currency'}); currencyNames.of('USD'); // "US Dollar" 
currencyNames.of('EUR'); // "Euro" 
currencyNames.of('TWD'); // "New Taiwan Dollar" 
currencyNames.of('CNY'); // "Chinese Yuan"


const languageNames = new Intl.DisplayNames(['en'], {type: 'language'}); languageNames.of('fr'); // "French" 
languageNames.of('de'); // "German" 
languageNames.of('fr-CA'); // "Canadian French" 
languageNames.of('zh-Hant'); // "Traditional Chinese"

Esto es algo muy útil. Funciona no solo con países y monedas: de la misma manera, puede trabajar con meses, días de la semana y muchas otras cosas que necesita como desarrollador.

Resultados y planes para el futuro


Hasta ahora, hemos hablado sobre las API existentes. Pasemos a nuestros planes para el futuro. Mi lengua materna es el portugués. Así que en mis sitios necesito admitir al menos portugués e inglés. Y como estamos muy cerca de España, el español también es útil. Portugal es un país muy pequeño, y Francia tampoco está tan lejos, por lo que sería bueno agregar el francés a esta lista.

Para nosotros MessageFormatmuy relevante, y aparecerá pronto. Hay bibliotecas y hay desarrolladores que trabajan en ellas. Todos estos desarrolladores están trabajando en temas relacionados. La mayoría de los creadores de las bibliotecas más populares y las empresas más grandes (Netflix, Amazon, Facebook) están de acuerdo al menos en una cosa: ahora existe una necesidad urgente de internacionalización. Esto también está indicado por dos millones de descargas por semana. Así que ahora podemos darnos el lujo de volver a escribir MessageFormat y hacerlo de manera de calidad.

¿Quién se beneficiará de una internacionalización adecuada? Toda la web: todas las empresas, todos los proyectos, todas las bibliotecas. Bibliotecas como Intl.MessageFormatno desaparecerá en ningún lado, pero comenzará a funcionar de una manera nueva. No necesitará descargar datos, ya que todos los datos ya estarán en el navegador. Lo más probable es que no necesite cambiar a una nueva biblioteca. Algunas de estas bibliotecas ya funcionan como polyfills para algunas implementaciones. Algunas implementaciones que mencioné se encuentran en la tercera etapa y no se implementan en todos los navegadores. Pero las bibliotecas como Intl.MessageFormat proporcionan rellenos de polietileno para esta funcionalidad. En general, se acerca un nuevo capítulo en la historia de la web: una verdadera revolución. La web será accesible y comprensible para todos. Esto es extremadamente importante.

Creo que es muy importante garantizar la singularidad de nuestro proyecto. Si hay un formato que se puede usar en C ++, Java y JavaScript, ¿por qué no usar este formato en todas partes? Cuando escribimos páginas web, a menudo necesitamos crear versiones móviles de ellas, en cuyo caso tenemos que hacer mucho trabajo dos veces. Si tuviéramos un formato para todo, entonces podríamos usar los recursos y API existentes. Necesitamos un nuevo nivel de integración con herramientas. La internacionalización es proporcionada no solo por el trabajo de los desarrolladores directamente involucrados en ella. Para ella, la modularidad es extremadamente importante, porque a menudo es conveniente usar sus propias herramientas de formateo, su propio código. Por lo tanto, no debe cerrar la API, deben estar abiertos para que puedan conectar lo que la situación requiere.Otro punto importante: estas API deben ser nativas. Los CLDR proporcionan los datos que necesita la API de internacionalización. Si está ejecutando Windows o MacOS, entonces ya está descargando datos del CLDR. CLDR es un repositorio único; nadie duplica su función. Esto significa que los datos pueden descargarse solo una vez y hacerse comunes a todo el sistema operativo. Si todos los datos de la API Intl ya están cargados en el sistema operativo, ¿por qué no proporcionarlos para todo el software en este sistema?Si todos los datos de la API Intl ya están cargados en el sistema operativo, ¿por qué no proporcionarlos para todo el software en este sistema?Si todos los datos de la API Intl ya están cargados en el sistema operativo, ¿por qué no proporcionarlos para todo el software en este sistema?

Nuestra experiencia nos enseñó a recordar que no estamos solos, que no solo los programadores están trabajando en la internacionalización. Somos desarrolladores, no traductores. Supongamos que necesitamos hacer un avance de línea en nuestra interfaz, los enviamos a la empresa de traducción. Pero los traductores a menudo no tienen contexto para estas líneas. Esto también está ausente en MessageFormat . A veces esto lleva a errores, como ya hemos visto en el ejemplo mencionado con el crematorio ruso.

Finalmente, creo que las API para la internacionalización deberían ser fáciles de usar, y todos deberían poder hacer la internacionalización; esto no debería requerir demasiado tiempo y esfuerzo. Al escribir código para la internacionalización, debe guiarse desde el principio. Después de todo, con TDD, primero escriben una prueba y luego codifican; Comencemos nuestros proyectos web sobre este principio con la internacionalización y localización correctas. Esto nos permitirá crear sitios que sean convenientes y accesibles para todos.
HolyJS 2020 Piter «Speak my language %app%». , , : . HolyJS 2020 Piter . , .

All Articles