KISS Translator 简约翻译:开源双语翻译扩展与油猴脚本的安装、配置与自定义接口全指南

原创2026-10-02 13:30:30653 阅读
文章标签:前端

KISS Translator 简约翻译:开源双语翻译扩展与油猴脚本的安装、配置与自定义接口全指南

导读

本文围绕 KISS Translator(简约翻译)项目的英文文档 README.en.md,系统讲解这一开源双语对照翻译扩展与油猴脚本的完整能力:从浏览器扩展与油猴脚本的安装方式、六大翻译场景、自定义快捷键,到"个人规则 > 订阅规则 > 全局规则"的规则优先级体系,再到自定义 API 与 Hook 的高级接入方案。读完本文,你将掌握 KISS Translator 的日常使用、常见故障排查(如 Ollama 接口测试失败)以及基于 Custom API 接入任意翻译服务的完整实操路径,并了解其源码级的实现原理。

项目定位:简约、开源、双语对照

KISS Translator 是一个"简约、开源的双语对照翻译扩展 & 油猴脚本",其英文文档开篇即点明项目理念:保持简单(Keep it simple, smart) 与 开放源代码。它不是一个单一定制功能的工具,而是一套覆盖"网页全文翻译、输入框翻译、划词翻译、悬停翻译、YouTube 字幕翻译"等主流场景的翻译工作台。

从仓库结构看,项目的双形态交付体现在:

  • 浏览器扩展形态:以 public/manifest.json 为入口,采用 Manifest V3,content_scripts 注入 content.js 并覆盖 <all_urls> 与 file://*/*;
  • 油猴脚本形态:通过 REACT_APP_CLIENT=userscript 构建,相关逻辑集中在 src/userscript.js,以 kiss-translator.user.js 形式分发。

文档明确建议优先使用浏览器扩展,原因是扩展功能更完整(本地语言识别、右键菜单等),而油猴脚本会面临更多使用问题(跨域问题、脚本冲突等)。这一建议也与仓库的构建脚本分工一致:pnpm build 会同时产出 chrome、edge、thunderbird、firefox、web、userscript-ios 等多个目标(见 package.json)。

六大核心翻译场景

README 将项目能力归纳为覆盖"常见翻译场景"的完整矩阵,下面结合源码逐一展开。

1. 网页双语对照翻译

这是项目的主打能力。它同时支持自动识别文本与手动规则两种模式:

  • 自动识别模式:绝大多数网站无需编写规则即可翻译完整;
  • 手动规则模式:可针对特定网站做极致优化。

翻译结果支持富文本翻译与渲染,尽量保留原文中的链接及其他文本样式;同时提供"仅显示译文(隐藏原文)"的开关。翻译样式(下划线、背景色等)均可自定义,相关默认样式定义在 src/config/styles.js。

2. 输入框翻译

通过快捷键即时将输入框内的文本翻译成其他语言,对应的快捷键为 Alt+I。该能力的核心实现在 src/libs/inputTranslate.js,并有配套测试 inputTranslate.test.js 覆盖其行为。

3. 划词翻译

在任意页面划选文字即可打开翻译弹窗,支持:

  • 多服务对比翻译:可用多种翻译服务同时翻译并对比结果;
  • 英文词典查询:内置 Bing、Youdao 等词典服务(常量定义见 src/config/api.js 中的 OPT_DICT_BING、OPT_DICT_YOUDAO);
  • 收藏词汇:可将生词保存到词汇本,相关组件与状态管理位于 src/views/Selection/FavBtn.js 与 src/hooks/FavWords.js。

4. 鼠标悬停翻译

悬停到网页段落即可触发翻译(toggle_hover_node 动作),相关实现可参考 src/hooks/MouseHover.js。

5. YouTube 字幕翻译

这是项目的特色功能之一,能力包括:

  • 支持任意翻译服务对视频字幕进行翻译并双语显示;
  • 内置基础的字幕合并与断句算法,提升翻译质量;
  • 支持 AI 断句 功能,进一步提升效果;
  • 字幕样式可自定义。

