i18n for Javascript

The WSO2 Carbon platform contains two UI technologies. Plain old JSPs and Javascript (DHTML/Ajax, the rich client stuff). When it comes to i18n JSPs are taken care of. In Javascript however, i18n seems a daunting task. Various Javascript libraries such as GWT, Dojo and even YUI have tried to address the issue in their own way. But when I did an evaluation last week of those, I wasn't really happy about the unnecessary complexity of their code and the additional QA overhead they will add.

So I wrote my own i18n implementation for Javascript, which will be used by all Javascript embedded components in the Carbon platform. The implementation uses both JSP and Javascript code to balance out processing overheads between the browser and server.

Server side processing is done with a JSP tag library, which reads a given Resource bundle and populates a JSON Object with the key-value pairs found within. The JSP authors can opt to either use one single Resource Bundle for all their i18n values or have a separate bundle for Javascript (JSResources.properties for instance). I recommend the latter because it will reduce the memory footprint of your i18n JSON Object.

This Tag library is named jsi18n (Apache Licensed). To include it in one's JSP, all they have to do is add the following code after including the it in their project. The library requires two parameters to be set. The mandatory 'request' parameter, which passes the ServletRequest and the 'resourceBundle' parameter which tells the library where it can find your i18n Resource Bundle in the classpath .

<carbon:jsi18n resourceBundle="org.wso2.carbon.server.admin.ui.i18n.JSResources" request="<%=request%>"/>

When the page is generated, it will contain a JSON object named jsi18n with key-value mappings found in your Resource Bundle. The tag library changes the values depending on the Browsers locale set by a user. If you view the source of a generated page after this tag library is invoked, you will see the following Javascript code embedded in it. The code below comes straight from a page in WSO2 Carbon, so the key-value pairs are specific to that page.

<script type = "text/javascript" >
var tmpPairs = '{"dialog.cancel":"Cancel","dialog.ok":"OK","graceful.shutdown.verify":"Do you really want to gracefully shutdown the server?","graceful.shutdown.error":"An error occurred while gracefully shutting down the server","graceful.shutdown.in.progress.message":"Server is being gracefully shutdown. This Management Console will no longer be accessible","restart.in.progress.message":"Server is being restarted. This Management Console will not be accessible for a few minutes.","shutdown.verification":"Do you really want to shutdown the server?","shutdown.error":"Error occurred while shutting down the server","graceful.restart.in.progress.message":"Server is being gracefully restarted. This Management Console will not be accessible for a few minutes.","graceful.restart.verification":"Do you really want to gracefully restart the server?","graceful.restart.error":"Error occurred while gracefully restarting the server","restart.verification":"Do you really want to restart the server?","restart.error":"Error occurred while restarting the server","shutdown.in.progress.message":"Server is being shutdown. This Management Console will no longer be accessible"}';

var jsi18n = YAHOO.lang.JSON.parse(tmpPairs);
</script>


Once the page is loaded, all Javascript code will have access to the jsi18n variable (the JSON object) in the above code. Therefore, to make one's Javascript messages i18ned, instead of writing

alert("Do you really want to gracefully shutdown the server?");

an author can use

alert(jsi18n["graceful.shutdown.verify"]);

in his code.

Depending on the Browser locale and the availability of a matching language Resource Bundle, the text of the above alert will change.

Comments

Why pass in the request object when taglibs already have access to it?
And one improvement would be to allow place holders in the string and let parameters to be passed in as we do in the jsp i18n case. Then the message can be composed using in the UI using the string and the passed parameters. Even though it may make this a bit complex, it will allow the messages to be truly i18n with a proper meaning in a particular language.
Jeroen Wyseur said…
You mention the jsi18n code is GPL licensed. Where could I find it? I need something almost like that.

I would still add a filter to only retrieve certain keys of the resourcebundle.
Tyrell said…
@Jeroen

Actually it's Apache Licensed even lesser restrictions than GPL :)

I didn't have time to extract the code out. But feel free to have a look in WSO2 Carbon code base.

The TagLib java code can be found at https://wso2.org/svn/browse/wso2/trunk/carbon/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/taglibs/JSi18n.java?revision=27227&content-type=text%2Fplain

The tld definition can be found at the end of the tld file found at https://wso2.org/svn/browse/wso2/trunk/carbon/org.wso2.carbon.ui/src/main/resources/web/WEB-INF/tlds/carbontags.tld?view=co

There's a dependency on YUI JSON library as you will see when going through the code. You need to add those two javascript imports too before using JSi18n

Hope this helps!

Popular Posts