Avg. Rating 4.3

Problem

You would like to find an easy and automatic way of compiling all your external resource manager localization bundles at once.

Solution

Create an Ant macro to compile your language resource, and invoke it when necessary.

Detailed explanation

The use of resource bundles as a localization tool in Flex is well understood and documented, however it may be the case that a developer wishes to externalize his resource bundles and load them at runtime using the ResourceManager's loadResourceModule() method. If this is the case, it becomes tedious to compile each bundle independently, because Flex Builder does not provide an easy way to do so.

Therefore, we go to Ant for the solution. Ant is an automated build framework that allows substantial amounts of automation for repetitive tasks including, among other things, compiling of various assets. To use Ant to compile your resource bundles you will need to complete the following 7 steps:

Step 1: Install Ant for Flex Builder

This step is not necessary if you are working with the Flex Builder Plug-In for Eclipse, because the required Java Development Libraries come with the default install. If, however, you are working with the default Flex Builder install, you will need to complete the following steps.

  1. From the Help menu, choose Software Updates > Find and Install.
  2. Select "Search for new features to install" and click next.
  3. Select "The Eclipse Project Updates".
    If it is not available, click on "New Remote Site", and input the following:
    Name: The Eclipse Project Updates
    http: http://update.eclipse.org/updates/3.3
  4. Click on "Finish"
  5. Wait for the respository index to download. Once it does, search for "Eclipse Java Development Tools" or "JDT" and select it. Click next.
  6. Follow the installation process until the JDT has been installed.

Step 2: Create your resource bundle files

For the purposes of this recipe, we will be using three language: United States English, German, and Mexican Spanish. While the explicit location may be defined anywhere, it is convenient to place our resource bundles in the project source directory since those assets will be automatically copied to any debug or release directory.

Create a directory called locale in the project's src directory, and three child directories named en_US, de_DE, and es_MX. In each of these directories, create a file called application.properties. For more information on the formatting and multiplicity of these files please read the documentation. In simplest terms, we can have as many of these files as we wish, as long as they are consistent across languages and follow basic info file formatting rules.

A sample resource properties file may look as follows. I have included a sample folder structure in the attached Examples.zip project file.

# Content of /src/locale/en_US/application.properties
helloWorld=Hello World!
howAreYou=How Are You Doing?

Step 3: Create a Build File

Ant runs everything from a build file. To create one, right-click on your project directory root and select New > File, calling your file build.xml. This is the default xml file which will be invoked whenever Ant is run in the project directory. Once you have created the file, open it and add the following basic information:

<project name="Localization Resource Compiler" default="build">

	<!-- Default Build Target. -->
	<target name="build">

	</target>

</project>

This creates a basic build file, an initial build target, and tells it that the default build target is the same.

Step 4: Set Global Flex Parameters

The Flex SDK comes with a library of pre-created ant libraries that assist in the creation of build scripts. These include Ant targets for the various Flex compilers mxmlc, compc, as well as a target which will auto-generate an html wrapper. To include these, we have to tell the build script where they are, as well as where the root directory for the currently used Flex SDK is. In this example, we're using the Flex 3.1.0 SDK. As you can see below, it is easy to swap to a different SDK. I have added a parameters called threads.maximum which also allows us to take advantage of Ant's multithreading capability which can greatly improve the speed of your compile, though it will consume a proportionally larger amount of resources.

The FLEX_HOME property is required by all of the imported Flex Tasks. Furthermore, it should be noted that the flexTasks.jar file has not changed its location in all Flex SDK's since 2.0.1, allowing you to switch SDK's by simply changing the path of FLEX_HOME.

<!-- Flex SDK Properties -->
<property name="FLEX_HOME" value="/Applications/Adobe Flex Builder 3 Plug-in/sdks/3.1.0" />

<!-- Import Flex Ant Tasks -->
<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />

<!-- Threading Properties -->
<property name="threads.maximum" value="4" />

Step 5: Create a Localization Macro

A Macro in Ant is equivalent to a function in Flex- it allows you to parameterize a series of commands which may be invoked multiple times. Of note are the following properties:

<macrodef> - This tag defines the name and description of your ant macro.

<attribute> - This tag allows you to set 'function parameters' and defaults for the macro. For this macro we are setting one property named "locale", which lets us invoke the macro for different locales at each invocation.

