|
As the 2nd part of my 3 part series on internationalizing Flex Applications, this article will explore the use of multiple instances of the ResourceBundle class to allow for run time switching of locales. As you may recall from the first article on this subject, the native use of the ResourceBundle class requires separate compiled swfs for each language. This is not always desirable, and there are times when you may want to allow for switching of languages at run time. One strategy I've used successfully for this is to trick the flex compiler and have several different properties in the same locale folder, and to create separate instances of the ResourceBundle class for each of them. This way, its a fairly simple process to determine what the current locale is, and to pull the labels from that ResourceBundle. To start, I took 3 properties files and placed them in a single directory.
Here is a simple example of how to get it working:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" creationComplete="doLangChange()">
<mx:Script>
<![CDATA[
import mx.formatters.DateFormatter;
import mx.resources.ResourceBundle;
[ResourceBundle("helloWorld_us")]
private var rb_us:ResourceBundle;
[ResourceBundle("helloWorld_uk")]
private var rb_uk:ResourceBundle;
[ResourceBundle("helloWorld_fr")]
private var rb_fr:ResourceBundle;
[Bindable]
private var today:Date = new Date();
[Bindable(event="langChange")]
private function geti18nText(key:String):String{
return this["rb_"+lang.selectedItem.lang].getString(key);
}
[Bindable(event="langChange")]
private function geti18nDate(dt:Date):String{
var formatter:DateFormatter = new DateFormatter();
formatter.formatString = geti18nText("dtformat");
return formatter.format(dt);
}
private function doLangChange():void{
var e:Event = new Event("langChange");
this.dispatchEvent(e);
}
]]>
</mx:Script>
<mx:DateFormatter id="smeNme" formatString="MM/DD/YYYY"/>
<mx:ApplicationControlBar dock="true">
<mx:ComboBox id="lang" change="doLangChange()">
<mx:dataProvider>
<mx:Object label="US English" lang="us"/>
<mx:Object label="UK English" lang="uk"/>
<mx:Object label="French" lang="fr"/>
</mx:dataProvider>
</mx:ComboBox>
</mx:ApplicationControlBar>
<mx:Label fontSize="50" text="{geti18nText('hello')}"/>
<mx:Label fontSize="50" text="{geti18nText('welcome')}"/>
<mx:Label fontSize="50" text="{geti18nDate(today)}"/>
</mx:Application>
I named each file based on the language it was there to support (helloWorld_fr.properties, helloWorld_uk.properties, helloWorld_us.properties). Notice that there is ResourceBundle instance for each of the three files. I've also added some simple functions to get the data from these files (geti18nText, geti18nDate). Bare in mind, this is a simplistic example. In real world apps, I tend to have a singleton responsible for embedding and retrieving the data from the files. But, even in this simple case, you can see the power of it, as simply switching the selected language in the combo box instantly translates the labels and dates to the appropriate format.
Remember to add a compiler argument to specify the proper directory for the locale files. In my case, all three files where in a locales/multi directory, so i added the argument: -sp ../locales/multi
I tried but it picks up only one resource (us only) what could be the
problem. When clicked to French, it displays blank entries
Nice but selecting french will still display month names in english
(January instead of Janvier).
deep/Laurent, I have had similar problems and almost gone crazy with the
Flex documentation, but have managed to work a lot of them out.
Jeff (or anyone who can help, pleeease say something):
Jeff, just so you have a little more info on this, here is what I have just
posted in the Adobe Flex General Discussion forum:
}
A great example. A little question, where I can get the property file?
Thanks
last blade, look at comment #3 above
Carlos have you tryied to use an event listener in your custom component to
broadcast (and listen) any change in language ???
Perhaps, have you already find an answer to your question ?
Thank hyou, maudinet:
maudinet, thank you for replying. You are probably on the right track: Jeff
Tapper mentions that, in real-world apps, he uses a singleton to handle the
data. The problem with me is I am so green at this, that ‘singleton’ might
was well be a Chinese character; I am barely beginning to understand what
getter/setters are, and I imagine I’ll get to the singleton part in due
time.
Ok no problem, I will let you know as soon as I've got something that
works.
See you then.
based on this solution, I made a tutorial on how to get this to work with
singleton etc ... :
Thanks for this example. It is very helpful