最开始锅巴汉化的那些网页放置游戏,采用的是源码汉化的方式。这个方式的坏处就是会无意间汉化到游戏的变量,以及同步英文版时,往往需要重新汉化,费时费力。
后来为了在汉化网页放置游戏时可以保证和英文版同步更新,咱们的麦子大佬帮忙优化了一波,最终形成了此插件。
话不多说,咱们先来看看这个汉化脚本是怎么使用的。
一、新建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、保存脚本后,刷新页面查看效果。
转载请注明文章出处:锅巴汉化,本文地址:http://g8hh.cn/hanhua/plugns/8.html


