// ==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 = `
当前版本
v${CURRENT_VERSION}
最新版本
v${remoteVersion}
`; 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); }; } })();