Flex 4 Localization Quick Start

March 15, 2011By 33 Comments

Recently I was tasked with localization of the Adobe AIR Launchpad application (making it multi-lingual) and thought I would write up some notes for those facing this task. Flex 4 makes the localization task much easier. To read more about framework localization in particular (such as modifying the defaults used in the Alert dialog or Date controls etc), skip to this part of the post.

The quick summary of steps is shown below, followed by more detail on each:

1) Update project compiler options
2) Create a locale folder
3) Create language subfolders
4) Create .properties files
5) Update your code with the metadata tag to reference the resource bundle
6) Update your code to select the locale to be used (or dynamically choose at runtime)
7) Update your code to substitute any text displayed in the application with the key from the properties file

1) Update Compiler Options – right click on your project and select Properties, then Compiler Options and on the Additional compiler options list the different languages to be supported in a comma-delimited fashion such as:
-locale=en_US,ja_JP,fr_FR -source-path=locale/{locale}

This will compile the resource bundles into the application. The other option is to load them at runtime. See this article for more details on how to do that.

2) Create locale folder – create a folder called ‘locale’ under the project root such as shown in the screenshot below… *** NOTE: do not create it in the /src folder. If you do happen to create it there, you will have to add an additional compiler option -allow-source-path-overlap or you will get a warning.

3) Create subfolders for each language you are going to support using the language code and country format, such as en_US (English spoken in the United States), fr_FR (French in France) or pt_BR (Portuguese spoken in Brazil versus pt_PT – Portuguese spoken in Portugal) etc. See above screenshot for others…

4) Create properties files (to be used for resource bundles) – don’t be afraid! Even though the name sounds kinda scary :), a resource bundle is simply an ActionScript class compiled from a text file with a .properties extension that maps key=value pairs of Strings. The text file should be in UTF-8 format so it can contain special characters. If you use Flash Builder it should detect the content and set this automatically so you shouldn’t need to do anything extra. You can check to make sure though by right-clicking on the file and viewing the properties, such as:


If you’re a Java person, this should seem familiar. The name of the file minus the properties extension becomes the bundle. For instance, the LocalizedStrings.properties file would compile to a bundle with the name LocalizedStrings that you would use when referencing the bundle in your code. You will need to create this file for each locale you are supporting, and use the same keys with different values (obviously) in the desired language. For instance, here’s a snippet from my English version:

And here is the same snippet from the French version:

You can choose any name for the file, such as MyBundle.properties or whatever… Each will have the same name within its corresponding language folder as shown in the following:

5) Update your code with the metadata tag to reference the resource bundle

 <fx:Metadata>
	[ResourceBundle("LocalizedStrings")]
</fx:Metadata>

in ActionScript classes you would use:

[ResourceBundle("LocalizedStrings")]
public class MyClass { 
    ...
}

6) Update your code to select the locale to be used (or dynamically choose at runtime)

Refer to the specific locale you want to use.

        resourceManager.localeChain = "en_US"; // This line specifies which properties file to use

This could also be selected from a drop-down by the user or detect their preferred OS language. To detect it you could use code such as:

var langs:Array = Capabilities.languages;
var prefLang:String = (langs[0] as String).toUpperCase();
				
if (prefLang.indexOf("EN")>-1)
	resourceManager.localeChain = ['en_US'];   
else if (prefLang.indexOf("ES")>-1)
	resourceManager.localeChain = ['es_ES'];

Note: the resourceManager variable is already included in any class that extends UIComponent (such as Application), so you already have access to it without doing anything else. If you have a class that does not have it implicitly, you can get access to it by using:

import mx.resources.ResourceManager;

var rm:ResourceManager = ResourceManager.getInstance(); 

7) Update your code to substitute any text displayed in the application with the key from the properties file
For example, in MXML you could do something like this:

<s:Label text="{resourceManager.getString('LocalizedStrings', 'SAMPLE_TXT')}" paddingLeft="10"/>

In my en_US LocalizedStrings.properties file under the locale folder, I have this defined:

SAMPLE_TXT=Select the sample code options to include in your application:

That text value set for the SAMPLE_TXT key would then show up in the Label component at runtime if my localeChain was set to en_US (see step 5). If it were set to es_ES (Spanish), it would use the following definition in the es_ES version of LocalizedStrings.properties file:

SAMPLE_TXT=Seleccione las opciones de código de muestra que desea incluir en la aplicación:

You’ll notice that in my properties files I used capital letters for my keys (just seemed like a good idea at the time to identify key versus value more clearly), but it’s not a requirement, and most of the ones you’ll see in other references do not do that.

