Mini gestor de idiomas para aplicaciones Flex
Muchas veces habrás tenido que gestionar varios idiomas desde tu aplicación, y ya sabrás que es un pelín tedioso.
En su día programé una clase muy simple que usaba en aplicaciones Flash, pero le he modificado un par de detalles para adaptarla a Flex, de tal manera que haga uso de su maravilloso DataBinding. Además he escrito dos ejemplos prácticos para:
- Cargar idioma por defecto (mediante flashvars)
- Cambio de idioma dinámico en tiempo de ejecución
A continuacíon explico el proceso completo para ponerlo todo en marcha:
Lo primero que debemos hacer es crear un archivo XML por cada idioma. Aquí van los archivos de ejemplo para “español” e “inglés”. Fíjate que lo único que cambia son los valores, y nunca las referencias, que se deberán mantener siempre igual en todos los idiomas que creemos (la referencia puede ser cualquier palabra que se te ocurra).
en.xml
<?xml version="1.0" encoding="utf-8" ?> <data> <node ref="catalogo" value="Catalogue" /> <node ref="criteriosBusqueda" value="Search parameters" /> <node ref="genero" value="Genre" /> <node ref="tipo" value="Type" /> <node ref="estilo" value="Style" /> <node ref="materiales" value="Materials" /> <node ref="colores" value="Colors" /> <node ref="colecciones" value="Collections" /> <node ref="color" value="Color" /> <node ref="imprimir" value="Print" /> <node ref="enviar" value="Send" /> <node ref="guardar" value="Save" /> <node ref="buscar" value="Search" /> <node ref="nuevaBusqueda" value="New Search" /> </data>
es.xml
<?xml version="1.0" encoding="utf-8" ?> <data> <node ref="catalogo" value="Catálogo" /> <node ref="criteriosBusqueda" value="Criterios de búsqueda" /> <node ref="genero" value="Género" /> <node ref="tipo" value="Tipo" /> <node ref="estilo" value="Estilo" /> <node ref="materiales" value="Materiales" /> <node ref="colores" value="Colores" /> <node ref="colecciones" value="Colecciones" /> <node ref="color" value="Color" /> <node ref="imprimir" value="Imprimir" /> <node ref="enviar" value="Enviar" /> <node ref="guardar" value="Guardar" /> <node ref="buscar" value="Buscar" /> <node ref="nuevaBusqueda" value="Nueva búsqueda" /> </data>
Luego, en cualquer parte de nuestra aplicación, instanciamos el componente “LanManager”:
<managers:LanManager id="lanManager" onXMLparsed="trace('lan xml parsed ok')" onXMLFault="trace('lan xml load error:', event.message)" />
Un ejemplo de botón para cargar un idioma:
<mx:Button x="346" y="10" label="English" click="lanManager.Source = 'lan/en.xml'"/>
Y ahora viene lo más interesante. Para que una caja de texto, adquiera el valor de por ejemplo, la referencia “catalogo”, lo haríamos así:
<mx:Text text="{lanManager.proxy.catalogo}" />A través de la propiedad “proxy”, podemos hacer binding con cualquiera de sus referencias. Si os fijáis en la clase “LanManager.as”, los datos (referencias y valores) se almacenan en un simple “Object”. Pero no podemos bindar las propiedades de un Object, por lo tanto he usado la clase “ObjectProxy”, que hace que todas las propiedades (en este caso las referencias) sean bindables.
Si necesitamos añadir referencias manualmente, tambien lo podemos hacer a través del proxy:
lanManager.proxy.otraReferencia = "loquesea";
Siempre que carguemos un idioma, todas las cajas de texto que estén vinculadas al objeto “proxy” se actualizarán automáticamente.
Ahora, para cargar un idoma por defecto, he añadido un parámetro en el “flashvars” del html, que luego uso en el inicio de la aplicación Flex. Esto tiene un motivo muy concreto: usar el mismo swf para mostrar distintos idomas. Mediante un script de servidor, podemos modificar el “flashvars” con el idoma adecuado. El HTML quedaría así:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Título</title>
<meta name="title" content="Site title" />
<meta name="Description" content="" />
<meta name="Keywords" content="" />
<meta name="date" content="2008-10-01" />
<meta name="sitecode" content="es" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript" src="js/swfaddress.js"></script>
<script type="text/javascript" src="js/swffit.js"></script>
<script type="text/javascript">
var flashvars = {lan:"es"};
var params = {allowFullScreen:"true"};
var attributes = {id:"Application"};
var ale = new Date().getTime();
swfobject.embedSWF("LanManagerTest.swf?a="+ale, "AlternativeContent", "500", "290", "9.0.0", "expressInstall.swf", flashvars, params, attributes);
swffit("Application", 500, 290, null, null, true);
</script>
</head>
<body>
<div id="AlternativeContent">
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
</a><br />
Necesita Adobe Flash Player 9 o superior y Javascript activado para ver los contenidos de esta página.<br />
Nombre del sitio o lo que sea
</div>
</body>
</html>Y la aplicación Flex completa:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:managers="net.xinterface.xflex.managers.*" width="500" height="290" applicationComplete="AppComplete()" viewSourceURL="srcview/index.html"> <mx:Style> Application { background-color: #ffffff; } Text { font-size: 12; font-family: "Verdana"; font-weight: bold; } </mx:Style> <mx:Script> <![CDATA[ private function AppComplete():void { lanManager.Source = 'lan/' + Application.application.loaderInfo.parameters.lan + '.xml'; } ]]> </mx:Script> <managers:LanManager id="lanManager" onXMLparsed="trace('lan xml parsed ok')" onXMLFault="trace('lan xml load error:', event.message)" /> <mx:Text text="{lanManager.proxy.catalogo}" x="70" y="77"/> <mx:Text text="{lanManager.proxy.criteriosBusqueda}" x="283" y="233"/> <mx:Text text="{lanManager.proxy.genero}" x="283" y="181"/> <mx:Text text="{lanManager.proxy.tipo}" x="283" y="207"/> <mx:Text text="{lanManager.proxy.estilo}" x="70" y="233"/> <mx:Text text="{lanManager.proxy.materiales}" x="283" y="155"/> <mx:Text text="{lanManager.proxy.colores}" x="283" y="129"/> <mx:Text text="{lanManager.proxy.colecciones}" x="283" y="103"/> <mx:Text text="{lanManager.proxy.color}" x="283" y="77"/> <mx:Text text="{lanManager.proxy.imprimir}" x="70" y="207"/> <mx:Text text="{lanManager.proxy.enviar}" x="70" y="181"/> <mx:Text text="{lanManager.proxy.guardar}" x="70" y="155"/> <mx:Text text="{lanManager.proxy.buscar}" x="70" y="129"/> <mx:Text text="{lanManager.proxy.nuevaBusqueda}" x="70" y="103"/> <mx:Button x="324" y="25" label="English" click="lanManager.Source = 'lan/en.xml'"/> <mx:Button x="398" y="25" label="Español" click="lanManager.Source = 'lan/es.xml'"/> <mx:HRule x="24" y="56" width="446" height="3"/> </mx:Application>
Y después de todo esto, lo ideal sería crear una referencia estática de la instancia “lanManager” para hacerla accesible desde cualquier parte de la aplicación.

febrero 22nd, 2009 at %H:%M 01Sun, 22 Feb 2009 13:31:05 -080005.
Muy buena solución.. Justo ahora estoy utilizando un sistema relativamente parecido ;)