I wanted to continue to play with a little fun project which I localized for three languages but my compiler showed me the error:
unable to open ‘/Applications/Adobe Flex Builder 3 Plug-in/sdks/3.0.2.2113/frameworks/locale/de_DE’
Hmm, this formerly worked so what changed? I changed the SDK to 3.0.2.2113 to upgrade to AIR 1.1 and all framework resources except default en_US are not part of the SDK and have to be created.
So here a little step by step tutorial how to enable localization from scratch with a new SDK. My reference for Flex localization is the article on Adobe Labs written by Gordon Smith which covers all necessary informations and is written in a funny style which I like a lot.
Create Framework Resources
- Open a console/terminal and change to the Flex SDK directory. In my case /Applications/Adobe Flex Builder 3 Plug-in/skds/3.0.2.2113
- Execute this command ./bin/copylocale en_US de_DE where you can replace de_DE with the locale you want to have in your app. After executing the command you see a lot of output on the console which gives you an overview what happens behind the scenes. Repeat this step for each locale you want to add.
- When you look into SKD_DIR/locale/de_DE you should now see the three new files airframework_rb.swc, framework_rb.swc and rpc_rb.swc where “rb” is short for resource bundle.
Setup Flex Project
- Open Flex Builder and create a new Flex project
- Create the directory locale as a project subdirectory
- Create the directories en_US and de_DE
- Create the file myResources.properties in locale/en_US and locale/de_DE
- Add this line to the english property file: Hello=Hello
- Add this line to the german (de_DE) property file: Hello=Hallo (Note in german it is different with “a”)
- Change the project compiler settings (right-click Project->Properties->Flex Compiler) and change the additional compiler settings to -locale en_US de_DE -source-path+=../locale/{locale}
Code with resource bundles in MXML or ActionScript Class
- Open the main MXML src/YourProjectName.mxml
Now you have got two ways to include the localized string:
-
<mx:Label text="@Resource(bundle='myResources', key='Hello')" />
-
<mx:Label text="{resourceManager.getString('myResources', 'Hello')}" />
The first option uses the compiler directive @Resource and runs out of the box. The second option does not give a compiler error but when you test the application you see no text appearing. This is because data binding is used which only evaluates at runtime. To tell the compiler upfront that we need the resource bundle myResources we have to add a Metadata tag and declare the resource bundle:
<mx:Metadata
[ResourceBundle("myResources")]
</mx:Metadata>
You can also declare this in an ActionScript class like this:
[ResourceBundle("myResources")
public class YourClass{...}
You can also use the resource metadata brackets in ActionScript classes:
[Resource(bundle="myResources", key="Hello")]
or use the ResourceManager singleton:
ResourceManager.getInstance().getString("myResources", "Hello");
Using Placeholders in Strings
Often you have to locate strings where parts have to be replaced by variables. Placeholder can be defined like this:
Welcome=Hello {0}!
As you want to replace the {0} with a variable this only works at runtime so you have to use data binding:
<mx:Label text="{resourceManager.getString('myResources', 'Welcome', [userObject.username])}" />
The third argument of getString is an Array of parameters where each index corresponds to the placeholder index so you could have a string like Foo=Hello {0}! The time is {1} and you have {2} new emails.
Multiline Strings and Comments
You can define multiline strings with “\” (backslash on OS X is alt+shift+7). Comments in a property file start with a #:
# this is a comment MyText=Here is a text written in two lines
HTML
There is also nothing to say against using HTML:
MyHTMLText=Here is <b>bold text</b>.
<mx:Label htmlText="{resourceManager.getString('myResources', 'MyHTMLText')}" />
Switch Locale and Fallback
Switching the locale depends on whether you have use the compiler directive @Resource or data binding. The easier thing is data binding because you can switch with one line of code:
resourceManager.localeChain = ["de_DE"];
As you see localeChain is an Array so you can define it like this:
resourceManager.localeChain = ["de_DE", "en_US"];
In this case first de_DE is looked up and when the key is not found the fallback is english so you show at least something up.
When it comes to the static implementation with @Resource the switch is a bit more difficult and also explained in the wiki article. There you have to compile the resource bundles via console to SWF and load them at runtime.
Use Resource Bundles for Code/Content Separation
I recommend to use resource bundles also if you do not localize your application. The separation of code and content will at least be beneficial when for instance someone has to review all text and you simply have to hand over property files instead of several MXML classes …
Links
- Feature Introduction Runtime Localization
- Building multilingual Flex Application on Adobe AIR
- as3localelib
- Wikipedia Locale
So far! These are the most basics for localization I hope. For more detailed information check the first link to Adobe Labs which covers all in detail. But there is much more possible which I did not cover like not using strings but to localize images or even classes but enough for now.







