Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Creative tools for business
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Flex Developer Center /

Localization in Flex – Part 2: Loading resources at runtime

by Charles Bihis

Charles Bihis
  • blogs.adobe.com/charles

Content

  • A look back
  • Moving on
  • Determine required resource bundles
  • Create your own resource module
  • Modify compiler options
  • Load your resource module at run time
  • Benefits and drawbacks and general approach for Flex developers
  • Where to go from here

Created

22 February 2011

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
design Flash Builder Flex forms localization

Requirements

Prerequisite knowledge

To complete the steps in this article you'll need to have a comfortable level of understanding and experience with Flex development, either with Flash Builder formerly Flex Builder or with the command line using the SDK. Previous knowledge of localization is not required.

User level

Intermediate

Required products

  • Flash Builder 4 (Download trial)

Sample files

  • localization-part-ii-start.zip
  • localization-part-ii-end.zip

In Part 1 of this series, I described how to enable localization in Flex by compiling the resources directly into the application. Now, in Part 2, I'll continue where Part 1 left off and show an alternative method of localization in which you compile the resource properties files separately and load them at run time. I will also discuss the benefits and drawbacks of each method, as well as a general approach to localization for all applications.

A look back

Before moving on, here is a recap of the steps you completed for Part 1.

  1. Set up the project with the appropriate directory structure.
  2. Create the properties files for the locales that you wish to support.
  3. Ensure that the localization framework files are in place.
  4. Set Flex compiler options to enable localization and specify the locales that you're supporting.
  5. Start localizing!

At this point, you have successfully enabled localization in your application by creating properties files and compiling them into your application. Once compiled into your application, they are called resource bundles and are accessed by the Flex resource manager to extract localized values. In this part of the tutorial, I will explain how to remove your compiled resource bundles from your application, and instead compile them into resource modules, which are collections of resource bundles that can be loaded at run time and accessed by the resource manager.

Moving on

Part 2 of this series is a continuation of Part 1, and as such, uses the resulting project from the end of Part 1. The starter project localization-part-ii-start is actually equivalent to the end project of Part 1 localization-part-i-end . Continuing from this point, you can follow the steps in this article to externalize your properties files and load them at run time.

After completing the steps in Part 1, there are only four additional steps required to externalize and load your resource bundles. They are:

  1. Determine which required resource bundles to include into your project.
  2. Create your own resource modules, one for each locale, and replace the properties files with them.
  3. Modify your compiler options to include the appropriate resource bundles as well as to specify that you will be using resource modules exclusively.
  4. Load the resource modules at runtime within your application.

Determine required resource bundles

Your application will use many resource bundles during its execution. Even without application-specific localization, many core Flex framework classes rely on resource bundles to localize run-time and compile-time warnings and errors. Because of this, before you can create your own resource module which is essentially a collection of resource bundles , you must first find out which resource bundles to include. This can be done quite easily using the Flex compiler. Simply use the -resource-bundle-list compiler option when compiling your application; for example:

mxmlc -locale= -resource-bundle-list=used-resource-bundles.txt Main.mxml

Note: You can do this by executing mxmlc via the command line directly, or you can add this compiler option to the Additional Compiler Arguments setting in Flash Builder.

bundles = collections components controls core effects layout resources skins styles textLayout

Create your own resource module

Now that you know what resource bundles your application uses, you can compile your own resource module. To do this, you must use mxmlc via the command line. You can't compile resource modules in Flash Builder yet.

To compile your resource module, simply specify four compiler options:

  • locale—This is the locale for which you are creating the resource module.
  • source-path—The location of the properties file to use for the resource module.
  • include-resource-bundles—A list of the required resource bundles that your application uses you found this in the last step .
  • output—The output SWF file that will be generated. This is your resource module!

Note: You do not specify an MXML file to compile.

  1. To compile the resource module for the sample application for the locale en_US execute the following command:
mxmlc -locale=en_US -source-path=locale/{locale} -include-resource-bundles=collections,components,controls,core,effects,layout,resources,skins,styles,textLayout -output resources.swf

Note: You can name your resource modules however you like in whatever directory structure you like, as long as you load them accordingly in your application which you will see how to do in Load your resource module at runtime .

