Archive

Archive for the ‘Adobe Flex’ Category

Adobe Flex 3: Load localization resources at runtime using XML

October 23rd, 2009 6 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:

  1. <resources>
  2. <resourceBundle name="myResources">
  3. <resource name="myResourceOrigin" value="English Lanugage; Culture Neutral"/>
  4. <resource name="myLocalizedLabel" value="Hello World!" />
  5. <resource name="myLocalizedButton" value="Color"/>
  6. <resource name="myResourceFlagImage" value="assets/images/english-flag.png"/>
  7. </resourceBundle>
  8. </resources>


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 10 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.

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

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.
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);
}

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.
[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;
   }
}


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.

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;
  }
}

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

Getting started with Spring Actionscript (Spring IOC/DI for Flex)

June 26th, 2009 No comments

I recently started integrating the SpringActionscript (formerly named “Prana Framework”) into my current Flex application. SpringActionscript is an Inversion of Control (IOC) and Dependency Injection (DI) framework for Flex that is syntactically based on the popular Java Spring Framework.  While there are several contending IOC frameworks for Flex, if you use Spring in your Java projects it is a natural decision to go with SpringActionscript.  Developers that switch between Java and ActionScript can make a mostly comfortable transition without a great deal of ramp up and learning a new syntax.

So I started with a sample project using the current released version 0.7.1 and followed the instructions in Chapter 2 in the Getting Started portion of the documentation.  The documentation is straight-forward and pretty clear on what you need to do.  However, when I went to run the project, I could never get it to recognize my objects defined in the applicationContext.xml file.  It would compile fine, but upon trying to access a named object at run-time (‘bean’ in Java speak)  I would get the following error message:

Error: An object definition for ‘exampleObject’ was not found.
at org.springextensions.actionscript.ioc.factory.supp ort::AbstractObjectFactory/getObject()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\spring extensions\actionscript\ioc\factory\support\Abstra ctObjectFactory.as:138]
at SpringActionScriptExample/applicationContext_completeHandler()[D:\repo\trunk\source\SpringActionScriptExample\src \SpringActionScriptExample.mxml:46]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at org.springextensions.actionscript.ioc.factory.xml: :XMLObjectFactory/_doParse()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\spring extensions\actionscript\ioc\factory\xml\XMLObjectF actory.as:343]
at org.springextensions.actionscript.ioc.factory.xml: :XMLObjectFactory/_loadNextProperties()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\spring extensions\actionscript\ioc\factory\xml\XMLObjectF actory.as:315]
at org.springextensions.actionscript.ioc.factory.xml: :XMLObjectFactory/_loadNextConfigLocation()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\spring extensions\actionscript\ioc\factory\xml\XMLObjectF actory.as:291]
at org.springextensions.actionscript.ioc.factory.xml: :XMLObjectFactory/_onLoaderComplete()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\spring extensions\actionscript\ioc\factory\xml\XMLObjectF actory.as:241]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()

I worked on this issue trying different combinations for a few hours before finally giving into defeat and posting a help request on the SpringSource forums.  Within a day the helpful members on the forums quickly pointed out that the namespace and schema defined for the <objects> node in my applicationContext.xml file was using a namespace and schema definition intended for the upcoming 0.8 version release.   So it turns out the published documentation is just a little ahead of the game and as soon as 0.8 is released, this should be a non-issue.

Here was my applicationContext.xml file using the namespace and schema locations as defined by the current documentation:

<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springactionscript.org/schema/objects"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.springactionscript.org/schema/objects
                              http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd">

    <object id="exampleObject">
      <property name="firstName" value="John" />
      <property name="lastName" value="Doe"/>
      <property name="age" value="41"/>
    </object>
</objects>


An here is my modified, working applicationContext.xml file using the older namespace and schema locations for versions older than 0.8:

<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.pranaframework.org/objects"�
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.pranaframework.org/objects
                             http://www.pranaframework.org/schema/objects/prana-objects-0.6.xsd">

    <object id="exampleObject">
      <property name="firstName" value="John" />
      <property name="lastName" value="Doe"/>
      <property name="age" value="41"/>
    </object>
</objects>


That’s all it took!  All is up and working now.
Here is my full working sample source code project:

SpringActionscriptExample.zip

Download ZIP

For the full details of this issue, please see this forum thread:  
http://forum.springsource.org/showthread.php?t=73932

Categories: Adobe Flex

RefCardz: FREE Cheat Sheets for Flex Developers!

June 23rd, 2009 No comments

Free Flex Related RefCardz at refcardz.dzone.com:

These are great reference cards to have handy if you are a Flex developer.


Very First Steps in Flex
Bruce Eckel and James Ward, author of First Steps in Flex

Features include Hello, World, Web Services, Remoting and Messaging with Java, Hot Tips and more.



Flex & Spring Integration
Jon Rose and James Ward
Contents Include: About Adobe Flex, About Spring, Why Adobe Flex and Spring, Integrating Adobe Flex and Spring, Hot Tips and More…


Flex & Spring Integration
Jon Rose and James Ward

Contents Include: About Adobe Flex, About Spring, Why Adobe Flex and Spring, Integrating Adobe Flex and Spring, Hot Tips and More…




Flexible Rails: Flex 3 on Rails 2
Peter Armstrong, author of Flexible Rails: Flex 3 on Rails 2

Features include Overview of Rails 2, Overview of Flex 3, Flex 3 and Rails 2 Together, Building a Flex + Rails Application, Hot Tips and more.





Categories: Adobe Flex