08/05/2013

Flex String internationalisation with Flexmojos


I wanted to support internationalisation on a pretty complex Flex project that was sharing some Components and Skins using Flex Libraries (swc files). I have spent a good amount of time searching for documentation and its just not there, the only examples I could find are the very simplest options you could possibly use and they are not even clear, so I'm going to try to write all the steps to get internationalisation working on your Flex app and compiling with Flexmojos here.

Flex Version: 4.6.b.23201 (I had to change to this from 4.6.0.23201 because I couldn't get this one from any online repository as easily as 4.6.b.23201, but they should behave the same way)
Maven repository: http://repository.sonatype.org/content/groups/flexgroup
Flexmojos version: 4.2-beta


This technique might also work with other versions, but I haven't tried.

Adding the properties files

First thing to note is where to add the properties files, I recommend to use the standard approach, which is adding a "locale" folder at the root of your project with the different language folders inside it. This applies both for a library and an application project:


As you can see, I am planning to support English, Spanish and Japanese.

Accessing the properties files from the code

Now, how do you access the properties files from the Flex application? I personally like resourceManager better, but there are different ways of doing it, you can read more about it here

A sample on my app would look like this:

 <s:Button id="registerBtn"  
           label="{resourceManager.getString('LoginComponentSkin','LoginComponentSkin.registerBtn_label')}"  
           height="30"  
           styleName="panel_text_button txtLinkBtn"  
           left="0" />  


Making Flexmojos compile language resource bundles

Configuration for the library project pom.xml

<plugin>
   <groupId>org.sonatype.flexmojos</groupId>
   <artifactId>flexmojos-maven-plugin</artifactId>

   <configuration>
      <localesSourcePath>${basedir}/locale/{locale}</localesSourcePath>

      <locales>
         <param>${flex.compiler.locale}</param>
      </locales>

      <localesRuntime>
         <locale>en_US</locale>
         <locale>es_ES</locale>
         <locale>ja_JP</locale>
      </localesRuntime>
   </configuration>
</plugin>


Note that the value of ${flex.compiler.locale} is:

<flex.compiler.locale>en_US,ja_JP,es_ES</flex.compiler.locale>

When you run mvn install on the library project it will produce different output files for each resource bundle that you include. The output should be something like this:



Configuration for the Application Project pom.xml

<configuration>
   <sourceFile>${basedir}/src/main/flex/MixAdminShell.mxml</sourceFile>

   <localesSourcePath>${basedir}/locale/{locale}</localesSourcePath>

   <locales>
       <param>${flex.compiler.locale}</param>
   </locales>

   <localesCompiled>
      <locale>en_US</locale>
      <locale>es_ES</locale>
      <locale>ja_JP</locale>
   </localesCompiled>
   ...
</configuration>
 
We also need to add dependencies to the resource bundles generated for the libraries on the dependencies section:

      <dependency>
         <groupId>com.investlab</groupId>
         <artifactId>flex-mix-components</artifactId>
         <version>${project.version}</version>
         <type>swc</type>
      </dependency>

      <dependency>
         <groupId>com.investlab</groupId>
         <artifactId>flex-mix-components</artifactId>
         <version>${project.version}</version>
         <type>rb.swc</type>
         <classifier>ja_JP</classifier>
      </dependency>

      <dependency>
         <groupId>com.investlab</groupId>
         <artifactId>flex-mix-components</artifactId>
         <version>${project.version}</version>
         <type>rb.swc</type>
         <classifier>en_US</classifier>
      </dependency>

      <dependency>
         <groupId>com.investlab</groupId>
         <artifactId>flex-mix-components</artifactId>
         <version>${project.version}</version>
         <type>rb.swc</type>
         <classifier>es_ES</classifier>
      </dependency>


MISSING TRANSLATIONS

Flex framework doesn't have all the libraries translated to all the languages, so when you compile you may find that some resource bundles from the framework are missing (in Spanish, for version 4.6.b.23201 the missing resource bundle libraries are flash-integration-4.6.b.23201-es_ES.rb.swc and  playerglobal-4.6.b.23201-es_ES.rb.swc). If you want to do a quick test on 4.6.b.23201 try adding Japanese only, all libraries are available for it.

Spanish versions available here:

How to do the needed translations

1- Download the English version of each file (I will do the example with one, but just apply the same to the rest of them):

Grab the English version from the framework:


Open it (do not decompress it! You can do this opening it with WinRAR on Windows or Springy on a Mac), the content will look like this:


2- You need to change the name of the folder "es_US" to your preferred language, in this case "es_ES"

3- In some cases "empty.properties" will contain strings in the associated language, you will need to translate them on that file to your preferred language

4- Open the file "catalog.xml" and change the reference to "en_US" for "es_ES" at the bottom:

 <?xml version="1.0" encoding ="utf-8"?>  
 <swc xmlns="http://www.adobe.com/flash/swccatalog/9">  
  <versions>  
   <swc version="1.2" />  
   <flex version="4.6.0" build="23201" minimumSupportedVersion="3.0.0" />  
  </versions>  
  <features>  
   <feature-script-deps />  
   <feature-files />  
  </features>  
  <libraries>  
   <library path="library.swf">  
    <script name="_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855_flash_display_Sprite" mod="1320959596103" signatureChecksum="480278969" >  
     <def id="_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855_flash_display_Sprite" />  
     <dep id="flash.display:Sprite" type="i" />  
     <dep id="AS3" type="n" />  
     <dep id="flash.system:Security" type="e" />  
    </script>  
    <digests>  
     <digest type="SHA-256" signed="false" value="8afed981420976a5478998fbde89d028e703063c306806a61d9d16b7d196a205"  />  
    </digests>  
   </library>  
  </libraries>  
  <files>  
   <file path="locale/en_US/empty.properties" mod="1303837923608" />  
  </files>  
 </swc>  

5- Now save your file, and you have to upload it to your Repository (in my case I use Artifactory), making sure that the properties of the deployed file match the english version's (DO NOT FORGET THE CLASSIFIER OPTION):

<dependency>
    <groupId>com.adobe.flex.framework</groupId>
    <artifactId>flash-integration</artifactId>
    <version>4.6.b.23201</version>
    <classifier>es_ES</classifier>
    <type>rb.swc</type>
</dependency>

If you run mvm clean install again it should pick up the new library and continue with the compilation further, probably until the next resource bundle is missing and you will have to repeat the translation process again for the new file until you have all the required bundles translated.

I hope it helps :)