This will create your resource module resources.swf with the locale en_US using the properties file in locale/en_US/ and including the additional resource bundles that you identified earlier.

  1. Once the resources.swf file for the en_US locale is created, simply place it alongside en_US properties file in locale\en_US\.

Note: The properties file is no longer needed in the project, but it's a good idea to keep it around in case changes are required in the future.

  1. Repeat steps 1 and 2 for the other three locales see Figure 1 .
Create one resources.swf file for each locale.
Figure 1. Create one resources.swf file for each locale.

Note: You may see the following error in your project: Unable to resolve resource bundle 'resources'. This is because you are now referencing a resource bundle that no longer exists it has been replaced with your newly created resource module . You will fix this error in the next section when you modify your compiler options.

Modify compiler options

With your newly created resource modules in place, you can now modify your compiler options to include the appropriate resource bundles as well as to specify that you will be using resource modules exclusively.

  • To include the appropriate resource bundles, use the -include-resource-bundles compiler argument and specify the list of resource bundles that you generated earlier.
  • To specify that you will be using resource modules exclusively, use the -locale compiler flag followed by the equal "=" sign, and nothing else. This step is optional, but since this application will indeed be using resource modules exclusively, it's good practice to let the compiler know.

Follow these steps to set the compiler options:

  1. Right-click your project and select Properties.
  2. Select Flex Compiler on the left, and use the following as the Additional Compiler Arguments settings:
-locale= -source-path ./locale/{locale} -include-resource-bundles collections components controls core effects layout resources skins styles textLayout

Note: When modifying the compiler options through Flash Builder, the values are not comma-separated.

Note: You may receive a warning stating that the source path for your locale is a subdirectory of the project's source path. You can resolve this by allowing source-path overlap using the following compiler option: -allow-source-path-overlap=true.

Load your resource module at run time

The final step is to modify your application to load your resource modules at runtime. Previously, in Part 1, you added a change event handler on the locales ComboBox that would change the locale based on the selected language in the ComboBox. The event handler function looked like this:

private function comboChangeHandler():void { resourceManager.localeChain = [localeComboBox.selectedItem.locale]; }

This was possible because the required resource bundles including your own custom resources resource bundle were compiled and loaded into the application for you. As a result, your resource bundle was accessible by the resource manager immediately. Now, however, since you didn't compile the resource bundles directly into the application, they must be loaded manually. To do this, you call the ResourceManager's loadResourceModule function. Then, once the resource module has been loaded, you can change the locale by changing the resource manager's localeChain property, just as in the comboChangeHandler function above.

There is really only one change that needs to be made to the comboChangeHandler event handler function to achieve this, and the logic is quite simple. First, check to see if the resource module for the desired locale has been loaded yet. If not, then load it. Otherwise, change the locale as normal.

  1. Edit Main.mxml in Source View.
  2. Replace the existing comboChangeHandler function with the following:
