开发者社区> sp42> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

对JavaScript繁简字切换的小改进

简介: 繁简即时切换脚本属于比较普遍常见的脚本,多应用于港澳台的公司企业网站上,一些面向大陆服务的站点也提供正体、简体的页面切换(“正体”一词乃台湾方面的新说法)。在前人梳理的经验上,推荐这个 StranBody 方案。
+关注继续查看

繁简即时切换脚本属于比较普遍常见的脚本,多应用于港澳台的公司企业网站上,一些面向大陆服务的站点也提供正体、简体的页面切换(“正体”一词乃台湾方面的新说法)。在前人梳理的经验上,推荐这个 StranBody 方案。此方案是从客户端出发而考虑,是直接基于 JavaScript 对浏览器 DOM 内容修改的纯客户端方案,因此具有不依赖服务端转换,减轻服务端运算符合等的好处。当然,如果用户关闭掉 JavaScript 脚本,就无法使用正体、简体切换的功能了。直接使用该脚本毫无问题,亦兼容 IE & FireFox 浏览器,但美中不足的是,笔者个人感觉代码写得比较乱,当然这乃是较早期的实现,对JS认识不如今天的应用是可以理解的。现在恰好客户需求,笔者正好可将此代码派上项目用场,加上笔者自身亦一时技痒,就打算重构一番这个早期的繁简切换脚本,多练练手。

观察 在线演示地址代码IE6 & FF 3.0/Ext Core 3.2下通过,。 edit:2012.12.27 该文链接已失效

代码约定,true 的话表示正体中文(繁体中文),反之 false 就是简体中文。并且需要说明的是,当然脚本以默认“简体中文”的网站为假设,如果本来是正体中文的,就需要按如下修改脚本的原始值:

$$.big5.language = true; // true表示正体中文,反之false就是简体中文

经过重构,该模块的命名空间是 $$.big5.*(请注意命名空间的设置:if(typeof $$ == 'undefined')$$={};)。使用方法很简单,执行 init() 对其送入元素 id 或元素对象即可。该元素就是用来切换的按钮。

$$.big5.init('StranLink'); // 修改StranLink为你的元素标识

繁、简切换的原理在是,先准备一“繁、简”对照表,如私有成员“ var 简化中文 = '啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺……”和“var 正体中文 = '啊阿埃挨哎唉哀皚癌藹矮艾礙愛隘鞍氨安……”,他们之间是一一对应的,知道任意一种字符的索引即可查得另一种字符的编码;然后,字符串的索引如何怎么查得呢?可通过字符串的indeOf()。charAt()方法返回指定索引位置处的字符。这样,凭借此对照表,按照顺序逐一替换为他种语言。以上的实现编码在 $$.big5.traditionalized() 及 $$.big5.simplized()方法中。

如何得到那些要的翻译文本?遍历 DOM 是前台开发中经常使用的一点,一般而言通过递归遍历 DOM。这一次,我们又是从 document.body 收集需要转换的内容。虽然说的比较简单,但是实际还有不少需要考虑的细节问题。先看看这个递归函数。

/** * 转换对象,使用递归,逐层剥到文本 * @param {HTMLElement} obj 从document.body开始, */ function StranBody(obj){ var obj = obj.childNodes ,node; for (var i = 0, j = obj.length; i < j; i++) { node = obj.item(i); if (("||BR|HR|TEXTAREA|".indexOf("|" + node.tagName + "|")) > 0 || (node == $$.big5.el.dom)){ continue; } if(node.title){ node.title = $$.big5.fn(node.title); }else if(node.alt){ node.alt = $$.big5.fn(node.alt); }else if(node.tagName == "INPUT" && node.value != "" && node.type != "text" && node.type != "hidden"){ node.value = $$.big5.fn(node.value); }else if(node.nodeType == 3){ node.data = $$.big5.fn(node.data); } else{ arguments.callee(node); } } }

不知看官有没有稍加注意,我们采用 arguments.callee(node);的技巧实现匿名递归。

控制切换的UI是$$.big5.el,类型是 Ext.Element。我是为了避免烦恼的跨浏览器问题,使用上了 Ext Core 库。如果需要通用,用户可以很快的修改通过的 w3c 方案,不算太困难。Ext Core 方案如下:

$$.big5.el = Ext.get(el).on('click', function(e, el){ $$.big5.language = !$$.big5.language;// 反相器 toggle($$.big5.language); StranBody(document.body); });

cookie 是记录在客户端的可控对象,可以透过 JavaScript 编程来创建和取回 cookie 的值。每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie。在本脚本中我们使用 Cookie 来记录用户选择了那一种语言,那么下一次客户离开页面再访问的时候,仍然可以转换到上一次选择的结果,无须用户手动设置。

设置Cookie,当按钮选择后发生。

// Sys.Big5.js 第53行 setCookie("ft" + window.location.hostname.replace(//./g, ""), b, 7);

每一次运行该脚本时都会执行下一行语句。如果用户从未选择过“繁体/简体”,那么这个方法总是返回 null 值。

// Sys.Big5.js 第96行 var c = getCookie("ft" + window.location.hostname.replace(//./g, ""));

至此,我们就对 StranBody 基本问题介绍了一遍。如果是原本的 StranBody 方案,那么到这儿就算结束了,——可如果马上结束就失去了本文的意义,尚有后面改进内容的介绍——

首先是重构后焕然一新的代码,从原来的全局变量重构为 JS 单例模式。表面上是这样,但其中最大变化的一点,可以说集中在 toggle() 函数中,从而避免源码混乱的状态管理。

/** * @param {Boolean} b True正体中文,false,简化中文 */ function toggle(b){ $$.big5.fn = b === true ? $$.big5.traditionalized : $$.big5.simplized; $$.big5.el.update(b === true ? "-》简体中文" : "-》繁体中文"); setCookie("ft" + window.location.hostname.replace(//./g, ""), b, 7); // 触发事件 if(b === true){ $$.big5.onBig5(); }else{ $$.big5.onSimpleChinese(); } }

JS的函数是第一要员,可灵活控制之。我们的$$.big5.fn正是这一种体现,无论是繁转简抑或是简转繁,反正调用$$.big5.fn即可!

其次,加入了事件$$.big5.onBig5、$$.big5.onSimpleChinese,那么等于增加了对图片和动画处理的手段了。我们重写这个两个方法就可以加入自定义的事件;还有依据浏览器的userLanguage自动选择繁体:

/** * 默认是否正体中文:true为正体;false简体。 * ASP版本: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; } }

 

有人不免要问,为什么不写成属性而是方法。因为方法的写法可避免在服务端下JS的报错。

最后,就是一个对 StranBody 的小 Patch 修正了,虽然属于别人的劳动成果,但既然公开了,应该不碍事吧!?还是可以借用一下的^_^,原文如下:

对上面的程序进行测试,可以发现,对于有行内框架(IFRMIE)内的内容没有转换,对脚本输出文本即alert. confirrmn和prompt函数输出的内容也末作转换,还有网页标题也末作转换,这显然是很不完美的事。于是,经过一番探索,终于找到很好的办法解决了这两个问题。

在此基础我修改了一下,就是函数hijackFn():

function hackjackFn(){ var _alert = window.alert; window.alert = function(s){ _alert($$.big5.fn(s)); } var _confirm = window.confirm; window.confirm = function(s){ _confirm($$.big5.fn(s)); } var _prompt = window.prompt; window.prompt = function(s){ _prompt($$.big5.fn(s)); } }

总结今次学习过程,可以明白繁简翻译、Cookie 控制、RegExp.exec()等等的细节问题,从中收获不少。

 

在线例子:http://playen.ajaxjs.com/playen/blog/big5/

edit:2011-05-29 14:35:32重新上传,修正了例子的链接。

 

参见:  唐乾林,牟向宇,《JavaScript在网站中繁简字体转换的应用》。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
剑指Offer——II. 青蛙跳台阶问题(JS实现)
剑指Offer——II. 青蛙跳台阶问题(JS实现)
90 0
剑指Offer——数字序列中某一位的数字(JS实现)
剑指Offer——数字序列中某一位的数字(JS实现)
79 0
剑指Offer——二维数组中的查找(JS实现)
剑指Offer——二维数组中的查找(JS实现)
76 0
剑指Offer——正则表达式匹配(JS实现)
剑指Offer——正则表达式匹配(JS实现)
65 0
剑指Offer——I. 斐波那契数列(JS实现)
剑指Offer——I. 斐波那契数列(JS实现)
71 0
剑指Offer——数值的整数次方(JS实现)
剑指Offer——数值的整数次方(JS实现)
83 0
剑指Offer——剪绳子II(JS实现)
剑指Offer——剪绳子II(JS实现)
60 0
剑指Offer——把字符串转换成整数(JS实现)
剑指Offer——把字符串转换成整数(JS实现)
101 0
剑指Offer——表示数值的字符串(JS实现)
剑指Offer——表示数值的字符串(JS实现)
50 0
剑指Offer——顺时针打印矩阵(JS实现)
剑指Offer——顺时针打印矩阵(JS实现)
189 0
+关注
sp42
移动项目技术负责人。多年全栈经验,熟悉 Java 和 JS,CSDN 博客技术专家,著有《ExtJS 详解与实践》等书。
294
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载