源码层面,src/subtitle/ 目录是一套完整的字幕子系统,包含 BilingualSubtitleManager.js(双语字幕管理)、YouTubeCaptionProvider.js(YouTube 字幕源)、sentenceBreaker.js(断句)与 youtubeAiSegmentation.js(AI 断句),并通过 src/injectors/xmlhttp.js 拦截字幕请求。manifest.json 中也将 injector-subtitle.js 声明为仅在 https://www.youtube.com/* 下可访问的资源。

6. 独立翻译窗与设置弹窗

Alt+D 打开独立翻译窗口,Alt+K 打开设置弹窗,Alt+O 打开完整设置页面,为桌面网页外的场景提供灵活入口。

支持的翻译服务与底层常量

README 列出的翻译服务覆盖传统机器翻译与 AI 大模型两条路线,在 src/config/api.js 中均有对应的标识常量与请求参数定义:

类别 服务(源码常量)
传统机器翻译 Google、Microsoft、Tencent、Volcengine、DeepL/DeepLX、Baidu、Yandex 等
AI 大模型 OpenAI、Gemini、Gemini2(OpenAI 兼容端点)、Claude、DeepSeek、Ollama、Cerebras、Zai 等
聚合平台 OpenRouter、OrcaRouter、Requesty、ePhoneAI、APIMart、OpenCodeGo
云平台/无服务器 AzureAI、CloudflareAI、SiliconFlow、AliyunBailian、QwenMT
浏览器内置 BuiltinAI(Chrome 内置 Gemini AI 翻译)

同一文件中还定义了影响翻译性能的关键默认参数,理解这些常量有助于你判断"聚合翻译"的行为边界:

  • DEFAULT_HTTP_TIMEOUT = 30:调用超时(秒);
  • DEFAULT_FETCH_LIMIT = 10:最大并行请求/任务数;
  • DEFAULT_BATCH_INTERVAL = 400:批处理合并请求的等待延迟(毫秒);
  • DEFAULT_BATCH_SIZE = 20:每次请求最多合并的 DOM 段落数;
  • DEFAULT_BATCH_LENGTH = 10000:每次请求的最大字符数;
  • DEFAULT_BATCH_CONCURRENCY = 10:同时执行的聚合批次数量;
  • DEFAULT_CONTEXT_SIZE = 3:AI 翻译的上下文历史条数上限。

聚合批量的调度实现位于 src/libs/batchQueue.js:它在 batchInterval 窗口内收集多个待翻译任务,按 batchSize/batchLength 合并为一次请求,同时为每个调用者保持独立的取消(Abort)能力——该文件的开头注释明确写着"Batch requests while keeping each caller's cancellation independent",并有配套的压力测试 batchQueue.cancellation.test.js。

安装指南:扩展与油猴脚本双通道

浏览器扩展(推荐)

目标平台 渠道
Chrome(含 Kiwi Android、Orion iOS) Chrome 网上应用店
Edge Edge 扩展商店
Firefox Firefox Add-ons(AMO)
Thunderbird 项目 Releases 下载
Safari 文档标记为"未提供"(Safari Mac/iOS 均未完成)

Chrome 系扩展的核心配置见 public/manifest.json:MV3、service_worker 后台、<all_urls> + file://*/* 内容脚本注入、storage/tts/contextMenus/scripting/declarativeNetRequest 等权限,并声明了 clipboardRead 为可选权限。图标资源位于 public/images/,包含 16/32/48/128 四档尺寸。

油猴脚本

  • Chrome/Edge/Firefox:配合 Tampermonkey / Violentmonkey 使用,安装 kiss-translator.user.js,也可从 Greasy Fork 获取;
  • iOS Safari:配合 Userscripts Safari 使用,安装 kiss-translator-ios-safari.user.js;
  • 油猴脚本的设置页面地址为 options.html(网页版设置页)。

油猴脚本注意事项:由于跨域限制,脚本需要把目标 API 域名加入白名单,否则无法发出请求;这也正是 README FAQ 中"填写的接口在油猴脚本不能使用"的答案。

自定义快捷键体系

README 给出的默认快捷键如下:

快捷键 功能
Alt+Q 切换翻译
Alt+D 打开独立翻译窗口
Alt+K 打开设置弹窗
Alt+S 打开翻译弹窗 / 翻译选中文字
Alt+O 打开设置页面
Alt+I 输入框翻译

