最开始锅巴汉化的那些网页放置游戏,采用的是源码汉化的方式。这个方式的坏处就是会无意间汉化到游戏的变量,以及同步英文版时,往往需要重新汉化,费时费力。
后来为了在汉化网页放置游戏时可以保证和英文版同步更新,咱们的麦子大佬帮忙优化了一波,最终形成了此插件。
话不多说,咱们先来看看这个汉化脚本是怎么使用的。
一、新建chs.js 和 core.js两个js文件,复制对应的代码到js里面。
core.js:
/* @name : 锅巴汉化 - Web汉化插件 @author : 麦子、JAR、小蓝、好阳光的小锅巴 @version : V0.6.1 - 2019-07-09 @website : http://www.g8hh.com @idle games : http://www.gityx.com @QQ Group : 627141737 */ var CNITEM_DEBUG = 0; function cnItemByTag(text, itemgroup, node, textori){ for (let i in itemgroup){ if (i[0] == '.') { //匹配节点及其父节点的class let current_node = node; while (current_node){ if ( current_node.classList && current_node.classList.contains(i.substr(1)) ){ return itemgroup[i]; } else if( current_node.parentElement && current_node.parentElement != document.documentElement ) { current_node = current_node.parentElement; } else { break; } } } else if (i[0] == '#'){ //匹配节点及其父节点的id let current_node = node; while (current_node){ if ( current_node.id == i.substr(1) ){ return itemgroup[i]; } else if( current_node.parentElement && current_node.parentElement != document.documentElement ) { current_node = current_node.parentElement; } else { break; } } } else if (i[0] == '$'){ //执行document.querySelector if (document.querySelector(i.substr(1)) != null){ return itemgroup[i]; } } else if (i[0] == '*'){ //搜索原始文本 if ( textori.includes(i.substr(1)) ){ return itemgroup[i]; } } // and more ... else{ CNITEM_DEBUG && console.log({text, itemgroup, dsc:"不识别的标签" + i}) } } return null; } //2.采集新词 //20190320@JAR rewrite by 麦子 var cnItem = function (text, node) { if (typeof (text) != "string") return text; let textori = text; //处理前缀 let text_prefix = ""; for (let prefix in cnPrefix) { if (text.substr(0, prefix.length) === prefix) { text_prefix += cnPrefix[prefix]; text = text.substr(prefix.length); } } //处理后缀 let text_postfix = ""; for (let postfix in cnPostfix) { if (text.substr(-postfix.length) === postfix) { text_postfix = cnPostfix[postfix] + text_postfix; text = text.substr(0, text.length - postfix.length); } } //处理正则后缀 let text_reg_exclude_postfix = ""; for (let reg of cnExcludePostfix) { let result = text.match(reg); if (result) { text_reg_exclude_postfix = result[0] + text_reg_exclude_postfix; text = text.substr(0, text.length - result[0].length); } } //检验字典是否可存 if (!cnItems._OTHER_) cnItems._OTHER_ = []; //检查是否排除 for (let reg of cnExcludeWhole) { if (reg.test(text)) { return text_prefix + text + text_reg_exclude_postfix + text_postfix;; } } //尝试正则替换 for (let [key, value] of cnRegReplace.entries()) { if (key.test(text)) { return text_prefix + text.replace(key, value) + text_reg_exclude_postfix + text_postfix; } } //遍历尝试匹配 for (let i in cnItems) { //字典已有词汇或译文、且译文不为空,则返回译文 if (typeof(cnItems[i]) == "string" && (text == i || text == cnItems[i])){ return text_prefix + cnItems[i] + text_reg_exclude_postfix + text_postfix; } else if ( typeof(cnItems[i]) == "object" && text == i ){ let result = cnItemByTag(i, cnItems[i], node, textori); if (result != null){ return text_prefix + result + text_reg_exclude_postfix + text_postfix; } else { CNITEM_DEBUG && console.log({text:i, cnitem:cnItems[i], node}); } } else { // continue; } } //调整收录的词条,0=收录原文,1=收录去除前后缀的文本 let save_cfg = 1; let save_text = save_cfg ? text : textori; //遍历生词表是否收录 for ( let i = 0; i < cnItems._OTHER_.length; i++ ) { //已收录则直接返回 if (save_text == cnItems._OTHER_[i]) return text_prefix + text + text_reg_exclude_postfix + text_postfix; } if (cnItems._OTHER_.length < 1000) { //未收录则保存 cnItems._OTHER_.push(save_text); cnItems._OTHER_.sort( function (a, b) { return a.localeCompare(b) } ); } //开启生词打印 CNITEM_DEBUG && console.log( '有需要汉化的英文:', text ); //返回生词字串 return text_prefix + text + text_reg_exclude_postfix + text_postfix; }; transTaskMgr = { tasks: [], addTask: function (node, attr, text) { this.tasks.push({ node, attr, text }) }, doTask: function () { let task = null; while (task = this.tasks.pop()) task.node[task.attr] = task.text; }, } function TransSubTextNode(node) { if (node.childNodes.length > 0) { for (let subnode of node.childNodes) { if (subnode.nodeName === "#text") { let text = subnode.textContent; let cnText = cnItem(text, subnode); cnText !== text && transTaskMgr.addTask(subnode, 'textContent', cnText); //console.log(subnode); } else if (subnode.nodeName !== "SCRIPT" && subnode.nodeName !== "STYLE" && subnode.nodeName !== "TEXTAREA") { if (!subnode.childNodes || subnode.childNodes.length == 0) { let text = subnode.innerText; let cnText = cnItem(text, subnode); cnText !== text && transTaskMgr.addTask(subnode, 'innerText', cnText); //console.log(subnode); } else { TransSubTextNode(subnode); } } else { // do nothing; } } } } ! function () { console.log("加载汉化模块"); let observer_config = { attributes: false, characterData: true, childList: true, subtree: true }; let targetNode = document.body; //汉化静态页面内容 TransSubTextNode(targetNode); transTaskMgr.doTask(); //监听页面变化并汉化动态内容 let observer = new MutationObserver(function (e) { //window.beforeTransTime = performance.now(); observer.disconnect(); for (let mutation of e) { if (mutation.target.nodeName === "SCRIPT"|| mutation.target.nodeName === "STYLE" || mutation.target.nodeName === "TEXTAREA") continue; if (mutation.target.nodeName === "#text") { mutation.target.textContent = cnItem(mutation.target.textContent, mutation.target); } else if (!mutation.target.childNodes || mutation.target.childNodes.length == 0) { mutation.target.innerText = cnItem(mutation.target.innerText, mutation.target); } else if (mutation.addedNodes.length > 0) { for (let node of mutation.addedNodes) { if (node.nodeName === "#text") { node.textContent = cnItem(node.textContent, node); //console.log(node); } else if (node.nodeName !== "SCRIPT" && node.nodeName !== "STYLE" && node.nodeName !== "TEXTAREA") { if (!node.childNodes || node.childNodes.length == 0) { if (node.innerText) node.innerText = cnItem(node.innerText, node); } else { TransSubTextNode(node); transTaskMgr.doTask(); } } } } } observer.observe(targetNode, observer_config); //window.afterTransTime = performance.now(); //console.log("捕获到页面变化并执行汉化,耗时" + (afterTransTime - beforeTransTime) + "毫秒"); }); observer.observe(targetNode, observer_config); }();
chs.js:
/* @name : 锅巴汉化 - Web汉化插件 @author : 麦子、JAR、小蓝、好阳光的小锅巴 @version : V0.6.1 - 2019-07-09 @website : http://www.g8hh.com @idle games : http://www.gityx.com @QQ Group : 627141737 */ //1.汉化杂项 var cnItems = { _OTHER_: [], //未分类: 'Save': '保存', 'Export': '导出', 'Import': '导入', "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", // 过滤不需要汉化的文本 'I': 'I', 'II': 'I', 'III': 'III', 'IV': 'IV', 'V': 'V', 'VI': 'VI', 'VII': 'VII', 'VIII': 'VIII', 'X': 'X', 'XI': 'XI', 'XII': 'XII', 'XIII': 'XIII', 'XIV': 'XIV', 'XV': 'XV', 'XVI': 'XVI', 'A': 'A', 'B': 'B', 'C': 'C', 'D': 'D', 'E': 'E', 'F': 'F', 'G': 'G', 'H': 'H', 'I': 'I', 'J': 'J', 'K': 'K', 'L': 'L', 'M': 'M', 'N': 'N', 'O': 'O', 'P': 'P', 'Q': 'Q', 'R': 'R', 'S': 'S', 'T': 'T', 'U': 'U', 'V': 'V', 'W': 'W', 'X': 'X', 'Y': 'Y', 'Z': 'Z', '': '', '': '', '': '', '': '', '': '', '': '', } //需处理的前缀,此处可以截取语句开头部分的内容进行汉化 var cnPrefix = { "\n": "\n", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": " ", " ": " ", //树游戏 "\t\t\t": "\t\t\t", "\n\n\t\t": "\n\n\t\t", "\n\t\t": "\n\t\t", "\t": "\t", "Show Milestones: ": "显示里程碑:", "Autosave: ": "自动保存: ", "Offline Prod: ": "离线生产: ", "Completed Challenges: ": "完成的挑战: ", "High-Quality Tree: ": "高质量树贴图: ", "Offline Time: ": "离线时间: ", "Theme: ": "主题: ", "Anti-Epilepsy Mode: ": "抗癫痫模式:", "In-line Exponent: ": "直列指数:", "Single-Tab Mode: ": "单标签模式:", "Time Played: ": "已玩时长:", "Shift-Click to Toggle Tooltips: ": "Shift-单击以切换工具提示:", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", "": "", } //需处理的后缀,此处可以截取语句结尾部分的内容进行汉化 //例如:13 Coin、14 Coin、15 Coin... 这种有相同结尾的语句 //可以在这里汉化结尾:" Coin":" 金币" var cnPostfix = { " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": "", " ": " ", " ": " ", "\n": "\n", "\n\t\t\t": "\n\t\t\t", "\t\t\n\t\t": "\t\t\n\t\t", "\t\t\t\t": "\t\t\t\t", "\n\t\t": "\n\t\t", "\t": "\t", "": "", "": "", "": "", "": "", "": "", "": "", } //需排除的,正则匹配 var cnExcludeWhole = [ /^(\d+)$/, /^\s*$/, //纯空格 /^([\d\.]+):([\d\.]+)$/, /^([\d\.]+):([\d\.]+):([\d\.]+)$/, /^([\d\.]+):([\d\.]+):([\d\.]+):([\d\.]+)$/, /^([\d\.]+):([\d\.]+):([\d\.]+):([\d\.]+):([\d\.]+)$/, /^([\d\.]+)h ([\d\.]+)m ([\d\.]+)s$/, /^([\d\.]+)y ([\d\.]+)d ([\d\.]+)h$/, /^([\d\.]+)\-([\d\.]+)\-([\d\.]+)$/, /^([\d\.]+)e(\d+)$/, /^([\d\.]+)$/, /^\(([\d\.]+)\)$/, /^([\d\.]+)\%$/, /^([\d\.]+)\/([\d\.]+)$/, /^\(([\d\.]+)\/([\d\.]+)\)$/, /^成本(.+)$/, /^\(([\d\.]+)\%\)$/, /^([\d\.]+):([\d\.]+):([\d\.]+)$/, /^([\d\.]+)K$/, /^([\d\.]+)M$/, /^([\d\.]+)B$/, /^([\d\.]+) K$/, /^([\d\.]+) M$/, /^([\d\.]+) B$/, /^([\d\.]+)s$/, /^([\d\.]+)x$/, /^x([\d\.]+)$/, /^([\d\.,]+)$/, /^\+([\d\.,]+)$/, /^\-([\d\.,]+)$/, /^([\d\.,]+)x$/, /^x([\d\.,]+)$/, /^([\d\.,]+) \/ ([\d\.,]+)$/, /^([\d\.]+)e([\d\.,]+)$/, /^([\d\.,]+)\/([\d\.]+)e([\d\.,]+)$/, /^([\d\.]+)e([\d\.,]+)\/([\d\.]+)e([\d\.,]+)$/, /^([\d\.]+)e\+([\d\.,]+)$/, /^e([\d\.]+)e([\d\.,]+)$/, /^x([\d\.]+)e([\d\.,]+)$/, /^([\d\.]+)e([\d\.,]+)x$/, /^[\u4E00-\u9FA5]+$/ ]; var cnExcludePostfix = [ ] //正则替换,带数字的固定格式句子 //纯数字:(\d+) //逗号:([\d\.,]+) //小数点:([\d\.]+) //原样输出的字段:(.+) //换行加空格:\n(.+) var cnRegReplace = new Map([ [/^([\d\.]+) hours ([\d\.]+) minutes ([\d\.]+) seconds$/, '$1 小时 $2 分钟 $3 秒'], [/^You are gaining (.+) elves per second$/, '你每秒获得 $1 精灵'], [/^You have (.+) points$/, '你有 $1 点数'], [/^Next at (.+) points$/, '下一个在 $1 点数'], [/^([\d\.]+)\/sec$/, '$1\/秒'], [/^([\d\.,]+)\/sec$/, '$1\/秒'], [/^([\d\.,]+) OOMs\/sec$/, '$1 OOMs\/秒'], [/^([\d\.]+) OOMs\/sec$/, '$1 OOMs\/秒'], [/^([\d\.]+)e([\d\.,]+)\/sec$/, '$1e$2\/秒'], [/^requires ([\d\.]+) more research points$/, '需要$1个研究点'], [/^([\d\.]+)e([\d\.,]+) points$/, '$1e$2 点数'], [/^([\d\.]+) elves$/, '$1 精灵'], [/^([\d\.]+)d ([\d\.]+)h ([\d\.]+)m$/, '$1天 $2小时 $3分'], [/^([\d\.]+)e([\d\.,]+) elves$/, '$1e$2 精灵'], [/^([\d\.,]+) elves$/, '$1 精灵'], [/^\*(.+) to electricity gain$/, '\*$1 到电力增益'], [/^Cost: (.+) points$/, '成本:$1 点数'], [/^Req: (.+) elves$/, '要求:$1 精灵'], [/^Req: (.+) \/ (.+) elves$/, '要求:$1 \/ $2 精灵'], [/^Usages: (\d+)\/$/, '用途:$1\/'], [/^workers: (\d+)\/$/, '工人:$1\/'], ]);
二、使用方法:
1、在网页的<body>下引入 chs.js 和 core.js 。
<body> <!-- 一般放在body下第一行的位置 --> <script src="chs.js"></script> <script src="core.js"></script> ... </body>
2、刷新页面,打开浏览器控制台,粘贴这句代码并回车,
cnItems._OTHER_
3、复制文本
然后就可以看到控制台输出了一个数组,里面就是脚本收集到的页面文本,可以选择需要汉化的语句,放在汉化文件里面进行汉化。
1、复制object是值复制所有文本为一个数组,需要粘贴到文本工具里面整理一下格式,再放到汉化文件里面。
2、可以复制单条语句依次进行汉化。
4、打开 chs.js,按左英文,右中文方式进行文本的录入。
"Effect": "效果", "Cost": "成本", "Goal:": "目标:", "Reward": "奖励", "Start": "开始", ...
5、保存脚本后,刷新页面查看效果。
转载请注明文章出处:锅巴汉化,本文地址:https://g8hh.cn/hanhua/plugns/8.html