Scribe

翻译

了解 scribe translate 的工作原理:状态哈希、Gemini 集成、输出验证、成本估算以及审校工具。

View as Markdown

Scribe 通过 LLM (Gemini) 将英文原文翻译成所有目标语言,并将结果直接存入 SQLite。你完全不需要手动修改多语言文件,只需编辑英文原文,重新运行 scribe translate,然后提交数据存储库即可。

翻译内容

每个文档中,只有两部分内容会被送入翻译引擎:

  1. 标记为 field.translatable() 的 Frontmatter 字段,包含嵌套在数组和对象中的字段。
  2. MDX 正文。

其他所有内容(如 field.structural()、关联项以及内置字段)在加载时均会从英文文档中直接复制。在启用 slugStrategy: "localized" 的情况下,翻译引擎还会为每种语言生成对应的 URL 别名(采用 ASCII 风格的 kebab-case 格式,针对非拉丁语系进行音译处理)。

即使某种语言尚未完成翻译,也不会在运行时出现报错。resolve() 会通过语言回退链提供最接近的可用翻译(例如 pt-BR 会回退到 pt,接着回退到默认语言),让你可以逐步发布不同语言的内容。

过期状态追踪

每份入库的翻译都会记录其对应的英文原文内容的 SHA-256 哈希值。scribe translate 仅在以下情况才会重新翻译页面:

  • 该语言的翻译尚未建立(缺失),或者
  • 英文源内容已发生修改(过期)。

修改结构化字段或 _redirects.json 条目不会将翻译标记为过期,因为这些字段本身不需要翻译。

输出验证

只有通过以下两项检查,翻译结果才会被保存:

  1. 返回的 MDX 正文必须能够成功解析(系统会自动修复模型偶尔生成的错误转义字符和 JSX 属性引号问题)。
  2. 返回的 Frontmatter 必须通过你设定的完整 Zod schema 验证。

未通过验证的内容会在运行结束时自动重试一次,系统会将验证错误反馈给模型以便其自行修正(批处理模式会作为一个额外的批处理任务进行重试,并继续享受批量计费费率)。如果重试依然失败,系统会在最终总结里列出这些内容及最新的错误信息,同时命令会以非零状态退出。这就保证了错误的模型输出绝不会进入存储库,更不可能被带到生产环境。

运行命令

export GEMINI_API_KEY=...        # also read from .env / .env.local

scribe status                     # coverage per type and locale
scribe translate                  # interactive picker in a TTY
scribe translate --locale fr de   # specific locales
scribe translate --preset active  # a localePresets group from the config
scribe translate --type blog      # one content type (comma-separated: --type blog,glossary)
scribe translate --slug my-post   # one document
scribe translate --dry-run        # show the worklist + est. tokens/cost, write nothing
scribe translate --force          # re-translate even when hashes match
scribe translate --strategy missing-only   # skip stale, only fill gaps
scribe translate --batch          # force batch mode (the default)
scribe translate --direct         # per-page API calls, immediate results
scribe translate --resume         # pick up pending batch jobs, submit nothing new
scribe translate --concurrency 5  # parallel requests (direct mode only)
scribe translate --model gemini-3.1-pro

在终端里执行时,scribe translate 会提供实时进度界面,展示批处理任务状态、每项内容的翻译结果、当前的 Token 消耗量以及预估的美元成本。思维链 Token 也计算在报告的使用量中,因此该预估值完全与 Google 的实际账单相符。如果想要逐行打印日志,可以传递 --no-progress 参数(或者在 CI 等非交互式环境中运行)。

--dry-run 只会打印待办列表而不写入任何数据,同时根据实际的提示词与英文负载大小,报告单项和总计的预估 Token 消耗及美元成本。在 --batch 模式下,预估成本会自动应用批量折扣,为你准确预览真实运行的开销。

最后请提交 .scribe/store.sqlite 文件。

批处理模式与断点续传

默认情况下,整个待办列表会通过 Gemini Batch API 处理,这种方式只需消耗直调成本的 50%。Scribe 会提前规划所有请求(每个模型一个任务,遇到超大任务列表时会分块处理),一次性提交全部任务,然后统一轮询,并在每个任务完成时立即保存结果。批处理任务通常几分钟内就能跑完,但 Google 只承诺在 24 小时内完成,因此该命令会持续等待,而不是逐页流式返回结果。

在开始轮询之前,每个任务及其提交时的英文原文快照都会记录到 SQLite 存储中。这种机制让你随时可以安全地中断操作:

  • 轮询期间直接退出 (Ctrl+C) 绝不会丢失任何进度。
  • scribe translate --resume 会检查挂起的任务,拉取已完成的结果,不再提交新的请求。
  • 正常运行 scribe translate 也会优先恢复挂起的任务,处理中的项目绝对不会被重复提交。
  • 在批处理期间修改英文页面完全没问题。系统会基于当时的翻译快照保存结果,并在下次运行时自动将其识别为过期。

想要按原价快速看到逐页的翻译结果?使用 --direct 就能恢复逐页的 API 调用,并支持通过 --concurrency 控制并发数。在终端中,交互式选择器也会提供相同的选项。无论是哪种模式,只要遇到临时性的 API 错误(如 429、5xx 或网络断开),系统都会通过指数退避机制自动重试。

翻译引擎引导

内置的提示词专为创译而非直译而设计。模型会化身为母语为目标语言的营销文案专家进行本地化创作。它会生动还原习语和文字游戏,摒弃字面翻译,并严格遵循当地语言的排版习惯(如引号、撇号以及标点符号的间距)。你配置的 contextrules 以及 prompt 都会在这个框架之上发挥作用。

项目级默认配置与按类型覆盖设置:

export default defineConfig({
  translate: {
    context: "MyBrand is a B2B SaaS. Never translate the brand name MyBrand.",
    rules: ["Keep numbers and statistics accurate."],
  },
  types: [
    defineContentType({
      id: "blog",
      // ...
      translate: {
        rules: [
          "Preserve all MDX/JSX component tags, props, and URLs exactly.",
          "Translate link anchor text; never change href paths.",
        ],
      },
    }),
  ],
});
选项作用域描述
context项目 + 类型添加到每个请求前的品牌或领域上下文(项目级和类型级上下文会合并生效)。
rules项目 + 类型追加在默认规则之后的额外规则。
prompt项目 或 类型附加的本地化指令,添加在目标语言指令之前(语言名称和代码会自动追加)。
defaultModel / model项目 / 类型Gemini 模型 ID。默认为 gemini-3.1-pro(也可以通过 PROSE_GEMINI_MODEL 环境变量或 --model 参数覆盖)。

内置的必选规则包括:除非品牌在目标市场有广为人知的本地名称,否则不翻译品牌名;返回包含真实换行符而非转义符的 MDX 正文;以及在值包含双引号时,自动修复 JSX 属性引号。

翻译审校

scribe history blog my-post fr    # EN snapshot timeline for one page
scribe studio                     # read-only web UI on :3600

每份翻译都会链接到生成它时的英文原文快照(存储在同一个 SQLite 文件中),方便你随时审计页面被翻译的时间、原内容以及使用的模型。scribe history 会打印出这条时间线。工作室界面则会展示各语言的覆盖率、当前缺失或过期的待办列表,并提供详细的单文档视图,将快照与最终入库的翻译并排显示。

语言预设配置

如果是为了渐进式发布,可以在配置中对语言组进行命名,并通过 --preset 指定目标:

localePresets: {
  active: ["fr", "es", "ja"],
  ultraLight: ["fr"],
}
scribe translate --preset ultraLight
翻译 · Scribe