Topics

从Google翻译API到LLM翻译的重构之旅 ― 通过Claude API与R2差分缓存实现多语言化

  • column

之前,我用Google翻译API对Astro SSG网站进行了多语言化尝试的文章。这是一种使用Google Cloud Translation API的方法,在构建后对静态HTML进行翻译,并生成各种语言版本。作为一种成本较低的简易多语言化方案,它非常实用。

不过,运营了一段时间后,我们在 SEO 和翻译质量这两个方面都遇到了令人担忧的问题。关于"为什么放弃了 Google 翻译"的详细讨论,请参阅另一篇文章。

文章:机器翻译从 Google Translate 迁移至 Claude API

本文是关于"那具体是怎样重新构建的"这一实现方案的讨论。我们将翻译引擎从 Google 翻译替换为 LLM(Claude API),同时也清理了之前遗留下来的运维手工操作。

在构建时使用 LLM 翻译,并在 R2 中缓存差异

基本方针与上次相同,翻译在构建时(服务器端)完成。不会从浏览器调用 Claude API。不同之处在于翻译引擎和缓存的存放位置。

构建流程是这样的。

npm run build
  ├── fetch-microcms   (microCMSから記事データ取得)
  ├── astro build      (日本語HTMLを生成 → dist/)
  ├── translate        (各ロケールのHTMLを生成 → dist/{locale}/)
  └── update-xml       (sitemap更新)

translate 的内容(translate-html-llm.mjs)大体按照这个顺序进行:

  1. 从 Cloudflare R2 下载翻译缓存(单个 JSON 文件)
  2. 使用 cheerio 读取 dist/ 目录下的各个 HTML 文件,并提取需要翻译的文本
  3. 如果缓存中存在就使用它,只将不存在的内容发送到 Claude API
  4. 用翻译结果替换文本,并将其写入 dist/{locale}/
  5. 将新翻译的部分合并到缓存中,然后上传到 R2

关键点是两个方面:一是"只翻译改变的部分"的差分翻译,二是将其缓存放在 R2 上。

① 如何自然地处理跨越内联标签的翻译

这正是这次我最想要改进的地方。

例如,假设本文中有这样的 HTML。

<p>私たちは<strong>ウェブアクセシビリティ</strong>を重視しています</p>

如果按常规方式处理翻译,我们 / 网络无障碍 / 高度重视这3个片段会被分别翻译。由于日语和中文的语序不同,把翻译后的片段放回原位置时,<strong>的作用范围会错位,或者本身就会变成不自然的句子。内联标签越多,问题越严重。这是旧系统最大的不满之处。

改进方法分为以下两个步骤。

第一点:按块级元素单位进行分块。翻译的最小单位不是"标签之间的间隙",而是整个块级元素的内容(innerHTML),例如 p、h1~h6、li、td、blockquote。不拆分句子。

「第二点:将内联标签替换为标记,将整个句子作为一个翻译单位传递。将分块中的 <strong> 或 <a> 暂时替换为 ... 这样的标记。」

私たちは[[T1]]ウェブアクセシビリティ[[/T1]]を重視しています

我向LLM指示:"这是一句话。在自然翻译的基础上,可以给应该强调的词语重新附加同样的标记。标记的位置可以根据翻译文本的词序移动。" 翻译返回后,我将标记恢复为原始的 <strong>、<a href="..."> 等。属性(href 和 class)保持原样。

这样,<strong>在英文端也能正确地修饰单词,句子也变得自然了。

② 差分翻译与R2缓存设计

如果每次都翻译所有内容,无论多少成本都不够。前面也有过 translate-cache.json 这样的缓存,这次改进了密钥的生成方式和保存位置。

修改提示词时自动重新生成翻译的机制

缓存的键是通过组合"原始日语 + 区域设置 + 翻译提示内容"生成的。这样做的好处是,如果原始日语发生变化,只有该条目会被自动标记为"缓存中不存在"并重新翻译;如果翻译指示或术语策略(提示)发生变化,所有条目都会被自动标记为"缓存中不存在"并重新翻译。

我们的目标是防止这种事故:"改进了提示词,但旧的翻译仍然留在缓存中"。实际上,我们使用这些的 sha256 哈希字符串作为键。

缓存的结构是这样的。

{"<sha256のキー>":{"value":"翻訳結果(マーカー込み)","locale":"en","model":"claude-haiku-4-5-20251001","translatedAt":"2026-06-12T..."}}

将缓存放在 R2 上,消除了手动操作

这是上次遗留任务的补偿。

之前是通过仓库内的 JSON 文件来管理缓存的。因此,当在 CMS 中添加文章并通过部署钩子触发构建时,服务器只能看到 Git 上的旧缓存。迫不得已,我们采用了「添加文章后在本地构建,然后将更新的缓存文件 push 到 Git」这样的运维规则来应对。

