FlexStore Revisited (with BabelFx)

Christophe Coenraets published a Flex4 update to the classic FlexStore application in his recent blog FlexStore Revisited. The Phone catalog data is actually loaded from an external XML file and a Filter bar allows users “quick filters” for rapid browsing. In the Flex 4 SDK version, he demonstrated the use of tile layouts and Spark DataGroups and experimented with cool hover effects in the “store” catalog display.

I will to demonstrate how easy it is to use the BabelFx framework (aka l10nInjection) to add multi-language ( l10n ) support to his FlexStore4 application. It is shockingly easy and results in an application (shown below) that is fun to demo.

With the BableFx solution, online visitors can now browse the FlexStore Phone catalog in English, Spanish, French, or Chinese. Meanwhile developers can continue with code implementation and enhancement efforts without almost no concerns for i18n requirements.

l10n FlexStore (Flex 4 SDK)
Figure 1: FlexStore Revisited with l10n (click to launch)

Source code is available for the application shown above. Simply right-click to see the “View Source” option. In order to add localization (l10n) features to the FlexStore, I needed to perform five (5) tasks to enable the application to support multi-languages:

  1. Include the BabelFx.swc framework in the FlexStore4 project
  2. Create an BabelFx LocalizationMap to specify which keys are used to inject resources into which targets.
  3. Compile and embed the resourceBundles inside the deployed swf.
  4. Translate the catalog.xml phone data to 4 localized versions

The ONLY changes to the FlexStore source code was in the FlexStore4.mxml application source (shown below). Only 2 lines (14 and 17)… only 2 MXML tags. No other source code was changed. And yet now the application displays the Phone catalog information in four different locales.

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
53
54
<?xml version="1.0" encoding="utf-8"?>
<s:Application width="500" height="704" 
			   applicationComplete="catalogLoader.send()" 
			   viewSourceURL="srcview/index.html" 
			   xmlns:local="*" 
			   xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" 
			   xmlns:tiles="store.layouts.*" >
 
 
	<fx:Declarations>
		<s:HTTPService 					id="catalogLoader" url="assets/data/catalog.xml" result="onCatalogLoaded(event)"/>
		<l10nInjection:LocalizationMap 	id="injectors"	   phone="{_selectedPhone}"            xmlns:l10nInjection="l10n.map.*" />	</fx:Declarations>
 
	<l10n:LanguageBar id="barLang" right="19" left="19"   y="644" height="40" xmlns:l10n="l10n.views.*"/>
 
	<!-- Phone Catalog Display Area -->
	<s:Label id="lblCatalog" x="25" y="102" text="Catalog:" alpha=".3"/>
	<s:BorderContainer y="119" height="381" backgroundColor="#EDEDED" left="20" right="20">
		<s:DataGroup width="100%" height="100%" x="0" y="0"
					 dataProvider="{_items}" 
					 itemRenderer="store.renderers.Phone_Zoom" 
					 mouseMove="onHoverPhone(event);" 
					 contentBackgroundColor="#EDEDED" >
			<s:layout>
				<tiles:FilteredTileLayout id="filterLayout" filteredItems="{_filteredItems}" />
			</s:layout>
		</s:DataGroup>
	</s:BorderContainer>
 
	<s:Label id="lblDescription" x="25" y="514" text="Description:" alpha=".3" visible="{_selectedPhone != null}"/>
	<s:TextArea id="txtPhoneDescription" 
				alpha="{_selectedPhone ? 1 : .2}"
				text="{_selectedPhone ? _selectedPhone.description : ''}"
				top="532" left="20" right="20" 
				editable="false"  contentBackgroundColor="#EDEDED" color="#3D3D3D" 
				paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"  height="100"/>
 
	<!-- Catalog Filter Options -->
	<mx:Canvas height="63" backgroundColor="#FAD1D1" borderAlpha="1.0" cornerRadius="5" borderColor="#080000" left="20" right="20" top="20" horizontalScrollPolicy="off" verticalScrollPolicy="off">
		<s:Label id="lblFilters" x="15" y="9" text="Filter Catalog:" color="#921010"/>
		<s:HGroup verticalAlign="middle" paddingLeft="8" x="6" y="30" height="28" >
			<s:Label id="lblMaxPrice" text="Max Price:" fontSize="11"/>
			<s:HSlider id="priceSlider" minimum="0" maximum="1000" snapInterval="100" value="@{_maxPrice}" change="onFiltersChanged()"/>
			<mx:Spacer width="20"/>
			<s:CheckBox id="chbxCamera"  label="Camera" selected="@{_camera}" change="onFiltersChanged()" fontSize="11"/>
			<s:CheckBox id="chbxVideo"   label="Video" selected="@{_video}" change="onFiltersChanged()" fontSize="11"/>
			<s:CheckBox id="chbxTriband" label="Triband" selected="@{_triband}" change="onFiltersChanged()" fontSize="11"/>
		</s:HGroup>
	</mx:Canvas>
 
