Adobe Flex 3: Load localization resources at runtime using XML
In a previous post, I wrote an article describing some of the localization weaknesses in Flex 3.
-> Adobe Flex 3.x Localization / Internationalization (i18n) Weaknesses
I had mentioned the concept of loading resources at runtime via a XML formatted document. In this article I will discuss how I accomplished this and provide a working sample and source code.
A fully working example and the source code are provided at the bottom of this article.
The Flex method for creating resource bundles for localization compiling them directly into SWF files works well for many applications and is an efficient method for handling localization. They even go as far as allowing you to load different localization bundle SWFs at runtime to reduce the size of the main application by only loading the resource files that you need. However, this method is not ideal for certain scenarios such as if you are creating a distributable application and want to allow your customers to edit or create resource files. It can also become annoying to have to recompile a SWF just to make a small change to a resource string. So for these types of scenarios you may prefer a resource solution that can load a simple text (XML) file at runtime. Fortunately Flex does provide a means of dynamically creating resource files programmatically.
I have created a XmlResourceLoader class that uses the URLLoader to load the necessary XML resource files at runtime and dynamically generate the resource bundles in the Flex ResourceManager. Since you may want to include a number of different fallback languages the XmlResourceLoader class accepts a chain Array on the load method. This allows you to define a locale specific resource chain such as “en_GB”, “en“. Using this chain, the XmlResourceLoader will load both the “en_GB.xml” resource file and the “en” resource file.
/** * this function will dynamically load the XML resource * files via HTTP if they have not already been * previously loaded into memory. */ public function load(localeChain:Array):void
This function will skip locales in the chain that have already been loaded. So if you allow users to change selected locales at runtime, then subsequent calls to the XmlResourceLoader load function will waste time and resources re-fetching the same content XML.
If you are interested in what specific files were loaded after the load method was invoked, you can access the ArrayCollection of loaded resource files using this method:
/** * returns a list of resource files in use * for the loaded locale chain. */ public function get resourceFiles():ArrayCollection
The XML resource files are simply formatted like this:
- <resources>
- <resourceBundle name="myResources">
- <resource name="myResourceOrigin" value="English Lanugage; Culture Neutral"/>
- <resource name="myLocalizedLabel" value="Hello World!" />
- <resource name="myLocalizedButton" value="Color"/>
- <resource name="myResourceFlagImage" value="assets/images/english-flag.png"/>
- </resourceBundle>
- </resources>
Each XML file may contain one or more resource bundles (<resourceBundle name=”myResources”>). Each resource bundle section may contain one or more resource definitions (<resource name=”myLocalizedButton” value=”Color”/>). Each resource definition contains two attributes: name and value. The name attribute is the resource key name used to resolve the resource string and the value is the localized value string that is returned for the Flex ResourceManager when attempting to resolve a named resource.
Sample Application Links





This is an awesome solution to this problem. I’ve never been satisfied with the traditional “compiled” resource bundle solution, especially when integrating with other technologies. I agree that the compiled solution is very fast, but it requires a recompilation each time there is a new language/locale added. I don’t find recompilation useful and feel it has haunted Flex for awhile now, especially if there is a need to localize at runtime.
Thanks and great work!
Glad you like it! I’m sure there is room for improvement, but this code should provide a nice start for the runtime loading of resources.
Thanks for stopping by!
-Robert
Reminds me of an alternate translation scheme from years ago in an MS-Access application.
Only 1 other idea: when you are sitting looking at source code
label=”{resourceManager.getString(‘myResources’, ‘myLocalizedButton’)}”
It’d be nice to do an instant lookup from IDE to reassure yourself: “is this string what I think it is?”.
Or, a capability to insert/update a special format trailing comment… with the actual text in the default language ??
I am using FlashDevelop right now, that’s the thing about Flex is the variety of IDEs or source editors people use. But if it was an external executable, it could be used by most IDEs that can invoke a command line utility and capture output.
Hi Richard,
I agree and wish there were better tooling for the localization effort.
Take a look at this post, I personally don’t like the idea of explicitly defining a resource manager string lookup every single place I need to perform localization, so I take this approach:
http://www.savage7.com/index.php/2009/08/adobe-flex-3-how-to-create-localized-ui-component-control/
Thanks
-Robert
Hey Richard,
I have a question regarding the resourceManager.update();
If you set the localechain it already executes the update event so this class does the update function twice and it dispatches the change event two times.
Is there a reason for the resourceManager.update(); to execute in this class?
thanks in advance,
pascal
@Pascal
Hi Pascal,
Thanks for pointing that out, I did not realize the update was happening automatically on the setting of the locale chain.
How can I use this to load icons dynamically?
Hi Patrick, not sure what you mean … the sample is loading graphic images dynamically based on the localized properties defined in each XML file.
I am trying to use your XMLLoader Component with Flex 4 (Spark) for runtime localization.
But I am getting the following below error. Except that it is not showing the changes if I select the locales and make the changes exactly what you did.
Need some urgent help
ReferenceError: Error #1069: Property -1 not found on __AS3__.vec.Vector. and there is no default value.
at spark.components::Label/truncateText()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\components\Label.as:1246]
at spark.components::Label/http://www.adobe.com/2006/flex/mx/internal::composeTextLines()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\components\Label.as:485]
at spark.components.supportClasses::TextBase/measure()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\components\supportClasses\TextBase.as:533]
at mx.core::UIComponent/measureSizes()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8042]
at mx.core::UIComponent/validateSize()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\core\UIComponent.as:7966]
at mx.managers::LayoutManager/validateSize()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:617]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:733]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1072]
Hi Robert-
Nice work!
I added the following line (any place you want) –
Click the button before you select a language – you will see the button with ‘OK’label
Then select language other that en or en_US
Click the button – you will see the button with ‘null’ label
I assume that we some default resource has been overwritten – any clue what is the problem?
Thanks
Charlie
@Charlie
the missing line should have button that shows alert in the click handler
click=”{Alert.show(‘Hi there’,'Test Alert’)}”
Hello there, how can I change the location from the XML file is read? I’ve tried modifying the line:
public static const RESOURCE_FILE_SERVER_PATH:String = “assets/resources/”;
How can I modify this to get the file from anywhere I want in the project? I’ve tried different folders but it doesn’t work, it just works on the bin-debug folder.
Hi Karl,
In my example, the XML files are not embedded inside the SWF at compile time, therefore they must be located in a path that will be deployed to the web server and resolvable at runtime for the web browser/flex app. If you wanted them compiled in, you could certainly do that, but you would need to modify the logic inside ‘XmlResourceLoader’ that loads the resource files for further processing.
Thanks – Robert
Karl, One other note … The source resource XML files are located in a subfolder under the ‘html-template’ directory. When you run/deploy these get copied to the ‘bin-debug’ (or whatever output folder you have configured in your project settings) path.
If you want to modify the XML files, make the changes the the files in the ‘html-template’ path, otherwise if you make changes to them in the ‘bin-debug’ path you changes will get overwritten anytime you recompile/run/deploy.
Hi Charlie,
I looked into this issue briefly and I believe this is caused because the default Flex resource files are using the locale “en_US”. In this sample project, anytime a non US locale is selected, the new locale chain created omits “en_US” from the list. For example, selecting “Spanish (Mexico)” results in a locale chain of “es_MX,es,en”. So “en” is included as a root locale, but “en_US” is not. In the XMLResourceLocalizationSample.mxml file, try adding “en_US in each in the supportedLocales:XML variable. This will at least give the resource manager the ability to attempt resource resolution in the Flex default resources.
Thanks – Robert
Attention!
If you are getting Flex Error #2148 …. Only local-with-filesystem and trusted local SWF files may access local resources. … then take a look at this article:
http://www.brettwidmann.com/2010/03/how-to-remedy-flex-error-2148/
Basically as a temporary fix to test this sample, you will need to add the compiler argument “-use-network=false“.
Hello again Robert. How does the source on the html folder gets copied to bin debug? is this programmed in your class file or is it copied by default?
@Karl
That is a default task performed by FlexBuilder/FlashBuilder whenever it compiles. If you were to build from command line or from an external tool like Maven, you would probably have to manually perform this task to copy any necessary files.
Greetings Robert
I got the following error, it’s similar to one written before
ReferenceError: Error #1069: Property -1 not found on __AS3__.vec.Vector. and there is no default value.
and several lines referring to methods like truncateText() ,validateSize() , measureSize()
This error only appears when I put a small sized button, then I believe that the problem is when the button isnt large enough for the label. Has this happened to you?
Robert, do you think the fact that all my alerts appear with null buttons no matter what, has something to do with me using your class for localization?
Hi Karl,
Yes, it is. I have had several people comment on this issue. I need to create another article to address the issue. The main issue is that the locale chain for a non-English languages do not include “en_US”. “en_US” is where Adobe includes all it’s default framework resources. To get the default English strings to show up instead of “NULL”, you can modify the local chain to always include “en_US” at the end of the chain, so that if no overriding resource property is found, it will at least use the default Adobe provided English strings instead of “NULL”.
See Comment #15 for additional details.
@Karl
Check out this new article for more information:
http://www.savage7.com/index.php/2011/01/adobe-flex-3-load-framework-localization-resources-at-runtime-using-xml/
Hi Robert,
Great work!
I’ve managed to apply format Dates for different locales, but they all display the formatted Dates in English. How can I get them to show the translated day and month strings?
Thanks in advance
To override the date formatting strings for different locales, you have to create framework resources. Please see this article for more information: http://www.savage7.com/index.php/2011/01/adobe-flex-3-load-framework-localization-resources-at-runtime-using-xml/
Hi Robert,
I couldn’t find a way to prevent the xml files from caching without editing your class.
It would be nice if an additional parameter could be passed to xmlResourceLoader.load( localeChain, cacheControl ), so this could be used if supplied to prevent caching.
Cheers
Paul
@Karl
Hi, I got that issue when using different controls, not only buttons. Any solving?
Amazing work, saved me a few hours of development!
Thanks !
Fabien