What’s the problem?
Just implementing resource bundles to localize your application doesn’t quite cut it. You need to do things like work with localized dates in the browser (including formatting), numbers, currencies, and who knows what else to munge your data. It sure would be nice if there were a way to transparently make this happen in a message oriented way that does not require server side awareness for services, can you help me with this problem? sure.
Built in ‘ization’ support in Appcelerator
Globalization (G11N) and Localization (L10N) both get lumped into Internationalization (I18N) - how to deal with languages, time, data formats and everything else that goes on making it so that people in different places in the world can use your glorious application. Appcelerator localization helps you out with this on some really simple levels with the langid attribute:
<span langid="account.number.title"></span>:<input type="text"></input>
This should arm you successfully with an ability to deal with things like simple messages and labeling in your application. Now if you want to blend in your data payload to render localized text, you can make use of appcelerator javascript functions Appcelerator.Localization.get and the more powerful but less documented Appcelerator.Localization.getWithFormat.
<script> var en_lang_bundle = { "invalidlogin.message": "Dear sir/madame, the username you provided '#{username}' does not exist:" } Appcelerator.Localization.addLanguageBundle("en",English",$H(en_lang_bundle)); </script> <span on="l:invalidlogin.response then value[text]"></span> <app:script on="r:invalidlogin.response then execute"> var text = Appcelerator.Localization.getWithFormat('invalidlogin.message', null,null,{username:'azuercher'}); $MQ('l:invalidlogin.response',{text:text}); </app:script>
This is a nice way to use message indirection for munging messages, but really is quite messy and anything but transparent. There must be a better way!
Interceptors
A lesser known feature of Appcelerator is the concept of interceptors - client side behavior that you can have play in-between the delivery of queued messages to their recipients. In the case for client-2-server orchestration all server requests and their corresponding response messages are enqueued and subject to perversion by interceptors. You just have to know how to implement them. Lets say that whenever I send a CRUD request to the server called ‘r:createorder.request’ I want to add a new attribute called last_modified_utc which is a numerical representation of a utc date as a long. I can add that to the payload to the back end service completely transparently with the Appcelerator.Util.ServiceBroker.addInterceptor method - the method takes a callback to the following:
- interceptQueue - where requests from client to server are intercepted
- interceptSendToListener - where responses from server to client are intercepted
In the example below I
- add ‘last_modified_utc’ as a current utc long to r:createorder.request which is consumed by my back end service
- transform ‘last_modified_utc’ in the r:createorder.response from utc to a localized string in the browser
<app:script> var interceptor = { interceptQueue: function(msg, callback, messageType, scope) { if (messageType=='remote:createorder.request') { msg.data.last_modified_utc = new Date().getTime(); } return true; }, interceptDispatch: function (requestid, type, data, datatype) { return true; }, interceptSendToListener: function (listener, messageType, data, datatype) { if (messageType=='createorder.response') { date = new Date(data.last_modified_utc); data.last_modified = date.toString(); } return true; } }; Appcelerator.Util.ServiceBroker.addInterceptor(interceptor); $MQ('r:createorder.request',{hi:'there'}); </app:script>
Obviously, you can take this a step further and then add interceptors that munge your data conditionally based on the current locale defined in Appcelerator.Localization. The benefit here is that this data transformation happens at a layer outside of my normal pub/sub for messages in Appcelerator - the normal pattern is to either replace or add attributes in the payload.
wrap up
Although not a shrink wrapped solution for I18N in all its glory, its not hard to implement interceptors to do so. Beyond I18N, a lot of other aspects for your messages can be mutated in the browser non-intrusively. Although the key demonstration here is data transformation, you would potentially add other horizontal services into your application.
this article cross-posted at http://blog.zuerchtech.com/2008/10/13/using-appcelerator-interceptors-for-i18n-l10n-g11n
Popularity: 7% [?]

October 20th, 2008 at 10:55 pm
looking forward for more information about this. thanks for sharing. Eugene