google-api-translate-java-maven-plugin

February 7th, 2010 No 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

Adobe Flex 3: Load localization resources at runtime using XML

October 23rd, 2009 4 comments

In a previous post, I wrote an article describing some of the localization weaknesses in Flex 3.

->  Adobe Flex 3.x Localization / Internationalization (i18n) Weaknesses

I had mentioned the concept of loading resources at runtime via a XML formatted document. In this article I will discuss how I accomplished this and provide a working sample and source code.


A fully working example and the source code are provided at the bottom of this article.


The Flex method for creating resource bundles for localization compiling them directly into SWF files works well for many applications and is an efficient method for handling localization.  They even go as far as allowing you to load different localization bundle SWFs at runtime to reduce the size of the main application by only loading the resource files that you need.  However, this method is not ideal for certain scenarios such as if you are creating a distributable application and want to allow your customers to edit or create resource files.  It can also become annoying to have to recompile a SWF just to make a small change to a resource string.   So for these types of scenarios you may prefer a resource solution that can load a simple text (XML) file at runtime.   Fortunately Flex does provide a means of dynamically creating resource files programmatically.

I have created a XmlResourceLoader class that uses the URLLoader to load the necessary XML resource files at runtime and dynamically generate the resource bundles in the Flex ResourceManager.   Since you may want to include a number of different fallback languages the  XmlResourceLoader class accepts a chain Array on the load method.  This allows you to define a locale specific resource chain such as “en_GB”, “en“.  Using this chain, the XmlResourceLoader will load both the “en_GB.xml” resource file and the “en” resource file.

        /**
        *  this function will dynamically load the XML resource
        *  files via HTTP if they have not already been
        *  previously loaded into memory.
        */
        public function load(localeChain:Array):void


This function will skip locales in the chain that have already been loaded.  So if you allow users to change selected locales at runtime, then subsequent calls to the XmlResourceLoader load function will waste time and resources re-fetching the same content XML.


If you are interested in what specific files were loaded after the load method was invoked, you can access the ArrayCollection of loaded resource files using this method:

        /**
        *  returns a list of resource files in use
        *  for the loaded locale chain.
        */
        public function get resourceFiles():ArrayCollection


The XML resource files are simply formatted like this:
[codesyntax lang="xml" lines="normal" lines_start="1" tab_width="4" title="XML Resource File"]
<resources>
<resourceBundle name=”myResources”>
<resource name=”myResourceOrigin” value=”English Lanugage; Culture Neutral”/>
<resource name=”myLocalizedLabel” value=”Hello World!” />
<resource name=”myLocalizedButton” value=”Color”/>
<resource name=”myResourceFlagImage” value=”assets/images/english-flag.png”/>
</resourceBundle>
</resources> [/codesyntax]


Each XML file may contain one or more resource bundles (<resourceBundle name=”myResources”>).  Each resource bundle section may contain one or more resource definitions (<resource name=”myLocalizedButton” value=”Color”/>).  Each resource definition contains two attributes: name and value.  The name attribute is the resource key name used to resolve the resource string and the value is the localized value string that is returned for the Flex ResourceManager when attempting to resolve a named resource.


Sample Application Links



Categories: Adobe Flex

Adobe Flex 3: How to create localized UI component / control

August 12th, 2009 8 comments

In a previous post, I wrote an article describing some of the localization weaknesses in Flex 3.

–>  Adobe Flex 3.x Localization / Internationalization (i18n) Weaknesses

One of issues outlined in that post is that the Flex UI components are not localization aware, or more simply put, the UI components do not have any built in support for resource localization.   Below we will recap the current method you use to implement localization strings and then a proposed alternative embedding localization handling directly into the UI controls.

The current de-facto methods used to render localized text for each control include either a compiler directive or run-time code for each property you want localized.

In this example the compiler directive @Resource() is used to define the resource string for the text property:

<mx:Label text="@Resource(bundle='myResources', key='text')"/>


