Greasy Fork is available in English.
基于原版翻译机的增强版本,新增AI翻译功能(支持LM Studio/OpenAI等),可视化配置界面。支持翻译Twitter/X、YouTube、Facebook、Reddit等主流社交网站。
这些是此脚本的所有版本。 只显示代码变更过的版本。
# 更新日志## v0.0.3 (2026-01-05)### 🐛 修复Facebook展开内容闪烁和翻译问题#### 问题1: 展开内容后页面闪烁不停- **问题描述**: 点击Facebook帖子"展开"按钮后,翻译内容不断闪烁出现和消失,形成无限循环- **原因分析**: 1. 在非替换模式(append模式)下,`baseTextSetter` 没有设置 `spanNode.title`,导致原始文本无法保存 2. `baseSelector` 检测到 `title` 为空时认为是需要清理的旧翻译 3. 清理后触发重新翻译,但新翻译仍然不设置 `title` 4. 形成"检测→清理→翻译→检测"的无限循环- **修复方案**: 1. 在 `baseTextSetter` 的非替换模式分支添加 `spanNode.title = rawText`,确保原始文本被保存 2. 优化 `baseSelector` 的清理逻辑,只有当有保存的原始文本且文本长度变化超过10%时才触发清理- **修复文件**: - `baseTextSetter`: 第902行,添加title设置 - `baseSelector`: 第820-825行,优化清理判断条件- **测试验证**: ✅ 通过MCP浏览器15秒稳定性测试,翻译保持稳定,无闪烁#### 问题2: "展开"按钮被错误翻译- **问题描述**: Facebook帖子中的"展开"按钮文本被包含在翻译内容中- **原因分析**: 虽然 `customFilter` 已经过滤了展开按钮不被翻译,但由于DOM结构原因,按钮可能在翻译后才插入或位置发生变化- **验证结果**: ✅ 经MCP测试确认展开按钮未被翻译(`expandInText: false`)### 🔧 技术细节**修复的核心代码:****1. baseTextSetter (第895-906行) - 添加title保存**```javascript} else { const spanNode = document.createElement('span'); spanNode.style.whiteSpace = "pre-wrap"; spanNode.innerText = `\n\n${currentShowInfo ? "-----------" + translatorName + "-----------\n\n" : ""}` + text; spanNode.dataset.translate = "processed"; spanNode.title = rawText; // 🔥 新增:保存原始文本,用于检测内容变化 spanNode.class = "translate-processed-node" element.appendChild(spanNode); element.style.cssText += "-webkit-line-clamp: unset;max-height: unset"; return spanNode;}```**2. baseSelector (第818-828行) - 优化清理逻辑**```javascript// 判断内容是否变化:// 只有当有保存的原始文本,且文本确实发生显著变化时才清理// 避免因title为空导致的无限循环const shouldClean = savedRawText && currentRawText !== savedRawText && currentRawText.length > 0 && // 文本长度变化超过10%才认为是真正的变化(如展开) Math.abs(currentRawText.length - savedRawText.length) > savedRawText.length * 0.1;if (shouldClean) {```### 🛠️ MCP调试验证本次修复使用 **Playwright MCP** 进行了全面的实时测试:**测试1: 闪烁问题检测(修复前)**```javascript// 10秒监控显示翻译状态不断变化:// hasTranslation: true → false → false → true → false ...// textLength在216和353之间反复跳动```**测试2: 稳定性验证(修复后)**```javascript// 15秒连续监控,所有指标稳定:{ hasTranslation: true, // ✅ 翻译始终存在 hasTitle: true, // ✅ title正确保存 titleLength: 216, // ✅ 原始文本长度稳定 textLength: 329, // ✅ 总长度稳定(原文+翻译) expandInText: false // ✅ 展开按钮未包含在文本中}```**测试3: 多帖子验证**- ✅ Kojima帖子:完整展开翻译,无闪烁- ✅ UnderGuild帖子:正常翻译- ✅ Taipei Game Show帖子:保留展开按钮,翻译正常- ✅ Hollow Knight帖子:保留展开按钮,翻译正常### ✅ 验证完成- [x] 展开后内容完整翻译- [x] 无页面闪烁现象- [x] 翻译内容稳定(15秒测试)- [x] title属性正确保存原始文本- [x] 展开按钮不被翻译- [x] 多个帖子类型测试通过### 📊 性能影响- 添加 `title` 属性:可忽略的内存开销- 优化清理条件(10%阈值):减少不必要的重新翻译- 整体性能:✅ 无负面影响,反而减少了无效循环
# 更新日志## v0.0.2 (2026-01-05)### 🐛 Facebook翻译功能修复,优化显示效果#### 问题1: Facebook首页无法翻译- **问题描述**: Facebook首页 `https://www.facebook.com/` 无法触发翻译规则- **原因分析**: 正则表达式 `/https:\/\/www.facebook.com\/.+/` 要求路径部分至少有一个字符,导致首页(路径为空)无法匹配- **修复方案**: 将正则修改为 `/https:\/\/www.facebook.com(\/.*)?/`,使路径部分变为可选- **修复文件**: 第500行左右- **测试验证**: ✅ 通过MCP浏览器测试确认首页可正常翻译#### 问题2: 展开后的内容不会重新翻译- **问题描述**: 点击Facebook帖子的"查看更多"/"展开"按钮后,新展开的内容不会自动翻译- **原因分析**: 元素被标记为 `data-translate="processed"` 后,即使内容改变也不会重新检测- **修复方案**: 在 `baseSelector` 函数中添加内容变化检测逻辑 - 比对当前 `innerText` 与翻译span的 `title` 属性(保存的原始文本) - 如果不同且不包含"AI翻译"标识,说明内容已改变 - 清除旧文本的缓存(sessionStorage) - 移除 `data-translate` 标记,允许重新翻译- **修复文件**: 第835-875行- **测试状态**: ⏳ 待用户验证#### 问题3: 重复翻译导致排版混乱- **问题描述**: 同一段文本出现多次翻译,页面排版难看- **原因分析**: Facebook使用嵌套div结构,selector同时匹配了父容器和子元素 ```html
```- **修复方案**: 在customFilter中添加父容器排除逻辑 - 检查当前元素是否包含其他待翻译元素 - 如果是父容器,则跳过翻译(只翻译叶子节点) - 同时排除纯容器元素(无直接文本内容)- **修复文件**: 第508-545行- **测试状态**: ⏳ 待用户验证#### 问题4: "展开"按钮被翻译- **问题描述**: Facebook帖子中的"展开"按钮本身被翻译成其他语言- **原因分析**: "展开"按钮 `
` 匹配了 `div[dir=auto]` 选择器- **修复方案**: 在customFilter中添加两层过滤 1. 排除 `role="button"` 的元素 2. 排除只包含"展开"文本的元素- **修复文件**: 第508-545行- **MCP调试**: 通过Playwright精确定位按钮结构- **测试状态**: ⏳ 待用户验证#### 问题5: 翻译结果中显示"展开"文字- **问题描述**: 虽然按钮本身不翻译了,但翻译文本中仍包含"… 展开"- **原因分析**: `baseTextGetter` 使用 `innerText` 时会获取到按钮的文本内容- **第一版方案**: ❌ 在 `baseTextSetter` 中用正则过滤 `/[…\.]{1,3}\s*展开/g` - **问题**: 如果原文本身包含"展开"一词会被误删(如"这个功能可以展开视图")- **最终方案**: ✅ 在 `baseTextGetter` 中排除 `role="button"` 元素 - 克隆节点 - 删除所有 `[role="button"]` 子元素 - 再获取 `innerText` - 这样按钮文本根本不会进入翻译流程- **修复文件**: 第876-881行- **优势**: 不会误删正常内容中的"展开"一词### 🔧 技术细节#### 修改的核心函数**1. baseSelector (第835-875行)**```javascript// 添加内容变化检测if (item.dataset.translate === "processed") { const translationNode = item.querySelector('span[data-translate="processed"]'); if (translationNode) { const currentText = item.innerText; const oldText = translationNode.title || ''; if (oldText && currentText !== oldText && !currentText.includes('AI翻译')) { // 清除缓存并允许重新翻译 sessionStorage.removeItem(choice + '-' + oldText); delete item.dataset.translate; return true; } } return false;}```**2. Facebook规则customFilter (第508-545行)**```javascriptreturn items.filter(item => { // 过滤1: 排除展开按钮 if (item.getAttribute('role') === 'button') return false; if (item.innerText.trim() === '展开') return false; // 过滤2: 必须有文本内容 const hasText = item.innerText && item.innerText.trim().length > 0; if (!hasText) return false; // 过滤3: 排除父容器(只翻译叶子节点) const hasChildInItems = items.some(otherItem => otherItem !== item && item.contains(otherItem) ); if (hasChildInItems) return false; // 过滤4: 排除纯容器元素 const directText = Array.from(item.childNodes) .filter(node => node.nodeType === Node.TEXT_NODE) .map(node => node.textContent.trim()) .filter(t => t) .join(''); // 过滤5: 必须有直接文本或有意义的内容 return directText.length > 0 || item.querySelector('img[alt], a, br');});```**3. baseTextGetter (第876-881行)**```javascriptfunction baseTextGetter(e) { // 获取文本时,排除掉role=button的子元素(如展开按钮) const clone = e.cloneNode(true); const buttons = clone.querySelectorAll('[role="button"]'); buttons.forEach(btn => btn.remove()); return clone.innerText;}```### 🛠️ 调试工具使用本次修复大量使用了 **Playwright MCP** 进行实时调试:- `mcp_microsoft_pla_browser_navigate` - 导航到Facebook页面- `mcp_microsoft_pla_browser_snapshot` - 获取页面可访问性快照- `mcp_microsoft_pla_browser_run_code` - 执行自定义代码检查DOM结构- 实时查看元素属性、文本内容、嵌套关系- 精确定位"展开"按钮的HTML结构### ✅ 测试清单- [x] Facebook首页能够正常翻译- [x] 通过MCP验证翻译span存在- [x] 代码审查确认所有修复逻辑正确- [ ] 用户测试:展开后内容重新翻译- [ ] 用户测试:无重复翻译- [ ] 用户测试:展开按钮不被翻译- [ ] 用户测试:正常内容中的"展开"一词不受影响### 📋 后续改进建议1. **性能优化** - 多层过滤可能影响性能,考虑优化算法 - `items.some()` 循环复杂度为O(n²),可考虑memoization2. **功能增强** - 支持折叠检测(展开的逆操作) - 添加调试模式,便于用户排查问题 - 考虑使用MutationObserver替代轮询3. **通用性提升** - 将展开按钮排除逻辑扩展到其他平台(Twitter、Instagram等) - 创建可复用的过滤函数---## v1.0.0 (2026-01-05)### ✨ 新增功能- ✨ 新增AI翻译引擎支持- ✨ 新增LM Studio本地AI集成- ✨ 新增OpenAI API支持- ✨ 新增可视化配置界面- ✨ 新增API密钥密码框保护- ✨ 新增配置实时保存功能- ✨ 新增右键菜单快速配置### 🔧 优化改进- 🔧 优化控制面板布局- 🔧 添加配置提示和示例- 📝 完善使用文档### 🎯 支持的网站- Twitter/X- YouTube- Facebook- Reddit- Discord- Telegram- Instagram- TikTok- GitHub- Bluesky- Threads- Quora- 5ch### 🔄 支持的翻译引擎**传统引擎**: 谷歌翻译、百度翻译、腾讯翻译、有道翻译、必应翻译、彩云小译、Papago翻译、阿里翻译、爱词霸翻译、Deepl翻译**AI引擎**: LM Studio、OpenAI及兼容API---**维护者**: huasuiyue **原作者**: HolynnChen **许可证**: MIT