()
| 24 | |
| 25 | // 恢复原文内容 |
| 26 | export function restoreOriginalContent() { |
| 27 | // 取消所有等待中的翻译任务 |
| 28 | cancelAllTranslations(); |
| 29 | |
| 30 | // 1. 遍历所有已翻译的节点 |
| 31 | document.querySelectorAll(`[${TRANSLATED_ATTR}="true"]`).forEach(node => { |
| 32 | const nodeId = node.getAttribute(TRANSLATED_ID_ATTR); |
| 33 | if (nodeId && originalContents.has(nodeId)) { |
| 34 | const originalContent = originalContents.get(nodeId); |
| 35 | node.innerHTML = originalContent; |
| 36 | node.removeAttribute(TRANSLATED_ATTR); |
| 37 | node.removeAttribute(TRANSLATED_ID_ATTR); |
| 38 | |
| 39 | // 移除可能添加的翻译相关类 |
| 40 | node.classList.remove('fluent-read-bilingual'); |
| 41 | } |
| 42 | }); |
| 43 | |
| 44 | // 2. 移除所有翻译内容元素 |
| 45 | document.querySelectorAll('.fluent-read-bilingual-content').forEach(element => { |
| 46 | element.remove(); |
| 47 | }); |
| 48 | |
| 49 | // 3. 移除所有翻译过程中添加的加载动画和错误提示 |
| 50 | document.querySelectorAll('.fluent-read-loading, .fluent-read-retry-wrapper').forEach(element => { |
| 51 | element.remove(); |
| 52 | }); |
| 53 | |
| 54 | // 4. 清空存储的原始内容 |
| 55 | originalContents.clear(); |
| 56 | |
| 57 | // 5. 停止所有观察器 |
| 58 | if (observer) { |
| 59 | observer.disconnect(); |
| 60 | observer = null; |
| 61 | } |
| 62 | if (mutationObserver) { |
| 63 | mutationObserver.disconnect(); |
| 64 | mutationObserver = null; |
| 65 | } |
| 66 | |
| 67 | // 6. 重置所有翻译相关的状态 |
| 68 | isAutoTranslating = false; |
| 69 | htmlSet.clear(); // 清空防抖集合 |
| 70 | nodeIdCounter = 0; // 重置节点ID计数器 |
| 71 | |
| 72 | // 7. 消除可能存在的全局样式污染 |
| 73 | const tempStyleElements = document.querySelectorAll('style[data-fr-temp-style]'); |
| 74 | tempStyleElements.forEach(el => el.remove()); |
| 75 | } |
| 76 | |
| 77 | // 自动翻译整个页面的功能 |
| 78 | export function autoTranslateEnglishPage() { |
no test coverage detected