Em grandes projetos web uma das principais preocupações dos arquitetos é a internacionalização do projeto. Fazer com que os usuários possam acessar e utilizar a aplicação sem ter que se preocupar com com a língua é um dos principais pontos positivos para um projeto se destacar no mercado.Visando isso, os arquitetos da Adobe aperfeiçoaram o recurso de internacionalização do Flex 3, este recurso é chamado de ResourceBundle. Desta maneira ficou muito simples e flexível aplicar I18n. Veja por que:
- Você pode compilar recursos para várias localidades em uma única aplicação ou módulo.
- Você acessar todos os recursos através do ResourceManager, no qual pode gerenciar os recursos para várias localidades. Você pode mudar em tempo de execução a localidade do recurso.
- Você também pode usar imagens, sons, etc, e não apenas Strings
Estes são apenas uns dos melhoramentos e vantagens de utilizar o ResourceBundle do Flex 3.
O ResourceBundle possui algumas exigências como criar um arquivo Locale para cada idioma, contudo existe uma forma de burlar isso utilizando arquivos properties. Neste artigo irei demonstrar como aplicar I18n usando o ResourceManager sem ter criar arquivos Locales.
I18n com ResourceBundle
Primeiramente, iremos criar um projeto Flex, irei chamá-lo de Flex_I18n_A. No projeto crie uma nova pasta chamada I18n, e nela crie os seguintes arquivos XML:
pt_BR, en_US e es_ES.
<?xml version="1.0" encoding="iso-8859-1"?><br /><locale lang="en_US"><br /> <property key="titulo_app" value="Applying I18n in Flex applications"/><br /> <property key="usuario" value="Username"/><br /> <property key="senha" value="Password"/><br /> <property key="login_erro" value="User credentials are wrong. Please try again"/><br /> <property key="bt_login" value="Login"/><br /> <property key="bt_logout" value="Logout"/><br /> <property key="msg_boas_vindas" value="User logged in successfully."/><br /> <property key="selecione_idioma" value="Select a language."/><br /></locale><br /><br /><locale lang="pt_BR"><br /> <property key="titulo_app" value="Aplicando I18n em aplicações Flex."/><br /> <property key="usuario" value="Usuário"/><br /> <property key="senha" value="Senha"/><br /> <property key="login_erro" value="Dados incorretos. Tente novamente. "/><br /> <property key="bt_login" value="Login"/><br /> <property key="bt_logout" value="Sair"/><br /> <property key="msg_boas_vindas" value="Usuário logado com sucesso ."/><br /> <property key="selecione_idioma" value="Selecione um idioma."/><br /></locale><br /><br /><locale lang="es_ES"><br /> <property key="titulo_app" value="Aplicando i18n aplicaciones en Flex."/><br /> <property key="usuario" value="Nombre de Usuario"/><br /> <property key="senha" value="Contraseña"/><br /> <property key="login_erro" value="Credenciales de usuario se equivoca. Por favor, inténtelo de nuevo."/><br /> <property key="bt_login" value="Inicio de sesión"/><br /> <property key="bt_logout" value="Cerrar sesión"/><br /> <property key="msg_boas_vindas" value="Usuario conectado correctamente."/><br /> <property key="selecione_idioma" value="Seleccione um idioma."/><br /></locale>Com os três arquivos criados, iremos criar a classe que irá fazer o carregamento dos arquivos xml.
Para cada key do XML será setado na propriedade content do ResourceBundle, desta maneira poderemos usar o metodo getString para pegar o value internacionalizado da key.
Agora iremos criar a classe com/flexI18n/utils/ConfigI18n
<strong>;</strong><strong>package</strong> com.flexI18n.utils {<br /><br /> <strong>import</strong> flash.events.Event;<br /><br /> <strong>import</strong> flash.net.URLLoader;<br /><br /> <strong>import</strong> flash.net.URLRequest;<br /><br /><br /><br /> <strong>import</strong> mx.resources.ResourceBundle;<br /><br /> <strong>import</strong> mx.resources.ResourceManager;<br /><br /><br /><br /> /**<br /><br /> * @author Fabiel Prestes<br /><br /> */<br /><br /> <strong>public</strong> <strong>class</strong> ConfigI18n {<br /><br /><br /><br /> <strong>private</strong> <strong>var</strong> resourceBundle:ResourceBundle;<br /><br /><br /><br /> [<strong>Bindable</strong>]<br /><br /> <strong>public</strong> <strong>var</strong> currentLocale:String = "pt_BR";<br /><br /><br /><br /> <strong>public</strong> <strong>function</strong> ConfigI18n() {<br /><br /> <strong>super</strong>();<br /><br /> }<br /><br /><br /><br /> /**<br /><br /> * Carrega o xml locale baseado na String passada como parametro.<br /><br /> */<br /><br /> public <strong>function</strong> loadLocale(locale:String= "pt_BR"):<strong>void</strong> {<br /><br /> currentLocale = locale;<br /><br /> <strong>var</strong> xmlLoader:URLLoader = <strong>new</strong> URLLoader();<br /><br /> xmlLoader.addEventListener(Event.COMPLETE, createBundle);<br /><br /> xmlLoader.load(<strong>new</strong> URLRequest("I18n/" + currentLocale + ".xml"));<br /><br /> }<br /><br /><br /><br /> /**<br /><br /> * @private<br /><br /> * Apos o xml ser carregado com sucesso, deve-se pegar cada chave (key) e valor <br /><br /> * (value) e adicionar no resourceBundle, para assim ser acessado em qualquer local da aplicação.<br /><br /> * @eventType Event<br /><br /> */<br /><br /> <strong>private</strong> <strong>function</strong> createBundle(e:Event):<strong>void</strong> {<br /><br /> <strong>var</strong> propertyList:XMLList = <strong>new</strong> XML(e.target.data).property;<br /><br /><br /><br /> resourceBundle = <strong>new</strong> ResourceBundle(currentLocale, "ApplicationResource");<br /><br /> <strong>for each</strong> (<strong>var</strong> property:XML <strong>in</strong> propertyList) {<br /><br /> resourceBundle.content[property.@key] = property.@value;<br /><br /> }<br /><br /><br /><br /> ResourceManager.getInstance().addResourceBundle(resourceBundle);<br /><br /> ResourceManager.getInstance().update();<br /><br /> ResourceManager.getInstance().localeChain = [currentLocale,"pt_BR"];<br /><br /> }<br /><br /> }<br /><br />}Apenas uma observação: na classe ConfigI18n, nós criamos uma variável ResourceBundle, aplicamos todas as mensagens internacionalizadas do XML e por final pegamos nosso resource e aplicamos no ResourceManager, que é um singleton. Lembrando que sempre após adicionar um novo resource deve-se fazer um update no ResourceManager para que todas as alterações sejam efetivadas.
Outro detalhe é que quando XML terminou de ser carregado, foi instanciado o ResourceBundle e, assim, definido um nome para o Locale e um identificador para o BundleName. É através deste identificador que conseguiremos recuperar as mensagens internacionalizadas do ResourceManager.
OK, com a classe responsável por carregar e configurar o ResourceBundle, vamos criar uma tela de login para para demonstrar a utilização do ResourceBundle.
Agora iremos criar a classe com/flexI18n/views/LoginUI
<?xml version="1.0" encoding="utf-8"?><br /><strong><mx:TitleWindow</strong> xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%"><br /><br /> <mx:Script><br />
<![CDATA[
<strong>import</strong> mx.controls.Alert;<br /> <strong>import</strong> mx.managers.PopUpManager;<br /> <strong>import</strong> com.flexI18n.utils.ConfigI18n; <br />
[<strong>Bindable</strong>] <br />
<strong>public</strong> <strong>var</strong> availableLocales:Array = [ {label:"English", data:"en_US"},<br /> {label:"Portuguese", data:"pt_BR"},<br /> {label:"Spanish", data:"es_ES"}];<br /><br /><strong> private</strong> <strong>function</strong> onLogin(e:Event):<strong>void</strong> {<br /> PopUpManager.removePopUp(<strong>this</strong>);<br /> Alert.show(resourceManager.getString(\\\'ApplicationResource\\\',\\\'msg_boas_vindas\\\'));<br /> }<br />
<strong>private</strong> <strong>function</strong> comboChangeHandler():<strong>void</strong> {<br /> <strong>var</strong> locale:LocaleController = <strong>new</strong> LocaleController();<br /> locale.loadLocale(localeComboBox.selectedItem.data); <br /> <strong>this</strong>.localeComboBox.selectedIndex = -1;<br /> } <br />
]]><br />
</mx:Script><br />
<mx:Form width="100%">
<mx:FormItem label="{resourceManager.getString(\\\'ApplicationResource\\\',\\\'usuario\\\')}">
<mx:TextInput id="username" width="200"/>
</mx:FormItem><br />
<mx:FormItem label="{resourceManager.getString(\\\'ApplicationResource\\\',\\\'senha\\\')}" direction="horizontal">
<mx:TextInput id="password" displayAsPassword="true" width="200"/>
</mx:FormItem><br />
<mx:FormItem label="{resourceManager.getString(\\\'ApplicationResource\\\',\\\'idioma\\\')}">
<mx:ComboBox id="localeComboBox" selectedIndex="-1"
dataProvider="{availableLocales}"
change="comboChangeHandler()"<br /> width="200" prompt="{resourceManager.getString(\\\'ApplicationResource\\\',\\\'selecione_idioma\\\')}"/><br /> </mx:FormItem><br />
</mx:Form><br />
<mx:ControlBar width="100%" horizontalAlign="right">
<mx:Button label="{resourceManager.getString(\\\'ApplicationResource\\\',\\\'bt_login\\\')}"
click="onLogin(event)" enabled="{username.text != \\\'\\\' && password.text != \\\'\\\'}" x="517" y="118"/><br />
</mx:ControlBar><br /><br /></mx:TitleWindow>Se vocês olharem a classe acima, verão que não foi, em nenhum momento, instanciado um objeto ResourceBundle. Mas, então, de onde saiu a variável resourceBundle usada? Muito simples: estamos usando o atributo da classe UIComponent.
A classe main fica da seguinte maneira:
<?xml version="1.0" encoding="utf-8"?><br /><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()"><br /><br />
<mx:Script><br />
<![CDATA[<br />
<strong>import</strong> mx.managers.PopUpManager;<br />
<strong>import</strong> com.flexI18n.views.LoginUI;<br />
<strong>import</strong> com.flexI18n.utils.LocaleController;<br /><br />
<strong>private</strong> <strong>function</strong> initApp():<strong>void</strong>{<br />
<strong>new</strong> ConfigI18n().loadLocale();<br /><br />
<strong>var</strong> login:LoginUI = <strong>new</strong> LoginUI();<br />
PopUpManager.addPopUp(login, <strong>this</strong>, <strong>true</strong>);<br />
PopUpManager.centerPopUp(login);<br />
}<br />
]]><br />
</mx:Script><br /><br />
</mx:Application> É isso aí, uma maneira simples e fácil de fazer sua aplicação ficar multi-idioma.
Espero ter ajudado e até a próxima.







