手把手从零复刻「英文网页 AI 翻译」Chrome 插件(新手向)

这篇只讲「怎么做」,不讲代码原理。你只需要会建文件夹、建文件、敲命令、点按钮。跟着做完,你就能搭出这个插件的完整骨架,核心逻辑文件每个都标了「负责什么、注意什么」,照着写即可。

0. 开始前,准备四样东西

准备项 要求 怎么准备
① Node.js 20.19 及以上(推荐 22 LTS) nodejs.org 下载 LTS 版,双击安装,一路「下一步」
② 编辑器 推荐 VS Code code.visualstudio.com 下载安装
③ 浏览器 Chrome 或 Edge 较新版本(Chrome 114+)
④ 一个 AI Key DeepSeek 等 platform.deepseek.com 注册 → 控制台 →「API Keys」→ 创建,复制那串 sk-... 保存好

确认 Node 装好了 :按 Win + R,输入 cmd 回车,黑窗口里输入 node -v,能打印版本号(如 v22.x.x)即可;再输入 npm -v 确认 npm 也在。

1. 创建项目文件夹

  1. 电脑任意位置新建文件夹 chrome-ai-translation(英文、别带中文和空格)。
  2. VS Code 菜单「文件 → 打开文件夹」,选中它。

2. 先看最终要建哪些文件

一共 17 个文件:4 个配置文件 + 13 个源码文件。先照这个结构把文件夹建出来:

text 复制代码
chrome-ai-translation/
├── package.json          # 配置文件(下面照抄)
├── tsconfig.json         # 配置文件(下面照抄)
├── vite.config.ts        # 配置文件(下面照抄)
├── manifest.json         # 配置文件(下面照抄)
└── src/
    ├── shared/           # 跨上下文复用
    │   ├── constants.ts
    │   ├── types.ts
    │   ├── messages.ts
    │   └── storage.ts
    ├── content/          # 从网页提取正文
    │   ├── extractor.ts
    │   └── index.ts
    ├── background/       # 编排 + 调用 AI
    │   ├── translator.ts
    │   └── index.ts
    ├── components/       # 通用组件
    │   └── MarkdownView.tsx
    └── panel/            # 侧边栏界面
        ├── index.html
        ├── main.tsx
        ├── App.tsx
        └── style.css

建文件夹方法 :VS Code 左侧资源管理器里右键 →「新建文件夹」,先建 src,再在 src 里建 sharedcontentbackgroundcomponentspanel 五个子文件夹;「新建文件」来建文件。

3. 四个配置文件(完整照抄)

这 4 个是「配置文件」,必须精确,直接复制粘贴即可。

文件 1/17:package.json(项目根目录)

json 复制代码
{
  "name": "chrome-ai-translation",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite",
    "clean": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\"",
    "build": "npm run clean && tsc --noEmit && vite build",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "@mozilla/readability": "^0.6.0",
    "dompurify": "^3.4.14",
    "md-wx": "^1.0.1",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "turndown": "^7.2.4"
  },
  "devDependencies": {
    "@crxjs/vite-plugin": "^2.7.1",
    "@types/chrome": "^0.2.7",
    "@types/react": "^18.3.31",
    "@types/react-dom": "^18.3.7",
    "@types/turndown": "^5.0.6",
    "@vitejs/plugin-react": "^5.2.0",
    "typescript": "^5.9.3",
    "vite": "^7.3.6"
  }
}

文件 2/17:tsconfig.json

json 复制代码
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "types": ["chrome"]
  },
  "include": ["src"]
}

文件 3/17:vite.config.ts

ts 复制代码
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { crx } from '@crxjs/vite-plugin'
import manifest from './manifest.json'

export default defineConfig({
  plugins: [react(), crx({ manifest })],
  build: {
    emptyOutDir: true,
  },
})

文件 4/17:manifest.json

json 复制代码
{
  "manifest_version": 3,
  "name": "英文网页 AI 翻译",
  "version": "0.1.0",
  "description": "一键提取英文网页正文,调用 AI 模型翻译并转为 Markdown",
  "action": {
    "default_title": "英文网页 AI 翻译"
  },
  "background": {
    "service_worker": "src/background/index.ts",
    "type": "module"
  },
  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "js": ["src/content/index.ts"],
      "run_at": "document_idle"
    }
  ],
  "side_panel": {
    "default_path": "src/panel/index.html"
  },
  "permissions": ["activeTab", "scripting", "storage", "sidePanel"],
  "host_permissions": ["https://api.deepseek.com/*", "http://*/*", "https://*/*"]
}

