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
Sample files
Localization is the process of preparing your Flex application—or any application—for international use. Because of this, it is an obvious keystone feature for any application with a global audience. Flex has a very powerful localization framework, which enables you to implement localization easily and efficiently through the use of simple text-based properties files. These properties files must be loaded into your application before they can be used, which is commonly done in one of two ways:
 
  • Compile the localization properties files directly into your application
  • Compile the localization properties files separately, leave them external to your application, and load them at run time.
This article covers the first (and simpler) option by stepping through the localization process for a basic Flex application. I'll cover the second method in Part 2 of this series.

 
Overview

Localization is a very important feature for any application intended for a global audience. It can seem like a daunting task, but with the help of the localization features in Flex, you will see how easy it can be. To illustrate the process, this article will step through the localization of a very simple Flex application. For the sake of brevity, I've included a starter project that you can use (localization-part-i-start) as your base. It is a simple Flex contact form with a handful of localizable fields, such as "Name", "Street Address", and so on. It also includes a drop-down menu that can be used to change the language (although at the start of this exercise, it doesn't work yet). Starting with this seed project, you can follow the steps in this article to localize it, even enabling language changes at run time! But, before you dive into the example, it will help to understand the process as a whole.
 
There are essentially four tasks that must be completed before your application can be localized:
 
  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.
The first two steps involve setting up the application so that your properties files are accessible and ready to be used. The third and fourth steps ensure that your application will get compiled properly by including the newly created properties files and using the appropriate compiler flags and localization framework files. Once this is done, your properties files are compiled into resource bundles. Resource bundles are available for use by your application via the Flex ResourceManager class. After that, all that's left is step 5.
 
  1. Start localizing! (This is the easy part.)

 
Set up the project and directory structure

Begin by importing the starter project in Flash Builder. You'll notice that this looks very similar to a brand new project except for a few minor changes:
 
  • Main.mxml isn't blank. It already has the content of the basic contact form.
  • There are two additional directories in the project:
    • /src/assets/ - This holds any assets used in the project (in this case, the flag images for each country you are targeting for localization).
    • /src/locale/ - This is the parent directory for all of the properties files for the locales that the application will support.
Inside the locale folder, there are four subfolders, one for each of the application's four locales. The convention for naming a locale is:
 
{language}_{country code}
For example, en_US represents English as spoken in the United States. The locale en_CA represents, as you can guess, English as spoken in Canada. The sample application will support four common languages: English, French, German, and Japanese (see Figure 1).
 
The project's directory structure.
 
Figure 1. The project's directory structure.
Note: The directory structure described here is not a standard, although it is an accepted convention. You can name and organize your localization files any way you like, but you should take care to reflect those changes in your compiler arguments. See Specify compiler options for more details on setting the compiler arguments.
 

 
Create properties files

A properties file is essentially a text file that defines the localization targets and their corresponding values. You place each properties file in its corresponding locale subfolder. Collectively, the properties files completely define all localization targets in your application that will be localized. Follow these steps to create your first properties file for the locale en_US as an example.
 
  1. Create a new text file in /src/locales/en_US, name it resources.properties, and save it as UTF-8.
  2. Copy the following content into the file:
## resources.properties file for locale en_US ## # contact-form labels and assets contact.title=Contact Form contact.flagImg=assets/us.gif contact.submit=Submit # contact-form fields contact.field.name=Name contact.field.streetAddress=Street Address contact.field.city=City contact.field.state=State contact.field.zipCode=ZIP Code contact.field.country=Country
Note: You can name the file anything you like; resources.properties is a commonly used name, but it is not required. Feel free to name it according to any convention that makes sense for your application. Also, you can have as many properties files as you wish. So, for instance, if you're separating image and asset sources for localization as well as text labels, you may want to use one file, assets.properties, for your assets, and another file, dictionary.properties, for your text labels.
 
As you can see, the properties file is a simple text file with a basic key/value pair structure describing the localization targets and values. In this example, the key is separated from the value with an equal sign ( =) . You can also use a colon ( : ), or just whitespace. For example:
 
  • key = value
  • key : value
  • key value
Comment lines within a properties file start with a # or ! ; for example:
 
! This is a comment # This is also a comment
Note: For additional rules for properties file syntax and usage, see Properties File Syntax.
 
Now that you've seen what the properties file for en_US looks like in the sample application, you can create the rest of the files and place them in their appropriate locale folders.
 
  1. Create the properties file for fr_FR with the following content:
## resources.properties file for locale fr_FR ## # contact-form labels and assets contact.title=Nom contact.flagImg=assets/fr.gif contact.submit=Soumettre # contact-form fields contact.field.name=Nom contact.field.streetAddress=Adresse contact.field.city=City contact.field.state=État contact.field.zipCode=Code Postal contact.field.country=Pays
  1. Create the properties file for de_DE with the following content:
## resources.properties file for locale de_DE ## # contact-form labels and assets contact.title=Kontaktformular contact.flagImg=assets/de.gif contact.submit=Senden # contact-form fields contact.field.name=Name contact.field.streetAddress=Strasse und Hausnummer contact.field.city=City contact.field.state=Staat contact.field.zipCode=Postleitzahl contact.field.country=Land
  1. Lastly, create the properties file for ja_JP with the following content:
## resources.properties file for locale ja_JP ## # contact-form labels and assets contact.title=お問い合わせフォーム contact.flagImg=assets/jp.gif contact.submit=送信 # contact-form fields contact.field.name=名contact.field.streetAddress=ストリートアドレス contact.field.city=市 contact.field.state=状態contact.field.zipCode=郵便番号 contact.field.country=国

 
Ensure localization framework files are in place

