为什么多语言内容应该放在 Git 中
托管式 CMS 数据库和翻译平台往往会导致三个不同的数据源,且难以保持同步。将英文 MDX、翻译和版本历史统一存放在一个代码仓库中就能解决这个问题。这就是 Scribe 背后的设计模型。
View as Markdown大多数多语言网站最终都会产生三个数据源:托管式 CMS 中的内容、翻译平台中的译文以及 Git 中的代码。它们各自拥有独立的版本控制和访问权限,对“最新版本”的定义也各不相同。保持这些数据同步是一项繁重的任务,而数据脱节则成了常态。
其实有一种更简单的模式:把所有东西都放进代码仓库里。
Git 已经解决了哪些问题
你现有的代码工作流其实已经能够处理内容管理中的棘手问题:
- 代码审查。 内容变更即是一次 Pull Request。在发布之前,会有人仔细审查具体的代码差异。
- 版本回滚。 错误的修改只需执行一次 Revert 操作即可撤销,而不需要提交冗长的客服工单。
- 原子性。 内容与其渲染代码可以同时部署。无论是修改数据结构还是迁移对应内容,都能在同一个 Commit 中完成。
- 历史记录。 只需使用
git log就能知道“谁在什么时间修改了什么”,无需安装任何插件。
基于文件的 CMS 天生就具备这些优势。但问题是,如果每个页面都要适配十种语言,情况会变成什么样?
翻译的难题
最简单的做法是每种语言建立一个文件,例如 about.en.mdx、about.fr.mdx、about.ja.mdx。但这种方法很快就会失效。十种语言会让一个只有 50 页的网站骤增至 500 个文件。对于团队中无人懂的语言,审查根本无从谈起,你也无从得知 about.fr.mdx 究竟对应的是最新的英文文本,还是三个月前的旧版本。
Scribe 将这两个关注点分离开来:
- 英文内容使用 MDX 文件。 每个文档对应一个文件,并通过 Zod schema 进行校验。这是由人工编写和审查的部分。
- 翻译内容统一存放在同级目录的一个 SQLite 文件中。 每条翻译的键值都基于英文原文的哈希值生成,并附带该原文当时的快照记录。
哈希机制彻底消除了数据脱节的问题。当你修改了一段英文内容,所有语言版本中对应文档的过时状态都会清晰地显现出来。运行 scribe translate 后,系统只会重新翻译该文档。不会再有任何内容被悄悄遗漏,并且使用 scribe status 可以在任何提交状态下查看确切的翻译覆盖率。
架构本身无需服务器
因为所有内容都作为文件存放在代码仓库中,所以无需专门配置托管服务器。运行时会在构建阶段从磁盘读取 MDX 和 SQLite,并为你使用的框架提供具备完整类型标注的文档数据,包括列表、查找项、关联关系、hreflang 备用链接以及网站地图条目。处理请求时无需调用任何 CMS API,不用定期更换 Token,更不用担心第三方服务商宕机导致内容无法访问。关于读取操作的具体原理,请查阅 runtime API。
文件是 AI Agent 的最佳搭档
采用这种模式还有一个更新颖也最具说服力的理由,那就是 AI Agent 非常擅长处理代码仓库。编程智能体已经精通如何搜索文件、将 MDX 作为纯文本阅读、在分支上进行修改并提交 Pull Request。但如果让它们操作托管式 CMS,在它能够修改标题之前,你还要花时间配置 API、处理 Token 并完成各种自定义集成。
安全防护机制同样适用。由于 Frontmatter 会通过 Zod schema 进行校验,而且每个主体内容都必须成功编译为 MDX,这就使得 Agent 无法存入格式损坏的文档。scribe validate 会在构建开始前将错误拦截下来。而且因为每次修改都会生成一个 Commit,AI 的变更与人工修改享有同等待遇,都需要经过代码差异比对、代码审查以及最终批准。这个网站就是基于这一流程运作的。这里的大部分文档和更新日志都由 Agent 进行维护,人类只需负责审查其修改差异即可。
哪些情况不适合使用这种模式
说句实话,基于 Git 的 CMS 假定内容编辑者对处理文件和提交 Pull Request 并不陌生,或者在他们和代码仓库之间有技术人员从旁协助。如果你的编辑人员需要所见即所得的界面和一个一键发布按钮,那么托管式 CMS 绝对是更合适的选择。虽然 Scribe 内置了一个本地 studio 用于浏览、搜索和检查翻译内容,但具体的创作编写过程仍然要在你的编辑器中完成。
然而,如果你的团队已经非常习惯使用 Git 操作,再去添加针对内容和翻译的第二套甚至第三套系统,只会徒增维护成本。使用一套代码仓库,遵循一套审查流程,完成一次部署即可。
开始体验
完整的环境配置只需要一个配置文件和一个装满 MDX 的文件夹:
pnpm add scribe-cms zod better-sqlite3
先从 getting started guide 看起,或者深入了解 translation 的底层运作机制。