让 Replit 应用支持多语言的做法是:把它的 Git 仓库连接到 GitHub,并把翻译目录作为已提交的文件保存在仓库中。Replit 本来就把每个 Agent checkpoint 存为 Git 提交,所以在你考虑语言之前,仓库就已经存在;要做的是把它推到 GitHub,让语言目录沿着同一条历史回来。globalize.now 是 AI 驱动的本地化基础设施:它生成翻译键和语言文件,由应用已有的运行时库来提供。运行时路径上没有控制台,页面加载后也没有任何东西再去翻译它。

为什么让 Agent 翻译应用行不通?

因为根本没有可供翻译的目标。你让 Replit Agent 做一个仪表盘时,它把 <h2>Your bookings</h2> 直接写进组件,而不是去目录里查找。每个标题、按钮、空状态、toast 和校验错误,都以你提示词所用语言的字面量写进 JSX。

所以当你之后让 Agent“把应用翻译成南非荷兰语”,只会得到两种半成品之一:一份换了文字的组件副本,或者一个手写的 translations 对象,只覆盖 Agent 碰巧看过的页面。两者都不是语言层,下一个功能依然是英文。我们在 Cursor 总是添加硬编码字符串 中记录过同样的问题;Replit Agent 也不例外,因为它解决的是眼前这条提示词,而不是背后的架构。

解法是结构性的:给字符串加翻译键,把译文放进文件,让运行时从文件读取。这才是代码库意义上的“多语言”,而且只需改造一次。

Replit Agent 实际生成了什么?

一个常规的 Web 项目,这是好消息。Replit 官方预置的应用类型以前端 React 搭配 ShadCN UI 为主,通常在同一个项目里配一个 Express 服务端,全部使用 TypeScript。自 2025 年 9 月起,Agent 也支持你带来的任意框架,包括导入的 GitHub 仓库,所以 Next.js 或 Vue 项目也行得通;默认路径仍是 React 技术栈。

对本地化来说,技术栈是唯一重要的事实,而这是标准场景。React + Vite + TypeScript 是 i18n 生态中支持最完善的组合:i18next、Lingui 和 react-intl 都直接适配。如果 Agent 生成的是 Next.js 应用,则要在 next-intl、react-i18next 和 Lingui 之间选择,那组对比 另有专文。

和纯前端构建工具不同的是项目的另一半。Replit 应用通常有服务端,而服务端同样有字符串。下文详述。

Replit 应用的 Git 仓库在哪里?

它本来就在。Replit 的版本控制底层就是 Git,Agent checkpoint 就是该仓库中的提交。每当 Agent 完成一个功能并给出回滚点,它就已经提交过了。Replit 官方文档也建议,在使用外部仓库时改用普通 Git 提交做长期追踪,这正是眼下的场景。

把它推到 GitHub 的步骤:

  1. 在项目编辑器的 Tools 区域添加 Git 工具。
  2. 在已连接的服务中连接 GitHub 账号,然后在 Git 面板连接仓库。如果项目从未初始化过,面板会先提示你初始化。
  3. 推送。面板一键即可推送,并且与你在 Shell 中执行的操作保持同步,所以 git push origin main 同样可行。

Replit 也支持 GitLab 和 Bitbucket,流程相同。重点不在于托管平台,而在于仓库现在位于本地化任务可以向它发起 PR 的地方。

在改动任何字符串之前先做这一步。本地化是文件层面的工作,审核它的最佳位置是 diff。

对 Replit 应用来说,“不用控制台”是什么意思?

意思是译文就是仓库里的文件,应用像提供其他静态资源一样提供它们。没有 script 标签,页面加载时没有外部请求,访客和你的文案之间也没有任何供应商账号。

另一种做法是运行时插件,在页面渲染之后替换文本。它的代价是结构性的:首屏是英文,译文不在爬虫最先读取的 HTML 中,生产路径上多了一个第三方脚本,字符串存放在供应商那里,想迁走就得导出。这套论证的 Lovable 版本见不用控制台,本地化 Lovable 应用,对 Replit 同样适用。

这一点在 Replit 上更重要,还有一个 Replit 特有的原因。Replit 替你部署应用,所以 Replit 域名上运行的就是部署时项目里的内容。插件是从外部去翻译这次部署的;而语言目录在仓库里,意味着部署本身就包含所有语言,发布前你就能在 Replit 预览中看到德语版本。