这些快捷键对应 public/manifest.json 中 commands 字段的 toggleTranslate、openSeparateWindow、openTranbox、_execute_action 等命令,其中 _execute_action 的默认键为 Alt+K,toggleTranslate 为 Alt+Q,openTranbox 为 Alt+S,openSeparateWindow 为 Alt+D。修改快捷键的位置在浏览器自身的扩展管理页面:Chrome 为 chrome://extensions/shortcuts,Firefox 为 about:addons。油猴脚本场景下如需自定义按键映射,可参考 src/libs/shortcut.js 与 src/hooks/Shortcut.js。

翻译规则体系与网页可视化编辑

规则优先级

规则优先级从高到低为:

个人规则 > 订阅规则 > 全局规则

其中全局规则优先级最低,但地位重要——它是系统的"兜底默认规则"。规则的加载与合并逻辑可参考 src/libs/rules.js 与 src/hooks/Rules.js。

在网页上直接编辑规则

README 中文版详细描述了可视化规则编辑器的完整流程(英文版简略,此处依据中文版与仓库实现补充):打开网页翻译面板,点击「编辑网站规则」,选择规则用途后点击「选取元素」,在网页上点选锁定元素;通过祖先路径调整层级,比较不同定位候选及匹配数量,点击「确认添加定位」加入草稿,最后在主面板「保存规则」落地。也可以通过「手动添加」输入 CSS 选择器。其关键设计约束包括:

  • 规则类型支持翻译目标、排除区域、根容器、保留原文、段落边界;
  • 编辑器的修改、删除、撤销、重做只作用于当前草稿与预览,点击「保存规则」后才写入本地并触发同步;
  • 打开编辑器不会自动保存规则,也不会改变「自动扫描页面」设置;目标选择器并非翻译白名单,需要严格指定时应「禁用」自动扫描;
  • 删除一条定位不等于排除区域,其他规则或自动扫描仍可能覆盖它;
  • 未保存草稿时退出或重新读取规则会弹出「保存规则 / 不保存 / 继续编辑」选择;保存失败或检测到外部冲突会保留草稿;
  • 「预计翻译范围」基于草稿规则只做高亮预览、不发送翻译请求,范围内部排除项与语言/长度过滤仍然生效;「查看译文」才会执行真实翻译。

该编辑器的前端实现位于 src/views/RuleEditor/,其中 index.js 是主面板,FloatingPanel.js 与 usePanelPosition.js 负责浮动面板与定位,会话与存储分别由 ruleEditorSession.js、ruleEditorStorage.js 承担。文档同时说明:可视化选取目前支持桌面普通 DOM 网页及其动态内容,iframe、Shadow DOM 内部、Canvas 文字与触屏专用操作暂未纳入;不同源页面共享的 GM 存储没有跨源原子事务保证,编辑器检测到外部变更时会提示重新读取(油猴同源页面通过浏览器 Web Locks 协调写入)。

自定义 API 与 Hook:接入任意翻译服务

README 将自定义接口定位为"理论上可以接入任何翻译接口",并指向独立的接口文档 custom-api_v2.md。这套机制的核心是默认接口规范 + 双 Hook(Request Hook / Response Hook)。

默认接口规范(无需 Hook)

非聚合翻译的请求体与响应体:

// Request body
{
  "text": "hello",      // 需要翻译的文本
  "from": "auto",       // 原文语言
  "to": "zh-CN"         // 目标语言
}

// Response(二选一)
{ "text": "你好", "src": "en" }
{ "text": "你好", "from": "en" }

聚合翻译的请求体与响应体:

// Request body
{ "texts": ["hello"], "from": "auto", "to": "zh-CN" }

// Response
[ { "text": "你好", "src": "en" } ]

// v2.0.4 起也支持:
{ "translations": [ { "text": "你好", "src": "en" } ] }

只要接口的请求/返回符合上述规范,就无需编写任何 Hook。

Prompt 占位符与类型