To support dynamic locale changes, a runtime binding expression accessing the ResourceManager class is used instead of the compiler directive: property:

<mx:Label text="{resourceManager.getString('myResources', 'text')}"/>


The two implementations above are perfectly functional, but very cumbersome to implement when localizing a large Flex application.


Why not embed the resource localization logic directly into each UIComponent and expose resourceName and resourceBundle as design time properties?

flex-resource-design


Well, that exactly what I did!  I created wrapper controls derived from the mx controls that add the resourceBundle and resourceName design time properties.



See the screenshot here where these properties are accessible in the FlexBuilder designer – control properties tool window.


With this concept (borrowed from ASP.NET) a resource string naming convention is also needed to actually provide localized strings for each string property of the control.  For example  with a Label control you may want to provide localized strings for the Label.text property and Label.toolTip property.  Since this implementation only exposes a single resourceName property for the control I adopted a convention that allows me to defined the resource strings in the resource property files with a dot property name appended to the control resourceName.

myLabel.text=This is the label text
myLabel.toolTip=This is the label toolTip


Note, the resource strings above are named with the control’s resourceName and then have “.text” and “.toolTip” appended.  This convention enables me to define a single resourceName on each control and gives me the flexibility to define multiple resource strings for the individual control properties.   The convention outlined here can greatly simplify the localization burden on the Flex developer in large Flex applications.

 

A complete detailed example and source code is available below.  
… However we can walk through the basic  logistics here:

First, create a UI control class that extends an existing UI Control such as ‘Label’
Then add private class member variables for a  resource name string and resource bundle string.

[codesyntax lang="actionscript3" title="class definition"]

