Adobe Flex 3: Load Framework Localization Resources at Runtime using XML

January 7th, 2011 No comments

In a previous post, I wrote an article describing how to perform localization in Adobe Flex at runtime by loading resource from a XML file.

->  Adobe Flex 3: Load localization resources at runtime using XML

Several comments came in discussing issues where default Flex framework resources would display “NULL” instead of “Ok”, “Yes”, “No”, etc.


This article is intended to address those NULL string issues and demonstrate how to provide localized Flex framework resources in the XML resource file.


The Problem

The default Adobe Flex strings for UI controls and Alert dialogs, etc  are located in framework resource bundles”.
Unfortunately Adobe does not ship default country neutral resource locales like “en” , they only include US English and Japanese specific locales like “en_US” and “ja_JP”.


The Hack

In order to get the US English resources to show up instead of “NULL” you will need to include the “en_US” locale at the end of the locale chain for each supported language/locale.   This way the resource resolution process can at least find the English resource string instead of printing NULL if no locale specific resource strings can be found.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0"?>
<locales>
    <locale id='en' label='English'>
        <localeChain>
            <item>en</item>
            <item>en_US</item>
        </localeChain>
    </locale>
    <locale id='en_US' label='English (United States)'>
        <localeChain>
            <item>en_US</item>
            <item>en</item>
        </localeChain>
    </locale>
    <locale id='en_GB' label='English (Great Britain)'>
        <localeChain>
            <item>en_GB</item>
            <item>en</item>
            <item>en_US</item>             
        </localeChain>
    </locale>
    <locale id='es' label='Spanish'>
        <localeChain>
            <item>es</item>
            <item>en</item>
            <item>en_US</item>             
        </localeChain>
    </locale>
    <locale id='es_MX' label='Spanish (Mexico)'>
        <localeChain>
            <item>es_MX</item>
            <item>es</item>
            <item>en</item>
            <item>en_US</item>             
        </localeChain>
    </locale>
    <locale id='fr' label='French'>
        <localeChain>
            <item>fr</item>
            <item>en</item>
            <item>en_US</item>             
        </localeChain>
    </locale>
    <locale id='fr_CA' label='French (Canada)'>
        <localeChain>
            <item>fr_CA</item>
            <item>fr</item>
            <item>en</item>
            <item>en_US</item>             
        </localeChain>
    </locale>
</locales>


The Solution

The real solution is to provide localized resource bundles for each supported language/locale.    You can use the Adobe way and create and compile their resource files for alternate locales, then statically link them into your compiled SWF.  You can find the Flex framework resource file in your FlexSDK directory under “frameworks/projects/framework/bundles/en_US”.   For example, the controls resource bundle (“controls.properties” file) contains the resources for the “okLabel”, “yesLabel”, and “noLabel”.


When adding other locales, you must also include the framework resources for that locale. The en_US locale is already provided. For all other locales, you must create the framework resources. To create a locale’s framework resources, use the copylocale utility in the /sdk/bin directory. For Flex Builder, the copylocale utility is located in flex_builder_install/sdks/3.0.0/bin. You can only execute this utility from the command line.

See this article for Adobe’s notes:


Now if you would prefer to load these framework resources using the same XML resource file as demonstrated in the previous article, its pretty simple to do.  The existing “XmlResourceLoader” class in the sample project already supports the handling of multiple resource bundles from each loaded XML resource file.   The goal here is to additionally define the framework resource bundle resource strings in each language/locale specific resource XML file.    If you look at the existing sample source code, it lists a single resource bundle in the XML file, but the code does support multiple bundles.  For example, you can additionally define the “controls” (framework) resource bundle and include all the resources strings needed in the “controls” bundle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0"?>
<!--
*************************
SPANISH RESOURCES
*************************
-->
<resources>
  <resourceBundle name="myResources">
    <resource name="myResourceOrigin" value="Spanish Lanugage; Culture Neutral"/>    
    <resource name="myLocalizedLabel" value="Hola Mundo!" />
    <resource name="myLocalizedButton" value="Color"/>
    <resource name="myResourceFlagImage" value="assets/images/spain-flag.png"/>        
  </resourceBundle>
 
  <resourceBundle name="controls">
    <resource name="okLabel" value="Bueno"/>  
    <resource name="yesLabel" value="Si" />
    <resource name="noLabel" value="No"/>
    <resource name="cancelLabel" value="Cancelar"/>
  </resourceBundle>
