Asp.net项目基于jQuery.i18n

主题概要
JS
前端页面,多语言
编辑
时间
新建
序号
参考资料
任何技术的引进都是为了解决问题,要想给一个好好运行的网站 , 支持多语言,如果设计的时候没进行相应设计,调整起来是相当麻烦的 。
假设有一个导航栏控件:

Asp.net项目基于jQuery.i18n

文章插图
为了把它做成中英文两套系统 , 用户登录的时候,根据他习惯的语言进行加载 。
权宜的做法是一个控件,写两份代码,if-else进行判断 。
这不但产生了大量的重复代码,而且以后要同时维护两份代码,如果每个控件,每个页面都这样处理,是给自己找罪受,十分不可取的 。
这里也用网上广泛使用的.i18n.进行处理 。
引进.i18n.
.i18n.在上的地址:
所谓引进,就是把它的.i18n..js文件复制下来,并引用到我们的页面内 。
为此,我在我们的文件夹下,新建个目录:
Asp.net项目基于jQuery.i18n

文章插图
用来存放js文件和翻译文件:
Asp.net项目基于jQuery.i18n

文章插图
..js是我们自己的js,zh-cn,eu-us分别是对应中文网站和英文网站 。
Zh-ch下,现在只有两个.,一个公共的翻译项,一个是特定页面的翻译项 , 比如现在这个.表示导航控件的翻译项 。
Asp.net项目基于jQuery.i18n

文章插图
在页面中引进这两个脚本进行使用:
使用.i18n.
在要进行多语言切换在页面,添加一个隐藏域:

其中,value表示用户登录时喜好的语言,name是表示当前页面用到的.文件,比如,上面-表示用到了.和.两个文件 。
Js中解析这个语言选项 , 和资源文件数组:
var optionEle = $("#i18n_pagename");if (optionEle.length < 1) {console.log("Unknown i18n_pagename");return false;};var sourceName = optionEle.attr('name');sourceName = sourceName.split('-');var optionLang = optionEle.attr('value');
自定义标记
为了让js判断以什么方式处理翻译 , 以及赋值什么内容,需要给需要进行多语言处理的元素自定义两个属性作为标记 。
假设为data-和data-:
data-i18nclassname="I18nHtmlText" data-i18npropname='Common-Nav-H1-Home'
【Asp.net项目基于jQuery.i18n】这里使用到了html5支持的以data-开始的自定义属性,data-指定以什么方式处理,data-指定要赋值的内容 。
这可能不好理解,举例说明:
还是以这个导航控件来说,假设有一级标题公告和新闻,注意它们后面有个倒三角图标:
可以看到 , 它其实是个a标签,“公告”后面还接了一个span 。
Asp.net项目基于jQuery.i18n

文章插图
同理,新闻标题,“新闻”后面也接了一个span 。
Asp.net项目基于jQuery.i18n

文章插图
而公告下面的二级标题:
Asp.net项目基于jQuery.i18n

文章插图
是在文字的左侧有个小三角 。
Asp.net项目基于jQuery.i18n

文章插图
Span是在“未读公告”的前面 。
换句话说,data-指示了span是在前面还是后面,data-指示了是表示新闻还是公告 。
这个控件只有两种类型的data-, ””,”” 。每种类型js中定义一种处理方式,用简单工厂方法 。
基类 , 传入的是当前选择的元素:
Asp.net项目基于jQuery.i18n