<mxmlc> - This is the imported mxmlc task from flexTasks.jar. For more information on the options available please refer to the documentation. Here we are making use of the basic parameters necessary to compile our localization resources.

<locale> - This tag makes use of the locale attribute to tell the compiler which locale to compile. Note that in many of the following properties we are setting the source and destination path to /src/locale/* - these paths are required, but do not necessarily need to be the same as the ones I have specified.

<source-path> - While this tag might appear to use an Ant parameter, in reality it does not. The {locale} component of the path provided is a text replacement hash used by mxmlc to point itself at the proper directory for the resource bundles.

<include-resource-bundles> - This tag may be used several times, and allows you to set multiple resources to compile into a single resource bundle. For instance, if you have resources named 'application.properties', 'menu.properties' and 'errors.properties', you can include this tag once for 'application', 'menu', and 'errors'.

<macrodef name="compileLocale" description="Compiles the Resource package for the given locale">
	<attribute name="locale" default="en_US"/>
	<sequential>
		<!--
		Create the Flex Home directory for the language in question.
		This is necessary to compensate for a bug in pre-3.2 releases of 
		mxmlc.
		-->
		<mkdir dir="${FLEX_HOME}/frameworks/locale/@{locale}"/>
	
		<!-- Invoke MXMLC -->
		<mxmlc output="${basedir}/src/locale/Resources_@{locale}.swf">
			<locale>@{locale}</locale>
			<source-path path-element="src/locale/{locale}"/>
			<include-resource-bundles>application</include-resource-bundles>
			<source-path path-element="${FLEX_HOME}/frameworks"/>
		</mxmlc>
		
	</sequential>
</macrodef>

Step 6: Invoke the Macro

Now that we have completed our macro, we need to make sure it is invoked when the build file is executed. For extra speed in our compile, we will add the <parallel> task so that we can take advantage of Ant's multithreading capabilities. Modify your initial build task to read the following:

<target name="build">
	<echo>Building Localization .swf's</echo>
	<parallel threadCount="${threads.maximum}">
		<compileLocale locale="en_US" />
		<compileLocale locale="de_DE" />
		<compileLocale locale="es_MX" />
	</parallel>
</target>

Note that I am using the previously created macro as a simple task, and am passing a different locale for each.

Step 7: Run your Ant Build File

To invoke your Ant Build Script, simply right-click on the file in Flex builder and select Run As > Ant Build. This will execute the build script and compile all your resources to the /src/locale/ directory, ready to be loaded by ResourceManager.loadResourceModule().

The Complete Build File

I have included a complete example build file below. You can use this file verbatim and modify it to your needs, or download the included Examples.zip file attached at the bottom of this recipe.

<project name="Localization Resource Compiler" default="build">

	<!-- Flex SDK Properties -->
	<property name="FLEX_HOME" value="/Applications/Adobe Flex Builder 3 Plug-in/sdks/3.1.0" />

	<!-- Threading Properties -->
	<property name="threads.maximum" value="4" />

	<!-- Import Flex Ant Tasks. -->
	<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />

	<!-- Default Build Target. -->
	<target name="build">
		<echo>Building Localization .swf's</echo>
		<parallel threadCount="${threads.maximum}">
			<compileLocale locale="en_US" />
			<compileLocale locale="de_DE" />
			<compileLocale locale="es_MX" />
		</parallel>
	</target>

	<!-- Compiles Localization Resource Bundle. -->
	<macrodef name="compileLocale" description="Compiles the Resource package for the given locale">
		<attribute name="locale" default="en_US"/>
		<sequential>
			<!--
			Create the Flex Home directory for the language in question.
			This is necessary to compensate for a bug in pre-3.2 releases of 
			mxmlc.
			-->
			<mkdir dir="${FLEX_HOME}/frameworks/locale/@{locale}"/>
			
			<!-- Invoke MXMLC -->
			<mxmlc output="${basedir}/src/locale/Resources_@{locale}.swf">
				<locale>@{locale}</locale>
				<source-path path-element="src/locale/{locale}"/>
				<include-resource-bundles>application</include-resource-bundles>
				<source-path path-element="${FLEX_HOME}/frameworks"/>
			</mxmlc>
		</sequential>
	</macrodef>
</project>
Examples.zip
[Sample Flex Project which demonstrates this recipe. Use "Import Project" in Flex to load this file.]
Report abuse

Related recipes