Friday, March 28, 2008

Internacionalizacion (i18n) con Flex 3

La version 3 de Macromedia Flex viene con un soporte para localizacion mucho mas flexible que la version 2. La opciones que ofrece esta nueva version son:
  1. Poner todos los recursos en modulos, en lugar de la aplicacion. Estos modulos se pueden pre-cargar para un locale en particular cuando se inicia la aplicacion y cargar luego mas locales si hiciera falta.
  2. Se pueden compilar mutiples locales en una sola aplicacion o modulo.
  3. Se accede a los recursos a traves de un nuevo ResourceManager. Se puede cambiar el idioma en tiempo de ejecucion y controlar en que locale se buscan recursos.
  4. Las expresiones que esten asociadas al ResourceManager (binding) se actualizan automaticamente si el locale cambia. Los componentes son notificados para que hagan los ajustes correspondientes.
  5. Es posible localizar images, sonidos y otros recursos, ademas de las cadenas de texto.
  6. Se pueden crear programaticamente recursos en tiempo de ejecucion a partir de archivos xml, queries a la base de datos, etc.
Paso a mostrarles una forma "facil" de hacer una aplicacion flex con i18n y despues les muestro algo que no vi en los manuales de Flex y que seguramente les resultara de utilidad: "Como cambiar el idioma de la aplicacion basado en el idioma del navegador".

Cambiado el idioma en tiempo de ejecucion desde la aplicacion

Los pasos a seguir son los siguientes:
  1. Creen un proyecto Flex...no es dificil
  2. En la raiz del proyecto creen una carpeta "locale"
  3. Dentro de esa carpeta vamos a armar 2 carpetas mas para los locales
  4. Una carpeta para idioma ingles gringo: en_US
  5. Otra carpeta para castellano criollo: es_AR
  6. Dentro de cada una de estas carpetas vamos a poner nuestros archivos de propiedades. Por ejemplo, recursos.properties
  7. En el archivo recursos.properties de la carpeta es_AR ponemos el par key=value siguiente: jota = Juan Bello
  8. En el archivo recursos.properties de la carpeta en_US ponemos el par key=value siguiente: jota = John Beatiful
  9. Actualizamos las opciones del compilador (boton derecho -> propiedades -> Flex compiler...sarasasasasa...) -locale=es_AR,en_US -allow-source-path-overlap=true -source-path=..\locale{locale}
  10. Bien, ahora tenemos que crear recursos localizados para es_AR porque solo estan disponibles out-of-the-box los idiomas en_US y ja (Ja-pones). Abrimos un shell (cmd)
  11. Vamos al directorio bin de la instalacion de Flex y ejecutamos: copylocale en_US es_AR
    10. Fijense en FLEX_HOME\frameworks\locale si aparecio una carpeta es_AR? si? Esto es para la localizacion de recursos de Flex. Si no lo hacen va aparecer un error que dice "No encuentro el recurso Collections para es_AR" y otros similares.
  12. Tolis!
Ahora al codigo fuente para probarlo.
jota = Juan Bello

jota = John Beautiful



Autodetectar el idioma del usuario para localizar una aplicacion Flex 3

Bien, segun el manual hay varias formas de hacer esto:
  1. Poner un combo y pedirle al usuario que elija. Despues guardo la opcion en una cookie o algo asi. Ya lo mostre en el caso anterior pero no es lo que quiero.
  2. Usar la propiedad Capabilities.language de ActionScript esto me da el lenguaje para Adobe® Flash® Player y Adobe AIR™ (no se si me da el idioma DEL USUARIO)
  3. Usar el header Accept-Language. Cuando el browser hace un request vienen los lenguajes posta..en el orden de preferencia. Hay que parsear el header y sacar el primero que es el que esta usando el usario. Es algo asi: en-us,es-ar;q=0.7,ja;q=0.3 (Yo tengo en_US, es_AR y ja...pones)
  4. Utilizar el lenguaje del sistema operativo o del browser usando Javascript.
La primera opcion es una cagada porque yo no quiero que el usuario seleccione nada. La segunda opcion no se si anda, es decir, me devuelve el idioma del player no se si corresponde con el del usuario. La cuarta desde ya les digo que NO ANDA. En mi caso tengo instalado Firefox en ingles y si accedo a Javascript para ver el idioma a traves del objeto navigator no obtengo NADA. Fijense bien pero a mi, navigator.userLanguage da "undefined" tanto para Firefox como para Explorer, lo mismo para con navigator.language. Siempre da el idioma del browser, NO el del usuario. En mi caso siempre devuelve en_US aunque tenga seleccionado es_AR.

La tercera opcion funciona.....pero es un poquito rebuscada. Les paso la receta a medio hacer:
  1. Hacen un servlet que tome el header "Accept-Language" y lo parsee.
  2. Dentro del proyecto Flex, en la carpeta html-template, agarran el archivo index.template.html
  3. Dentro de ese archivo hacen una llamada asicrona el servlet (seh...con AJAX..XMLHTTPRequest) para obtener el idioma
  4. En el mxml usan el ExternalInterface para hacer la llamada a Javascript
  5. Listo el pollo!
Pseudo-codigo a medias para pruebas:

public function callWrapper():void {
if (ExternalInterface.available) {
var wrapperFunction:String = "getLanguage";
idioma = ExternalInterface.call(wrapperFunction);
//Alert.show(idioma);
} else {
// Defecto
idioma = "es_US";
}
resourceManager.localeChain = [idioma];
}


protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String prefLanguage = req.getHeader("Accept-Language");
// Parsing sarasa..sasaa
System.out.println(prefLanguage);
super.doGet(req, resp);
}


function getLanguage() {
return navigator.language; // Esto no anda, sepanlo!..Aca iria XMLHTTPRequest..get..sarassaaaa
}