Pages

搜尋此網誌

2013年12月25日 星期三

extjs 在 sencha Architect 中的多語系處理

extjs 在 sencha Architect 中的多語系處理

關於 extjs 的多語系處理,我們可以參考下列網址:Quick add multiple language to extjs + grails application,或者你可以使用別人寫的 extjs-locale-loader

基本的概念是, 你可以將你的語系資料定義在一個全域的 json Object,如此一來就可以在需要顯示對應語系的地方替換成 json object 裡面的某個屬性,但是在使用 Architect 時,有些屬性不一定可以透過他進行調整,比如說我們希望調整 Panel.title,在 Architect 你只能在 title 的屬性輸入文字屬性不能輸入變數,就算輸入了也會被當字串處理,這狀況確實令人苦惱,不過在遍尋相關資料後,總算讓筆者找到解法,就在官方的文件中關於 config_panel 說明中 Using Variables with Configs 章節,概念上是:title 雖然不能調整資料的類型,但我們可以在任一元件新增 Process config 他會建立一個函式,在裡面可以對 config 進行裡面的欄位調整,光看文件的說明很難想像到底是如何運作,我們可以來看實際產生的程式碼,在還未加入 Process config 之前:


Ext.define('foodprint.view.ItemEditor', {
    extend: 'Ext.tab.Panel',
    alias: 'widget.itemeditor',
    itemId: 'itemEditor',
    activeTab: 0,

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            items: [
                {
                    xtype: 'panel',
                    layout: {
                        align: 'stretch',
                        type: 'vbox'
                    },
                    title: 'list',
                    items: [
                        {
                            xtype: 'itemgrid'
                        }
                    ]
                },
                {
                    xtype: 'panel',
                    layout: {
                        align: 'stretch',
                        type: 'vbox'
                    },
                    title: '資料維護',
                    items: [
                        {
                            xtype: 'itemviewer',
                            flex: 1
                        }
                    ]
                }
            ]
        });

        me.callParent(arguments);
    }

});

很標準的寫法,我們在 initComponent 將我們需要的加入的元件定義好,其中包括 title 是一個文字 ‘list’,也就是我們沒辦法利用 Arcitect 修改的地方,接著我們來看加入 Process config 之後的程式碼:

Ext.define('foodprint.view.ItemEditor', {
    extend: 'Ext.tab.Panel',
    alias: 'widget.itemeditor',
    itemId: 'itemEditor',
    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            items: [
                me.processLocalized({
                    xtype: 'panel',
                    layout: {
                        align: 'stretch',
                        type: 'vbox'
                    },
                    title: 'list',
                    items: [
                        {
                            xtype: 'itemgrid'
                        }
                    ]
                }),
                {
                    xtype: 'panel',
                    layout: {
                        align: 'stretch',
                        type: 'vbox'
                    },
                    title: '資料維護',
                    items: [
                        {
                            xtype: 'itemviewer',
                            flex: 1
                        }
                    ]
                }
            ]
        });

        me.callParent(arguments);
    },

    processLocalized: function(config) {
        config.title=foodprint.string.list;
        return config;
    }

});

一旦加入了 Process config 之後可以看到在 initComponent 這個函式中他將 json object 作為參數傳入 processLocalized 如此一來我們就可以在該函式進行所謂的語系替換,也就可以做到將 title 替換成變數,就解決了沒辦法調整 title 資料型態的窘境。

接著,我們就可以定義我們的語系檔,範例如下:

var foodprint = {};  
foodprint.string = {};  
foodprint.string.list = "瀏覽清單";  

並且在 Architect 中引入該 js 檔案,如圖:

link

至於動態載入不同的語系檔,這邊就不做探討,那是另一個議題,網路上也有一些解法,就先留給各位讀者研究囉。

另外關於語系的處理,我們可以用到 extjs 對於 javascript 的String 類別的強化,參考 API:Ext.String-method-format,對於一些訊息的呈現我們可以將相關參數傳進去,如此在定義語系時,變數的位置就可以被空下來,使用 extjs 原生的函式進行替換,使用方式可參考範例:

var cls = 'my-class',
    text = 'Some text';
var s = Ext.String.format('<div class="{0}">{1}</div>', cls, text);
// s now contains the string: '<div class="my-class">Some text</div>'

一開始發現此問題時,直覺反應是這也太不方便了吧!不過在體驗了這樣的作法之後,又覺得這樣做真的很神奇,好處是語系的替換不會散佈在程式碼各處,透過不同函式負責不同的處理,一旦需要新增語系也可以有一致的處理方式,另外在 Architect 進行開發時,畫面上的呈現也可以是簡單易讀的明確文字,確實是兼顧可讀性的處理方式,給大家參考,若有更好的方式也請讓我知道!

張貼留言