Framework Localization
When you are looking at localization, you need to consider not only the Strings in your application (such as labels etc), but also those that come from the framework itself (such as the Yes/No buttons in an Alert dialog etc). What’s great in Flex 4 is that the framework is already localized into a bunch of different languages so you don’t have to worry about it if you need one of the following shown in this screenshot below. You can see this in your own SDK by going to your Flash Builder 4 root/sdks/4.1/frameworks/locale/ folder.

If you want to change any of these, you can just unzip the properties files from the swc’s located in that path above for the given language and update as desired. For instance, when unzipping the framework_rb.swc under es_ES (Spanish), you’ll get the following:

If you then open up the controls.properties file, you can see some of the Strings used for the days of the week, Alert control etc and could modify as desired, then repackage the swc for use:



Notes:

  • As pointed out at the beginning of this post, this method shown above will compile the resource bundles into the application. If you’re going to support multiple locales, you may want to load them at runtime instead. This is beyond the scope of this post, but see this link for details.
  • There’s another way to reference your Strings in your MXML using the @Resource directive, but it is more limiting. To find out more on how to use that, view this link.


Other references:
Adobe Help
Adobe Devnet Flex localization article – Part 1
Adobe Devnet Flex localization article – Part 2

Filed in: Adobe FlexFlex 4Flex/AIR Tags:

About the Author ()

Comments (33)

