Trabajando con intl

Internacionalización: algo de lo que escuchas hablar constantemente a los desarrolladores, pero que rara vez se ve a la gente que usa en la práctica, se está poniendo de moda con la nueva API de internacionalización de ECMAScript. Actualmente compatible con Chrome 24, Chrome para Android, Firefox 29, IE 11 y Opera 15 (lamentablemente no es compatible con Safari), el nuevo espacio de nombres de Intl proporciona un conjunto de funciones para agregar la internacionalización a sus números, fechas y clasificación. En este artículo, demostraré las características principales de Intl y lo guiaré en el camino para adoptar el apoyo para los miles de millones de personas en Internet que viven fuera de su país.!

Características principales

El espacio de nombres de Intl cubre tres áreas principales de funcionalidad:

  • Formatear numeros
  • Fechas de formato
  • Clasificación de cuerdas

Dentro de cada uno de estos hay varias opciones para controlar tanto las configuraciones regionales utilizadas para el formato como las opciones de formato. Como ejemplo, el formateador de números incluye soporte para el manejo de la moneda. El formateador de fecha tiene opciones para que partes de la fecha se muestren.

Veamos algunos ejemplos..

Nuestra aplicacion

Nuestra primera aplicación es un simple reportero de datos. Utiliza AJAX para obtener un conjunto de datos que contienen fechas y números. Primero, el HTML:

Listado 1: test1.html:

          

Estadísticas actuales

Fecha Visitas

Toma nota de la mesa vacía. Ahí es donde estaremos volcando nuestros datos. Ahora echemos un vistazo al JavaScript..

Listado 2: app1.js:

$ (document) .ready (function () // obtener la tabla dom $ table = $ ("# stats tbody"); // ahora, obtenga nuestros datos del api, que es falso btw $ .getJSON ("stats .json "). done (función (es) // iterar sobre las estadísticas y agregar a la tabla para (var i = 0; i < s.length; i++)  $table.append(""+s[i].date+""+s[i].views+"");  ).fail(function(e)  console.log("we failed"); console.dir(e); ); ); 

Todo lo que hace el código aquí, es hacer una llamada AJAX a un archivo y renderizar el resultado a los datos. El archivo de datos, stats.json, es simplemente una matriz de diez valores codificados. Aquí hay una porción del archivo:

["date": "1/4/2013", "views": 938213, "date": "4/2/2013", "views": 238213, 

Como puedes ver, las fechas están formateadas como mes / fecha / año y los números se pasan, como es. Esto hace aceptable:

Pero tenga en cuenta que los números son un poco difíciles de leer sin formato. Comencemos agregando algún formato a los números..

Agregando Formato de Número

Las siguientes modificaciones se pueden ver en app2.js y probado con test2.html. Primero, modificaré mi código para llamar a una nueva función., formato numérico:

$ table.append ("" + s [i] .date + "" + numberFormat (s [i] .views) + "");

Y aquí está esa función:

function numberFormat (n) // caché el formateador una vez si (window.Intl &&! window.numberFormatter) window.numberFormatter = window.Intl.NumberFormat (); if (window.numberFormatter) return window.numberFormatter.format (n);  else return n; 

La función comienza comprobando si Intl existe como parte de la ventana objeto. Si es así, verificamos si hemos hecho el formateador antes. los Intl object crea un objeto de formato que puede reutilizar, y como estamos formateando un grupo de números, solo queremos crearlo una vez. Que es exactamente lo que hacemos tan pronto como vemos que también necesitamos. No nos molestamos con ninguna opción por ahora, solo para mantenerlo simple. Finalmente, si no hubiera apoyo para Intl En todo, simplemente devolvemos el número como está. El resultado es una mejora significativa, con un trabajo mínimo:

¡Guay! Entonces, ¿cómo probamos otros idiomas? Puede estar tentado a verificar la configuración de su navegador. Todos los navegadores tienen preferencia por el idioma, pero desafortunadamente, cambiando el idioma en el navegador no es suficiente. Cambiándolo hace impactar cómo se comporta el navegador. 

Si abres tus herramientas dev y miras las solicitudes de red, puedes ver un encabezado llamado "Aceptar-lanage"cambiará según su configuración. Si agrega francés, por ejemplo (supongo que no es un hablante nativo de francés), verá"fr"añadido a este encabezado. Pero esto no afecta Intl. En su lugar, debe cambiar el idioma de su sistema operativo y reiniciar el navegador. Esto es no Tan aterrador como suena. Cuando hice la prueba, me preocupaba que todo mi sistema operativo cambiara de inmediato. Pero en mis pruebas, pude cambiar el idioma, reiniciar mi navegador y ver el cambio. Rápidamente me cambié de nuevo. Las funciones del formateador Intl le permiten anular la configuración regional actual y pasar una en su lugar.

Modifiqué la aplicación para permitir que el usuario final especifique un idioma a través de un menú desplegable. Aquí está la modificación hecha al HTML. (Esta modificación se puede encontrar en test3.html)

Los idiomas que elegí eran bastante arbitrarios. Siguiente: actualicé el código de mi aplicación para escuchar los cambios en este menú desplegable, así como para verificar la configuración regional deseada al formatear.

Listado 3: app3.js:

function numberFormat (n) if (window.Intl) var lang = $ ("# langDropdown"). val (); if (lang === "") lang = navigator.language; var formatter = new window.Intl.NumberFormat (lang); volver formatter.format (n);  else return n;  función getStats () $ .getJSON ("stats.json"). done (funciones (s) // iterar sobre las estadísticas y agregar a la tabla para (var i = 0; i < s.length; i++)  $table.append(""+s[i].date+""+numberFormat(s[i].views)+"");  ).fail(function(e)  console.log("we failed"); console.dir(e); );  $(document).ready(function()  //get the table dom $table = $("#stats tbody"); //notice changes to drop down $("#langDropdown").on("change", function(e)  $table.empty(); getStats(); ); getStats(); ); 

Comenzando en la parte inferior: tenga en cuenta que he agregado un controlador de eventos simple para los cambios en el menú desplegable. Cuando se detecta un cambio, la tabla se vacía y la función getStats se ejecuta Esta nueva función simplemente abstrae el código AJAX utilizado anteriormente. El verdadero cambio ahora está en formato numérico. Verifico el idioma seleccionado y si uno de ellos fue elegido, lo pasamos como la configuración regional al Formato numérico constructor. Tenga en cuenta que si algo no fue elegido, por defecto lenguaje de navegación. Esto ahora nos da una manera de probar rápidamente diferentes configuraciones regionales y ver cómo representan los números..

Agregar formato de fecha

Ahora es el momento perfecto para ocuparse de la otra columna de datos: los números. Seguí el mismo estilo que antes y agregué una llamada a una nueva función, formato de fecha.

$ table.append ("" + dateFormat (s [i] .date) + "" + numberFormat (s [i] .views) + "");

Y aqui esta formato de fecha (Puedes encontrar el código en app4.js, que es utilizado por test4.html):

function dateFormat (n) // Se usa para mostrar la fecha var opts = ; opts.day = "numérico"; opts.weekday = "long"; opts.year = "numérico"; opts.month = "long"; if (window.Intl) var lang = $ ("# langDropdown"). val (); if (lang === "") lang = navigator.language; var formatter = new window.Intl.DateTimeFormat (lang, opts); n = nueva fecha (n); volver formatter.format (n);  else return n;  

Esto es muy similar al formato de números, excepto que esta vez estamos pasando explícitamente algunas opciones cuando creamos el formateador. Las opciones especifican tanto los campos que son visibles en la fecha, como la forma en que se ven. Cada parte de una fecha se puede mostrar o no, y cada una tiene diferentes opciones. Las opciones incluyen:

  • día laborable
  • era
  • año
  • mes
  • día
  • hora
  • minuto
  • segundo
  • timeZoneName

Para obtener una lista completa de los valores que puede usar, consulte la documentación de MDN para DateTimeFormat, pero como ejemplo, los meses se pueden mostrar como un número o en diferentes formas textuales. Entonces, ¿qué crea esto? Aquí está la versión en inglés:

Y aquí está en francés:

Quizás se esté preguntando: ¿qué cubre la ubicación de cada campo? Por lo que puedo decir, no tienes control sobre esto. Por supuesto, podría crear varios formateadores y luego combinarlos, pero el uso de un formateador en el diseño de los campos se basa en la lógica interna. Si apaga el día del mes, por ejemplo, esto es lo que recibe: el lunes de abril de 2013. ¿Por qué? Honestamente no tengo idea.

Finalmente, tenga en cuenta que debe pasar un valor de fecha, no una cadena, al formateador. Puede ver dónde uso el constructor de fecha en el formateador para analizar mi fecha basada en cadenas. Esto es, un poco flojo, así que tenlo en cuenta cuando uses esta funcionalidad..

Muéstrame el dinero

El formato de moneda no es un objeto separado, sino un uso opcional del formateador de números. Para la siguiente demostración, hemos creado un nuevo archivo de datos, stats2.json, y agregó una columna de "ventas" a nuestros datos. Aquí hay una muestra:

"date": "4/1/2013", "views": 938213, "sales": 3890.21, "date": "4/2/2013", "views": 238213, "sales": 9890.10 

La columna fue agregada al HTML (test5.html), agregado dentro del JavaScript iterando sobre las filas de datos (ver app5.js), y pasó a una nueva función llamada monedaFormato. Echemos un vistazo a eso.

función currencyFormat (n) var opts = ; opts.style = "moneda"; opts.currency = "USD"; if (window.Intl) var lang = $ ("# langDropdown"). val (); if (lang === "") lang = navigator.language; var formatter = new window.Intl.NumberFormat (lang, opts); volver formatter.format (n);  else return n;  

Mostrar números como monedas requiere dos valores opcionales. Primero, un estilo de "moneda", y luego el tipo de moneda. También existen otras opciones (como mostrar el nombre de la moneda). Aquí viene la parte que puede hacerte tropezar un poco. Tú debe especifique el tipo de moneda. 

Puede pensar: ¿cómo diablos puedo averiguar el tipo de moneda para todos los valores posibles? Los valores posibles se basan en una especificación (http://www.currency-iso.org/en/home/tables/table-a1.html) y en teoría podría analizar su XML, pero no quiere hacer eso. La razón por la cual es bastante obvia, pero honestamente puedo decir que inicialmente también la olvidé. No desea simplemente volver a mostrar un número en particular en una moneda específica del entorno local. ¿Por qué? Porque diez dólares americanos es ciertamente no Lo mismo que diez dólares en pesos. Eso es bastante obvio y espero que sea la única persona que olvide eso..

Usando el código anterior, podemos ver los siguientes resultados en la configuración regional francesa. Observe cómo los números tienen el formato correcto para la configuración regional y el símbolo de moneda se coloca después del número.

Clasificación con el clasificador

Para nuestro ejemplo final, veremos el Traductor constructor. Los traductores le permiten manejar la clasificación de texto. Mientras que algunos idiomas siguen un simple sistema de ordenamiento de la A a la Z, otros idiomas tienen reglas diferentes. Y, por supuesto, las cosas se vuelven aún más interesantes cuando empiezas a agregar acentos. ¿Puedes decir, con seguridad, si ä viene después de un? Sé que no puedo. El constructor del clasificador toma una serie de argumentos para ayudarlo a especificar exactamente cómo debe ordenarse, pero el valor predeterminado probablemente funcione bien para usted..

Para este ejemplo, hemos creado una demo completamente nueva, pero una similar a la de los ejemplos anteriores. En test6.html, Puedes ver una nueva tabla, para Estudiantes. Nuestro nuevo código cargará un paquete JSON de estudiantes y luego los clasificará en el cliente. Los datos JSON son simplemente una matriz de nombres, así que omitiré mostrar un extracto. Veamos la lógica de la aplicación..

Listado 4: app6.js:

clasificador de funciones (x, y) if (window.Intl) var lang = $ ("# langDropdown"). val (); if (lang === "") lang = navigator.language; return window.Intl.Collator (lang) .compare (x, y);  else return x.localeCompare (y);  función getStudents () $ .getJSON ("students.json"). done (función (s) // iterar sobre las estadísticas y agregar a la tabla s.sort (clasificador); para (var i = 0; i < s.length; i++)  $table.append(""+s[i]+"");  ).fail(function(e)  console.log("we failed"); console.dir(e); );  $(document).ready(function()  //get the table dom $table = $("#students tbody"); //notice changes to drop down $("#langDropdown").on("change", function(e)  $table.empty(); getStudents(); ); getStudents(); ); 

Como dije, este código es bastante similar a los ejemplos anteriores, así que concéntrate en obtenerestudiantes primero. La línea crucial aquí es: s.sort (clasificador). Estamos usando la función incorporada para que las matrices realicen la clasificación a través de una función personalizada. Esa función se pasará dos cosas para comparar y se debe devolver. -1, 0, o 1 para representar cómo deben ordenarse los dos elementos. Ahora veamos clasificador.

Si tenemos un Intl objeto, creamos un nuevo Traductor (y otra vez, te estamos permitiendo pasar en una configuración regional) y luego ejecutamos el comparar función. Eso es. Como dije, hay opciones para modificar cómo se ordenan las cosas, pero podemos usar los valores predeterminados. La alternativa es localeCompare, que también intentará utilizar el formato específico de la configuración regional, pero tiene (en esta forma) un soporte ligeramente mejor. Podríamos revisar ese soporte también y agregar un respaldo adicional para De Verdad Buen apoyo, pero te lo dejo como ejercicio..

También hemos modificado la interfaz para usar el sueco como idioma. Hice esto porque la excelente documentación de MDN mostró que era una buena manera de ver la clasificación en acción. Aquí está el tipo de inglés de nuestros nombres de estudiantes:

Y aquí está en sueco:

Observe cómo ätest se ordena de manera diferente. (Lo siento, no pude pensar en un nombre que comenzó con ä.)

Envolver

Con todo, el Intl clase proporciona algunos muy Formas sencillas de agregar formato específico a la configuración regional a su código. Esto es ciertamente algo que puede encontrar ahora, probablemente en unos pocos miles de bibliotecas de JavaScript diferentes, pero es genial ver a los fabricantes de navegadores agregando soporte directamente dentro del mismo idioma. La falta de soporte de iOS es un fastidio, pero espero que se agregue pronto.

Gracias a la excelente red de desarrolladores de Mozilla por su excelente documentación de Intl..