JavaScript快速切换繁体中⽂和简体中⽂的⽅法及⽹站⽀持简繁体切换的绝招
⼀般商业⽹站都有⼀个语⾔的需求,就是为了照顾使⽤正体中⽂的国⼈,会特地提供⼀个切换到正体中⽂的选项(或⽈“繁体中⽂”)。传统做法是在服务端完成的,即通过某些控件或者过滤器转换⽂本语
⾔。这⾥笔者介绍⼀种简单可⾏的⽅法,不是在服务端⽽是利⽤前端的 JavaScript 就可以切换正体中⽂。
⼤概六年前我还专门写过这议题的博⽂,这篇也是奠基在那篇⽂章(旧⽂也是参考了⼀⾼⼿代码)之上,《对 JavaScript 繁简字切换的⼩改进》。时过境迁,有必要把代码进⾏更新⼀下——以前的太稚
嫩啦。
如下图,我们把切换按钮放在页脚(当然你也可以放置在“导航”或者其他更醒⽬的位置)。
由于页⾯假设设定均使⽤ Unicode 字符集,于是⼀般不⽤考虑 GB2312/BIG5 字符集问题,伟⼤的 Unicode 字符集已经涵盖了繁体字的字符了(UTF-8 编码)。
怎么在页⾯调⽤这个功能呢?很简单,⾸先引⼊下⾯ Js(注意还依赖 Function.prototype.delegate(),下⾯会提及):
;(function(){
var 简化中⽂ = '啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆⼋疤巴拔跋靶把耙坝霸罢爸⽩柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥薄雹保堡饱宝抱报暴豹鲍爆杯碑悲var 正体中⽂ = '啊阿埃挨哎唉哀皚癌藹矮艾礙愛隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翺襖傲奧懊澳芭捌扒叭吧笆⼋疤巴拔跋靶把耙壩霸罷爸⽩柏百擺佰敗拜稗斑班搬扳般頒板版扮拌伴瓣半辦絆邦幫梆榜膀綁棒磅蚌鎊傍謗苞胞包褒剝薄雹保堡飽寶抱報暴豹鮑爆杯碑悲/**
* 默认是否正体中⽂:true为正体;false简体。 HTTP
* 头读取:Request.ServerVariables("http_accept_language")
*
* @return {Boolean}
*/
function getClientLanguage() {
var s = navigator.userLanguage || navigator.language;
switch (s.toLowerCase()) {
case 'zh-cn':
return false;
case 'zh-tw':
return true;
default:
return null;
}
}
/
**
* 转换对象,使⽤递归,逐层剥到⽂本
* @param {HTMLElement} obj 从document.body开始,
*/
function translate(el, coverntFn){
el = el.childNodes;
var node;
for (var i = 0, j = el.length; i < j; i++) {
node = el.item(i);
// || (node == $$.big5.el)
if (("||BR|HR|TEXTAREA|".indexOf("|" + node.tagName + "|")) > 0)continue;
if(node.title){
node.title = coverntFn(node.title);
}else if(node.alt){
node.alt = coverntFn(node.alt);
}else if(node.tagName == "INPUT" && node.value != "" && pe != "text" && pe != "hidden"){
node.value = coverntFn(node.value);
}else deType == 3){
node.data = coverntFn(node.data);
}else{
arguments.callee(node, coverntFn);
}
}
}
function translateText(text, isBig5) {
var str = [], _char, charIndex, result;
for (var i = 0, j = text.length; i < j; i++) {
_char = text.charAt(i);
charIndex = isBig5 ? 简化中⽂.indexOf(_char) : 正体中⽂.indexOf(_char);
result = isBig5 ? 正体中⽂.charAt(charIndex) : 简化中⽂.charAt(charIndex);
str.push(charIndex != -1 ? result : _char);
}
return str.join('');
}
var traditionalized = translateText.delegate(null, true), simplized = translateText.delegate(null, false);
var cookieName = 'ChineseType';
// 转换为正体中⽂(繁体中⽂)
el.addCls('selected');
document.querySelector(".simpleChinese").removeCls('selected');
translate(document.body, traditionalized)
Cookie.set(cookieName, true);
}
// 转换为简体中⽂
el.addCls('selected');
document.querySelector(".Chinese").removeCls('selected');
translate(document.body, simplized);
Cookie.set(cookieName, false);
}
var Cookie = {
set: function (name, val) {
var exp = new Date();
exp.Date() + 600 * 1000);
}, del: function (name) {
}, get: function (name) {
var cookieArray = kie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
if (cookieArray != null) return unescape(cookieArray[2]);
else return null;
}
};
var value = (cookieName);
if( value == null && getClientLanguage() || value == 'true') {
// 没有检查出 cookie 则为第⼀次运⾏。
/
/ cookie保留了⽤户选择的正体,将原来的简化字转换为默认的正体!
} else if(value == null && !getClientLanguage() || value == 'false') {
// 虽然第⼀次运⾏,但对⽅正是简体中⽂,不⽤转。
// 原来已经是简体,⽆须转换。
}
})();
然后绑定按钮事件,我们简单地使⽤ onclick 绑定来全局函数 Chinese(el)、SimpleChinese(el)。el 是按钮元素。
// 转换为正体中⽂(繁体中⽂)
el.addCls('selected');
document.querySelector(".simpleChinese").removeCls('selected');
translate(document.body, traditionalized)
Cookie.set(cookieName, true);
}
// 转换为简体中⽂
el.addCls('selected');
document.querySelector(".Chinese").removeCls('selected');
translate(document.body, simplized);
Cookie.set(cookieName, false);
}
js 代码中⽐较长的两个字符串变量分别是简体中⽂和繁体中⽂,他们之间的切换没有什么神奇之处,只是所有⽂本经过这些变量⼀⼀对应即可。当然这⾥只是常⽤的繁简对应,⽽且是机械的,有些特殊的翻译需要联系上下⽂的,那种⾼级转换不在此讨论之列。
⾸先我们看看变量函数 translate,执⾏它会通过递归遍历完整个 DOM(可以说⽐较笨的⽅法)
/**
* 转换对象,使⽤递归,逐层剥到⽂本
* @param {HTMLElement} obj 从document.body开始,
*/
function translate(el, coverntFn){
el = el.childNodes;
var node;
for (var i = 0, j = el.length; i < j; i++) {
node = el.item(i);
// || (node == $$.big5.el)
if (("||BR|HR|TEXTAREA|".indexOf("|" + node.tagName + "|")) > 0)continue;
if(node.title){
node.title = coverntFn(node.title);
}else if(node.alt){
node.alt = coverntFn(node.alt);
}else if(node.tagName == "INPUT" && node.value != "" && pe != "text" && pe != "hidden"){
node.value = coverntFn(node.value);
}else deType == 3){
node.data = coverntFn(node.data);
}else{
arguments.callee(node, coverntFn);
}
}
}
转换 DOM 内容,我们第⼀时间想到的可能是 el.innerHTML,但其实⼤可不必,⽽且递归的时候 innerHTML 不太⽅便。不妨再想想看,我们其实只需要对⽂本转换即可,DOM API 能够判断⽂本节点(deType == 3),然后可读可写的 data 属性就是设置⽂本的(textNode.data),由此我们就可以完成到繁体的切换。节点其他属性 title、alt、value 亦是同样原理。另外,if
(("||BR|HR|TEXTAREA|".indexOf("|" + node.tagName + "|")) > 0)continue; 是排除某些节点的⽅法,其思路⽐较特别,可以多观摩下。
⾄于 coverntFn 是⼀函数参数。通过根函数 translateText(text, isBig5) 新⽣成两个函数:var traditionalized = translateText.delegate(null, true), simplized = translateText.delegate(null, false);
function translateText(text, isBig5) {
var str = [], _char, charIndex, result;
for (var i = 0, j = text.length; i < j; i++) {
_char = text.charAt(i);
charIndex = isBig5 ? 简化中⽂.indexOf(_char) : 正体中⽂.indexOf(_char);
result = isBig5 ? 正体中⽂.charAt(charIndex) : 简化中⽂.charAt(charIndex);
str.push(charIndex != -1 ? result : _char);
}
return str.join('');
}
var traditionalized = translateText.delegate(null, true), simplized = translateText.delegate(null, false);
Function.prototype.delegate() ⽅法如下。
/**
* 函数委托参见 blog.csdn/zhangxin09/article/details/8508128
* @return {Function}
*/
Function.prototype.delegate = function () {
var self = this, scope = this.scope, args = arguments, aLength = arguments.length, fnToken = 'function';
return function(){
var bLength = arguments.length, Length = (aLength > bLength) ? aLength : bLength;
nodeselector// mission one:
for (var i = 0; i < Length; i++)
if (arguments[i])args[i] = arguments[i]; // 拷贝参数
args.length = Length; // 在 MS jscript下⾯,arguments作为数字来使⽤还是有问题,就是length不能⾃动更新。修正如左:
// mission two:
for (var i = 0, j = args.length; i < j; i++) {
var _arg = args[i];
if (_arg && typeof _arg == fnToken && _arg.late == true)
args[i] = _arg.apply(scope || this, args);
}
return self.apply(scope || this, args);
};
};
繁简的转换基本如此了。值得⼀提的是,浏览器其实替我们识别语⾔环境的变量,主要是 navigator.userLanguage || navigator.language。这个变量在服务端也可以获取,头读取:
Request.ServerVariables("http_accept_language")。
/**
* 默认是否正体中⽂:true为正体;false简体。 HTTP
* 头读取:Request.ServerVariables("http_accept_language")
*
* @return {Boolean}
*/
function getClientLanguage() {
var s = navigator.userLanguage || navigator.language;
switch (s.toLowerCase()) {
case 'zh-cn':
return false;
case 'zh-tw':
return true;
default:
return null;
}
}
最后我们还通过 cookie 来保存语⾔状态。
下⾯给⼤家介绍下三步让你的⽹站⽀持简体繁体切换
不少⽹站为了更好地照顾不同⽤户使⽤简体/繁体的阅读习惯,会提供简体繁体两种版本字体切换,提⾼
⽤户体验。例如hexo虽然作者是来⾃台湾的,但是hexo的官⽹不仅提供了适合台湾同胞阅读的繁体中⽂版,还提供了适合我们内地同胞阅读的简体中⽂版,照顾了我们这些习惯使⽤简体读写的⼤陆⽤户,hexo得到了不少内地忠实粉丝追捧。同样,我们也可以提供繁体版来照顾那些使⽤繁体字的台湾、⾹港同胞阅读习惯。
具体实现:
⾸先,点击这⾥右键另存下载简繁字体切换所需的 tw_cn.js ⽂件,上传到⾃⼰的⽹站空间。
其次,修改模板,在你想要显⽰简繁转换按钮的地⽅加上下⾯⼀段代码,正常情况添加到 header.php 或者 siderbar.php 就可以了。
<a id="translateLink" href="javascript:translatePage();">繁體</a>
最后,在footer.php添加下⾯代码,记得更改 cookieDomain 这⼀项。
<script type="text/javascript" src="/js/tw_cn.js"></script>
<script type="text/javascript">
var defaultEncoding = 2; //⽹站编写字体是否繁体,1-繁体,2-简体
var translateDelay = 0; //延迟时间,若不在前, 要设定延迟翻译时间, 如100表⽰100ms,默认为0
var cookieDomain = "/"; //Cookie地址, ⼀定要设定, 通常为你的⽹址
var msgToTraditionalChinese = "繁體"; //此处可以更改为你想要显⽰的⽂字
var msgToSimplifiedChinese = "简体"; //同上,但两处均不建议更改
var translateButtonId = "translateLink"; //默认互换id
translateInitilization();
</script>
这就基本完成了简体繁体切换功能,不管你是hexo,jelly,Octopress等静态博客,还是wordpress,typecho,emlog,Z-Blog等动态的,都可以⽤上。具体的演⽰效果可以点击我博客底部简体中⽂切换字体,⾄于简体繁体切换按钮嘛,⽂字和样式可以按个⼈喜好⾃⾏更改。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论