取舍是真实存在的,值得直说:修改文案意味着一次提交加一次重新部署,而不是点一下保存。对在 Replit 上独立开发的人来说这不算什么;但如果你希望不碰项目就能实时改文案,这就是一个限制。

仓库原生方案如何运作?

在 globalize.now 应用中连接仓库。转换只对代码库运行一次:硬编码字符串变成带翻译键的目录条目,组件改为从运行时库读取,而不再持有字面量。这是一次性操作,之后不会重复执行。

转换完成后,随着应用增长,每次推送都会翻译新增的目录条目。让 Agent 新增一个设置页面,推送后,新条目会被翻译,已有条目保持不变。目录以已提交文件的形式回来(JSON 或 PO,取决于运行时库),放在一个 PR 中,你像审核其他改动一样审核它。

有两条边界要说清,因为这个领域的概念很混乱。globalize.now 不取代运行时库,i18next、Lingui 和 next-intl 照常工作;它也不是与 DeepL 竞争的翻译引擎。它是中间那一层,负责生成翻译键和语言文件。开发者概览 介绍了具体机制。

译文如何回到 Replit?

通过同一个 Git 面板,只是方向相反。这一步与 Bolt 或 Lovable 不同,因为 Replit 同时也是应用运行的地方。

  1. 在 GitHub 上审核并合并 PR。
  2. 在 Replit 的 Git 面板中选择 Pull。如果你或 Agent 在此期间修改过同一批文件,面板会标出冲突,你需要先在编辑器中解决,再完成合并。
  3. 重新部署。语言目录现在已是项目的一部分,所以部署包含所有语言。

有一个 Replit 特有的注意事项:Agent checkpoint 会恢复整个项目状态,包括文件。如果你回滚到拉取翻译分支之前创建的 checkpoint,语言目录也会一并消失。请把这次合并当作一个里程碑,让 Agent 在合并后创建 checkpoint,并回滚到这个 checkpoint,而不是更早的那个。

哪些字符串在服务端?

前端不以 JSX 形式看到的那些。带 Express 后端的 Replit 应用有第二处字符串:API 错误信息、校验响应、邮件主题、通知正文、CSV 表头,以及服务端在发送前生成的一切内容。前端目录覆盖不到它们,插件更是完全看不见,因为它们从不出现在 DOM 中。

思路与客户端相同,只是放到服务端执行。给服务端引入一份运行时库,从请求中读取访客的 locale(Accept-Language 请求头,或用户记录上的 locale 字段),并从语言目录而不是字符串字面量生成响应。键命名空间保持共享,因此 errors.booking.overlap 在 toast 提示和 409 响应里含义一致。

漏掉这一步,应用在出现第一个错误之前看起来都是多语言的,一报错就开始说英文。

添加第二种语言之前要检查什么?

转换之前先过一遍这份清单。每一项现在修都更便宜,等五种语言上线后再改就贵了:

  • 拼接的字符串。 翻译人员无法调整 "Welcome back, " + user.name 的语序,请改用插值。
  • 复数。 英语有两种形式,波兰语有三种,阿拉伯语有六种。对 count === 1 用三元表达式,在大多数语言里都是错的。
  • 日期、数字和货币。 客户端和服务端都用 Intl,不要手写字符串格式化。
  • 布局。 德语和芬兰语比英语长。固定宽度的按钮会撑破,Tailwind 类名在文本到位之前看着都没问题。
  • 从右到左(RTL)。 如果路线图里有阿拉伯语或希伯来语,现在就要决定。后期补做 RTL 成本最高。
  • 语言目录漂移。 语言目录建好之后,某个键只加在一个 locale 里、其他 locale 没有,就是一个悄无声息的 bug。翻译文件为什么会不同步 讲了它如何发生,以及推送任务如何解决。

定价按工作区计算,不按席位收费,也不按语言收费,所以支持多少种语言是产品决策,而不是预算问题。最新价格见定价页。想看其他构建工具的同类流程,可以从 vibe coder 总览 开始。

从哪里开始

如果你的 Replit 项目已经连接了 GitHub,下一步就是对该仓库执行转换,而不是纠结选什么工具。如果还没连接,先在 Git 面板里完成连接,再回到这一步。

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

免费试用 globalize.now