</resources>


You would of course need to define resources for each of the framework resource bundles for each of the language/locales that you intend to support. Too bad Adobe does not provide more localized framework resource bundles in the SDK.


Categories: Adobe Flex

google-api-translate-java-maven-plugin 1.5 RELEASED

October 14th, 2010 No comments

The Google API Translate Maven Plugin (Version 1.5) has been  RELEASED and is now available on  Maven Central!

http://repo1.maven.org/maven2/com/systemsplanet/plugin/google-api-translate-java-maven-plugin/1.5/

Please check out the project site for more information:

Categories: Maven Mojos

maven-external-dependency-plugin 0.4 RELEASED

October 7th, 2010 No comments

The Maven External Dependency Plugin (Version 0.4) has been  RELEASED and is now available on  Maven Central!

http://repo1.maven.org/maven2/com/savage7/maven/plugins/maven-external-dependency-plugin/0.4/

A few features have been added since I first wrote about this project, including extracting artifacts from downloaded ZIP files and validating artifact checksums against the Sonatype Maven repository as a cautionary  measure  to ensure that artifact group ID, artifact ID, version, and checksum do not conflict with some other existing artifact in the public repository.

Please check out the project site for more information:


Categories: Maven Mojos

google-api-translate-java-maven-plugin

February 7th, 2010 2 comments

I recently joined as a contributor to the open source “google-api-translate-java-maven-plugin”  project.  This project provides a Maven Mojo/Plug-in that will perform automated language translations for your Java resource property files using the Google Translation API.

To aid the development process, it is helpful to see your application running in other languages so that you can see where resource string may have been missed and where text positioning, sizing, and alignment issues show up.   I personally feel that it is helpful to have this early on in the project development cycle long before the resource property files are ready to be sent out of house for proper translation.   So how can I get my property files translated and add that as an automated step in my lifecycle management or build process?   … Enter “google-api-translate-java-maven-plugin“.  This Maven plugin can be pointed at a source language file and can be configured for all the desired languages to generate, as long as it is a supported language by the Google Language API.

While this plugin certainly worked to meet my needs out of the box, there were a few features that I wanted to expose to provide greater flexibility and control over the translation process.    I added the following features as Version 1.3:

console progress display to show the current translation cycle status
overriding source properties file name
output file encoding options
exclusion list of named properties to exclude from generated output files
comment header for generated output files
smart-sync feature to limit translation effort to only added and changed properties
pass-thru list of named properties to include in the generated output files, but not translate
  • console progress display to show the current translation cycle status
  • overriding source properties file name
  • output file encoding options
  • exclusion list of named properties to exclude from generated output files
  • comment header for generated output files
  • smart-sync feature to limit translation effort to only added and changed properties
  • pass-thru list of named properties to include in the generated output files, but not translate

For a complete detailed listing of these features and their configuration properties, please visit this Wiki article on the project’s Google Code site:  New_Features_Version_1_3

Here is an example of a Maven project POM file configured to use these options:  UTF-8 Sample Project POM

The feature that I am most proud of is the Smart Sync feature.  Rather than performing translations on all property values for all generated output property files in all languages, I wanted a way to only perform the translation work on property values that have been added or updated and remove any properties form the output files that were removed from the source language property file.  This feature greatly reduces the amount of time it take to run this plugin since it is really only calling out to the Google API for additions and updates.  Before this feature it was taking in excess of 30-45 minutes to run through and perform the automated translations, and this length of time made it prohibitive to include this step in the regular build process.   With this feature enabled, it can take as little as 5 seconds :-)