public class Label extends mx.controls.Label
{
   // resource localization variables
   private var _resourceName:String;
   private var _resourceBundle:String;

[/codesyntax]
Add a class constructor to register two event listeners.
The first event listener listens for when the UI components is ADDED to the layout/stage.
The second event listener is on the resourceManager and listens for changes to the resourceManager.
Both of these event listeners define the same callback handler method.
[codesyntax lang="actionscript3" title="class constructor"]

public function Label()
{
super();
// register event listener to handle resource localization when object is added
addEventListener(Event.ADDED,resources_LocalizationHandler);
// register as a weak listener for 'change' events from the ResourceManager.
// this is to capture runtime resource manager changes of locale
resourceManager.addEventListener(Event.CHANGE, resources_LocalizationHandler, false, 0, true);
}

[/codesyntax]
Next, we need to add public property getters and setters to expose the ‘resourceBundle’ and ‘resourceName’ component properties.  Note the ‘Inspectable’ annotation/metadata, this allows these properties to be exposed in the Flex 3 GUI Designer properties window.
[codesyntax lang="actionscript3" title="public resource properties"]

[Inspectable(category="Localization")]
public function get resourceBundle():String
{
   return _resourceBundle;
}

public function set resourceBundle(value:String):void
{
   // set new resource bundle
   if (_resourceBundle != value)
   {
      _resourceBundle = value;
   }
}

[Inspectable(category="Localization")]
public function get resourceName():String
{
   return _resourceName;
}

public function set resourceName(value:String):void
{
   // set new resource name
   if (_resourceName != value)
   {
      _resourceName = value;
   }
}

[/codesyntax]

The last step is to add the event handler method registered in the two event listeners defined earlier.
Here is where we will implement the actual resource lookup and replacement for the control’s properties.

[codesyntax lang="actionscript3" title="event handler"]

private function resources_LocalizationHandler(event:Event):void
{
// ensure the resource bundle and resource name properties are not empty
if(resourceBundle != null && resourceName != null)
{
// get the localized resource strings for all localized properties
var localizedText:String = resourceManager.getString(resourceBundle, resourceName + ".text");
var localizedToolTip:String = resourceManager.getString(resourceBundle, resourceName + ".toolTip"); // apply the localized resource string for 'text' property
if(localizedText != null && localizedText != '')
this.text = localizedText; // apply the localized resource string for 'toolTip' property
if(localizedToolTip != null && localizedToolTip != '')
this.toolTip = localizedToolTip;
}
}

[/codesyntax]
This type of implementation is highly dependent on establishing resource naming conventions for each control’s set of properties that you wish to localize, but it greatly simplifies the resource localization implementation of proliferated controls throughout a large Flex application.

Sample Application Links

Categories: Adobe Flex

TODO & FIXME Tasks for Flex Builder 2 & 3 in the Eclipse IDE

July 4th, 2009 No comments

For Java development the Eclipse IDE comes with a helpful Tasks feature that enumerates all your “TODO” and “FIXME” comments throughout your code.   This is a very nice feature for when you want to leave a reminder note in your source file to fix a bug/defect or a reminder note to complete some implementation.   The Tasks view window lists all your TODOs and FIXMEs and includes a reference to where each is located in the source.  Double-clicking a record in the Tasks view will open the source file and place the cursor on the line in the source where the comment was made.

Unfortunately the Eclipse plug-in fror Adobe FlexBuilder 2 and FlexBuilder 3 did not come with the TODO / FIXME tasks feature implemented in the Flex source editor, so these TODO and FIXME comments in Flex code are not listed in the Eclipse Tasks window.  Fortunately Eclipse is an extensible IDE and Dirk Eisman at http://www.richinternet.de/blog/ has provided a plug-in extension that enables this feature.

How it works: the plugin parses every MXML/AS file when opened and searches comments (both MXML and AS comments) for TODO and FIXME tokens (this search is case insensitive, so it also finds todo). The same action takes place after a file has been saved. If a token is found, a new Task gets generated with its message set to the comment and displayed in the Task View (To open Task View choose Window–>Other Views…–>Basic–>Tasks in Flex Builder 2 standalone and Window–>Show View–>Other–>Basic–>Tasks when running Flex Builder 2 as a plugin in Eclipse). Note: to really delete a Task you have to delete the comment – deleting a Task from the Task View does not kill the comment, so after you save the file the Task will reappear.

Installation: unzip the ZIP file and move the content of the plugins folder to the plugins folder of Flex Builder 2 / Eclipse. Then, close Flex Builder 2 / Eclipse and restart. The ZIP also contains a Test.mxml file which can be used to test the functionality.

Currently, the plugin only processes single-line comments but it ignores whitespaces between the start of a comment line and the TODO/FIXME token. I’m open for comments and enhancement requests, so please post them here.

The preceeding text was written byDirk Eisman on his blog @ http://www.richinternet.de/blog/index.cfm?entry=911D4B57-0F0D-5A73-AF6F4D4D04099757

In Eclipse 3.4 with the FlexBuilder 3.0.2 plug-in, all I did get this working was:

  1. download the Flex Builder Task Plug-in ZIP file (link below)
  2. close Eclipse / Flex Builder
  3. extract the “de.richinternet.flexbuilder.task_1.0.0.jar” file from the “plugins” folder in the ZIP
  4. copy the extraced “de.richinternet.flexbuilder.task_1.0.0.jar” file to the “plugins” folder in my Eclipse installation folder “C:\install\eclipse\plugins
  5. open Eclipse / Flex Builder
  6. in the Flex Development perspective, select “Window” / “Show View” / “Other” from the main menu.
  7. Under the “General” folder, select the “Tasks” view and then select “OK”.
  8. add some TODO / FIXME comments to a .MXML file and an .AS file and save the files

That’s it, the tasks started showing up in the Tasks view window.

Download ZIP



Download Flex Builder Task Plug-in 1.0.0



Thank you Dirk for providing this plug-in extension for Flex Builder, this is a very helpful add-on!


If you would like to see this functionality added to Flex Builder, please VOTE for this enhancement here:

https://bugs.adobe.com/jira/browse/FB-17231



Categories: Adobe Flex