From c993c15c9226e53ac0df34768d053628ebdfffb2 Mon Sep 17 00:00:00 2001 From: Gabe Date: Wed, 1 Oct 2025 21:18:53 +0800 Subject: [PATCH] feat: support translate all now --- src/common.js | 2 +- src/config/i18n.js | 6 ++--- src/config/rules.js | 2 +- src/config/setting.js | 1 + src/libs/detect.js | 4 ++-- src/libs/translator.js | 45 ++++++++++++++++++++++++++---------- src/views/Options/Rules.js | 19 --------------- src/views/Options/Setting.js | 15 ++++++++++++ 8 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/common.js b/src/common.js index 20d32ac..93d7bc5 100644 --- a/src/common.js +++ b/src/common.js @@ -201,7 +201,7 @@ export async function run(isUserscript = false) { // 翻译网页 const rule = await matchRule(href, setting); - const translator = new Translator(rule, setting); + const translator = new Translator(rule, setting, isUserscript); // 适配iframe if (isIframe) { diff --git a/src/config/i18n.js b/src/config/i18n.js index a406844..9850da4 100644 --- a/src/config/i18n.js +++ b/src/config/i18n.js @@ -355,9 +355,9 @@ export const I18N = { zh_TW: `滾動載入翻譯(建議)`, }, mk_pageopen: { - zh: `页面打开全部翻译`, - en: `Page Open`, - zh_TW: `頁面開啟全部翻譯`, + zh: `立即全部翻译`, + en: `Translate all now`, + zh_TW: `立即全部翻譯`, }, mk_mouseover: { zh: `鼠标悬停翻译`, diff --git a/src/config/rules.js b/src/config/rules.js index 8b2f0e1..3ad3ed0 100644 --- a/src/config/rules.js +++ b/src/config/rules.js @@ -73,7 +73,7 @@ background: linear-gradient( export const DEFAULT_SELECTOR = "h1, h2, h3, h4, h5, h6, li, p, dd, blockquote, figcaption, label, legend"; export const DEFAULT_IGNORE_SELECTOR = - "aside, button, footer, form, header, pre, mark, nav"; + "aside, button, footer, form, pre, mark, nav"; export const DEFAULT_KEEP_SELECTOR = `a:has(code)`; export const DEFAULT_RULE = { pattern: "", // 匹配网址 diff --git a/src/config/setting.js b/src/config/setting.js index f86ebcf..6066974 100644 --- a/src/config/setting.js +++ b/src/config/setting.js @@ -149,4 +149,5 @@ export const DEFAULT_SETTING = { langDetector: OPT_TRANS_MICROSOFT, // 远程语言识别服务 mouseHoverSetting: DEFAULT_MOUSE_HOVER_SETTING, // 鼠标悬停翻译 preInit: true, // 是否预加载脚本 + transAllnow: false, // 是否立即全部翻译 }; diff --git a/src/libs/detect.js b/src/libs/detect.js index 32f52e1..7745a53 100644 --- a/src/libs/detect.js +++ b/src/libs/detect.js @@ -51,9 +51,9 @@ export const tryDetectLang = async ( try { const res = await browser?.i18n?.detectLanguage(text); const lang = res?.languages?.[0]?.language; - if (OPT_LANGS_MAP.has(lang)) { + if (lang && OPT_LANGS_MAP.has(lang)) { deLang = lang; - } else if (lang.startsWith("zh")) { + } else if (lang?.startsWith("zh")) { deLang = "zh-CN"; } } catch (err) { diff --git a/src/libs/translator.js b/src/libs/translator.js index e0eec53..ef1bee6 100644 --- a/src/libs/translator.js +++ b/src/libs/translator.js @@ -309,7 +309,7 @@ export class Translator { return `${Translator.BUILTIN_IGNORE_SELECTOR}, ${this.#rule.ignoreSelector}`; } - constructor(rule = {}, setting = {}, isUserscript) { + constructor(rule = {}, setting = {}, isUserscript = false) { this.#setting = { ...Translator.DEFAULT_OPTIONS, ...setting }; this.#rule = { ...Translator.DEFAULT_RULE, ...rule }; this.#apiSetting = @@ -767,6 +767,16 @@ export class Translator { // 开始/重新监控节点 #startObserveNode(node) { + if ( + !this.#observedNodes.has(node) && + this.#enabled && + this.#setting.transAllnow + ) { + this.#observedNodes.add(node); + this.#processNode(node); + return; + } + // 未监控 if (!this.#observedNodes.has(node)) { this.#observedNodes.add(node); @@ -992,7 +1002,10 @@ export class Translator { wrapper.appendChild(inner); nodes[nodes.length - 1].after(wrapper); - this.#translationNodes.set(wrapper, nodes); + this.#translationNodes.set(wrapper, { + nodes, + isHide: transOnly === "true", + }); const currentRunId = this.#runId; try { @@ -1210,8 +1223,9 @@ export class Translator { this.#processedNodes.delete(el.parentElement); // 如果是仅显示译文模式,先恢复原文 - if (this.#rule.transOnly === "true") { - this.#restoreOriginal(el); + const { nodes, isHide } = this.#translationNodes.get(el) || {}; + if (isHide) { + this.#restoreOriginal(el, nodes); } this.#translationNodes.delete(el); @@ -1219,8 +1233,7 @@ export class Translator { } // 恢复原文 - #restoreOriginal(el) { - const nodes = this.#translationNodes.get(el); + #restoreOriginal(el, nodes) { if (nodes) { const frag = document.createDocumentFragment(); nodes.forEach((n) => frag.appendChild(n)); @@ -1231,23 +1244,27 @@ export class Translator { // 移除多个节点 #removeNodes(nodes) { - const frag = document.createDocumentFragment(); - nodes.forEach((n) => frag.appendChild(n)); + if (nodes) { + const frag = document.createDocumentFragment(); + nodes.forEach((n) => frag.appendChild(n)); + } } // 切换译文和双语显示 #toggleTranslationOnly(node, transOnly) { this.#findTranslationWrappers(node).forEach((el) => { const br = el.querySelector(":scope > br"); + const { nodes } = this.#translationNodes.get(el) || {}; if (transOnly === "true") { // 双语变为仅译文 if (br) br.hidden = true; - const nodes = this.#translationNodes.get(el) || []; this.#removeNodes(nodes); + this.#translationNodes.set(el, { nodes, isHide: true }); } else { // 仅译文变为双语 - this.#restoreOriginal(el); if (br) br.hidden = false; + this.#restoreOriginal(el, nodes); + this.#translationNodes.set(el, { nodes, isHide: false }); } }); } @@ -1396,7 +1413,11 @@ export class Translator { this.#runId++; if (this.#isInitialized) { - this.#reIOViewNodes(); + if (this.#setting.transAllnow) { + this.rescan(); + } else { + this.#reIOViewNodes(); + } } else { this.#init(); } @@ -1507,7 +1528,7 @@ export class Translator { } } - if (needsRescan) { + if (needsRescan || (this.#enabled && this.#setting.transAllnow)) { this.rescan(); return; } diff --git a/src/views/Options/Rules.js b/src/views/Options/Rules.js index 110c632..e99f449 100644 --- a/src/views/Options/Rules.js +++ b/src/views/Options/Rules.js @@ -474,25 +474,6 @@ function RuleFields({ rule, rules, setShow, setKeyword }) { onChange={handleChange} /> - {/* - - {GlobalItem} - {OPT_TIMING_ALL.map((item) => ( - - {i18n(item)} - - ))} - - */} diff --git a/src/views/Options/Setting.js b/src/views/Options/Setting.js index 3b5b25c..c7d0c5d 100644 --- a/src/views/Options/Setting.js +++ b/src/views/Options/Setting.js @@ -122,6 +122,7 @@ export default function Settings() { preInit = true, skipLangs = [], detectRemote = true, + transAllnow = false, } = setting; const { isHide = false, fabClickAction = 0 } = fab || {}; @@ -300,6 +301,20 @@ export default function Settings() { {i18n("secondary_context_menus")} + + + {i18n("mk_pagescroll")} + {i18n("mk_pageopen")} + +