// ==UserScript==
// @name Dream Incremental丨梦境增量 汉化脚本
// @namespace http://tampermonkey.net/
// @version 1.0.3
// @description 汉化脚本,安装即可用,支持汉化开关、后台挂机
// @author 技术:麦子、JAR、小蓝、好阳光的小锅巴 汉化:林雷丨LinLei_Baruch
// @match https://raceproxatedev.github.io/DreamIncremental/
// @match https://g8hh666.github.io/dream-incremental/
// @match https://dream-incremental.g8hh.com.cn/
// @icon http://www.abc.com
// @grant GM_info
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @connect scriptcat.org
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// ================= 更新检测 =================
const CURRENT_VERSION = GM_info.script.version;
const SCRIPT_NAME = GM_info.script.name;
const UPDATE_URL = 'https://www.tampermonkey.net/script_installation.php#url=https://scriptcat.org/scripts/code/6946/Dream%20Incremental%E4%B8%A8%E6%A2%A6%E5%A2%83%E5%A2%9E%E9%87%8F%20%E6%B1%89%E5%8C%96%E8%84%9A%E6%9C%AC.user.js';
const CHECK_INTERVAL = 60 * 60 * 1000;
function compareVersions(v1, v2) {
const parts1 = v1.split('.').map(Number);
const parts2 = v2.split('.').map(Number);
const maxLen = Math.max(parts1.length, parts2.length);
for (let i = 0; i < maxLen; i++) {
const a = parts1[i] || 0;
const b = parts2[i] || 0;
if (a < b) return -1;
if (a > b) return 1;
}
return 0;
}
function checkForUpdate(manual = false) {
const lastCheck = GM_getValue('last_update_check', 0);
const now = Date.now();
if (!manual && (now - lastCheck < CHECK_INTERVAL)) return;
GM_setValue('last_update_check', now);
GM_xmlhttpRequest({
method: 'GET',
url: UPDATE_URL,
headers: { 'Cache-Control': 'no-cache' },
onload: function(response) {
if (response.status === 200) {
const text = response.responseText;
const versionMatch = text.match(/@version\s+([^\s\n]+)/);
if (versionMatch) {
const remoteVersion = versionMatch[1].trim();
GM_setValue('remote_version', remoteVersion);
if (compareVersions(CURRENT_VERSION, remoteVersion) < 0) {
showUpdateNotification(remoteVersion);
} else if (manual) {
showToast('✅ 当前已是最新版本 v' + CURRENT_VERSION);
}
}
} else if (manual) {
showToast('❌ 检查更新失败,HTTP状态:' + response.status);
}
},
onerror: function() {
if (manual) {
showToast('❌ 检查更新失败,网络错误');
}
}
});
}
function showUpdateNotification(remoteVersion) {
const skippedVersion = GM_getValue('skipped_version', '');
if (skippedVersion === remoteVersion) return;
const styleEl = document.createElement('style');
styleEl.textContent = `
@keyframes guoba-overlay-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes guoba-dialog-in {
from { opacity: 0; transform: translateY(30px) scale(0.95); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes guoba-shimmer {
0% { background-position: -200% center; }
100% { background-position: 200% center; }
}
@keyframes guoba-pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.04); }
}
`;
document.head.appendChild(styleEl);
const overlay = document.createElement('div');
overlay.style.cssText = `
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
z-index: 2147483647;
display: flex; align-items: center; justify-content: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", sans-serif;
animation: guoba-overlay-in 0.3s ease;
`;
const dialog = document.createElement('div');
dialog.style.cssText = `
background: #1a1a2e;
border-radius: 16px;
max-width: 440px; width: 92%;
box-shadow: 0 25px 80px rgba(0, 0, 0, 0.5), 0 0 40px rgba(99, 102, 241, 0.15), inset 0 1px 0 rgba(255,255,255,0.05);
overflow: hidden;
animation: guoba-dialog-in 0.4s cubic-bezier(0.16, 1, 0.3, 1);
border: 1px solid rgba(255, 255, 255, 0.06);
`;
const titleBar = document.createElement('div');
titleBar.style.cssText = `
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%);
padding: 18px 24px;
position: relative;
overflow: hidden;
`;
const titleShimmer = document.createElement('div');
titleShimmer.style.cssText = `
position: absolute; top: 0; left: 0; right: 0; bottom: 0;
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.1) 50%, transparent 100%);
background-size: 200% 100%;
animation: guoba-shimmer 3s ease-in-out infinite;
pointer-events: none;
`;
titleBar.appendChild(titleShimmer);
const titleIcon = document.createElement('div');
titleIcon.style.cssText = `
display: flex; align-items: center; gap: 10px; position: relative; z-index: 1;
`;
titleIcon.innerHTML = `
⚠️
${SCRIPT_NAME}
锅巴汉化 · 汉化注入器
`;
titleBar.appendChild(titleIcon);
const closeBtn = document.createElement('div');
closeBtn.style.cssText = `
position: absolute; top: 14px; right: 16px; z-index: 2;
width: 28px; height: 28px; border-radius: 8px;
background: rgba(255,255,255,0.1);
display: flex; align-items: center; justify-content: center;
cursor: pointer; transition: all 0.2s;
color: rgba(255,255,255,0.7); font-size: 16px; line-height: 1;
`;
closeBtn.textContent = '✕';
closeBtn.addEventListener('mouseenter', () => {
closeBtn.style.background = 'rgba(255,255,255,0.2)';
closeBtn.style.color = '#fff';
});
closeBtn.addEventListener('mouseleave', () => {
closeBtn.style.background = 'rgba(255,255,255,0.1)';
closeBtn.style.color = 'rgba(255,255,255,0.7)';
});
closeBtn.addEventListener('click', () => {
overlay.style.opacity = '0';
setTimeout(() => { overlay.remove(); styleEl.remove(); }, 300);
});
titleBar.appendChild(closeBtn);
dialog.appendChild(titleBar);
const body = document.createElement('div');
body.style.cssText = `padding: 28px 28px 8px;`;
const header = document.createElement('div');
header.style.cssText = `text-align: center; margin-bottom: 22px;`;
header.innerHTML = `
🎉
发现新版本
更新以获取最新的汉化内容
`;
body.appendChild(header);
const versionCard = document.createElement('div');
versionCard.style.cssText = `
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.06);
border-radius: 12px;
padding: 16px 20px;
display: flex; align-items: center; justify-content: center; gap: 16px;
margin-bottom: 24px;
`;
versionCard.innerHTML = `
→
`;
body.appendChild(versionCard);
const actions = document.createElement('div');
actions.style.cssText = `display: flex; gap: 10px; margin-bottom: 16px;`;
const updateBtn = document.createElement('button');
updateBtn.textContent = '🚀 前往更新';
updateBtn.style.cssText = `
flex: 1; padding: 12px 20px;
background: linear-gradient(135deg, #6366f1, #8b5cf6);
color: #fff; border: none; border-radius: 10px;
font-size: 14px; font-weight: 600; cursor: pointer;
transition: all 0.25s;
box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
letter-spacing: 0.3px;
`;
updateBtn.addEventListener('mouseenter', () => {
updateBtn.style.transform = 'translateY(-1px)';
updateBtn.style.boxShadow = '0 6px 25px rgba(99, 102, 241, 0.45)';
});
updateBtn.addEventListener('mouseleave', () => {
updateBtn.style.transform = 'translateY(0)';
updateBtn.style.boxShadow = '0 4px 15px rgba(99, 102, 241, 0.3)';
});
updateBtn.addEventListener('click', () => {
window.open(UPDATE_URL, '_blank');
overlay.style.opacity = '0';
setTimeout(() => { overlay.remove(); styleEl.remove(); }, 300);
});
const skipBtn = document.createElement('button');
skipBtn.textContent = '稍后再说';
skipBtn.style.cssText = `
flex: 1; padding: 12px 20px;
background: rgba(255, 255, 255, 0.04);
color: #94a3b8; border: 1px solid rgba(255,255,255,0.08);
border-radius: 10px;
font-size: 14px; font-weight: 500; cursor: pointer;
transition: all 0.25s;
`;
skipBtn.addEventListener('mouseenter', () => {
skipBtn.style.background = 'rgba(255, 255, 255, 0.08)';
skipBtn.style.color = '#cbd5e1';
});
skipBtn.addEventListener('mouseleave', () => {
skipBtn.style.background = 'rgba(255, 255, 255, 0.04)';
skipBtn.style.color = '#94a3b8';
});
skipBtn.addEventListener('click', () => {
const skipCheckbox = document.getElementById('guoba-skip-version');
if (skipCheckbox && skipCheckbox.checked) {
GM_setValue('skipped_version', remoteVersion);
}
overlay.style.opacity = '0';
setTimeout(() => { overlay.remove(); styleEl.remove(); }, 300);
});
actions.appendChild(updateBtn);
actions.appendChild(skipBtn);
body.appendChild(actions);
const skipLabel = document.createElement('label');
skipLabel.style.cssText = `
display: flex; align-items: center; justify-content: center; gap: 6px;
padding: 10px 0 6px;
font-size: 12px; color: #475569; cursor: pointer;
transition: color 0.2s;
user-select: none;
`;
skipLabel.addEventListener('mouseenter', () => skipLabel.style.color = '#64748b');
skipLabel.addEventListener('mouseleave', () => skipLabel.style.color = '#475569');
skipLabel.innerHTML = `
不再提醒此版本
`;
body.appendChild(skipLabel);
dialog.appendChild(body);
overlay.appendChild(dialog);
overlay.addEventListener('click', (e) => {
if (e.target === overlay) {
overlay.style.opacity = '0';
setTimeout(() => { overlay.remove(); styleEl.remove(); }, 300);
}
});
document.body.appendChild(overlay);
}
function showToast(message) {
const toast = document.createElement('div');
toast.textContent = message;
toast.style.cssText = `
position: fixed; top: 24px; right: 24px;
background: linear-gradient(135deg, #1e1e2e, #2a2a3e);
color: #e2e8f0;
padding: 14px 22px;
border-radius: 12px;
font-size: 14px; font-weight: 500;
z-index: 2147483647;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255,255,255,0.05);
border: 1px solid rgba(255, 255, 255, 0.06);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", sans-serif;
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
transform: translateX(0);
backdrop-filter: blur(10px);
`;
document.body.appendChild(toast);
setTimeout(() => {
toast.style.opacity = '0';
toast.style.transform = 'translateX(30px)';
setTimeout(() => toast.remove(), 400);
}, 3000);
}
// 注册手动检查更新菜单
GM_registerMenuCommand("🔄 检查更新", () => checkForUpdate(true));
// 页面加载时自动检查更新
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => setTimeout(() => checkForUpdate(false), 3000));
} else {
setTimeout(() => checkForUpdate(false), 3000);
}
// ================= 开关控制 =================
const isEnabled = GM_getValue('translation_enabled', true);
GM_registerMenuCommand(isEnabled ? "🟢 汉化已开启 (点击关闭)" : "🔴 汉化已关闭 (点击开启)", () => {
GM_setValue('translation_enabled', !isEnabled);
location.reload();
});
const isBgRunEnabled = GM_getValue('background_run_enabled', false);
GM_registerMenuCommand(isBgRunEnabled ? "🟢 后台挂机已开启 (点击关闭)" : "🔴 后台挂机已关闭 (点击开启)", () => {
GM_setValue('background_run_enabled', !isBgRunEnabled);
location.reload();
});
// ================= 后台挂机注入 =================
if (isBgRunEnabled) {
const startBackgroundAudio = () => {
if (window.__bgAudioStarted) return;
const audio = new Audio('https://download.samplelib.com/mp3/sample-9s.mp3');
audio.loop = true;
audio.volume = 0.01;
audio.play().then(() => {
window.__bgAudioStarted = true;
console.log("🟢 锅巴汉化:后台挂机音频已启动,浏览器防休眠已激活!");
}).catch(() => {});
};
startBackgroundAudio();
const initAudioOnInteract = () => {
startBackgroundAudio();
if (window.__bgAudioStarted) {
document.removeEventListener('click', initAudioOnInteract);
document.removeEventListener('keydown', initAudioOnInteract);
}
};
document.addEventListener('click', initAudioOnInteract);
document.addEventListener('keydown', initAudioOnInteract);
const bgScript = document.createElement('script');
bgScript.textContent = `
(function() {
try {
Object.defineProperty(document, 'hidden', { get: () => false });
Object.defineProperty(document, 'webkitHidden', { get: () => false });
Object.defineProperty(document, 'visibilityState', { get: () => 'visible' });
const events = ['visibilitychange', 'webkitvisibilitychange', 'blur', 'focus', 'pagehide'];
for (let ev of events) {
document.addEventListener(ev, e => e.stopImmediatePropagation(), true);
window.addEventListener(ev, e => e.stopImmediatePropagation(), true);
}
console.log("🟢 锅巴汉化:游戏防暂停劫持已激活!");
} catch (e) {}
})();
`;
if (document.head || document.documentElement) {
(document.head || document.documentElement).appendChild(bgScript);
bgScript.remove();
}
}
if (!isEnabled) {
console.log("汉化注入器已关闭。");
return;
}
// ================= 字典数据 =================
const cnItems = {
//设置
'Dream Incremental':'梦境增量',
'Save': '保存',
"Settings": "设置",
'Data':'存档数据',
'Hard Reset':'硬重置',
'Export Save':'导出存档',
'Import Save':'导入存档',
'Automation':'自动化',
'Teleport': '传送',
'World 1':'世界 1',
//Automation 自动化
'Memory Upgrades Autobuyer: ON': '记忆升级自动购买:开启',
'Memory Upgrades Autobuyer: OFF': '记忆升级自动购买:关闭',
'Dream Upgrades Autobuyer: ON': '梦境升级自动购买:开启',
'Dream Upgrades Autobuyer: OFF': '梦境升级自动购买:关闭',
'Auto Buy Void Upgrades: ON': '自动购买虚空升级:开启',
'Auto Buy Void Upgrades: OFF': '自动购买虚空升级:关闭',
//Memory Upgrades 记忆升级
'Memory Upgrades':'记忆升级',
'Bought!': '已购买!',
//Dreamify 梦境
'Dreamify':'梦境',
'Dreamifying will reset your Memory and Memory Upgrades.': '“梦境”将重置你的记忆和记忆升级。',
'Wake up': '醒来',
'You need 10,000 Memories': '你需要 10,000 记忆',
'Dream Upgrades':'梦境升级',
//Rest 休息
'Rest':'休息',
'Resting will reset all Memory and Memory Upgrades (except permanent) and also all Dream and Dream Upgrades': '休息将重置所有记忆和记忆升级(永久除外),以及所有梦境和梦境升级。',
'Meet the requirement to Rest': '需要满足休息的条件',
'2x Memories, 1.5x Dreams':'2x 记忆,1.5x 梦境',
'+25% Dreams per Rest starting at 2 Rests': '从第 2 次休息开始,每次休息梦境 +25%',
'5x Memories, 2x Dreams, passively generate 1% of Dreams per second.': '5x 记忆,2x 梦境,每秒被动生成 1% 的梦境。',
'Automate Memory Upgrades.': '自动升级记忆。',
'Automate Dream Upgrades but 1.5x Rest Scalings.': '自动升级梦境,但休息缩放为 x1.5。',
'3x Dreams and Memories but 1.6x Rest Scalings.': '3x 梦境和记忆,但休息缩放为 x1.6。',
'10x Memories and 5x Dreams': '10x 记忆和 5x 梦境',
'+100 Memory Buyable 2 Cap.': '记忆可购买项 2 上限 +100。',
'Unlock the next layer. 1e100x Rest scalings.': '解锁下一层。休息缩放 x1e100。',
//Lucidify 清醒
'Lucidify': '清醒',
'Lucidifying will reset Everything before this.': '“清醒”将重置此前的所有内容。',
'Lucid Dream Upgrades': '清醒梦境升级',
'1.25x Lucid Dreams, 3x Dreams':'1.25x 清醒梦境,3x 梦境',
'100x Lucid Energy, 10x Memories':'100x 清醒能量,10x 记忆',
'1,000x Lucid Energy, 50x Memories':'1,000x 清醒能量,50x 记忆',
'^1.3 Lucid Energy, 333.3x Memories':'^1.3 清醒能量,333.3x 记忆',
'1e9x Lucid Energy, 10,000x Memories':'1e9x 清醒能量,10,000x 记忆',
'remember.': '记住。',
'1e20x Lucid Energy, ^1.25 Memories':'1e20x 清醒能量,^1.25 记忆',
'1e45x Lucid Energy, 100x Dreams, 10x Lucid Dreams':'1e45x 清醒能量,100x 梦境,10x 清醒梦境',
'1e100x Lucid Energy, ^1.25 Memories':'1e100x 清醒能量,^1.25 记忆',
//Infinitize 无限
'Infinitize':'无限',
'You reached your Memory limit, all your memories will be converted to Infinite Memories': '你已达到记忆上限,你所有的记忆将被转换为无限记忆。',
'Resets everything (yes, everything) at this point': '此时重置所有内容(是的,所有内容)。',
'You need 1.79e308 Memories': '你需要 1.79e308 记忆',
'Infinity Milestones':'无限里程碑',
'+1 Rest Bulk':'+1 批量休息',
'+100% Lucid Dreams per Infinitize': '每次无限化 +100% 清醒梦境',
'Dreams Reset nothing': '梦境不重置任何内容',
'+2 Rest Bulk':'+2 批量休息',
'Break Infinity': '突破无限',
'Unlock ???':'解锁 ???',
'Infinitize Upgrades':'无限升级',
'Infinitize Challenges':'无限挑战',
'Infinity Challenges':'无限挑战',
'Warning: Entering/Exitting a Challenge performs a Infinitize Reset': '警告:进入/退出挑战将执行一次无限化重置。',
'Start Challenge':'开始挑战',
'Exit Challenge':'退出挑战',
'Challenge Completed': '挑战已完成',
'Start?':'开始?',
'Memory Deficiency I': '记忆匮乏 I',
'Goal: 1.79e308 Memories':'目标:1.79e308 记忆',
'Reward: 3x Memories':'奖励:3x 记忆',
'Forgotten': '被遗忘的',
'Reward: 10x Dreams':'奖励:10x 梦境',
'World 2': '世界 2',
'ERROR':'错误',
'You cant turn back': '你无法回头',
'Goal: ???':'目标:???',
'Reward: ???':'奖励:???',
//Void 虚空
'Void Upgrades':'虚空升级',
//Think 思绪
'Think':'思绪',
'Thinking will reset your void and void Upgrades.': '“思绪”将重置你的虚空和虚空升级。',
'Meet the requirements': '需满足要求',
'2x Void, Unlock Thinking Energy':'2x 虚空,解锁思绪能量',
'5x Void, 2x Thinking Energy':'5x 虚空,2x 思绪能量',
'-^0.14 Void divider, 3.5x Thinking Energy':'-^0.14 虚空分隔器,3.5x 思绪能量',
'negate Void divider but disable Void upgrade #2 and 100x Think scalings.': '抵消虚空分隔器,但禁用虚空升级 #2 且思绪缩放为 x100。',
'2x Thinking Energy and 10x Void.':'2x 思绪能量和 10x 虚空。',
'Autobuy Void Upgrades (Just the first Upgrade).': '自动购买虚空升级(仅限第一项升级)。',
'^1.1 Void, Unlock ???':'^1.1 虚空, 解锁 ???',
'Thinking Energy':'思绪能量',
//Nightmare 梦魇
'Nightmare': '梦魇',
'Resets Everything before this point.': '重置此前的所有内容。',
'Not enough Void': '虚空不足',
'Dreamify formula is improved ((Memories/10,000)^0.6) -> ((Memories/8,000)^0.65)': '梦境化公式已改进 ((记忆/10,000)^0.6) -> ((记忆/8,000)^0.65)',
'5x Memories if Memories are less than 1,000': '若记忆少于 1,000,则 5x 记忆',
'1.5x Void if Void is less than 1e10': '若虚空少于 1e10,则 x1.5 虚空',
'3x Rest gain if Rest is less than 6': '若休息少于 6,则 x3 休息收益',
'/1.5 Dreams if Dreams are more than 1e30': '若梦境多于 1e30,则 /1.5 梦境',
'Improve heavily Lucid Dream formula': '大幅改进清醒梦境公式',
'Passively generates 1% of Lucid Dreams per second but /3 Lucid Dreams': '每秒被动生成 1% 的清醒梦境,但清醒梦境 /3',
'/10 Memory and Dreams': '/10 记忆和梦境',
'100x Memory if Memory is less than 1e20': '若记忆少于 1e20,则记忆 x100',
'Unlock a button in settings.': '在设置中解锁一个按钮。',
'Unlock Trials': '解锁试炼',
//Nightmare Trials 梦魇试炼
'Nightmare Trials':'梦魇试炼',
'Nightmare Trial 1':'梦魇试炼 1',
'Goal: Complete it.': '目标:完成它。',
'Reward: 100x Void': '奖励:100x 虚空',
//梦魇试炼 1
'Upgrade Tree': '升级树',
'Bought':'已购买',
'10 Shards': '10 碎片',
'200 Shards': '200 碎片',
'2x Shards, simple.': '2x 碎片,简单。',
'3x Shards': '3x 碎片',
'50 Shards': '50 碎片',
'Doubled #1': '翻倍 #1',
'Shards boosts themselves': '碎片增益自身',
'Synergied #3': '协同 #3',
'Tripled #2': '三倍 #2',
'+^0.05 #3 Effect': '+^0.05 #3 效果',
'+^0.1 #3 Effect': '+^0.1 #3 效果',
'+^0.2 to #3 Effect': '+^0.2 #3 效果',
'1,000,000 Shards': '1,000,000 碎片',
'10,000 Shards': '10,000 碎片',
'10x Shards': '10x 碎片',
'15,000 Shards': '15,000 碎片',
'150,000 Shards': '150,000 碎片',
'20,000 Shards': '20,000 碎片',
'25x Shards': '25x 碎片',
'2x Shards': '2x 碎片',
'4x Shards': '4x 碎片',
'80,000 Shards': '80,000 碎片',
'800 Shards': '800 碎片',
'Basic #11': '基础 #11',
'Exponential #8': '指数 #8',
'Great boost #7': '大幅提升 #7',
'Hyper Boost #6': '超强提升 #6',
'Prepare #10': '准备 #10',
'Synergied II #5': '协同 II #5',
'Synergied III #9': '协同 III #9',
'Synergied IV #13': '协同 IV #13',
'Tenfolded #4': '十倍 #4',
'Warmup #12': '热身 #12',
'^1.01 Shards': '^1.01 碎片',
'^1.1 Shards': '^1.1 碎片',
'1.25x Prestige Points': '1.25x 声望点',
'1.5x Shards': '1.5x 碎片',
'10 Energy': '10 能量',
'100 Energy': '100 能量',
'20 Prestige Points': '20 声望点数',
'2x Energy': '2x 能量',
'30 Energy': '30 能量',
'50 Prestige Points': '50 声望点数',
'Energetic #15': '充满能量 #15',
'Energy': '能量',
'Energy is useful #16': '能量很有用 #16',
'Powerful #17': '强大 #17',
'Prestige Points boost Shard Gain': '声望点数提升碎片获取',
'Prestigeful #18': '声望满载 #18',
'Synergied V #14': '协同 V #14',
'Unlock Energy': '解锁能量',
//声望
'This will reset Shards and Shard Upgrades [You need atleast 1e9 Shards]': '这将重置碎片和碎片升级 [你至少需要 1e9 碎片]',
'5 Prestige Points': '5 声望点数',
'2 Prestige Points': '2 声望点数',
'1 Prestige Point': '1 声望点数',
//无需汉化
'I': 'I', 'II': 'II', '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',
};
const 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",
};
const 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",
};
const cnExcludeWhole = [
/^(\d+)$/, /^\s*$/, /^([\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\.]+)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]+$/
];
const cnExcludePostfix = [];
const cnRegReplace = new Map([
[/^\+([\d.eE+-]+[KMBT]?)% Memories \[([\d.eE+-]+[KMBT]?)\/([\d.eE+-]+[KMBT]?)\]$/, '+$1% 记忆 [$2/$3]'],
[/^Unlock Dreams \[([\d.eE+-]+[KMBT]?)\/([\d.eE+-]+[KMBT]?)\] \[Permanent\]$/, '解锁梦境 [$1/$2] [永久]'],
[/^\+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Dreams on Reset$/, '重置时获得 +$1 梦境'],
[/^Dream Upgrades \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Dreams\]$/, '梦境升级 [$1 梦境]'],
[/^Unlock Rest \[([\d.eE+-]+[KMBT]?)\/([\d.eE+-]+[KMBT]?)\] \[Permanent\]$/, '解锁休息 [$1/$2] [永久]'],
[/^\+([\d.eE+-]+[KMBT]?)% Dreams \[([\d.eE+-]+[KMBT]?)\/([\d.eE+-]+[KMBT]?)\]$/, '+$1% 梦境 [$2/$3]'],
[/^Rest Milestones \[Rests: ([\d.eE+-]+[KMBT]?)\]$/, '休息里程碑 [休息: $1]'],
[/^You need ([\d.,eE+-]+[KMBT]?) Dreams$/, '你需要 $1 梦境'],
[/^\+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Lucid Dreams$/, '获得 +$1 清醒梦境'],
[/^Lucid Dream Upgrades \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Lucid Dreams\]$/, '清醒梦境升级 [$1 清醒梦境]'],
[/^\+1 Rest bulk \[([\d.eE+-]+[KMBT]?)\/([\d.eE+-]+[KMBT]?)\]$/, '+1 批量休息 [$1/$2]'],
[/^Unlock Lucid Energy \[([\d.eE+-]+[KMBT]?)\/([\d.eE+-]+[KMBT]?)\]$/, '解锁清醒能量 [$1/$2]'],
[/^Lucid Energy Milestones \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Lucid Energy \[\+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?)\/s\]\]$/, '清醒能量里程碑 [$1 清醒能量 [+$2/秒]]'],
[/^Infinitize \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Infinities\]$/, '无限化 [$1 无限]'],
[/^In return, \+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Infinity Dreams$/, '作为回报,+$1 无限梦境'],
[/Automatically Rest if you have the Rest requirements./,'若满足休息条件,则自动休息。'],
[/Unlock Infinity Challenges/,'解锁无限挑战'],
[/^Infinity Dream Upgrades \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Infinity Dreams\]$/, '无限梦境升级 [$1 无限梦境]'],
[/^Void: ([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) \[\+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?)\/s\] \[\/([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?)\]$/, '虚空:$1 [+$2/秒] [/$3]'],
[/^Thinking Milestones \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Thoughts\]$/, '思绪里程碑 [$1 思绪]'],
[/^You need ([\d.,eE+-]+[KMBT]?) Void$/, '你需要 $1 虚空'],
[/^Thinking Energy \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Thinking Energy \[\+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?)\/s\]\]$/, '思绪能量 [$1 思绪能量 [+$2/秒]]'],
[/^Nightmare Milestones \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Nightmares\]$/, '梦魇里程碑 [$1 梦魇]'],
[/^Shards: ([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) \[\+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?)\/s\] \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?)%\]$/, '碎片:$1 [+$2/秒] [$3%]'],
[/^Prestige \[([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Prestige Points\]$/, '声望 [$1 声望点数]'],
[/^\+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) Prestige Points$/, '+$1 声望点数'],
[/^Energy: ([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?) \[\+([\d,]+(?:\.\d+)?(?:[eE][+-]?\d+)?[KMBT]?)\/s\]$/, '能量:$1 [+$2/秒]'],
[/Infinity Dreams/,'无限梦境'],
[/Memories/,'记忆'],
[/Memory:/,'记忆:'],
[/\/s/,'/秒'],
[/Lucid Dreams/,'清醒梦境'],
[/Lucid Energy/,'清醒能量'],
[/Dreams/,'梦境'],
[/Rests/,'休息'],
[/Rest/,'休息'],
[/Infinity/,'无限'],
[/Infinities/,'无限'],
[/Void divider/,'虚空分隔器'],
[/Void/,'虚空'],
[/Unlock Toughts/,'解锁思绪'],
[/Permanent/,'永久'],
[/Thoughts/,'思绪'],
[/Thought/,'思绪'],
[/Nightmares/,'梦魇'],
[/Nightmare/,'梦魇'],
]);
// ================= 核心翻译逻辑 =================
function cnItem(text, node) {
if (typeof (text) != "string" || !text) return text;
let textori = text;
let text_prefix = "";
for (let prefix in cnPrefix) { if (text.startsWith(prefix)) { text_prefix += cnPrefix[prefix]; text = text.substr(prefix.length); } }
let text_postfix = "";
for (let postfix in cnPostfix) { if (text.endsWith(postfix)) { text_postfix = cnPostfix[postfix] + text_postfix; text = text.substr(0, text.length - postfix.length); } }
for (let reg of cnExcludeWhole) { if (reg.test(text.trim())) return textori; }
if (cnItems[text]) return text_prefix + cnItems[text] + text_postfix;
for (let [key, value] of cnRegReplace.entries()) {
if (key.test(text)) return text_prefix + text.replace(key, value) + text_postfix;
}
return textori;
}
function translateAttribute(el, attrName) {
const original = el.getAttribute(attrName);
if (!original) return;
const translated = cnItem(original, el);
if (translated !== original) el.setAttribute(attrName, translated);
}
function translateNode(rootNode) {
if (!rootNode) return;
let walker = document.createTreeWalker(rootNode, NodeFilter.SHOW_TEXT, null, false);
let textNode;
while (textNode = walker.nextNode()) {
let parent = textNode.parentNode;
if (parent && ['SCRIPT', 'STYLE', 'CODE'].includes(parent.nodeName)) continue;
let translated = cnItem(textNode.nodeValue, textNode);
if (textNode.nodeValue !== translated) textNode.nodeValue = translated;
}
const elements = rootNode.nodeType === Node.ELEMENT_NODE ? [rootNode, ...rootNode.querySelectorAll('*')] : rootNode.querySelectorAll?.('*') || [];
for (let el of elements) {
if (['SCRIPT', 'STYLE'].includes(el.tagName)) continue;
translateAttribute(el, 'placeholder');
translateAttribute(el, 'title');
translateAttribute(el, 'alt');
translateAttribute(el, 'aria-label');
translateAttribute(el, 'data-tooltip');
if (el.tagName === 'INPUT' && ['button', 'submit', 'reset'].includes(el.type)) {
const val = el.value;
const tVal = cnItem(val, el);
if (val !== tVal) el.value = tVal;
}
if (el.shadowRoot) translateNode(el.shadowRoot);
}
}
// ================= 翻译页面标题 =================
function translateTitle() {
const titleEl = document.querySelector('title');
if (!titleEl) return;
const original = titleEl.textContent;
if (!original) return;
const translated = cnItem(original, titleEl);
if (translated !== original) {
titleEl.textContent = translated;
console.log(`📝 标题翻译: "${original}" → "${translated}"`);
}
}
// ================= 启动与监听 =================
console.log("锅巴汉化:正在注入汉化...");
translateNode(document.body);
translateTitle();
// 监听 body 变化
const observer = new MutationObserver(function (mutations) {
for (let mutation of mutations) {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.TEXT_NODE) {
let t = cnItem(node.nodeValue, node);
if (node.nodeValue !== t) node.nodeValue = t;
} else if (node.nodeType === Node.ELEMENT_NODE) {
translateNode(node);
}
});
} else if (mutation.type === 'characterData') {
let t = cnItem(mutation.target.nodeValue, mutation.target);
if (mutation.target.nodeValue !== t) mutation.target.nodeValue = t;
} else if (mutation.type === 'attributes') {
const attr = mutation.attributeName;
const target = mutation.target;
if (['placeholder', 'title', 'alt', 'aria-label', 'data-tooltip'].includes(attr)) {
translateAttribute(target, attr);
} else if (attr === 'value' && target.tagName === 'INPUT') {
const tVal = cnItem(target.value, target);
if (target.value !== tVal) target.value = tVal;
}
}
}
});
observer.observe(document.body, {
childList: true, subtree: true, characterData: true,
attributes: true,
attributeFilter: ['placeholder', 'value', 'title', 'alt', 'aria-label', 'data-tooltip']
});
// ================= 监听标题变化 =================
// 1. 通过 MutationObserver 监听 元素变化
const titleObserver = new MutationObserver(() => {
translateTitle();
});
const titleEl = document.querySelector('title');
if (titleEl) {
titleObserver.observe(titleEl, {
childList: true,
characterData: true,
subtree: true
});
}
// 2. 劫持 document.title 的 setter(用于 SPA 动态修改标题)
const originalTitleDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'title');
if (originalTitleDescriptor && originalTitleDescriptor.set) {
Object.defineProperty(document, 'title', {
get: originalTitleDescriptor.get,
set: function(value) {
const translated = cnItem(value, this);
originalTitleDescriptor.set.call(this, translated);
},
configurable: true
});
}
// ================= 劫持浏览器弹窗进行翻译 =================
(function hijackDialogs() {
// 保存原始方法
const originalAlert = window.alert;
const originalConfirm = window.confirm;
const originalPrompt = window.prompt;
// 翻译函数(复用已有的 cnItem)
function translateDialogText(text) {
if (typeof text !== 'string' || !text) return text;
return cnItem(text, null);
}
// 劫持 alert
window.alert = function(message) {
const translated = translateDialogText(message);
if (translated !== message) {
console.log(`🔔 Alert 翻译: "${message}" → "${translated}"`);
}
return originalAlert(translated);
};
// 劫持 confirm
window.confirm = function(message) {
const translated = translateDialogText(message);
if (translated !== message) {
console.log(`❓ Confirm 翻译: "${message}" → "${translated}"`);
}
return originalConfirm(translated);
};
// 劫持 prompt
window.prompt = function(message, defaultValue) {
const translated = translateDialogText(message);
if (translated !== message) {
console.log(`📝 Prompt 翻译: "${message}" → "${translated}"`);
}
// defaultValue 也进行翻译(如果它存在且是字符串)
let translatedDefault = defaultValue;
if (typeof defaultValue === 'string' && defaultValue) {
translatedDefault = translateDialogText(defaultValue);
}
return originalPrompt(translated, translatedDefault);
};
console.log("🟢 锅巴汉化:弹窗劫持已激活 (alert/confirm/prompt)");
})();
// ================= 劫持 window.showModalDialog (旧式弹窗) =================
// 部分旧网站可能使用 showModalDialog,但已被废弃,这里做个兼容
if (window.showModalDialog) {
const originalShowModalDialog = window.showModalDialog;
window.showModalDialog = function(url, argument, features) {
// 这个函数无法直接翻译对话框内容,因为它是加载独立页面
// 但我们可以尝试翻译传入的 argument(如果有)
if (argument && typeof argument === 'string') {
const translated = cnItem(argument, null);
if (translated !== argument) {
console.log(`📦 showModalDialog argument 翻译: "${argument}" → "${translated}"`);
argument = translated;
}
}
return originalShowModalDialog.call(this, url, argument, features);
};
}
})();