Hook 中可替换的占位符包括 {{from}}、{{to}}(语言名称)、{{fromLang}}、{{toLang}}(语言代码)、{{text}}、{{tone}}(风格)、{{title}}、{{description}} 等;Prompt 类型分为 systemPrompt(聚合翻译 System Prompt)、nobatchPrompt(非聚合 System Prompt)、nobatchUserPrompt(非聚合 User Prompt)、subtitlePrompt(字幕翻译 System Prompt)。在源码中,src/config/prompt.js 定义了 line/xml/json 三种聚合协议(PROMPT_PROTOCOL_LINE/XML/JSON),并管理着 batch system prompt、user prompt、subtitle prompt、dictionary prompt 四类模板的预设列表。

两个实战 Hook 示例

Ollama(开启聚合翻译),URL 为 http://localhost:11434/v1/chat/completions:

async (args) => {
  const body = {
    model: "gemma3", // 或 args.model
    messages: [
      { role: "system", content: args.systemPrompt },
      {
        role: "user",
        content: JSON.stringify({
          targetLanguage: args.toLang,
          segments: args.texts.map((text, id) => ({ id, text })),
        }),
      },
    ],
    temperature: 0,
    max_tokens: 20480,
    stream: false,
  };
  return { url: args.url, body, headers: { "Content-type": "application/json" }, method: "POST" };
};

async ({ res, parseAIRes }) => {
  return { translations: parseAIRes(res?.choices?.[0]?.message?.content) };
};

注意:文档明确提示 Ollama 需要设置环境变量 OLLAMA_ORIGINS=* 才能允许浏览器跨域访问(详见 FAQ 的 403 排查),并可用 systemctl show ollama | grep OLLAMA_ORIGINS 验证环境变量是否生效。

硅基流动(禁用聚合翻译),URL 为 https://api.siliconflow.cn/v1/chat/completions:

async (args) => {
  const body = {
    model: "tencent/Hunyuan-MT-7B", // 或 args.model
    messages: [
      { role: "system", content: args.systemPrompt },
      { role: "user", content: args.userPrompt },
    ],
    temperature: 0,
    max_tokens: 20480,
  };
  return {
    url: args.url,
    body,
    headers: { "Content-type": "application/json", Authorization: `Bearer ${args.key}` },
    method: "POST",
  };
};

async ({ res }) => {
  return { translations: [[res?.choices?.[0]?.message?.content || ""]] };
};

语言代码约定:Hook 参数中 toLang/fromLang 是插件标准语言代码,to/from 是转换为特定接口适用的代码;若你的接口与标准代码表不一致,需要自行映射(custom-api_v2.md 内附 36 种语言的标准代码表,从 en、zh-CN、zh-TW 到 vi 等)。

OpenCode 会话请求头

内置 OpenCodeGo 接口会自动添加 x-opencode-session 请求头:同一页面、同一接口配置与 URL 的请求复用一个随机 ID(覆盖聚合、非聚合、流式、字幕及摘要请求),刷新页面或 SPA 地址变化后开始新会话,ID 不包含页面地址、原文或 API Key。使用 OpenAI 兼容接口接入 OpenCode 或需要手动指定会话 ID 时,可在 Request Hook 中构造并清理同名请求头:

async (args, req = args.req) => {
  const sessionId = "8fd946a1-bb92-4aa6-9766-724c9e435832";
  const headers = { ...req.headers };
  for (const name of Object.keys(headers)) {
    if (name.toLowerCase() === "x-opencode-session") delete headers[name];
  }
  headers["x-opencode-session"] = sessionId;
  return { ...req, headers };
};

字幕请求不执行 Request Hook,如需为字幕手动指定 ID,应在"自定义请求头"中配置 JSON(如 {"x-opencode-session":"..."}),内置接口会保留这个显式配置。

常见问题排查(FAQ 精要)

接口(Ollama 等)测试失败

