前已有博客,可优化,以充实转换表,优化查找比对:
基于 JS实现页面字体繁简转换
一、代码重构
源代码过于繁琐、注释过多,可重构。重构过后,保证原作者都看不出来这是基于谁的作品。
(function(){
//简繁对照表,重构之时与原文一致,故省略
var zh_t = '皚……';
var zh_s = '皑……';
var translated;
function tradition(s) {
var s1=zh_s,s2=zh_t;
var a = '';
for(var i=0, l=s.length;i<l;i++){
var c = s.charAt(i);
var p = s1.indexOf(c)
a += p < 0 ? c : s2.charAt(p);
}
return a;
}
function simplify(s) {
var s1=zh_t,s2=zh_s;
var a = '';
for(var i=0, l=s.length;i<l;i++){
var c = s.charAt(i);
var p = s1.indexOf(c)
a += p < 0 ? c : s2.charAt(p);
}
return a;
}
function T(s) {
if(s) {
var s1=zh_s;
for(var i=0, l=s.length;i<l;i++){
if(s1.indexOf(s.charAt(i))) return 1;
}
}
return 0;
}
function S(s) {
if(s) {
var s1=zh_t;
for(var i=0, l=s.length;i<l;i++){
if(s1.indexOf(s.charAt(i))) return 1;
}
}
return 0;
}
function getNextNode(n, e) {
var a = n.firstChild;
if (a) return a;
while (n && n!=e) {
if (a = n.nextSibling) {
return a
}
n = n.parentNode
}
return 0;
}
function zhTran(t, rootNode) { // t 为繁简转换类型,可为 0,1,2
debug('zhTran', rootNode)
var e=rootNode,n=e, fn=t==1?tradition:simplify, tn=t==1?T:S;
if(t==0) {
if(translated) {
while(n=getNextNode(n,e)) {
if (n.nodeType==3 && n._zhy) {
n.data = n._zhy;
n._zhy = undefined;
}
}
translated = 0;
}
} else {
// detect pass
while(n=getNextNode(n,e)) {
if (n.nodeType==1) {
if(' SCRIPT STYLE LINK IFRAME '.indexOf(' '+n.tagName+' ') > 0)
continue;
if (tn(n.title)) break;
if (tn(n.alt)) break;
if (n.tagName == "INPUT" && tn(n.value))
break;
}
else if (n.nodeType==3 && tn(n.data))
break;
}
translated = !!n;
// convert pass
while(n) {
if (n.nodeType==1) {
if(' SCRIPT STYLE LINK IFRAME '.indexOf(' '+n.tagName+' ') > 0) {
n=getNextNode(n,e)
continue;
}
if (n.title) n.title = fn(n.title);
if (n.alt) n.alt = fn(n.alt);
if (n.tagName == "INPUT")
n.value = fn(n.value);
}
else if (n.nodeType==3){
var data=n.data, text=fn(data);
if(data!=text) {
if(!n._zhy) n._zhy = data;
n.data = text;
}
}
n=getNextNode(n,e)
}
}
}
function zh_tran(t) {
zhTran(t, document.body);
}
window.zh_tran = zh_tran;
})()
解释:代码0表示不转换,1表示转换为繁体,2表示转换为简体。
至于节点遍历,替换原文的递归遍历(zh_tranBody
)为基于nextSibling的单循环节点遍历(getNextNode
),思想学自 rangy.js :
function getNextNode(n, e) { // 获得当前节点n的下一节点。 n 为当前节点, e 为终止节点(父容器)
var a = n.firstChild;
if (a) return a;
while (n && n!=e) {
if (a = n.nextSibling) {
return a
}
n = n.parentNode
}
return 0;
}
转换流程:先用大写的方法T、S测试,检测是否需要页面转换为目标(繁、简)字体。如需转换,再分别调用转换方法。
var fn=t==1?tradition:simplify, tn=t==1?T:S;
二、充实简繁对照表
原文转换表只有1275字,且不包含多个繁体对应同一简体的情况。我综合了github上一个python库和一个java库的字表,得两千多字,且包含一百多个N对1的情况:
个個箇
为為爲
么幺麼麽
产產産
仑侖崙
众眾衆
伪偽僞
冲沖衝
净凈淨
凫鳧鳬
别別彆
勋勛勳
升昇陞
卤鹵滷
历歷厤曆
厕廁厠
参參蔘
发發髮
只衹隻
台檯臺颱
叹嘆歎
向嚮曏
启啟啓
团團糰
坛壇墰壜罈罎
墙牆墻
壳殼殻
复復複
奖獎奬
妫媯嬀
尝嘗嚐
尽盡儘
干乾幹榦
并並併
弥彌瀰
当當噹
录錄録
恶惡噁
悫愨慤
戚慼鏚
曲麯麴
术術朮
榉櫸欅
毁毀燬譭
汇匯彙滙
沩溈潙
溯泝遡
炼煉鍊
画畫畵
瘘瘺瘻
竖豎竪
签簽籤
系係繫
纤纖縴
线線綫
绝絕絶
绣綉繡
绦絛縧
绱緔鞝
绷綳繃
绿綠緑
缰韁繮
胡衚鬍
脏臟髒
艳艷豔
苏蘇囌甦
荡盪蕩
药葯藥
获獲穫
莼蒓蓴
蒙懞矇
蕴蘊藴
说說説
谣謠謡
谫譾謭
赃贓贜
赍齎賫
赝贗贋
赞贊讚
酝醞醖
采埰寀採
里裏裡
鉴鑒鑑
钟鍾鐘
钩鈎鉤
钵缽鉢
铲鏟剷
锈銹鏽
锐銳鋭
锤錘鎚
锨杴鍁
镌鐫鎸
镢钁鐝
镰鐮鎌
闲閑閒
阅閱閲
面麪麫麵
须須鬚
颓頹頽
颜顏顔
饥飢饑
骂罵駡
鲇鯰鮎
鲞鯗鮝
鳄鱷鰐
鸡雞鷄
鹚鶿鷀
三、优化查找
原查找方法仅仅是基于js的字符串查找(indexOf
),可替换为二分法查找,提高效率。当转换为繁体,而存在“N繁体对应1简体”的情况时,可手动将更常用的一对排前面,二分法能查到首个大于等于查询键值的位置。
不过二分法所需容量过多、步骤繁琐,所以干脆用Map了
四、小结
通过充实字表,可以转换更多繁体为简体。通过采用二分法,可以有效提升效率。群里还有人发给我更详细的字表,六千多对,不过许多字都显示为方框了。
仍有不足,当存在N对1的情况下,无法判断哪一对是正确的。所以转换结果仅供参考。
五、源代码
源代码备份在无限词典asset文件夹中的zh.js
之中。字表备份于Kasemap.ali
。
…