One other notable feature is the support for saving the output generated property files with alternate file encodings such as UTF-8 and the option to include byte-order-mark (BOM) bytes at the beginning of the file.   While the default Java Properties reader and writer cannot make use of this,  there are other property file  implementation such as the one in the Spring Framework that can make use of UTF-8 or UTF-16 encoded files.  With the files encoded in UTF-8, we can see Japanese, Chinese, Russian, and Arabic character sets in the property file editor and all of the bytes that make of these characters do not have to be escaped making for an unreadable property file.

For more information an examples on how to use this Maven plugin, please visit the project Google Code site:  “google-api-translate-java-maven-plugin

Categories: Maven Mojos

maven-external-dependency-plugin

February 7th, 2010 2 comments

Well, I have started my first open source project. It is called “maven-external-dependency-plugin“ and is hosted over on the Google Code site. I started using Maven about a year ago in a large project at work and have really gown to love all that it offers and its immense extensibility. We use Maven for Java and Adobe Flex based projects and it works very well for us. However, one of the really frustrating things for me is to come across dependencies that are not hosted in a public Maven repository. On the Java side, this is a bit of a more rare occurrence, but with Flex, a large portion of that community is not Maven-minded. This means that I have to mange those dependencies by adding them to my local M2 repository and then manually deploy them to a group repository so that all team members can access these artifacts. Keeping them up to date becomes a pain mainly because of the manual effort involved and because it is not part of the standard workflow. I have been using batch files for managing these one-offs but that leaved me as the sole person responsible for maintaining these dependencies.

So … there has to be a better way … Right?

Well, I have thought for a long time … wouldn’t it be helpful to have a Maven plugin that could automatically download a file from a URL and install it to my local repository and them maybe also deploy it to my group’s Maven repository?    I has looked around at several Maven plugins out there trying to piece together a solution to perform this task.  But I did not find an out of the box solution that could be easily implemented and be robust and straight-forward.   So why not created my own mojo and contribute to the community?   How difficult could it be?

My first experience with Maven plugin development was working on a custom modified version of the Israfil Flex plugin to compile our Flex-based projects about a year ago.  Out of the box it got me to 90% of what I needed to accomplish, but there were something it could not do when compiling Flex modules, I don’t remember the specifics now but I think it had something to do with compiling multiple Flex modules and generating multiple module artifacts in a single project.  I abandoned this effort long ago in favor of the much more capable and powerful  “flex-mojos“.  So I jumped into the Java code for this plugin and made the necessary tweaks to meet my needs.

I remembered how simple it was to extend and how easy it was to create a Maven plugin so this weekend I created the “maven-external-dependency-plugin“.  This Maven (mojo) plugin is used to aid in managing external Maven artifacts that are not published public Maven repositories.

The goal of this project is to allow you to define a configuration for external (not hosted in M2 repo) artifacts that will automatically download the artifact, install to you local M2 repository and optionally deploy to your team/company M2 repository.

Granted there is still a bit of manual effort involved for updating the POM configuration information for these external dependencies when new versions are available, but this should eliminate the manual effort of having to install and deploy these types of files by hand.

Here is an example of an artifact configured to download from an external URL and install to the local Maven repository

   <!-- THIS JAR IS HOSTED ON GOOGLE CODE,
        BUT IS NOT AVAILABLE IN A MAVEN REPO -->
   <artifactItem>
       <groupId>com.google.code</groupId>
       <artifactId>google-api-translate-java</artifactId>
       <version>0.92</version>
       <packaging>jar</packaging>
       <downloadUrl>
          http://google-api-translate-java.googlecode.com/files/google-api-translate-java-{version}.jar
       </downloadUrl>
       <install>true</install>
       <force>false</force>
   </artifactItem>

Please visit this link for a complete example of a POM file configured to this this plugin: http://code.google.com/p/maven-external-dependency-plugin/source/browse/trunk/maven-external-dependency-plugin-test/pom.xml

Please visit the “maven-external-dependency-plugin” project site on Google Code for more information.

Categories: Maven Mojos