import mx.events.ResourceEvent; private function comboChangeHandler():void { var newLocale:String = String(localeComboBox.selectedItem.locale); // Ensure that you are not loading the same resource module more than once. if (resourceManager.getLocales().indexOf(newLocale) != -1) { completeHandler(null); } else { // Build the file name of the resource module. var resourceModuleURL:String = "./locale/" + newLocale + "/" + "resources.swf"; var eventDispatcher:IEventDispatcher = resourceManager.loadResourceModule(resourceModuleURL); eventDispatcher.addEventListener(ResourceEvent.COMPLETE, completeHandler); } function completeHandler(event:ResourceEvent):void { resourceManager.localeChain = [localeComboBox.selectedItem.locale]; } }

The code starts with a simple if statement that checks to see if the resource module for the selected locale has already been loaded. If so, then it invokes the completeHandler function, which simply changes the locale of the resource manager using the same line of code used in the original comboChangeHandler function . If the resource has not yet been loaded, then it proceeds to load it. First, it identifies the location of the resource module, and then it calls the resourceManager.loadResourceModule function. The completeHandler function is invoked once the resource module is loaded and ready to use.

Note: Do not try to use the resource module immediately after calling loadResourceModule . The ResourceManager's loadResourceModule function makes calls asynchronously, and so the resource module may not yet be loaded and ready for use by the time the call is complete. Instead, always attach an event handler to listen for the ResourceEvent.COMPLETE event. Only when this event is dispatched can you be sure that your resource module is loaded and ready for use.

  1. Run the application.

You'll notice that when the application loads, no text is shown in the form at all.

As it stands now, the application will load an appropriate resource module and change locales whenever a language is selected from the combo box. However, when the application first runs, no resource modules are loaded, so no text is displayed.

To fix this, simply add a creationComplete event handler function to your main application that, when invoked, will initiate the loading of the default locale en_US . Since the combo box by default displays the English language, you can simply invoke the comboChangeHandler function to simulate that the language has just been selected.

  1. Add the following function to your Main.mxml:
private function init():void { comboChangeHandler(); }
  1. Finally, add creationComplete="init " to the main <s:Application> tag.

Once you've completed all of these changes, your main MXML file for the sample application should look like this:

<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="init()"> <fx:Script> <![CDATA[ import mx.events.ResourceEvent; [Bindable] private var locales:Array = [{label:"English (United States)", locale:"en_US"}, {label:"German (Germany)", locale:"de_DE"}, {label:"French (France)", locale:"fr_FR"}, {label:"Japanese (Japan)", locale:"ja_JP"}]; private function init():void { comboChangeHandler(); } private function comboChangeHandler():void { var newLocale:String = String(localeComboBox.selectedItem.locale); // Ensure that you are not loading the same resource module more than once. if (resourceManager.getLocales().indexOf(newLocale) != -1) { completeHandler(null); } else { // Build the file name of the resource module. var resourceModuleURL:String = "./locale/" + newLocale + "/" + "resources.swf"; var eventDispatcher:IEventDispatcher = resourceManager.loadResourceModule(resourceModuleURL); eventDispatcher.addEventListener(ResourceEvent.COMPLETE, completeHandler); } function completeHandler(event:ResourceEvent):void { resourceManager.localeChain = [localeComboBox.selectedItem.locale]; } } ]]> </fx:Script> <fx:Metadata> [ResourceBundle("resources")] </fx:Metadata> <s:layout> <s:VerticalLayout horizontalAlign="center" verticalAlign="middle" /> </s:layout> <s:Panel title="{resourceManager.getString('resources','contact.title')}" color="black" borderAlpha="0.15" width="350"> <s:layout> <s:VerticalLayout horizontalAlign="center" paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10" /> </s:layout> <mx:Form width="100%" color="0x323232"> <mx:FormItem label="{resourceManager.getString('resources','contact.field.name')}"> <s:TextInput /> </mx:FormItem> <mx:FormItem label="{resourceManager.getString('resources','contact.field.streetAddress')}"> <s:TextInput /> </mx:FormItem> <mx:FormItem label="{resourceManager.getString('resources','contact.field.city')}"> <s:TextInput /> </mx:FormItem> <mx:FormItem label="{resourceManager.getString('resources','contact.field.state')}"> <s:TextInput /> </mx:FormItem> <mx:FormItem label="{resourceManager.getString('resources','contact.field.zipCode')}"> <s:TextInput /> </mx:FormItem> <mx:FormItem label="{resourceManager.getString('resources','contact.field.country')}"> <s:TextInput /> </mx:FormItem> <mx:FormItem> <s:Button label="{resourceManager.getString('resources','contact.submit')}" /> </mx:FormItem> </mx:Form> </s:Panel> <mx:Spacer height="15" /> <s:HGroup width="350" verticalAlign="middle"> <mx:Spacer width="100%" /> <mx:Image source="{resourceManager.getString('resources','contact.flagImg')}"/> <mx:ComboBox id="localeComboBox" dataProvider="{locales}" change="comboChangeHandler()"/> </s:HGroup> </s:Application>

You're done! Build your application, run it, and select different languages to see the contact form load the appropriate resource modules at run time. If you run into any problems, refer to the completed project files available in localization-part-ii-end.zip.

This content requires Flash To view this content, JavaScript must be enabled, and you need the latest version of the Adobe Flash Player. To view this content, JavaScript must be enabled, and you need the latest version of the Adobe Flash Player.

Benefits and drawbacks and general approach for Flex developers

You've now completed both parts of this two-part tutorial! You've covered and implemented localization with the Flex framework using two common methodologies:

  • Compiling the resource bundles directly into the application.
  • Compiling the resource bundles externally, and loading them into the application at runtime.

Now that you've learned them, it would be beneficial to recap the benefits and drawbacks of each approach so that you can use the right technique when building localization into your next application.

Table 1. Pros and cons of compiling directly.

Pros

Cons

  • Definitely the easier and quicker approach.
  • Properties files are easy to read and modify.
  • No increased load-time added to the application to load resource modules.
  • The properties files are turned into resource bundles which are then compiled directly into the application. Depending on the number and size of each properties file, this can have a noticeable effect on the size of your application's deliverable SWF.
  • Any change to the properties files requires a complete recompilation of your entire project.

Table 2. Pros and cons of compiling externally.

Pros

Cons

  • Since your resource bundles are compiled into resource modules separately from you application, they have no effect on the size of your application's main SWF.
  • You can modify your localization strings without having to recompile your entire project.
  • If your application is set up to read the available locales dynamically, then you can actually add new locales at any time.

 

  • This requires a more involved process for generating and loading resource modules.
  • Modifying a localization string requires a recompilation of the resource module.
  • Loading the resource modules at runtime, initially, will take longer than if they were compiled into the application. Also, depending on how your application is set up, this may also require additional network calls. It is worthwhile to test out this scenario to see what kind of improvement, if any, your application sees at startup.

You might be wondering what approach you should take with your applications. In general, the use of compile-time resources is most suited for applications with a limited number of locales to support. Larger applications and applications that support many locales with a large number of localization strings would benefit more from the use of resource modules.

However, this doesn't mean that you must take only one approach. A hybrid approach can be very useful for many applications. For instance, you may want to use compile-time resources for your default or most commonly used locales, say English and French. For the rest, you can use resource modules and load them at run time. This would give you quick access for your common two locales, as well as support for many other locales via resource modules without having to increase the size of your application SWF.

Where to go from here

Localization is an important feature for any application with a global audience. It is important to know the two approaches available and how to implement them to ensure that your application not only supports the appropriate locales, but also makes efficient use of the framework. Knowing both of these approaches, as well as their benefits and drawbacks, will help you make better-informed decisions on the most suitable approach to take with your own applications.

For a more thorough look at localization in Flex, including alternative methods, additional features, and common pitfalls that are beyond the scope of this article, refer to the Flex 4 Localization documentation.

Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License+Adobe Commercial Rights

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

More Like This

  • Using Flex styles
  • Providing XML to controls with E4X
  • Hello! Flex 4 book excerpt: FXG and MXML graphics—Building a game
  • Foundation Flex for Designers excerpt: Flex with Photoshop and Illustrator
  • Foundation Flex for Designers excerpt: Flex Builder and Flash
  • AdvancED Flex 3 excerpt: Sculpting interactive business intelligence interfaces
  • Tips for using Flex containers
  • Layout mirroring with Flex
  • Developing interfaces for RIAs: Displaying data using the DataGrid control with Flex
  • Skinning a Flex 4 desktop application with MXML graphics

Tutorials & Samples

Tutorials

  • Flex mobile performance checklist
  • Flex and Maven with Flexmojos – Part 3: Journeyman
  • Migrating Flex 3 applications to Flex 4.5 – Part 4

Samples

  • Twitter Trends
  • Flex 4.5 reference applications
  • Mobile Trader Flex app on Android Market

Flex User Forum

More
07/25/2011 Flash Player Debug Issues - Safari 5.1 & Chrome 13
04/22/2012 Loader png - wrong color values in BitmapData
04/22/2012 HTTPService and crossdomain.xml doesn't work as expected
04/23/2012 Memory related crashes in Flex application

Flex Cookbook

More
04/06/2012 How to detect screen resize with a SkinnableComponent
02/29/2012 Embed Stage3D content inside Flex application components
02/15/2012 Custom WorkFlow Component
02/09/2012 Using Camera with a MediaContainer instead of VideoDisplay

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement