jul
23
The support for multiple languages in a Flex application is well integrated in Flex 3. The Adobe documentation gives an excellent overview of the general process and the technical details associated with internationalizing your application.
The documentation, however, does not explicitly cover the case where some localized parts of your application reside in one or more Flex libraries (.swc files.) We are addressing that case here below.
A while ago, Vic on Flex had posted an article describing how to organize resource bundles and localized libraries so that one can build a localized Flex application that depends on them. The presented method produced one swc file per locale, per library, and also involved changing compilation parameters manually for each generated swc. Although the solution still works, it cannot be automated easily in FlexBuilder. Moreover, if your application requires switching locales at runtime, the resulting application’s swf file will bundle as many copies of your library as the number of locales to support.
So following up on Vic’s approach, here is a fully automated way to localize a Flex library with multiple locales in one single swc file with no overhead.
0. Check the Flex SDK
1. The resource bundles
2. The library
3. The application
4. Demo
Let’s build a small application that can switch from US English to French at runtime. For the sake of this exercise, we make the (plausible) assumption that the locale switch is implemented in the main application, while the localized content comes from a library.
0. Check the Flex SDK
In order to compile an application or library with support for a given locale, the Flex framework must be configured to recognize that locale. By default, US English (en_US) and Japanese (ja_JP) are configured out of the box for the Flex sdk 3.0.0.
The one time procedure to add an unsupported locale, say French (fr_FR), is as follows.
# in a UNIX terminal, # go to the 'Adobe Flex Builder 3 Plug-in' directory and type: cd sdks/3.0.0 bin/copylocale en_US fr_FR
1. The resource bundles
In a localized project without libraries, resource bundles are usually located in the main project, in the locale directory, next to src. When working with libraries, re-usability is a concern, and it may be useful to extract resource bundles from a given project to promote their (re-)use across projects.
So we create a general project in Eclipse/FlexBuilder, named my-resources. By default its location is ${DOCUMENTS}/my-resources, where ${DOCUMENTS} refers to the user’s workspace in Eclipse/FlexBuilder.
Then we create two files, both named resources.properties, in directories locale/en_US and locale/fr_FR, respectively. Here is the content of those files:
# ${DOCUMENTS}/my-resources/locale/en_US/resources.properties
ENGLISH=English
FRENCH=French - Français
TEXT=Let's switch languages!
# ${DOCUMENTS}/my-resources/locale/fr_FR/resources.properties
ENGLISH=Anglais - English
FRENCH=Français
TEXT=Changeons de langue !
Note: If you cannot see or type accented characters when editing your resource bundle, check the encoding settings of your editor. In Eclipse/FlexBuilder, the text file encoding can be set in the Resource section of the file properties. By default ISO-8859-1 is set for a property file. Choose the encoding that is appropriate for the locale.
Western resource bundles should be edited in utf-8 mode, in order to correctly input or display accented latin characters.
At this point Eclipse/FlexBuilder should contain the following project structure:
2. The Library
Now we create a Flex Library project named my_library. (Note that Flex library names cannot contain dashes.) Open the project properties, and do the following.
- In the Flex Library Build Path, add
${DOCUMENTS}/my-resources/locale/{locale}to the source path.

- (Optional) Enter
srcas the Main source folder - In the Flex Library Compiler section, edit the Additional compiler arguments with the following:
-locale=en_US,fr_FR -include-resource-bundles resources

- Close the Properties window and create mxml component
MyComponentin packagei18n.<?xml version="1.0" encoding="utf-8"?> <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Metadata> [ResourceBundle("resources")] </mx:Metadata> <mx:Label text="{resourceManager.getString('resources', 'TEXT')}"/> </mx:Canvas>
- Open the project properties window again, and verify that the class(es) found under
srcare included in the library.

- Build the project. This creates
bin/my_library.swc, which now contains the localization for bothen_USandfr_FRlocales.
Here is what the structure of project my_library may look like. You will notice that the [Source path] cannot be browsed, probably because the source path is set to point to one locale, whereas the compiler settings indicate to consider more than one. Do not change these settings, as they make the single swc localized with more than one language possible.

Note: the use of a variable like ${DOCUMENTS} to refer to files across projects is highly recommended for team work, so that project files don’t contain absolute local paths. The system automatically replaces paths segments with their corresponding variable names when using file choosers. Use your own variable when you do not use Eclipse/FlexBuilder’s default workspace. (You can define them in the General | Workspace | Linked resources section of the Preferences panel.)
3. The application
For the main application, we create a Flex Project named my-application, with the main source file named MyApplication.mxml.
Open the project properties, and do the following.
- In the Flex Build Path, add
${DOCUMENTS}/my-resourcesto the source path. Note that this setting differs from the similar setting in the Flex library.

- In the Flex Build Path, add the
my_libraryproject to the library path.

- In the Flex Compiler section, edit the Additional compiler arguments with
-locale=en_US,fr_FR -source-path=locale/{locale} -allow-source-path-overlap=true
- Close the project properties window and edit the main application file
MyApplication.mxmlwith the content that follows.<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:i18n="i18n.*" layout="absolute" creationComplete="handleCreationComplete();"> <mx:Metadata> [ResourceBundle("resources")] </mx:Metadata> <mx:Script> <![CDATA[ import mx.events.ItemClickEvent; private const en_US:String = "en_US"; private const fr_FR:String = "fr_FR"; private function handleCreationComplete():void { languageType.selection = english; } private function handleLanguageTypeClick(event:ItemClickEvent):void { var rbg:RadioButtonGroup = event.currentTarget as RadioButtonGroup; switch (rbg.selectedValue) { case en_US: case fr_FR: resourceManager.localeChain = [rbg.selectedValue]; break; default: break; } } ]]> </mx:Script> <mx:Panel title="Localized Flex Library" layout="absolute" horizontalCenter="0" verticalCenter="0" backgroundColor="#FFFFFF" backgroundAlpha="0.75"> <mx:VBox left="10" right="10" top="10" bottom="10"> <mx:VBox> <mx:RadioButtonGroup id="languageType" itemClick="handleLanguageTypeClick(event);"/> <mx:RadioButton id="english" value="en_US" label="{resourceManager.getString('resources', 'ENGLISH')}" groupName="languageType"/> <mx:RadioButton id="french" value="fr_FR" label="{resourceManager.getString('resources', 'FRENCH')}" groupName="languageType"/> </mx:VBox> <mx:HRule width="100%"/> <i18n:MyComponent/> </mx:VBox> </mx:Panel> </mx:Application>
- Build and run the project. Click on the radio buttons to change locales at runtime. The main application and the library component will update accordingly.
Project my-application should be structured as follows:
4. Demo
To see a full page demo (with source view), click here.



theremin
August 1st, 2008 at 5:13 amthank you. very nice.
joe
October 8th, 2008 at 1:53 pmExcellent, is the MyComponent placeholder necessary?
didier
October 8th, 2008 at 9:25 pmThe purpose of this article is to localize a library. At least one component is needed to populate the library for the sake of the example. Rather than being a placeholder, it shows the typical structure of a localized component when several locales need to be embedded in a single library.