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) => (
-
- ))}
-
- */}
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() {
+
+
+
+
+
+