这次我们把缓存放在了 Cloudflare R2 上的单一 JSON blob 中。每次构建时从 R2 获取,完成后写回。这样即使通过 webhook 进行构建,缓存也能持久化,完全消除了本地构建→push 的手工操作。只要添加文章并 push,新增的部分就会被翻译,缓存也会自动更新。

翻译优先级

译语的不一致(如公司名称 Liberogic 的表示方式不统一等)在上次也是个难点。这次我们通过四个阶段来处理。

  1. 手动覆盖(data-i18n-key) — 在 HTML 中标记了 data-i18n-key 的元素会使用预先准备好的手工翻译进行固定。这样既不依赖 LLM,也不依赖字典,让你能够精确控制「这里必须用这个翻译」的需求。
  2. 用语词典(glossary) ─ 导航菜单或页面标题等重复出现的固定标签,通过 JSON 词典固定译语。修改词典后重新构建,即可立即生效。
  3. R2 缓存 ― 如果上述两者都不存在,我们会检查缓存。
  4. Claude API — 只有其他方案都没有的功能,才最后才交给LLM处理。

文中术语的统一不能被仅面向逐字对应的辞典完全覆盖,所以我们通过系统提示词一侧的术语提示来做出宽松的对齐。

与LLM的「习性」共存

机器翻译输出有误的情况在上次也出现过,但LLM有其自身的习性特点。下面介绍一些在实际运营中发现的例子。

  • 技术性文本整段保留为英文。API、React、Vue等「不翻译术语」列表被过度应用,导致整个句子以英文返回。我们通过在用户提示词中强调「用目标语言输出」来应对。
  • 标记位置在语义上反向。对应强调词汇的判断出错,导致<strong>涵盖范围不当。删除相应条目并重新翻译可以解决。
  • CJK语言响应中途截断。汉字每字符消耗较多token,一次性提交大量内容会导致输出达到上限,JSON损坏。我们通过提升max_tokens并减少单批处理数量来解决。
  • 字面量中的和CJK日期格式崩坏。换行以字符串形式混入,或2026年05月22日出现多余空格等情况。这些由后处理脚本统一清理。

一个有效的运维经验是,逐条删除有问题的项并重新翻译,成功率最高。试图一次性修复多个问题时,LLM容易将相同结构进行相同的误判。这是「欲速则不达」的道理。

成本话题

引擎统一使用Claude Haiku 4.5。我们优先考虑成本,若出现质量问题则首先通过调整提示词和辞典来改进。系统提示词启用prompt caching,压缩每次相同固定部分的成本开销。

实际成本目标大致如下。

内容

成本

某个区域的首次完整翻译

约 $2.5-3

所有区域的首次完整翻译

约 $20

常规部署(仅缓存命中)

基本上 $0

添加一篇文章(多项翻译)

约 $0.01

日常的部署几乎免费,添加文章也只需1日元到几日元。虽然初期重建需要一笔费用,但度过这个阶段后,运营成本反而比之前更低了。

总结

从Google翻译切换到LLM翻译后,运营成本基本没有增加,翻译质量也有了明显提升。

LLM并非万能,不能自动完成所有工作并保证完美。我们仍需要进行日常的调整工作来发现并消除问题。不过,由于修改内容集中在提示词和字典这些容易理解的地方,改进的循环变得更容易实施了。

本文作者

从DTP跨越到Web世界,不知不觉中已掌握标签、前端开发、创意指导、无障碍设计等各项技能的"技术高手"。从Liberogic创业初期就活跃至今,如今是公司内部的"活百科"。最近沉迷于"能否在无障碍适配上更多依赖AI?"这样的思考,正在探索借助AI提示词提高效率的方法。技术实力和思维方式都还在不断进化中

二俣 歩

IAAP 认证网络无障碍专家 (WAS) / 标记语言工程师 / 前端工程师 / 网络总监

查看本员工的文章

安心的团队体制和迅速的反应能力是我们的优势

Liberogic 拥有经验丰富的员工团队,积极推进项目,因此获得了客户的高度评价。
我们会妥善分配项目经理和总监,确保整个项目顺利进行。 通过避免不必要的全职投入导致的成本增加,并采用适当配置人力资源的方式,从把握业务内容到估价的制作和提交速度都赢得了良好的口碑。

* 本公司不积极开展SES驻场工作等业务,敬请谅解。

Slack、Teams、Redmine、Backlog、Asana、Jira、Notion、Google Workspace、Zoom、Webex 等,您可以使用几乎所有主要的项目管理工具和沟通协作工具。

请咨询我们的网站相关问题。

案例分析