文章插图
/*I18n的类型基类 , 不同的类型有不同的处理方式*/function I18nClassBase(select) {this.select = select;}I18nClassBase.prototype.doI18n = function() {}
一级标题类,把小三角到属性值的后面:
/*处理Html文本类型的i18n*/function I18nHtmlTextClass(select) {this.select = select;}I18nHtmlTextClass.prototype = new I18nClassBase(this.select);I18nHtmlTextClass.prototype.doI18n = function() {var propNam = "";try {propName = $(this.select).data(I18nGlobalConst.I18nPropName());var propValue = http://www.kingceram.com/post/$.i18n.prop(propName);var child = $(this.select).children();$(this.select).empty().append(propValue).append(child);} catch (ex) {console.log("I18n propName[" + propName + "] failed");console.log(ex);}}
二级标题类,把属性值到小三角的后面:
function I18nHtmlTextLeftArrClass(select) {this.select = select;}I18nHtmlTextLeftArrClass.prototype = new I18nClassBase(this.select);I18nHtmlTextLeftArrClass.prototype.doI18n = function() {var propNam = "";try {propName = $(this.select).data(I18nGlobalConst.I18nPropName());var propValue = http://www.kingceram.com/post/$.i18n.prop(propName);var child = $(this.select).children();$(this.select).empty().append(child).append(propValue);} catch (ex) {console.log("I18n propName[" + propName + "] failed");console.log(ex);}}
简单工厂:
/*简单工厂,实例每种I18n的处理类型*/function I18nFactory(className, select) {switch (className) {case I18nGlobalConst.I18nHtmlText():return new I18nHtmlTextClass(select);case I18nGlobalConst.I18nHtmlTextLeftArr():return new I18nHtmlTextLeftArrClass(select);default:return new I18nClassBase(select);}}
其它语言转来客串js的,有强迫症,把常量用闭包封装到一个类中:
var I18nGlobalConst = (function() {var i18nHtmlText = 'I18nHtmlText';var i18nHtmlTextLeftArr = 'I18nHtmlTextLeftArr';var i18nPropName = 'i18npropname';var i18nPathRoot = '/Scripts/i18n_properties/';var constants = {};constants.I18nHtmlText = function() {return i18nHtmlText;}constants.I18nPropName = function() {return i18nPropName;}constants.I18nPathRoot = function() {return i18nPathRoot;}constants.I18nHtmlTextLeftArr = function() {return i18nHtmlTextLeftArr;}return constants;})();
执行入口函数:
/*** 执行页面i18n方法* @return*/var execI18n = function() {/*获取一下资源文件名*/var optionEle = $("#i18n_pagename");if (optionEle.length < 1) {console.log("Unknown i18n_pagename");return false;};var sourceName = optionEle.attr('name');sourceName = sourceName.split('-');var optionLang = optionEle.attr('value');/* 需要引入 i18n 文件*/if ($.i18n == undefined) {console.log("Please reference i18n js file")return false;};/*这里需要进行i18n的翻译*/jQuery.i18n.properties({name: sourceName, //资源文件名称path: I18nGlobalConst.I18nPathRoot() + optionLang + '/', //资源文件路径mode: 'map', //用Map的方式使用资源文件中的值//language: optionLang,callback: function() { //加载成功后设置显示内容console.log('Init i18n');try {$('[data-i18nclassname]').each(function() {var className = $(this).data('i18nclassname');new I18nFactory(className, this).doI18n();});} catch (ex) {console.log(ex);}console.log('Finish init i18n');}});}
可以看到,回调的时候,如果有新的类型 , 比如三级标题,四级标题等加进来,这里不用改一行代码,只要写对应的子类就行了 。
Asp.net项目基于jQuery.i18n

文章插图
加载完页面后执行:
$(function() {execI18n();});
完整代码:
/*全局常量*/var I18nGlobalConst = (function() {var i18nHtmlText = 'I18nHtmlText';var i18nHtmlTextLeftArr = 'I18nHtmlTextLeftArr';var i18nPropName = 'i18npropname';var i18nPathRoot = '/Scripts/i18n_properties/';var constants = {};constants.I18nHtmlText = function() {return i18nHtmlText;}constants.I18nPropName = function() {return i18nPropName;}constants.I18nPathRoot = function() {return i18nPathRoot;}constants.I18nHtmlTextLeftArr = function() {return i18nHtmlTextLeftArr;}return constants;})();/*I18n的类型基类 , 不同的类型有不同的处理方式*/function I18nClassBase(select) {this.select = select;}I18nClassBase.prototype.doI18n = function() {}/*处理Html文本类型的i18n*/function I18nHtmlTextClass(select) {this.select = select;}I18nHtmlTextClass.prototype = new I18nClassBase(this.select);I18nHtmlTextClass.prototype.doI18n = function() {var propNam = "";try {propName = $(this.select).data(I18nGlobalConst.I18nPropName());var propValue = http://www.kingceram.com/post/$.i18n.prop(propName);var child = $(this.select).children();$(this.select).empty().append(propValue).append(child);} catch (ex) {console.log("I18n propName[" + propName + "] failed");console.log(ex);}}function I18nHtmlTextLeftArrClass(select) {this.select = select;}I18nHtmlTextLeftArrClass.prototype = new I18nClassBase(this.select);I18nHtmlTextLeftArrClass.prototype.doI18n = function() {var propNam = "";try {propName = $(this.select).data(I18nGlobalConst.I18nPropName());var propValue = http://www.kingceram.com/post/$.i18n.prop(propName);var child = $(this.select).children();$(this.select).empty().append(child).append(propValue);} catch (ex) {console.log("I18n propName[" + propName + "] failed");console.log(ex);}}/*简单工厂,实例每种I18n的处理类型*/function I18nFactory(className, select) {switch (className) {case I18nGlobalConst.I18nHtmlText():return new I18nHtmlTextClass(select);case I18nGlobalConst.I18nHtmlTextLeftArr():return new I18nHtmlTextLeftArrClass(select);default:return new I18nClassBase(select);}}/*** 执行页面i18n方法* @return*/var execI18n = function() {/*获取一下资源文件名*/var optionEle = $("#i18n_pagename");if (optionEle.length < 1) {console.log("Unknown i18n_pagename");return false;};var sourceName = optionEle.attr('name');sourceName = sourceName.split('-');var optionLang = optionEle.attr('value');/* 需要引入 i18n 文件*/if ($.i18n == undefined) {console.log("Please reference i18n js file")return false;};/*这里需要进行i18n的翻译*/jQuery.i18n.properties({name: sourceName, //资源文件名称path: I18nGlobalConst.I18nPathRoot() + optionLang + '/', //资源文件路径mode: 'map', //用Map的方式使用资源文件中的值//language: optionLang,callback: function() { //加载成功后设置显示内容console.log('Init i18n');try {$('[data-i18nclassname]').each(function() {var className = $(this).data('i18nclassname');new I18nFactory(className, this).doI18n();});} catch (ex) {console.log(ex);}console.log('Finish init i18n');}});}$(function() {execI18n();});
文件
按名值对这样存储,比如 , 英文:
Asp.net项目基于jQuery.i18n

文章插图
对应的中文:
Asp.net项目基于jQuery.i18n

文章插图
把值赋到data-属性中 , data-=’-Nav-H1-’,根据当前登录的语言 , 就可显示是“公告“还是”” 。
IIS填坑
参考
主要在web.中配置IIS对.的支持 。
Asp.net项目基于jQuery.i18n

文章插图