04/02/2010

Doc?

I'm falling in love with this Adobe AIR tool to read APIs. It takes a few minutes to get it fully functional with all the APIs you want, but after that it can be extremely useful.

Http://www.airdoc.be/



07/12/2009

A handy AIR app - Ruler

I used to have a firefox plugin (MeasureIt) to measure pixels while working on my application interface, but since I updated to FP10 it stopped working for me :(

Fortunately I just found this useful Air application:

http://www.pixelwindowapp.com





15/07/2009

Increasing Eclipse memory in Windows and Mac

This is something I have to look for every now and then, so I decided to post it here to make my live easier:

WINDOWS

This are the parameters we have to use:
-vmargs -Xms512m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=128m

We have two options:
  1. Modify the file eclipse.ini available on the Eclipse instalation root
  2. Modify a direct access to eclipse (right click/properties). In this case it should look something like this: C:\eclipse\eclipse.exe -vmargs -Xms512m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=128
MAC

We have to modify eclipse.ini to add the same values as in Windows. To find this file we have to go to the app file (Eclipse.app), right click on it and select "Show package content". We will get a new finder window with a folder named "Contents", we have to navigate to "Contents/MacOS" and we will find "eclipse.ini" in there, you have to edit this file and add the parameters in there.

This is how the file looks on my 4Gb MacBookPro:

-showsplash
org.eclipse.platform
-startup
../../../plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
--launcher.library
../../../plugins/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731
-vmargs
-Xdock:icon=../Resources/Eclipse.icns
-XstartOnFirstThread
-Xms1024m
-Xmx1024m
-XX:PermSize=256m
-XX:MaxPermSize=256m
-Dosgi.requiredJavaVersion=1.5
-Dorg.eclipse.swt.internal.carbon.smallFonts


I hope it helps ;)

UPDATE

Thanks to Brooks we have a screencast explaining how to do this:

http://www.brooksandrus.com/blog/2006/11/23/setting-eclipse-and-java-application-jvm-heap-size-on-mac-os-x/

03/06/2009

Adobe BrowserLab

Adobe has just launched a new Flash application that allows you to test your webpage in multiple browser emulations, I´m sure designers will be very happy about this.

Check it out here!

02/06/2009

Morgan Stanley - Matrix

I am now allowed to talk about Matrix, the largest project I have ever worked on. The client, Morgan Stanley, one of the biggest investment Banks in the world, and the application, Matrix, a trading platform, but furthermore, a whole world for sharing ideas and opportunities in real time while you trade with all the media you might need attached to them (videos, charts, links, etc.. ).

Its the biggest Flex application I´ve made so far, I worked with some of the most talented Flex developers of the moment and never stopped learning.

The team has created a microsite to expain what the application is about, and I am sure it will create a tremendous explossion in the market once its launched.

Enjoy the intro: http://www.morganstanley.com/matrixinfo/

19/05/2009

Closing the "Add watch expression" dialog on Eclipse

YESSSSSS!!!! I just read this blog entry on Mike Morearty´s blog about closing the "Add watch expression in Flex Builder.

