Bookmark and Share

Lee's 程序人生

HTML CSS Javascript XML AJAX ATLAS C# C++ 数据结构 软件工程 设计模式 asp.net Java 数字图象处理 Sql 数据库
  博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

如何本地化ext

Posted on 2008-07-25 19:27  analyzer  阅读(676)  评论(0编辑  收藏  举报

引言

如果你是英语的用户就不必做任何本地化的工作了,这篇教程是为非英语用户所准备的,好像一般的用户,开发主管,业务员等,他们的外语可能稍逊,这样就需要你对如何本地化ext的整个流程了解一番了。

慢慢开始

如果你曾浏览Ext 2.x目录的树状结构,你就会发现source/locale的目录(或SVN目录的src/locale)。 此目录包含了Ext本地化类。 先不长篇大论地讲太多概念的东西,我们应了解如何先使用。


下面的一个例子就是使用了本地化的ext,但是不是在ext同一个目录下的。因此通常的,你需要调整head标签内的路径,以正确指向Ext的安装目录。尤其注意本地化的那个目录路径。

把你服务器的路径Copy and paste到相应文件路径中:

注意: 下里的代码我是动态加载到head头部的,只能在FireFox通过。不过实际情况你不必如此,你只要在服务端指定script的路径而不必动态加载。

  1<html>
  2<head>
  3    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  4    <link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
  5    <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
  6    <script type="text/javascript" src="../ext/ext-all-debug.js"></script>
  7    <script type="text/javascript">
  8 
  9    //根据url上指定的语言进行解码
 10    var locale = window.location.search 
 11                 ? Ext.urlDecode(window.location.search.substring(1)).locale 
 12                 : '';
 13 
 14    // 将本地化的JS文件加入head元素内
 15    var head = Ext.fly(document.getElementsByTagName('head')[0]);
 16    if(locale) {
 17        Ext.DomHelper.append(head, {
 18             tag:'script'
 19            ,type:'text/javascript'
 20            ,src:'../ext/src/locale/ext-lang-' + locale + '.js'
 21        }
);
 22    }

 23 
 24    //预先定义的window继承类
 25    Ext.ns('Tutorial');
 26    Tutorial.LocalizationWin = Ext.extend(Ext.Window, {
 27        initComponent:function() {
 28            Ext.apply(this{
 29                 width:500
 30                ,id:'winid'
 31                ,height:300
 32                ,layout:'fit'
 33                ,border:false
 34                ,closable:false
 35                ,title:Ext.get('title').dom.innerHTML
 36                ,items:[{
 37                     xtype:'form'
 38                    ,frame:true
 39                    ,defaultType:'textfield'
 40                    ,items:[{
 41                          xtype:'combo'
 42                         ,fieldLabel:'Select Language'
 43                         ,name:'locale'
 44                         ,store:new Ext.data.SimpleStore({
 45                             id:0
 46                            ,fields:['file''locale']
 47                            ,data:[
 48                                 ['cs''Czech']
 49                                ,['''English']
 50                                ,['fr''French']
 51                                ,['de''German']
 52                                ,['gr''Greece']
 53                                ,['hu''Hungarian']
 54                                ,['it''Italian']
 55                                ,['ja''Japaneese']
 56                                ,['pl''Polish']
 57                                ,['pt''Portugal']
 58                                ,['ru''Russian']
 59                                ,['sk''Slovak']
 60                                ,['es''Spanish']
 61                                ,['sv_SE''Swedish']
 62                                ,['tr''Turkish']
 63                            ]
 64                         }
)
 65                        ,listeners:{
 66                            select:{fn:function(combo){
 67                                window.location.search = '?' 
 68                                    + Ext.urlEncode({locale:combo.getValue()})
 69                                ;
 70                            }
}

 71                        }

 72                        ,mode:'local'
 73                        ,editable:false
 74                        ,forceSelection:true
 75                        ,valueField:'file'
 76                        ,displayField:'locale'
 77                        ,triggerAction:'all'
 78                        ,value:locale
 79                     }
,{
 80                         fieldLabel:'Text Field'
 81                        ,allowBlank:false
 82                    }
,{
 83                         xtype:'datefield'
 84                        ,fieldLabel:'Date Field'
 85                        ,allowBlank:false
 86                    }
]
 87                }
]
 88            }
); // eo apply
 89            Tutorial.LocalizationWin.superclass.initComponent.apply(this, arguments);
 90        }
 // eo function initComponent
 91    }
); // eo Tutorial.LocalizationWin
 92 
 93Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';
 94Ext.onReady(function() {
 95    Ext.QuickTips.init();
 96    Ext.form.Field.prototype.msgTarget = 'side';
 97 
 98    // create example window
 99    var win = new Tutorial.LocalizationWin();
100    win.show();
101}
);
102    
</script>
103    <title id="title">Localization Example</title>
104</head>
105<body>
106</body>
107</html>

 

现在完整的本地化工作是限于ComboBox、TextField和DateField这些Ext基础组件。试试在已翻译好的DataPicker组件中输入一些文字。

原理是??

原理是一改变cobmo box里面的"Select Language"就会包含(include)相应的Ext本地化文件(这里我使用了一些技巧性的做法,改变本地化文件的过程是用过客户端脚本完成的)

本地化文件的葫芦里卖的什么药?

首先要打开本地化文件来看看,读懂里面的源码后不但对Ext的理解有帮助而且对整个程序的本地化,也是有帮助的。我们以法语版的DatePicker为例子:

 1if(Ext.DatePicker){
 2   Ext.override(Ext.DatePicker, {
 3      todayText         : "Aujourd'hui",
 4      minText           : "Cette date est antérieure à la date minimum",
 5      maxText           : "Cette date est postérieure à la date maximum",
 6      disabledDaysText  : "",
 7      disabledDatesText : "",
 8      monthNames        : Date.monthNames,
 9      dayNames          : Date.dayNames,
10      nextText          : 'Mois suivant (CTRL+Flèche droite)',
11      prevText          : "Mois précédent (CTRL+Flèche gauche)",
12      monthYearText     : "Choisissez un mois (CTRL+Flèche haut ou bas pour changer d'année.)",
13      todayTip          : "{0} (Barre d'espace)",
14      okText            : " OK ",
15      cancelText        : "Annuler",
16      format            : "d/m/y",
17      startDay          : 1
18   }
);
19}

 

 

通过观察,我们得知如果DataPicker对象存在(这是需要检测的,事因有些ext是你自己可制定的)就重写DataPicker的部分属性; 更严格说,我们是把法语的文字替换掉英语的文字而已。Ext.override的作用是在DatePicker建立实例之前改变class的原型。

应用程序的本地化

我们对范例文件略加修改,把所有的静态文本变为类成员,修改过后看起来是这样的:

  1<html>
  2<head>
  3    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  4    <link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
  5    <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
  6    <script type="text/javascript" src="../ext/ext-all-debug.js"></script>
  7 
  8    <!-- Ext localization javascript -->
  9    <script type="text/javascript" id="extlocale"></script>
 10 
 11    <!-- Locale and example extension javascript -->
 12    <script type="text/javascript">
 13 
 14    // decode language passed in url
 15    var locale = window.location.search 
 16                 ? Ext.urlDecode(window.location.search.substring(1)).locale 
 17                 : ''
 18    ;
 19 
 20    // append locale script to the head
 21    var head = Ext.fly(document.getElementsByTagName('head')[0]);
 22    if(locale) {
 23        Ext.fly('extlocale').set({src:'../ext/src/locale/ext-lang-' + locale + '.js'});
 24    }

 25 
 26    // create pre-configured example window extension class
 27    Ext.ns('Tutorial');
 28    Tutorial.LocalizationWin = Ext.extend(Ext.Window, {
 29         titleText:'Localization Example'
 30        ,selectLangText:'Select Language'
 31        ,textFieldText:'Text Field'
 32        ,dateFieldText:'Date Field'
 33        ,initComponent:function() {
 34            Ext.apply(this{
 35                 width:500
 36                ,id:'winid'
 37                ,height:300
 38                ,layout:'fit'
 39                ,border:false
 40                ,closable:false
 41                ,title:this.titleText
 42                ,items:[{
 43                     xtype:'form'
 44                    ,frame:true
 45                    ,defaultType:'textfield'
 46                    ,items:[{
 47                          xtype:'combo'
 48                         ,fieldLabel:this.selectLangText
 49                         ,name:'locale'
 50                         ,store:new Ext.data.SimpleStore({
 51                             id:0
 52                            ,fields:['file''locale']
 53                            ,data:[
 54                                 ['cs''Czech']
 55                                ,['''English']
 56                                ,['fr''French']
 57                                ,['de''German']
 58                                ,['gr''Greece']
 59                                ,['hu''Hungarian']
 60                                ,['it''Italian']
 61                                ,['ja''Japaneese']
 62                                ,['pl''Polish']
 63                                ,['pt''Portugal']
 64                                ,['ru''Russian']
 65                                ,['sk''Slovak']
 66                                ,['es''Spanish']
 67                                ,['sv_SE''Swedish']
 68                                ,['tr''Turkish']
 69                            ]
 70                         }
)
 71                        ,listeners:{
 72                            select:{fn:function(combo){
 73                                window.location.search = '?' 
 74                                    + Ext.urlEncode({locale:combo.getValue()})
 75                                ;
 76                            }
}

 77                        }

 78                        ,mode:'local'
 79                        ,editable:false
 80                        ,forceSelection:true
 81                        ,valueField:'file'
 82                        ,displayField:'locale'
 83                        ,triggerAction:'all'
 84                        ,value:locale
 85                     }
,{
 86                         fieldLabel:this.textFieldText
 87                        ,allowBlank:false
 88                    }
,{
 89                         xtype:'datefield'
 90                        ,fieldLabel:this.dateFieldText
 91                        ,allowBlank:false
 92                    }
]
 93                }
]
 94            }
); // eo apply
 95            Tutorial.LocalizationWin.superclass.initComponent.apply(this, arguments);
 96        }
 // eo function initComponent
 97    }
); // eo Tutorial.LocalizationWin
 98    </script>
 99 
100    <!-- Application localization javascript -->
101    <script type="text/javascript" id="applocale"></script>
102 
103    <!-- Set src for application localization javascript -->
104    <script>
105    if(locale) {
106        Ext.fly('applocale').set({src:'app-lang-' + locale + '.js'});
107    }

108    </script>
109 
110    <!-- Main application -->
111    <script type="text/javascript">
112    Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';
113    Ext.onReady(function() {
114        Ext.QuickTips.init();
115        Ext.form.Field.prototype.msgTarget = 'side';
116 
117        // create example window
118        var win = new Tutorial.LocalizationWin();
119        win.show();
120    }
);
121    </script>
122    <title id="title">Localization Example</title>
123</head>
124<body>
125</body>
126</html>

 

最后一步,我们需要为特定的语种创建程序本地化的文件(翻译,语种)。这里是app-lang-sk.js文件因为我操的是斯洛伐克语的缘故。你可因应你需求的语种去设置(保存html的格式放到同一目录下或修改上面代码的目录): 

 

 1/**
 2 * 斯洛伐克语版的教程之本地化文件
 3 */

 4if(Tutorial.LocalizationWin) {
 5    Ext.override(Tutorial.LocalizationWin, {
 6         titleText:'Príklad lokalizácie'
 7        ,selectLangText:'Zvoľ jazyk'
 8        ,textFieldText:'Textové pole'
 9        ,dateFieldText:'Dátumové pole'
10    }
);
11}

 

高级提示

请明确,要做Ext程序的本地化需要遵循哪些的原则。关键点在于将所有翻译文本作为公共类的成员出现,重写原先类的prototype的属性

Advanced developers will immediately feel some drawback of having, maintaining and deploying that many localization files especially if they already have a server with some translating infrastructure such as GNU gettext. For these users I would recommend to generate localization files on the fly by the server using gettext as backend.

这种做法最大的好处是可讲翻译文件集中在一块(*.po),客户端和服务端都可以使用。

如果本地化这主题反映还不错的话而读者又非常想进一步了解我会写进阶的Ext本地化。

Enjoy!

 

 

我要啦免费统计