</s:Application>

The LocalizationMap instance handles all of the complexities and issues of supporting multiple languages and resource bundles, updating your view code, responding to view state changes, data model changes, and more… Note that when the locale changes, the localized version of the XML data is also reloaded; see line 29. Each localized data file actually has a different set of phones in the catalog. When switching locales, the visitor can easily see the Phone display update along with localized text.

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
<?xml version="1.0" encoding="utf-8"?>
<LocaleMap 	xmlns="http://com.asfusion.mate/l10n"
			xmlns:mx="http://www.adobe.com/2006/mxml" >
 
	<mx:Metadata>
	<!--
		Using compiler arguments -locale=en_US,es_ES,fr_FR,zh_CN -allow-source-path-overlap=true -source-path+=locale/{locale}
	    with the metaTag below forces the compiler to EMBED the compiled resource bundles
	-->
	[ResourceBundle("store")]
	</mx:Metadata>
 
	<mx:Script>
		<![CDATA[
		import l10n.views.LanguageBar;
 
		[Bindable] 
		public var phone : Object = null;
 
		/**
		 *  EventHandler when locales change to new Catalog xml data to be loaded
		 *  This xml data has localized versions of the catalog.
		 */
		private function onLocaleChanged(event:Event):void {
			var sri : SmartResourceInjector  = (event.target as SmartResourceInjector);
			var app : FlexStore4             = sri.targetInstances[0] as FlexStore4;
 
			// Dynamically reload the XML data with localized text for each Phone catalog entry
			if (app != null) app.catalogLoader.send();		}			
		]]>
	</mx:Script>
 
	<SmartResourceInjector bundleName="store" target="{FlexStore4}" localeChange="onLocaleChanged(event);">
		<ResourceProxy property="catalogLoader.url" 			key="data.url" />
 
		<ResourceProxy property="lblDescription.text" 			key="details.title" parameters="{[phone.name]}"/>
		<ResourceProxy property="lblCatalog.text" 				key="catalog.title" />
 
		<ResourceProxy property="lblFilters.text" 				key="filters.title" />
		<ResourceProxy property="lblMaxPrice.text" 				key="filters.maxPrice" />
		<ResourceProxy property="chbxCamera.label" 				key="filters.option.camera" />
		<ResourceProxy property="chbxVideo.label" 				key="filters.option.video" />
		<ResourceProxy property="chbxTriband.label" 			key="filters.option.triband" />
	</SmartResourceInjector>
 
	<SmartResourceInjector bundleName="store" target="{LanguageBar}">
		<ResourceProxy property="lblBarHelp.text" 	key="languagebar.title" />
	</SmartResourceInjector>
 
</LocaleMap>

Another interesting addition is LanguageBar.mxml. The LanguagBar view component provides a visual toolbar to allow visitors to dynamically switch to alternate locales. I encourage the reader to check out the LanguageBar to see how the bar is constructed dynamically from a list of embedded resources. Note that selecting a Flag button in the LanguageBar dispatches a LocaleEvent.LOAD_LOCALE event, BabelFx responds, and “magic” happens to the entire FlexStore application.

A great, hidden feature of the new BabelFx framework is auto-detection. At application startup, BabelFx will auto-detect the visitors OS language preference and auto-switch the FlexStore to match the visitor’s locale/language settings (if that locale has been embedded).

I encourage developers to check out the GitHub repository for samples and the framework source code.

Last, but not least, I will be presenting an BabelFx/l10nInjection session at the upcoming cf.Objective( ) 2010 conference (Minneapolis, MN April 22-24, 2010). Below are the slides that will be presented that detail the issues with i18n and the processes within BabelFx.



GD Star Rating
loading...

2 Responses to “FlexStore Revisited (with BabelFx)”

  1. In order to support multiple languages in our Flex application we were looking for a localization framework which could also be used to together with the Flex Mate framework. We ran into the I10nInjection framework and first created a proof-of-concept in order to check whether the framework was of any use for us.

    We found out that by using the I10nInjection framework our need for multilanguage was easy fulfilled. We then applied the framework to our large commercial application with success! Localizing an application was never so easy! We ran into some minor issues due to edge-cases with using l10nInjection in our application, but they were fixed immediately.

    I would recommend this framework to anyone who wants to implement localization in a Flex application.

  2. Social comments and analytics for this post…

    This post was mentioned on Twitter by ChromeLocalizer: FlexStore Revisited (with #i18n) – http://bit.ly/bkaoJo...

Leave a Reply

GD Star Rating
loading...

Please leave these two fields as-is:

Protected by Invisible Defender. Showed 403 to 2,816 bad guys.