Internacionalización en javascript

De ChuWiki

Veamos cómo internacionalizar nuestra aplicación javascript de forma que aparezca en varios idiomas. Casi todo lo comentado aquí y todo el código javascript está copiado de http://24ways.org/2007/javascript-internationalisation


Ficheros con los textos[editar]

Como en casi todas las internacionalizaciones, necesitamos ficheros con los textos en cada idioma. Y para no cargar al navegador con todos los textos posibles en todos los idiomas disponibles, lo mejor es hacer ficheros separados de forma que se sólo se cargue en el navegador el que se necesite. Los ficheros pueden tener esta pinta

/* en.js */
var i18n {
   "gracias":"Thank you",
   "hola":"Hello",
   "adios":"Bye"
};

Los "gracias","hola" y "adios", más que textos en español, son las claves que uaremos en nuestro código javascript para conseguir el texto real en el idioma deseado. De todas formas y como veremos más adelante, conviene que sean textos legibles por un humano en el idioma que queramos por defecto.

Una forma de decidir qué fichero en concreto incluir, puede ser por medio de nuestro lenguaje de servidor. Por ejemplo, si usamos jsp, podemos generar en la página html lo siguiente

   <script src="path/<%= idiomaElegido %>.js" ...></script>
   <script src="path/nuestraaplicacion.js" ...></script>

siendo "idiomaElegido" alguna variable jsp que contenga "es", "en", "fr" ... es decir el idioma/nombre de nuestro fichero. Normalmente todos los lenguajes web del servidor (php, jsp, etc) tienen forma de obtener el idioma del navegador a partir del request.

Aunque no lo he probado, podemos sin usar lenguaje del servidor, cargar el fichero de lenguaje javascript directamente desde javascript http://www.anieto2k.com/2007/02/06/cargar-el-javascript-que-queremos-cuando-queremos/ . Para ello necesitamos hacernos una función include como esta

function include(file_path){
	var j = document.createElement("script");
	j.type = "text/javascript";
	j.src = file_path;
	document.body.appendChild(j);
}

y una vez elegido el lenguaje (desde javascript podemos tomar el idioma del navegador con navigator.userLanguage para internet explorer o navigator.language en el resto. Ojo con lo que devuelven estas variables, porque debería coincidir con el nombre de nuestro fichero.

include ("path/" + navigator.language +".js");

Poniendo el texto en nuestro código[editar]

Para poner el texto en nuestro código, debemos usar algo como i18n['gracias'], de forma que nos devuelve "Thank you". Sin embargo esto queda un poco feo y además deberíamos hacer comprobaciones como que existe i18n, que existe dentro 'gracias', etc. Para ello, nos podemos hacer una función javascript que haga todo esto

function _(s) {
   if (typeof(i18n)!='undefined' && i18n[s]) {
      return i18n[s];
   }
   return s;
}

La función _ comprueba si existe i18n y si existe el texto. Si es así, devuelve ese texto. En caso contrario, devuelve lo mismo que se le pasa. La llamada sería _('gracias')

Una buena idea es que esas claves "gracias", "hola", etc sean textos válidos para usuario en el idioma por defecto. De esta forma, si llamamos a _('Error grave'), nos salrá "Error grave", ya que no existe en la variable i18n.


Textos con parámetros[editar]

A veces un texto tiene una parte variable que se decide sobre la marcha, por ejemplo, "tienes 3 correos nuevos", donde ese 3 depende del número de correos que tengamos nuevos.

Una forma de hacer esto es con una función similar al sprintf() de C. A esta función se la llamaría así sprintf("tienes %d correos nuevos", 3), de forma que ella se encarga de reemplazar el %d por el número que se le pasa de segundo parámetro, devolviendo "tienes 3 correos nuevos".

Esta función sprintf() se puede hacer en javascript de esta forma

function sprintf(s) {
   var bits = s.split('%');
   var out = bits[0];
   var re = /^([ds])(.*)$/;
   for (var i=1; i<bits.length; i++) {
      p = re.exec(bits[i]);
      if (!p || arguments[i]==null) continue;
      if (p[1] == 'd') {
         out += parseInt(arguments[i], 10);
      } else if (p[1] == 's') {
         out += arguments[i];
   }
   out += p[2];
}
return out;
}

que entendería %d para enteros y %s para strings. La llamada sería entonces

sprintf(_("tienes %d correos"), numeroCorreos);

donde en i18n deberíamos tener una clave "tienes %d correos" que devuelva el texto en el idioma indicado, con el %d incluido

/* en.js */
var i18n {
   "gracias":"Thank you",
   "hola":"Hello",
   "adios":"Bye",
   "tienes %d correos":"You have %d emails"
};

y así sprintf recibirá sprintf("You have %d emails", 3) y se mostrará el texto en el idioma deseado.


jQuery[editar]

Hay varios plugins de jQuery para internacionalización, algunos son variantes de esto mismo, otros comparten ficheros .properties de java.