README 归纳了四类典型原因与对策:

  1. 地址填错:例如 Ollama 有原生接口地址与 OpenAI 兼容地址,本项目统一支持 OpenAI 兼容地址(http://localhost:11434/v1/chat/completions),不支持 Ollama 原生接口地址;
  2. 某些 AI 模型不支持聚合翻译:可禁用聚合翻译,或改用自定义接口(参考 custom-api_v2.md);
  3. 某些 AI 模型参数不一致:如 Gemini 原生接口参数不一致、部分模型版本不支持某些参数导致报错,可通过 Hook 修改请求 body,或更换为 Gemini2(OpenAI 兼容地址);
  4. 服务器跨域限制(403):如 Ollama 需在启动时设置 OLLAMA_ORIGINS=*。

规则优先级

个人规则 > 订阅规则 > 全局规则,全局规则作为兜底。

快捷键设置

在浏览器扩展管理页设置:Chrome 为 chrome://extensions/shortcuts,Firefox 为 about:addons。

油猴脚本接口不可用

需要把目标 API 域名加入脚本白名单(@connect 等授权),否则请求无法发出。

跨客户端数据同步与关联项目

项目支持通过 KISS-Worker(Cloudflare/Docker 自部署)或 WebDAV 实现跨客户端数据同步,相关实现集中在 src/hooks/Sync.js 与 src/libs/sync.js,另有大量验收测试(如 SyncRollbackSerialization.acceptance.test.js)验证同步的健壮性。同步服务采用"自己部署、自己管理、数据私有"的模式,可同时用于分享个人私有规则列表。此外,社区订阅规则由独立的 kiss-rules 仓库维护,提供最新最全的订阅规则列表。

开发指南与外部触发

构建流程

git clone https://gitcode.com/gh_mirrors/ki/kiss-translator.git
cd kiss-translator
git checkout dev # 提交 PR 建议推送到 dev 分支
pnpm install
pnpm build

项目使用 pnpm 管理依赖(见 pnpm-lock.yaml),pnpm build 内部会依次执行版本同步(src/scripts/sync-version.mjs)、格式化,以及 build:chrome、build:edge、build:thunderbird、build:firefox、build:web、build:userscript-ios、build:rules 等多个目标构建(见 package.json)。版本号管理机制可参考 VERSION_MANAGEMENT.md。config-overrides.js 用于 react-app-rewired 的自定义配置。

外部触发事件

网页环境可以通过派发自定义事件与扩展交互,README 给出了完整动作清单:

// `toggle_translate`   切换翻译
// `toggle_styles`      切换样式
// `toggle_popup`       打开/关闭控制面板
// `toggle_transbox`    打开/关闭翻译弹窗
// `toggle_hover_node`  翻译鼠标悬停段落
// `input_translate`    翻译输入框
window.dispatchEvent(new CustomEvent("kiss_translator", {detail: { action: "toggle_translate" }}));

事件名常量在 src/config/msg.js 中定义:EVENT_KISS_INNER = "kiss_translator_inner" 用于插件沙箱/内容脚本内部通信,EVENT_KISS_TRANSLATOR = "kiss_translator" 暴露给网页环境。这意味着任何网页开发者都可以通过一行 dispatchEvent 在页面内触发翻译,为第三方页面深度集成提供了公开入口。

未来规划方向

README 明确了项目后续的功能方向,其中已完成(标记 [x])的有:聚合发送文本(优化请求策略、减少接口调用、提升性能)、增强富文本翻译、强化自定义/AI 接口(流式传输、上下文记忆、多轮对话)、英文词典备灾机制(翻译服务失效时 fallback 到本地词典)、优化 YouTube 字幕支持(改进流式字幕合并、减少断句)。规划中(标记 [ ])的方向包括:边缘 AI 计算(本地轻量 LLM/ASR/OCR/TTS)、分布式共享平台、文档翻译(TXT/PDF/图片/漫画)、自研翻译 Agent 以及使用现代框架的整体项目重构。

结语

KISS Translator 的价值在于"简约而不简单":它以一套统一的接口抽象同时驾驭传统机器翻译与 AI 大模型,用聚合批量和流式传输优化翻译体验,以可扩展的自定义 API 与 Hook 保持了对任意翻译服务的接入能力。无论是作为日常网页翻译工具、YouTube 字幕双语工具,还是作为研究"翻译工具链如何抽象多接口"的参考实现,它都提供了清晰的落地路径与完整的开源源码可供深入。

登录后查看全文
kiss-translator