Localizing your ARP application.

ARP, Flash Add comments

Another update to my ARP lab. I have been thinking about localization for a while but didn't really have the time to work something out untill now. Continuing on the e-learning project we are working on, we came to the point where we needed to have multi-lingual user interfaces. So why not write a generic way in the ARP framework instead of having a custom implementation for our project.

Download the sample files here.

How it works (Nils, you won't like this!)

Each locale has its own XML file that holds the localized strings. In the application, there is a LocaleManager class that knows what the current locale is and, when a new locale is set, will load and parse the localized strings. This loading and parsing happens in a class called ResourceBundle, which "bundles" the "resources", the localized strings, into a collection.

The XML files look like this.

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <resources>
  3.     <resource key="firstname" value="Firstname"/>
  4.     <resource key="lastname" value="Name"/>
  5.     <resource key="submit" value="Submit"/>
  6. </resources>

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <resources>
  3.     <resource key="firstname" value="Voornaam"/>
  4.     <resource key="lastname" value="Familienaam"/>
  5.     <resource key="submit" value="Verzenden"/>
  6. </resources>

This is pretty much the same idea as the XML files to configure your ARP application with the AppSettings class. Each string has a key and a value. Notice that the keys should be the same for the different resource files. The XML files are saved with the following naming convention: they start with "resources_" and a string representation of the locale is appended to it. Example names are "resources_en.xml", "resources_du_BE.xml" or "resources_du_NL.xml". As you can see, we have a common resource file for English strings and 2 more specific ones for Dutch. One for Belgium and one for The Netherlands.

When the application starts, each view/form that is interested in localized content should:
- register as a listener with the LocaleManager
- implement the LocaleListener interface which makes it possible to be added as a listener to the LocaleManager and which forces the form to implement the localeChanged() event handler.

From the example, here is what the RegistrationForm class looks like.

Actionscript:
  1. import mx.controls.*;
  2. import mx.utils.*;
  3.    
  4. import org.osflash.arp.ArpForm;
  5. import org.osflash.arp.util.*;
  6.  
  7. class com.herrodius.localization.view.RegistrationForm extends ArpForm implements LocaleListener{
  8.   var language_cb:ComboBox;
  9.   var firstname_lbl:Label;
  10.   var lastname_lbl:Label;
  11.   var submit_btn:Button;
  12.  
  13.   public function RegistrationForm(){
  14.   }
  15.  
  16.   /**
  17.     * toString.
  18.     */
  19.   public function toString():String{
  20.     return "[com.herrodius.localization.view.RegistrationForm]";
  21.   }
  22.  
  23.   function onLoad():Void{
  24.     TRACE(Flashout.INFO);
  25.  
  26.     //listeners
  27.     LocaleManager.getInstance().addListener(this);
  28.     language_cb.addEventListener("change", Delegate.create(this, languageComboBox_Change));
  29.  
  30.     //selected item in combobox
  31.     language_cb.selectedIndex = 2;
  32.   }
  33.  
  34.   /**
  35.     * The user chooses another language from the combobox.
  36.     * We need to create a new locale and set it in the LocaleManager.
  37.     */
  38.   function languageComboBox_Change(evt:Object):Void{
  39.     var locale:Locale = Locale.fromString(evt.target.selectedItem.data);
  40.     LocaleManager.getInstance().setLocale(locale);
  41.   }
  42.  
  43.   /**
  44.     * The locale has changed.
  45.     * Change the labels text and the button label.
  46.     */
  47.   function localeChanged():Void{
  48.     var localeManager:LocaleManager = LocaleManager.getInstance();
  49.     firstname_lbl.text = localeManager.getString("firstname");
  50.     lastname_lbl.text = localeManager.getString("lastname");
  51.     submit_btn.label = localeManager.getString("submit");
  52.   }
  53. }

Notice that a new locale is created when the user chooses a different language from the combobox. Here the locale is created through a static method called fromString() because we allready have all the locale details we need in a string. You can ofcourse also instantiate a new locale by calling the Locale's constructor and passing in the language and the region. After creating the locale, we assign it to the LocaleManager through the setLocale() method. This will create a new resourcebundle and load the localized content. As you can see, I implemented it in a way so that you don't have to take care of the resourcebundles yourself. The LocaleManager does it for you. Finally, when the content is loaded and parsed, the localeChanged() method gets called. This is the method you use to update your view. You can fetch the localized strings with the getString() method on the LocaleManager. When the string is not found in the resourcebundle, an error is thrown.

Download

You can download the example here. The following classes should be added in the package "org.osflash.arp.util":
- Locale
- LocaleListener
- LocaleManager
- ResourceBundle

Related content:

- Configuring your ARP application


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

3 Responses to “Localizing your ARP application.”

  1. Christoph Atteneder Says:

    Hi Christophe,

    Thx for sharing =).

    I have to admit that I havn´t wrote a localized application by now, just a few thoughts on your localization example anyway .
    @XML Format: I also first thought about putting the localized strings into an xml file, but on the other side in java world, resource bundles have a format like:
    DOCUMENT_DOWNLOAD=Download Document
    If you use it that way, you can use existing resource bundle tools. On the other hand and xml file would be easier to parse for the first time.
    Another idea would be parsing the file serverside and filling a VO, which is transfered with remoting to the client. The advantage of this method would be that you
    can automatically generate a VO for the clientside developer, who can easily use code completion for setting the locale strings. So there are less typos.

    I also thought about eliminating the need of a localeChanged event with a kind of databinding. But for this I need first an instance of my ressource bundle, which is referenced by the different views. e.g.: firstname_lbl.text = ressourceBundle.FIRSTNAME;. After data is received from serverside or xml the ResourceBundle instance is updated and because of the existing references the views too.

    What do you think?

    cheers

    Christoph

  2. Christophe Says:

    Hi Christoph,

    thx for the feedback.

    About the XML: the easy parsing of the resources is why I chose XML as a dataholder. The format is so easy and generic that you never need to extend your parser. The idea of using VO’s to hold the localized strings would indeed have the big advantage of having type checking and code completion. However it felt like too much work to update the VO’s and the parsers every time we need new strings. My aim is also to provide a built in way of handling localization inside ARP. The less you have to do as a developer, the better IMO.

    About the localeChanged event and the databinding: That’s actually something we’ve been thinking about as well. We didn’t implement it though because we were afraid that it wouldn’t be flexible enough for reasons that we couldn’t come up with at that moment. We could still introdude a new class LocaleBinder or something that lets you bind certain properties to certain resource strings in the resourcebundle.

    Note that the localization efforts are experimental. Be sure to check back for new thoughts or updates. In the meantime, your thoughts are more than welcome.

    regards,
    Christophe

  3. novio Says:

    Has anybody already used mx.lang.Locale ?

Leave a Reply

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Login