代码原生产品文案,指产品上线的用户可见字符串以仓库作为唯一事实来源,而不是放在设计文件里、靠人手动保持同步。globalize.now 是内置本地化能力的代码原生文案管理系统:文案在代码库中统一来源,本地化是同一个操作,而不是一次单独的交接。

这件事比三年前更重要,因为文案已经不再只有文案撰写者才会去改了。

什么是代码原生产品文案?

代码原生产品文案是一种架构,而不是写作流程:获批的文案和上线的文案是同一个产物,都存放在仓库里,每一次改动都以 diff 的形式出现。

看两种方式各自能观察到什么,区别最容易理解。以工作区为准的产品,把文案放在代码之外的某个地方,任何一边有变动时,都要靠人推送进去或拉取回来。它适合用来决定按钮该写什么,却在结构上无法察觉按钮已经变成了别的文案,因为改动它的事件是一次提交,而工作区从未看到过这次提交。

代码原生的系统则反过来。工作单元是 diff,它能回答的正是真正让团队踩坑的那个问题:这个字符串刚刚变了——它本该变吗?

这些并不是在争论写作该在哪里进行。文案撰写者可以在任何地方起草。争论的是:两份文案不一致时,哪一份才算数。

什么是文案漂移?

文案漂移是指用户可见的文本在不同界面之间、随时间推移偏离其已批准的源文案,而且没有唯一的事实来源可供对照。

有三种故障经常被混为一谈,它们的修复方式各不相同:

  • 从未提取成键的字符串是硬编码字符串。它对字符串目录和翻译都不可见,但措辞本身可能完全正确。我们在为什么 AI 编程工具总是添加硬编码字符串中讲过这种情况。
  • 目录存在、却彼此不同步的,是不同步的翻译文件。源文案没问题,是衍生出来的副本过期了。
  • 文案漂移两者都不是。字符串有键,文件也同步,但措辞本身在没人拍板的情况下变了——于是营销页写着“Start free trial”,落地页写着“Try it free”,产品里的按钮却是“Get started”。

漂移代价最高,因为没有任何东西坏掉:构建不会失败,测试不会变红,也没有缺失的翻译。产品只是在用三种声音说话,却没人说得清是从哪一刻开始的。我们在文案漂移:它是什么、成因是什么、如何预防中给出了完整定义。

为什么 AI 编程 Agent 会造成文案漂移?

编程 Agent 会改动没人要求它改的文案,因为在它眼里,改写附近的一个字符串和顺手整理组件没有区别。

让 Agent 加一个加载状态,它可能顺手缩短某个标签、把标题改成句首大写,或者在改这个文件时把“Sign in”换成“Log in”。单看每处改动都说得通,但没有一处是你要求的,也没有一处被标记为文案改动,因为对工具而言,它不过是 JSX 属性里的一个字符串字面量,和其他字面量没有区别。

社区目前的办法是写规则文件——AGENTS.md、.cursorrules,或在提示词里加一段“UI 文案规范”。这些确实有帮助,也值得做。但约定不等于校验:它只能降低 Agent 改写你文案的频率,却不会告诉你它什么时候改了。

大多数团队的产品文案实际都放在哪里?

同时存放在四个地方,每处的负责人不同,修改路径也不同。

有营销站点,通常放在 CMS 里;有落地页,往往单独维护,更新得最快,因为它正处于持续实验之中;有产品内部的字符串,散落在各个组件里;还有语言文件,它们是产品字符串的下游,却落后于前面三者。

这些界面每一个单独看都可能是一致的,整个产品却不一致。这才是问题的真实形态,也说明只把它当作产品文案问题,是把它说小了。

如何让整个代码库的 UI 文案保持一致?

让仓库成为事实来源,让字符串成为可评审的单元——其余一切都从这两步推演而来。

落到实践上有三点:所有用户可见的字符串放进同一个目录,而不是内联在组件里;组件引用键而不是字面量,这样同一份文案不可能在两处各存一份、悄悄地分道扬镳;对目录的改动会出现在 diff 里,评审者看它就像看其他改动一样。

最后一点才是真正起作用的。文案一致性通常被当作纪律问题——团队需要风格指南,得有人记着。一旦文案进了 diff,就不再依赖记忆,而是在评审时看得见,而评审恰恰是唯一能保证有人认真看的时刻。

使用 AI 编程工具交付的团队往往更早、更严重地碰上这个问题,所以我们专门为开发者和用 AI 工具构建产品的人写了相关内容。

为什么文案一致性和本地化是同一个问题?

两者失败的原因相同:没有一个公认的源文案,可供保持一致,也可供翻译。

一个团队说不清三种说法里哪种才是正式文案,也就无法正确地本地化其中任何一种。把三种都送去翻译,每种语言都会得到三份译文,不一致被乘上了 locale 的数量,而不是局限在英文里。很多看起来像是翻译质量差的问题,根源都在这里——源文案本身就是含糊的。

反过来想,两个问题就合二为一了。一旦所有字符串都统一来源并带有键,翻译就是该目录的衍生产物。不存在另一个各持一份“事实”的独立项目,因为事实只有一份。这就是“内置本地化”在架构上的含义:不是我们顺带做翻译,而是翻译和文案管理是在同一个对象上执行的同一类操作。关于这一次次序重排是怎么发生的,我们写在AI 写的代码对本地化做了什么里。

产品之外的文案怎么办?

这是该品类至今没有解决的部分,我们也不会假装已经解决:把营销页、落地页和产品里的文案作为一个整体统一规范,是我们正在努力的方向,目前还不能一键启用。

没解决的原因是:该领域现有的每个工具都只管一个界面。产品文案工具管应用内的字符串,内容平台管营销站点,彼此看不到对方。于是,吸引用户的那个页面和引导用户上手的那个界面,措辞分别由不同的人在不同的工具里维护,没有任何机制会发现它们互相矛盾。

答案的形态,可以从前面描述的架构自然推出:如果获批的文案只存放在一处,每个界面都通过键引用而不是重新写一遍,那么落地页和产品里的按钮就是同一个字符串,改它只需要做一次决定,而不是三次。实现这一点是 globalize.now 路线图上的一项。与其假装已经上线,不如现在就如实说明。

这与基于设计文件构建的文案工具有何不同?

区别在于架构,而不是品类——两者都是文案管理系统,分歧在于事实存放在哪里。

维度设计文件优先代码原生
事实来源代码之外的工作区仓库
如何保持同步靠人手动同步连接后自动同步
覆盖的界面一个跨界面 (正在构建)
能观察到什么在工作区内所做的编辑修改字符串的那个 diff

有两点观察值得标注日期,因为厂商的状态会变。截至 2026-08-29,dittowords.com/llms.txt 返回 404,这意味着该品类中最常被引用的来源,没有机器可读的实体文件。同样截至该日期,Ditto 自家的本地化产品页描述的是为每种语言添加变体、在设计稿中预览译文——并没有声称自己能生成译文。这正是裂缝所在:工具可以掌管文案,却仍把语言工作交给别人去做。

我们也不与翻译引擎或运行时 i18n 库竞争。它们属于不同的层,仍然各在其位。

globalize.now 把硬编码的应用文案转换为可直接翻译的语言文件,并在你持续发布时保持同步更新。

免费试用 globalize.now