这一份最关键side_panel 字段让插件从右侧打开侧边栏(而不是传统弹窗),action 里也没有 default_popup。想做成侧边栏就靠这里。

4. 十三个源码文件(只列职责,不贴代码)

这 13 个是「逻辑源码」,按职责自己实现即可。每个文件都标了「干什么 + 注意什么」,照着写。

4.1 src/shared/ ------ 跨上下文复用的基础(4 个)

文件 负责什么
constants.ts 常量:默认 API 地址 https://api.deepseek.com、默认模型 deepseek-chat、存储 key、侧边栏通信端口名 panel
types.ts 领域类型:ExtractPayload(markdown/title/author/url)、TranslationResultSettings(apiKey/baseUrl/model)、状态枚举(idle/extracting/translating/done/error)
messages.ts 消息协议:后台 / 内容脚本 / 侧边栏三方之间所有消息的强类型定义(提取请求与结果、翻译请求与流式分片、设置读写)
storage.ts 存储层:封装对 chrome.storage.local 的读写------「最近一次翻译结果」和「设置项」,设置项读取时合并默认值

4.2 src/content/ ------ 从网页提取正文(2 个)

文件 负责什么
extractor.ts 提取核心管线:克隆 DOM → 归一化懒加载图片地址(data-src/srcset → 绝对 src)→ Readability 识别正文 → 长度校验(正文 < 50 字走选择器兜底)→ DOMPurify 消毒 → Turndown 转 Markdown → 取标题 / 作者
index.ts 内容脚本入口:监听后台「提取正文」消息,调用 extractor 返回结果

4.3 src/background/ ------ 编排 + 调用 AI(2 个)

文件 负责什么
translator.ts 翻译核心:用原生 fetch 调 OpenAI 兼容流式接口(stream: true),逐行解析 SSE 增量(data: 开头、[DONE] 结束);System Prompt 约束「只翻译正文、保留 Markdown 结构和图片」;组装 # 标题 / > 作者 / > 链接 / 正文
index.ts 后台入口:点击图标打开侧边栏、管理 Port 连接、编排「提取 → 翻译 → 流式推送 → 存储」全流程;内容脚本未注入时用 scripting.executeScript 兜底注入

4.4 src/components/ + src/panel/ ------ 界面(5 个)

文件 负责什么
components/MarkdownView.tsx md-wx 的 MarkdownRenderer 渲染 Markdown,关闭设置 / 复制 / 主题切换等多余 UI
panel/index.html 侧边栏入口 HTML,挂载 #root + 引入 main.tsx
panel/main.tsx React 挂载入口,渲染 App
panel/App.tsx 主界面:翻译按钮 + 设置面板(Key / Base URL / 模型)+ 流式打字机展示(60ms 节流)+ 下载 .md / 复制;连接 Port 接收后台推送
panel/style.css 侧边栏样式(头部工具栏、按钮、状态条、错误条、正文区)

实现要点(写逻辑时注意这几条)

  • 三个上下文用一套强类型消息 :后台 / 内容脚本 / 侧边栏之间的消息都在 messages.ts 里定义,改协议时 TypeScript 直接报错,少踩隐性的坑。
  • 正文提取先「克隆 DOM」再处理:别污染用户正在看的原页面;图片一定要做懒加载归一化,否则正文图会全丢。
  • 翻译接口走 OpenAI 兼容协议 :只改 base_url / api_key / model 三处,就能在 DeepSeek / Qwen / GLM 之间自由切换,不绑死一家。
  • API Key 只放后台:内容脚本和页面共享上下文,绝不能碰 Key;页面 HTML 一律当不可信数据,提取后必须 DOMPurify 消毒。
  • 侧边栏高度自动撑满、宽度需手动拖 :点击图标直接打开侧边栏靠 setPanelBehavior({ openPanelOnActionClick: true })

5. 安装依赖