Trackback URL | Comments RSS Feed

  1. Holly,
    I enjoyed your post; especially the sections on building properties files and framework localization.

    The only sections I dis-agree with are sections (5) and (7). Modifying your view code to “pull” in localized content actually mangles your design view mode and clutters the code with difficult-to-maintain l10n snippets.

    I highly recommend that developers consider http://www.BabelFx.org to inject or “push” localized content as needed.

    At its essence is a LocalizationMap that serves as a central registry to define where resource values should be injected into which target properties…

    BabelFx is open-sourc and free and dramatically reduces maintenance issues.

    - ThomasB

  2. Nice overview of translation process.

    Lupo tools can handle translation process and they’re very handy when it comes to text extraction.

    You can find it here
    http://www.dehats.com/drupal/?q=taxonomy/term/45

    I wrote few sentences about it: http://georgik.sinusgear.com/2010/08/28/lupo-nastroje-na-preklad-air-aplikacii/

    BTW: For developers – IntelliJ idea can handle property files with translation, so translation is faster.

    Note – link to: Adobe Devnet Flex localization article – Part 1 – is broken

  3. Nice post. Our company has extensive amounts of experience with this type of localization. If any readers are interested, we can be found at http://www.inwhatlanguage.com.

    -Cody B.

  4. Sergey says:

    Thank you, this is an incredible piece for any beginner or experienced Flex developer!

    Lately I was looking for a tool to help with crowdsourced translations for my app.

    Some generous translators have volunteered to help so I want to provide them with a tool to use that will make their job as easy as possible.
    So far I’ve found the collaborative localization tool Crowdin (http://crowdin.net)

    May be useful for some readers.

  5. Tolis says:

    Thanks for the great article. It saved the day! The only problem I had was with
    import mx.resources.ResourceManager;
    var rm:ResourceManager = ResourceManager.getInstance();

    which didn’t work because it wanted the IResourceManager as the type of the variable.

  6. Michael says:

    Hi Holly,

    Great article, thanks!
    Do you know how I can make a mx:MenuBar in more than one language? I know that this works in Flex 3, but I haven’t found a solution for Flex 4.

    Have an idea?

    - Michael

  7. John says:

    Silly question.. where is the resourceManager variable defined? I see you using it.. but I dont see it being defined! Is there a complete example somewhere?

    • devgirl says:

      Hi John! Not a silly question at all, I wondered the same thing when I first saw it. It’s actually a property off the UIComponent class which WindowedApplication extends from and has access to. It’s a singleton so one instance of it is always used. If you look at the AS Docs for UIComponent you will find out more details! Hope that helps :) Holly

  8. John says:

    oops. Please disregard. :-) I see how its being done. Cool!

  9. Michael says:

    Nobody has an idea how I can solve my problem (take a look at my first post of April 19)?

    Thanks in advance,
    Michael

    • devgirl says:

      Hi Michael, can you tell me again what you’re specifically trying to do? What are you running into that doesn’t work from Flex 3 to Flex 4? Thanks!! Holly

      • Michael says:

        Hi Holly!

        So, here’s my problem.
        With Flex 3, it’s possible to translate the mx:MenuBar in multiple languages, like this:

        In Flex 4, I’m trying to do the same thing, but it didn’t work.
        I don’t know what the problem is. The resourceManager works everywhere else in my application, except the menuBar.

        Thanks in advance!
        Regards, Michael

        • Michael says:

          Oh no, my code went lost…
          How can I send it to you?

        • devgirl says:

          Hi Michael!

          You’ll need to use the labelFunction to perform localization for your menuBar strings versus just using the labelField. So based on your code, for instance, you would want to do something more like this:

          
          protected function myLabelFunction(item:Object):String
          {
          				trace("Item " + item.@label + " " + resourceManager.getString("resources",item.@label));
          				return resourceManager.getString("resources",item.@label);
          				
          }
          
          <mx:MenuBar height="70%" width="100%" labelFunction="myLabelFunction"  iconField="@icon"> 
                <mx:XMLList> 
                      <menuitem label="Menu1">
                              <menuitem label="SubMenu11"/> 
                              <menuitem label="SubMenu12"/>
                      </menuitem> 
                </mx:XMLList> 
          </mx:MenuBar> 
          
          

          So you are just specifying your keys in your menuitem declaration and then looking up the value in the labelFunction.

          That should do it, thanks!!
          Holly

          • Michael says:

            Hi Holly!

            This is awesome, thank you so much!
            The Submenu works now. I hope I can solve the problem with the menu, the name still doesn’t change.

            But your code helped a lot, thanks!

            Cheers, Michael

  10. johnyBe says:

    Hello Holly,
    Thanks for your great articles!!

    I am currently trying to port a FLEX 3 project to FLEX 4.5 SDK and I am having some troubles with resource bundles…

    Flash Builder reports the following errors:
    “Call to a possibly undefined method getResourceBundle through a reference with static type Class.”

    Also I am getting the following warning:
    “ResourceBundle metadata is deprecated. Please use class level ResourceBundle metadata.”

    I need to use multiple bundles inside the same AS3 class so I use the following:
    [ResourceBundle("Components_ZBasicInfo")]
    private var bundle:ResourceBundle; ”

    I know that the [ResourceBundle()] directive must go up in the class definition level for FLEX 4 but this somehow confuses me cause I really need to pass this ‘bundle’ variable as an argument to a wrapper class that utilizes the resourceManager in order to get the localized string I wish :)

    Any help would be much appreciated!

    Thanks!

  11. Ajay Nagar says:

    Great blog post ! I want to fully understand whenever you update your blog, you believe sign up for your blog?.Them assisted me a large amount. I was little aware about this but yet your post set it up distinct strategy

  12. Riaz says:

    Hi,
    Can we change the value of key in .properties file in locale folder after release build. Do we need to compile the application to reflect the new changes or it will change the value in application.

  13. Swathi says:

    Hi Holly,

    Thank you for the article. Is it bad practise to have locale folder in the src directory instead of the project directory?

    I encountered this and your note of adding additional compiler arguments for ‘allow-source-path-overlap” helped. But, please let me know which one is best to put the locale src or project directory?

    Thanks in advance,
    Swathi.

  14. Atec says:

    Thanks a lot, your guide about labelFunction rocks!

  15. Judah says:

    It seems Flex 4.5 wrecks havoc on localization.

    It seemed to work if you remove the -source-path argument and parameters.

    In Flash Builder if you create a something.properties file it uses the default encoding which is not utf-8 (not for me). I had to open the file, place the cursor in it and goto Edit > Set Encoding and select UTF-8. You can also right click on the file and select properties and that opens a dialog that lets you change the encoding there but it’s not clear if it changes the encoding of the file or how the file is read.

    Judah

  16. Daniel says:

    Hi Great Article

    Do you know how you can change the setting so the app only specifies english as the only language supported?

    I have created a app for iOS and Android and when I upload it to the market it lists a bunch of extra languages as being supported. But I only want english.
    You have a great Blog!

  17. Debbie says:

    This article was awesome, easy to understand for a relative newbie like myself. I set up new folders for en_CA and fr_FR, but still want it to access the standard language files.
    BUT, it then gives me 1,000′s of errors like
    ‘unable to resolve resource bundle “blah blah”‘. I can guess that this is because it wants the en_US swc file strings in the “Program Files\Adobe\Adobe Flash Builder 4\sdks\4.1.0\frameworks\locale” folder. But, how do I set this up. it seems that my new files override everything.

    ideas?? thanks for the post

  18. Debbie says:

    I realized my mistake, apparently I have to use the locales that are set up in the Frameworks/locale folder, so en_CA was giving me a problem. I have changed the name of my new strings folder to en_US and all is good.

  19. Debbie says:

    sorry, me again. I still have a problem. I can get my own added text to show in French or English, but I don’t know how to get the overall GUI language to change, such as “I want to”, “More”, “Find and Address”. what do I have to do, or in what mxml page do I set up the “English/French” selection??

    thanks for your help & patience.

  20. crikos says:

    Hi Holly,
    yet another very awesome article – like a lot others. It Helped me to come up with Multilanguage support on my applications. Now I need to support Korean – do you know any Tutorial, how to realize that ?
    Thank you very much, Regards

Leave a Reply