For every locale that you support in your application, you must ensure that the framework resources for that locale are present. Essentially for each of your application's locales, a specific set of SWCs must be in place for your application to compile and work properly. You can see what these files look like in the following folder:
 
FLEX_HOME/sdks/x.x.x/frameworks/locale/en_US/
 
So, for instance, if you want to support Italian (it_IT) in your application, you'll want to make sure that the necessary localization files are also present in a folder it_IT within the frameworks/locale folder alongside en_US. Conveniently, the Flex SDK provides a utility, named copylocale, that simplifies this process. You can find it at the following location:
 
FLEX_HOME/sdks/x.x.x/bin/ copylocale
 
Simply open up a terminal and invoke the command using the following syntax:
 
copylocale original_locale new_locale
This utility creates a new folder in the frameworks directory for the new locale and then copies the necessary framework files into it. You need a locale in the frameworks folder for each locale that your application will support.
 
Note: Flash Builder and the Flex 4 SDK come with support for 16 of the most common locales already, meaning that these folders will already be present and populated with the necessary files. Before creating any of your own, check in the locale folder to see which locales are already supported. If all of the locales that you wish to support are already there, then you don't have to do anything here. Only run the utility for locales that you don't already see.
 
For this tutorial example, you need the folders en_US, de_DE, fr_FR, and ja_JP. The en_US folder is present by default (and you may have all of the others as well). Use the copylocale utility to add support for any of the other three locales that don't already exist. From the command line, run the following command if you don't see the fr_FR folder:
 
copylocale en_US de_DE copylocale en_US ja_JP
Note: If you don't see folders being created as you run the utility, you may need admin privileges. On Windows, make sure to run the terminal as Administrator. On Max OS X, make sure to use sudo.
 
You should now have (at least) the following four folders in your frameworks/locale folder:
  • en_US
  • fr_FR
  • de_DE
  • ja_JP

 
Specify compiler options

With the directory structure created, the properties files in place, and the necessary framework files copied, you just need to tell the compiler that you're enabling localization. You do this by specifying two compiler options:
  • locale—for the additional locales that the application supports
  • source-path—for the path to the properties files for each of these locales
There are various ways to set these option but the two simplest are via the command line and via Flash Builder.
 
Setting the additional locales and source paths via the command line
To set the additional locales and source paths via the command line, simply add the –locale flag and –source-path flag when calling mxmlc; for example:
 
mxmlc –locale=en_US,fr_FR,de_DE,ja_JP –source-path=./locale/{locale}
 
Setting the additional locales and source paths by changing the compiler arguments in Flash Builder
To set the additional locales in Flash Builder, you can simply add them to the compiler arguments:
 
  1. Right-click your project and select Properties.
  2. Select Flex Compiler on the left, and add the following to the Additional Compiler Arguments settings:
-locale en_US de_DE fr_FR ja_JP –source-path ./locale/{locale}
Note: When modifying the compiler arguments this way, there is no equal sign (=) and the locales are not comma-separated.
 
  1. Click OK.
The {locale} at the end of the source-path value for each of these methods is used to dynamically specify the locales for the application. The {locale} is replaced by each of the locale values that you specify using the - locale option. So, if you modify the names of your locale folders, make sure those changes are reflected in the compiler arguments as well. As an alternative, you could also add each source path manually (for example: src/locale/en_US , src/locale/de_DE , and so on).
 
Note: You may get a compiler warning, “Source path entry, ‘PROJECT_HOME/localization-part-i-end\src\locale\en_US', is a subdirectory of source path entry, 'PROJECT_HOME\localization-part-i-end\src’”. This is normal, and won’t stop your application from functioning as expected. However, if you want to remove this warning, add the additional compiler argument “-allow-source-path-overlap=true”.

 
Localize!

At this point, you've set up your project to compile the properties files into resource bundles and make them available for use in your application. Once you have all of this in place, all of the hard work is done! To reference the values in the properties files, you use the ResourceManager class. The ResourceManager class is actually a Singleton and is in charge of handling all of the resource bundles that you want to use in your application. First, you must declare the resources that you want to use. In the steps above, you named the properties files resources.properties, so the resource bundles are called resources .
 
  1. Add the following MXML below the </fx:Script> tag in Main.mxml:
<fx:Metadata> [ResourceBundle("resources")] </fx:Metadata>
Alternatively, you can make the declaration in ActionScript using the following code:
 
[ResourceBundle("resources")] public class MyComponent extends UIComponent { ... }
  1. Next, you'll need to add a change handler to the language ComboBox control to detect locale changes. Add the following within the <fx:Script> tag :
// within the Script tag private function comboChangeHandler():void { resourceManager.localeChain = [localeComboBox.selectedItem.locale]; }
  1. Add the change handler to the ComboBox control:
<mx:ComboBox id="localeComboBox" dataProvider="{locales}" change="comboChangeHandler()"/>
  1. Finally, replace any text or assets in your application with the localizable values. For instance, find the Label for "Name":
<mx:FormItem label="Name">
And change it to:
 
<mx:FormItem label="{resourceManager.getString('resources','contact.field.name')}">
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"> <fx:Script> <![CDATA[ [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 comboChangeHandler():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>
  1. Build the application, run it, and select different languages to see the contact form labels change.

 
Where to go from here

Localization is a key feature for any global application or website. As you've seen, with only a few simple steps, you can localize a Flex application quite easily. It's not only efficient, but scalable as well. With all the preparation done, your application can easily grow to support more localization targets and locales as your user audience expands. There are other ways to achieve localization as well (including loading resources at run time, which I'll discuss in Part 2), but this is one of the simplest and most common methods. Adhere to the steps covered above, and you'll be localizing your applications in no time.
 
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.