VS Code 里按 ``Ctrl + ```(反引号)打开终端,粘贴回车:

bash 复制代码
npm install

等 1~3 分钟,看到 added N packages 就成功。报网络错误就换国内镜像:

bash 复制代码
npm install --registry=https://registry.npmmirror.com

6. 构建

bash 复制代码
npm run build

看到 ✓ built in xx.xxs 即成功。重点 :产物在项目根目录新生成的 dist 文件夹里------待会儿要加载的是 dist,不是 src,也不是项目根目录。

7. 加载到浏览器

  1. 地址栏输入 chrome://extensions(Edge 输 edge://extensions),回车。
  2. 打开右上角「开发者模式」开关。
  3. 点左上角「加载已解压的扩展程序」。
  4. 进入项目文件夹,选中里面的 dist 文件夹,点「选择文件夹」。

出现「英文网页 AI 翻译」卡片即装好。

8. 配置 API Key 并首次使用

  1. 点浏览器工具栏的插件图标(可能收在拼图 🧩 图标里,点开它可「固定」到工具栏)。
  2. 右侧滑出侧边栏
  3. 展开「设置(API Key / 模型) 」,填入:
    • API Key :第 0 步在 DeepSeek 创建的那串 sk-...
    • Base URL :保持默认 https://api.deepseek.com
    • 模型 :保持默认 deepseek-chat
  4. 点「保存设置」。
  5. 打开任意英文文章 → 点插件图标 → 点「翻译当前页面」。
  6. 译文逐字蹦出,完成后可「下载 .md 」或「复制」。

搞定 🎉

9. 常见问题(FAQ)

问题 原因 & 解决
没有 dist 文件夹 先执行 npm run build,成功后它才出现
加载报「manifest 无效」 选错文件夹了,要选 dist/,不是 src/ 或项目根目录
点了图标没反应 / 侧边栏不打开 浏览器版本太旧(需 Chrome 114+);或在扩展页点「重新加载」再试
翻译报 HTTP 403 API Key 填错 / 过期,或模型名填错(要用 chat 模型如 deepseek-chat,不是 embedding 类)
提示「无法读取当前页面」 刷新网页再点翻译;确认打开的是 http/https 网页
提示「请先在插件设置中填写 API Key」 第 8 步的「保存设置」没点,或没填 Key
侧边栏太窄 手动拖侧边栏左边缘调宽(高度会自动撑满)

10. 想改成你自己的?

  • 改插件名 :打开 manifest.json,把两处 "英文网页 AI 翻译" 换成你的名字,重新 npm run build 并「重新加载」。
  • 换 AI 服务商:不用改代码,侧边栏「设置」里改 Base URL / 模型 / Key 即可(只要是 OpenAI 兼容接口都能用)。

到这里你就从零搭出了这个插件的完整骨架。核心逻辑文件(正文提取、流式翻译、侧边栏 UI)按第 4 节的职责描述实现即可。想了解背后实现原理和开发踩坑,可以再看技术复盘篇。

相关推荐
Dovis(誓平步青云)7 小时前
模拟器横评:电脑上看小说、追短剧用什么模拟器?MuMu、雷电、腾讯手游助手实测
android·java·服务器·前端·javascript·电脑
xiaominlaopodaren7 小时前
three.js最小地图运行时(十):接入离线逻辑瓦片剖面
javascript·gis·three.js
独立开发之道8 小时前
【Three.js教程】 图元速查:官方内置的立体图形
开发语言·javascript·ecmascript
单线程_0117 小时前
从案例分析 Vue3 Tokenizer 源码一
前端·javascript·vue.js
大模型码小白18 小时前
AI 对话流性能调优:万级消息的虚拟滚动落地
java·大数据·前端·javascript·人工智能·算法·机器学习
m0_5474866618 小时前
《JavaScript核心原理 》全套PPT课件2026
开发语言·javascript·ecmascript
xm_xm_xm_119 小时前
react17版本以前类组件常用操作
前端·javascript·react.js
lzhdim20 小时前
13、JavaScript事件循环机制 - JavaScript学习系列文章
开发语言·前端·javascript·学习·ecmascript
liangshanbo121520 小时前
Vue 3 <script setup> 的本质原理是什么?它与普通 setup()有何区别?
前端·javascript·vue.js
七牛开发者1 天前
实测推荐 3 个 Skill,轻松上手 Codex 网页设计与交付流程
前端·javascript·后端