Monday, October 8, 2012

Extjs i18n

http://gaver.dyndns.org/elmasse/site/index.php/blog/4-posts/10-i18nbundle-resource-bundle-extjs-extension-



Ext.i18n.bundle - Resource Bundle ExtJS extension




This is a Resource Bundle implementation for ExtJS. What's a Resource Bundle? This idea comes from Java world where you can separate all the locale based information from the source code. This helps to maintain the source code and facilitates the translations.
In this version of Ext.i18n.Bundle you can store only Strings. A Bundle file is a properties file where you store your key-value pairs. Every bundle has a hierarchical naming structure based on the language selected. Let's take for example a bundle named 'Application', the Ext.i18n.Bundle component will try to find first the specific language file. If no language is specified, it will guess the language based on the browser settings. Let's assume that your browser language is english US, so the bundle file name will be

Application_en-US.properties

If that file doesn't exists, it will try to load the default file:

Application.properties

Note: For those who are familiar with Java Resource Bundles, this is not exactly the same implementation. This component will only load one properties file. This means that if you don't store a key-value in the loaded file it wont be searched from the parent file, which is the behavior in Java.

Implementation

Constructor
The Ext.i18n.Bundle has a few parameters in the constructor. Most of them are optional.

Ext.i18n.Bundle(config)

config:

    bundle: {String} the bundle name.
    path: {String} the uri to the resource folder where the properties files are stored. Optional.
    lang: {String} the language code. It must be in the format xx-YY where xx specifies the 2 character language code (lowercase) and YY is the 2 characters country code (uppercase). Example: 'en-US'. Optional. Default to the browser language.
    method: {String} the method used by the HttpProxy to retrieve the files. Optional. Default to 'GET'.



Methods
Ext.i18n.Bundle has a few methods.

onReady(function)
This method must be executed in order to get access to the bundle. All the code that need to access to the bundle must be executed into the function.

    function: {Function} The function that contains all the code that will reference to bundle.



getMsg(key)
This method returns the content associated with the passed key. If the key cannot be found then it returns {key}.undefined

    key: {String} the bundle key



Let's see an example

In this example I will show you the basic usage of the component. You can find this example code into the zip file with the sources.
    Ext.onReady(function(){
        var bundle = new Ext.i18n.Bundle({bundle:'Application', path:'resources'}); //#1
        bundle.onReady(function(){
   
            var panel = new Ext.Panel({
                renderTo: 'panelTest',
                title: bundle.getMsg('panel.title'),  //#2
                height: 300,
                width: 800,
                html: bundle.getMsg('panel.html') //#3
            });
            
        }); //bundle.onReady
    });

In this code we create the bundle component associated with 'Application' bundle file. At #1 we just defined the bundle name and the path where we store or expose our properties files. In this case the files will be loaded from http://{your.domain}/resources . If the browser language is en-US, then the resources/Application_en-US.properties file will be loaded. And, if it cannot be found, then resources/Application.properties file will be loaded.
My Application_en-US.properties looks like:

panel.title "'panel title with quotes'"
panel.html "Something goes here!"

As you can see I defined 2 key values: panel.title and panel.html. Once the file is loaded then the onReady method is executed. At this point I can access the file content. I show in #2 and #3 how to retrieve the key content.

Some considerations

First, you need to execute this code from a web container. It cannot be executed locally since we are using an HttpProxy.
Second, all the bundlelized messages will be available inside the Ext.i18n.Bundle.onReady method. This means that you can use the bundle inside that method. But, you can also use it if you define your classes in separate js files. The only restriction is that the code must be called from the onReady function. Let me show you an example:
    // Main.js
    Ext.onReady(function(){
            
        var bundle = new Ext.i18n.Bundle({bundle:'Application', path:'resources'});
        bundle.onReady(function(){
   
            var panel = new MyPanel();
            
        }); //bundle.onReady
    });
   
    //MyPanel.js
    MyPanel = function(config){
            MyPanel.superclass.constructor.call(this,{
                renderTo: 'panelTest',
                title: bundle.getMsg('panel.title'),
                height: 300,
                width: 800,
                html: bundle.getMsg('panel.html')
            });
    };
    Ext.extend(MyPanel, Ext.Panel);

This is a correct usage of the bundle component. But, if you try to use the bundle reference into a prototype definition you will get an undefined reference.
    //MyPanel.js
   
    MyPanel = Ext.extend(Ext.Panel, {
        title: bundle.getMsg('panel.title')
        //other prototype definitions...
    });
Here javascript will evaluate the bundle variable at parsing time, and there bundle is undefined yet, so you cannot access it. Anyway, if the bundle variable were defined at that time, it will not retrieve the key content until the file is loaded, which occurs inside the onReady method.

Download the code and example

Go to Downloads section in the Main Menu.




Last weekend I was working on i18n with Ext.js, and there is a feature that I miss (so much) from jsp and it is the Resource Bundle. So I realized that I should get something similar to this and I started to write an Ext.i18n.ResourceBundle. The main idea is to create an object that can get a bundle, it means that taking the resource bundle, i.e. from a resource name and the browser's language it tries to find a .properties, so if the language is es-ES it looks for the [bundle]_es-ES.properties file and if it does not exist then it reads the [bundle].properties.

Then you can get a message by the key property through the getMsg(key) method.
This is the entire code and a little example. Enjoy it!

Code and Example could be found here


Usage:

var bundle = new Ext.i18n.Bundle({bundle='Application'});
bundle.onReady(
alert('example'+ bundle.getMsg('key1'));
);

This would read:
-An Application_es-ES.properties file like this if the browser's language is es-ES:
#This is a simple comment
key1 "Mensaje para la propiedad key1"


-If the Application_es-ES.properties doesn't exist then tries to find the Application.properties file like this:
#This is a simple comment
key1 "this is the message for key1"

Bundle(config): config: {bundle: , resource:}
bundle: The bundle name for the properties file.
{bundle: 'mybundle'}
This looks for the file located in:
http:/yourdomain/yourApp/mybundle_[language].properties.
You will need at least the mybundle.properties file.


path: (optional) the path to the bundle file.
{bundle: 'mybundle, path: 'resources'}
This looks for the file located in:
http:/yourdomain/yourApp/resources/mybundle_[language].properties.


Take into account that you need to write your application in the bundle.onReady() method in order to be able to access to your bundle.

0 comments:

Post a Comment