This has been anoying me for a looooong time.. I think I will very quickly get used to hit "SHIFT + RETURN" on my keyboard to close the dialog :)

Thanks Mike!

I hope it helps ;)

24/02/2009

Using mock4as for testing

We have reciently introduced mock4as in our project, I found it very easy to use and very helpfull when mocking for tests.

I don´t pretend to write a full especification on how to use it, you can find that in deep detail on their site, so I´m just going to post a tiny example so you can have a quick idea of how it works, lets test a serer call on a delegate:

First of all we need to create a Mock delegate for out tests (a nice approach to do this is just to implement the same interface both on your delegate and on your mock delegate). This mock delegate neds to have a PUBLIC variable of the type "Mock" (from the mock4as framework:

MyMockDelegate.as:
public var mock : Mock = new Mock();
So from our Test class we are going to tell the mock variable which call we spect Flex to do, then we will trigger the action that is supposed to do that call and add the assertion to see if the call was eventually done or not:

MyTest.as
public function testSomething () : void
{
myMockDelegate.mock.expects("getSomething");
somePM.trigger();
assertTrue( myMockDelegate.mock.errorMessage(), myMockDelegate.mock.success() );
}
And now, the only bit left is to register the call on the mock delegte:

MyMockDelegate.as
override public function getSomething( resultHandler : Function ) : void
{
mock.record( "getSomething" );
}
And thats it! So, summarizing, the execution of the test would be as follows:

1 - We tell the test what we spect to be called
2 - We call the trigger function, this will cause the app to call the mockDelegate "getSomething()" function, which will register the call into the "mock" variable.
3 - The assertions will verify that the call we where expecting was done

Piece of cake, isn´t it?

I hope it helps ;)

09/02/2009

Working remotely - First impressions

I have recently joined a team of great developers in a medium-sized project. When I accepted the role I was told that I was sometimes going to work remotely from home and I had never really done that before. What I didn´t spect at first is that I was actually going to kick-off on the project remotely, and I was a little nervious about it.. how was I going to know how they work? How long would it take me to catch up with the guys that had been working there for months? What would I do if I got stucked?

Well, I have now finished my first week on the project, and yes, from Spain and updating my changes to Denmark. The experience has been really good, although it is true that there are some things you need to do face to face, I think the solution comes through finding a balance on the time remoting and time in the office (maybe 80% - 20%???).

SHARING INFORMATION: We have plenty of tools now-a-days to help us on communication. The one we have found the best so far is the well known Skype, we keep a "developers chat" window open with all the developers in the project on it, this makes it really quick to ask/notify your collegues about anythig going on the project, and it also keeps "the human touch" when developers share jokes on it. It is important to see that the final use of the chat is not actually "chatting", but sharing info related to the project, so jokes are good, but just every now and then ;)

CODING: This is the bit that changes the less. You just connect to your remote SVN/CVS repository and then work just as if you where in the office. I have actually had more problems with repositories in a box next to me that hundreds of miles away...

AGILE DEVELOPMENT - STAND UP MEETINGS: What we currently do is just to dial into a meeting room on the main offices building, people onsite just get into the room and people remoting just join the conference call. I have to say that starting on the project remotely straight away made it a bit hard to follow this meetings at first as I don´t know who is talking and I can´t "put faces" to the voices, but I guess this will get better tomorrow when I phisically meet my workmates :) I think that in the future when we all have better Internet connections at home this will be done in a conference call with webcams (maybe it could be done today without problems), and this will help newys catching up quicker.

DEVELOPERS DAY-A-DAY LIFE: you wake up at 8:30, you look out the window and its raining really heavily, you take a warm shower, go to the kitchen and turn on the TV to see the news, they show all the main roads in the city collapsed by millions of cars with people dressed up with suits and stressed out, you can´t help smiling a little bit.... you have your breakfast and.. and thats it! you can start working!! no 45 minutes on the tube, no conmutes, no gloves, scarf, coat, double pair of soxes, etc... lovely. Furthermore, I personally find it much better in terms of concentration when coding as you don´t have all the office noise (all that people talking, printers, etc..), in fact I have noticed that I take less breaks when remoting, and once you´re finished, you are already home :)
Don´t missunderstand, I think face to face is necessary, in fact I consider miself a very social animal, but using the appropiate tools this time can be brought down without being harmfull to the project.

Summarizing, I think the future in terms of app development is mre remoting, less offices. If you think about it, if you have people onsite, the company will need a bigger office, which translates into more expensive rental, there might be some things hat take "a bit" longer when remoting, but in long term your developers are going to be much more productive (and happier!)

What is your experience working remotely?

Hope it helps ;)

24/12/2008

Merry Christmas!



I wish you all a merry Christmas and a happy 2009!