ExtJS的默认语言是 English , 但我们的用户不一定是 English-using ,所以我们要面临本地化的问题。本地化的思想很简单,为非是替换掉显示给用户的文字。本地化不简单,涉及到多方面,比如:乱码问题。
先转一篇文章:
(文章源地址:http://www.sencha.com/learn/legacy/Tutorial:Localizing_Ext_(Chinese)
【这里也有转载http://www.iteye.com/topic/186973】)
(英文原版:http://www.sencha.com/learn/legacy/Tutorial:Localizing_Ext)
通常的,你需要调整head标签内的路径,以正确指向Ext的安装目录。尤其注意本地化文件的那个目录路径。(source/locale的目录 或SVN目录的src/locale)。
注意: 下里的代码我是动态加载到head头部的,只能在FireFox通过。不过实际情况你不必如此,你只要在服务端指定script的路径而不必动态加载。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
<script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext/ext-all-debug.js"></script>
<script type="text/javascript">
//根据url上指定的语言进行解码
var locale = window.location.search
? Ext.urlDecode(window.location.search.substring(1)).locale
: '';
// 将本地化的JS文件加入head元素内
var head = Ext.fly(document.getElementsByTagName('head')[0]);
if(locale) {
Ext.DomHelper.append(head, {
tag:'script'
,type:'text/javascript'
,src:'../ext/src/locale/ext-lang-' + locale + '.js'
});
}
//预先定义的window继承类
Ext.ns('Tutorial');
Tutorial.LocalizationWin = Ext.extend(Ext.Window, {
initComponent:function() {
Ext.apply(this, {
width:500
,id:'winid'
,height:300
,layout:'fit'
,border:false
,closable:false
,title:Ext.get('title').dom.innerHTML
,items:[{
xtype:'form'
,frame:true
,defaultType:'textfield'
,items:[{
xtype:'combo'
,fieldLabel:'Select Language'
,name:'locale'
,store:new Ext.data.SimpleStore({
id:0
,fields:['file', 'locale']
,data:[
['cs', 'Czech']
,['', 'English']
,['fr', 'French']
,['de', 'German']
,['gr', 'Greece']
,['hu', 'Hungarian']
,['it', 'Italian']
,['ja', 'Japaneese']
,['pl', 'Polish']
,['pt', 'Portugal']
,['ru', 'Russian']
,['sk', 'Slovak']
,['es', 'Spanish']
,['sv_SE', 'Swedish']
,['tr', 'Turkish']
]
})
,listeners:{
select:{fn:function(combo){
window.location.search = '?'
+ Ext.urlEncode({locale:combo.getValue()})
;
}}
}
,mode:'local'
,editable:false
,forceSelection:true
,valueField:'file'
,displayField:'locale'
,triggerAction:'all'
,value:locale
},{
fieldLabel:'Text Field'
,allowBlank:false
},{
xtype:'datefield'
,fieldLabel:'Date Field'
,allowBlank:false
}]
}]
}); // eo apply
Tutorial.LocalizationWin.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
}); // eo Tutorial.LocalizationWin
Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';
Ext.onReady(function() {
Ext.QuickTips.init();
Ext.form.Field.prototype.msgTarget = 'side';
// create example window
var win = new Tutorial.LocalizationWin();
win.show();
});
</script>
<title id="title">Localization Example</title>
</head>
<body>
</body>
</html>
本地化文件的葫芦里卖的什么药?
首先要打开本地化文件来看看,读懂里面的源码后不但对Ext的理解有帮助而且对整个程序的本地化,也是有帮助的。我们以法语版的DatePicker为例子:
if(Ext.DatePicker){
Ext.override(Ext.DatePicker, {
todayText : "Aujourd'hui",
minText : "Cette date est antérieure à la date minimum",
maxText : "Cette date est postérieure à la date maximum",
disabledDaysText : "",
disabledDatesText : "",
monthNames : Date.monthNames,
dayNames : Date.dayNames,
nextText : 'Mois suivant (CTRL+Flèche droite)',
prevText : "Mois précédent (CTRL+Flèche gauche)",
monthYearText : "Choisissez un mois (CTRL+Flèche haut ou bas pour changer d'année.)",
todayTip : "{0} (Barre d'espace)",
okText : " OK ",
cancelText : "Annuler",
format : "d/m/y",
startDay : 1
});
}
通过观察,我们得知如果DataPicker对象存在(这是需要检测的,事因有些ext是你自己可制定的)就重写DataPicker的部分属性;更严格说,我们是把法语的文字替换掉英语的文字而已。Ext.override的作用是在DatePicker建立实例之前改变class的原型。 应用程序的本地化
我们对范例文件略加修改,把所有的静态文本变为类成员,修改过后看起来是这样的:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
<script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext/ext-all-debug.js"></script>
<!-- Ext localization javascript -->
<script type="text/javascript" id="extlocale"></script>
<!-- Locale and example extension javascript -->
<script type="text/javascript">
// decode language passed in url
var locale = window.location.search
? Ext.urlDecode(window.location.search.substring(1)).locale
: ''
;
// append locale script to the head
var head = Ext.fly(document.getElementsByTagName('head')[0]);
if(locale) {
Ext.fly('extlocale').set({src:'../ext/src/locale/ext-lang-' + locale + '.js'});
}
// create pre-configured example window extension class
Ext.ns('Tutorial');
Tutorial.LocalizationWin = Ext.extend(Ext.Window, {
titleText:'Localization Example'
,selectLangText:'Select Language'
,textFieldText:'Text Field'
,dateFieldText:'Date Field'
,initComponent:function() {
Ext.apply(this, {
width:500
,id:'winid'
,height:300
,layout:'fit'
,border:false
,closable:false
,title:this.titleText
,items:[{
xtype:'form'
,frame:true
,defaultType:'textfield'
,items:[{
xtype:'combo'
,fieldLabel:this.selectLangText
,name:'locale'
,store:new Ext.data.SimpleStore({
id:0
,fields:['file', 'locale']
,data:[
['cs', 'Czech']
,['', 'English']
,['fr', 'French']
,['de', 'German']
,['gr', 'Greece']
,['hu', 'Hungarian']
,['it', 'Italian']
,['ja', 'Japaneese']
,['pl', 'Polish']
,['pt', 'Portugal']
,['ru', 'Russian']
,['sk', 'Slovak']
,['es', 'Spanish']
,['sv_SE', 'Swedish']
,['tr', 'Turkish']
]
})
,listeners:{
select:{fn:function(combo){
window.location.search = '?'
+ Ext.urlEncode({locale:combo.getValue()})
;
}}
}
,mode:'local'
,editable:false
,forceSelection:true
,valueField:'file'
,displayField:'locale'
,triggerAction:'all'
,value:locale
},{
fieldLabel:this.textFieldText
,allowBlank:false
},{
xtype:'datefield'
,fieldLabel:this.dateFieldText
,allowBlank:false
}]
}]
}); // eo apply
Tutorial.LocalizationWin.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
}); // eo Tutorial.LocalizationWin
</script>
<!-- Application localization javascript -->
<script type="text/javascript" id="applocale"></script>
<!-- Set src for application localization javascript -->
<script>
if(locale) {
Ext.fly('applocale').set({src:'app-lang-' + locale + '.js'});
}
</script>
<!-- Main application -->
<script type="text/javascript">
Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';
Ext.onReady(function() {
Ext.QuickTips.init();
Ext.form.Field.prototype.msgTarget = 'side';
// create example window
var win = new Tutorial.LocalizationWin();
win.show();
});
</script>
<title id="title">Localization Example</title>
</head>
<body>
</body>
</html>
最后一步,我们需要为特定的语种创建程序本地化的文件(翻译,语种)。这里是app-lang-sk.js文件因为我操的是斯洛伐克语的缘故。你可因应你需求的语种去设置(保存html的格式放到同一目录下或修改上面代码的目录):
/**
* 斯洛伐克语版的教程之本地化文件
*/
if(Tutorial.LocalizationWin) {
Ext.override(Tutorial.LocalizationWin, {
titleText:'Príklad lokalizácie'
,selectLangText:'Zvoľ jazyk'
,textFieldText:'Textové pole'
,dateFieldText:'Dátumové pole'
});
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果仅仅使用的话添加如下就可以了:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title>Hello ExtJS</title>
<link rel="stylesheet" type="text/css" href="../plugins/ext_3_3_0/resources/css/ext-all.css" />
<script type="text/javascript" src="../plugins/ext_3_3_0/adapter/ext/ext-base.js">
</script>
<script type="text/javascript" src="../plugins/ext_3_3_0/ext-all.js">
</script>
<script type="text/javascript" src="../plugins/language/ext-lang-zh_CN.js">
</script>
<script type="text/javascript" src="app.js"></script>
<style type="text/css">
body {
font: normal normal normal 12px / normal Verdana, Arial, Helvetica, sans-serif;
padding:10px;
}
</style>
</head>
<body>
</body>
</html>
==================================================================================
EXTJS3.0.3的本地资源包乱码的问题
来源: http://andy-ghg.iteye.com/blog/517803不是编码的问题,的确是语言文件有问题,自己改一下就好
改好的:
/*!
* Ext JS Library 3.0.3
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
/*
* Simplified Chinese translation
* By DavidHu
* 09 April 2007
*
* update by andy_ghg@163.com
* 2009-11-15 23:36:04
*/
Ext.UpdateManager.defaults.indicatorText = '<div class="loading-indicator">加载中...</div>';
if(Ext.DataView){
Ext.DataView.prototype.emptyText = "";
}
if(Ext.grid.GridPanel){
Ext.grid.GridPanel.prototype.ddText = "选择了 {0} 行";
}
if(Ext.TabPanelItem){
Ext.TabPanelItem.prototype.closeText = "关闭此标签";
}
if(Ext.form.Field){
Ext.form.Field.prototype.invalidText = "输入值非法";
}
if (Ext.LoadMask) {
Ext.LoadMask.prototype.msg = "读取中...";
}
Date.monthNames = [
"一月",
"二月",
"三月",
"四月",
"五月",
"六月",
"七月",
"八月",
"九月",
"十月",
"十一月",
"十二月"
];
Date.monthNumbers = {
"1" : 0,
"2" : 1,
"3" : 2,
"4" : 3,
"5" : 4,
"6" : 5,
"7" : 6,
"8" : 7,
"9" : 8,
"10" : 9,
"11" : 10,
"12" : 11
};
//有兴趣的同学可以加上下面这几行代码
Date.getShortMonthName = function(month) {
return "" + (month + 1);
};
Date.getMonthNumber = function(name) {
return Date.monthNumbers[name.substring(0, name.length - 1)];
// or simply parseInt(name.substring(0, name.length - 1)) - 1
};
Date.dayNames = [
"日",
"一",
"二",
"三",
"四",
"五",
"六"
];
Date.formatCodes.a = "(this.getHours() < 12 ? '上午' : '下午')";
Date.formatCodes.A = "(this.getHours() < 12 ? '上午' : '下午')"; // no case difference
if(Ext.MessageBox){
Ext.MessageBox.buttonText = {
ok : "确定",
cancel : "取消",
yes : "是",
no : "否"
};
}
if(Ext.util.Format){
Ext.util.Format.date = function(v, format){
if(!v) return "";
if(!(v instanceof Date)) v = new Date(Date.parse(v));
return v.dateFormat(format || "Y-m-d");
};
}
if(Ext.DatePicker){
Ext.apply(Ext.DatePicker.prototype, {
todayText : "今天",
minText : "日期必须大于最小允许日期",
maxText : "日期必须小于最大允许日期",
disabledDaysText : "",
disabledDatesText : "",
monthNames : Date.monthNames,
dayNames : Date.dayNames,
nextText : '下个月 (Ctrl+Right)',
prevText : '上个月 (Ctrl+Left)',
monthYearText : '选择一个月 (Control+Up/Down 来改变年份)',
todayTip : "{0} (空格键选择)",
format : "Y-m-d",
okText : "确定",
cancelText : "取消"
});
}
if(Ext.PagingToolbar){
Ext.apply(Ext.PagingToolbar.prototype, {
beforePageText : "第",
afterPageText : "页,共 {0} 页",
firstText : "第一页",
prevText : "上一页",
nextText : "下一页",
lastText : "最后页",
refreshText : "刷新",
displayMsg : "显示 {0} - {1}条,共 {2} 条",
emptyMsg : '没有数据'
});
}
if(Ext.form.TextField){
Ext.apply(Ext.form.TextField.prototype, {
minLengthText : "该输入项的最小长度是 {0} 个字符",
maxLengthText : "该输入项的最大长度是 {0} 个字符",
blankText : "该输入项为必输项",
regexText : "",
emptyText : null
});
}
if(Ext.form.NumberField){
Ext.apply(Ext.form.NumberField.prototype, {
minText : "该输入项的最小值是 {0}",
maxText : "该输入项的最大值是 {0}",
nanText : "{0} 不是有效数值"
});
}
if(Ext.form.DateField){
Ext.apply(Ext.form.DateField.prototype, {
disabledDaysText : "禁用",
disabledDatesText : "禁用",
minText : "该输入项的日期必须在 {0} 之后",
maxText : "该输入项的日期必须在 {0} 之前",
invalidText : "{0} 是无效的日期 - 必须符合格式: {1}",
format : "y年m月d日"
});
}
if(Ext.form.ComboBox){
Ext.apply(Ext.form.ComboBox.prototype, {
loadingText : "加载中...",
valueNotFoundText : undefined
});
}
if(Ext.form.VTypes){
Ext.apply(Ext.form.VTypes, {
emailText : '该输入项必须是电子邮件地址,格式如: "user@domain.com"',
urlText : '该输入项必须是URL地址,格式如: "http:/'+'/www.domain.com"',
alphaText : '该输入项只能包含半角字母和_',
alphanumText : '该输入项只能包含半角字母,数字和_'
});
}
if(Ext.form.HtmlEditor){
Ext.apply(Ext.form.HtmlEditor.prototype, {
createLinkText : '添加超级链接:',
buttonTips : {
bold : {
title: '粗体 (Ctrl+B)',
text: '将选中的文字设置为粗体',
cls: 'x-html-editor-tip'
},
italic : {
title: '斜体 (Ctrl+I)',
text: '将选中的文字设置为斜体',
cls: 'x-html-editor-tip'
},
underline : {
title: '下划线 (Ctrl+U)',
text: '给所选文字加下划线',
cls: 'x-html-editor-tip'
},
increasefontsize : {
title: '增大字体',
text: '增大字号',
cls: 'x-html-editor-tip'
},
decreasefontsize : {
title: '缩小字体',
text: '减小字号',
cls: 'x-html-editor-tip'
},
backcolor : {
title: '以不同颜色突出显示文本',
text: '使文字看上去像是用荧光笔做了标记一样',
cls: 'x-html-editor-tip'
},
forecolor : {
title: '字体颜色',
text: '更改字体颜色',
cls: 'x-html-editor-tip'
},
justifyleft : {
title: '左对齐',
text: '将文字左对齐',
cls: 'x-html-editor-tip'
},
justifycenter : {
title: '居中',
text: '将文字居中对齐',
cls: 'x-html-editor-tip'
},
justifyright : {
title: '右对齐',
text: '将文字右对齐',
cls: 'x-html-editor-tip'
},
insertunorderedlist : {
title: '项目符号',
text: '开始创建项目符号列表',
cls: 'x-html-editor-tip'
},
insertorderedlist : {
title: '编号',
text: '开始创建编号列表',
cls: 'x-html-editor-tip'
},
createlink : {
title: '转成超级链接',
text: '将所选文本转换成超级链接',
cls: 'x-html-editor-tip'
},
sourceedit : {
title: '代码视图',
text: '以代码的形式展现文本',
cls: 'x-html-editor-tip'
}
}
});
}
if(Ext.grid.GridView){
Ext.apply(Ext.grid.GridView.prototype, {
sortAscText : "升序",
sortDescText : "降序",
lockText : "锁定列",
unlockText : "解除锁定",
columnsText : "列"
});
}
if(Ext.grid.PropertyColumnModel){
Ext.apply(Ext.grid.PropertyColumnModel.prototype, {
nameText : "名称",
valueText : "值",
dateFormat : "Y-m-d"
});
}
if(Ext.layout.BorderLayout && Ext.layout.BorderLayout.SplitRegion){
Ext.apply(Ext.layout.BorderLayout.SplitRegion.prototype, {
splitTip : "拖动来改变尺寸.",
collapsibleSplitTip : "拖动来改变尺寸. 双击隐藏."
});
}
========================================
ExtJS 4 待续......