如果无论添加什么语言,你的 Lovable 应用都只显示英文,原因在于技术栈变了:自 2026 年 5 月中旬起,新的 Lovable 项目基于启用服务端渲染的 TanStack Start,而不是旧的 React 加 Vite 单页应用。globalize.now 是 AI 驱动的本地化基础设施,适配这套新技术栈:它把字符串提取到已提交的 Lingui PO 语言目录中,让正确的语言在服务端渲染,而不是在浏览器里替换。解决办法不是再加一个插件,而是把翻译放进你的仓库,让服务器能渲染、搜索引擎能收录。
为什么 Lovable 应用的本地化突然变难了?
因为旧建议赖以成立的前提变了。大多数“翻译你的 Lovable 应用”指南都假定应用是客户端渲染的单页应用,插件可以在页面加载后改写 DOM,没人会察觉。对新项目来说,这个假设已经不成立。
Lovable 把新项目切换到启用 SSR 的 TanStack Start,让爬虫在首次请求就拿到完整渲染的 HTML,无需执行 JavaScript。这对 SEO 是实打实的提升,但也颠覆了翻译的工作方式:首次响应已经渲染完成,再到浏览器里翻译就晚了。
如果你在最近几个月构建了应用,并接入了运行时翻译插件,你看到的就是这个症状:先闪现英文,随后才被替换。globalize.now 的 Lovable 集成正是为了在合适的层面解决这个问题。
Lovable 切换到 TanStack Start,究竟改变了什么?
渲染模型从客户端渲染变成了服务端渲染。此前,Lovable 生成的是用 React 和 Vite 构建的单页应用,以静态文件部署,完全在浏览器中渲染。现在的基础是 TanStack Start,一个全栈 React 框架,支持按路由选择 SSR、SSG 和 CSR,还可以把服务端函数与组件放在一起。
对本地化来说,有三点很关键。第一,HTML 在到达浏览器之前就在服务端生成,所以语言由服务端决定。第二,路由现在支持真正按 locale 划分的 URL。第三,任何依赖浏览器专有 API 选择语言的逻辑,都是在服务端已经选定语言之后才运行的。
大多数出问题的配置都栽在第三点上。保存在 localStorage 中的 locale,服务器看不到,于是服务器渲染默认语言,客户端稍后再把它纠正过来。
为什么运行时翻译插件在 SSR 下会闪现英文?
因为它们是在服务器已经发出英文之后才翻译的。在新的技术栈上,流程是这样的:服务器用默认语言渲染 HTML,浏览器绘制页面,随后插件的 JavaScript 加载并改写文本。绘制和改写之间的间隔,就是英文闪现的那一下,而这现在是结构性问题,不是调优能解决的。
对 SEO 的代价比闪现更严重。爬虫读取首次响应后就离开了。如果翻译后的文本要等客户端 JavaScript 运行后才出现,爬虫就会为每个 locale 都收录英文,你也就没有可供排名的各语言页面。Lovable 转向 SSR 的初衷,也就是可被收录的 HTML,被浏览器端翻译一笔勾销了。
已提交的语言目录从设计上就避开了这个问题。翻译字符串存放在你的仓库里时,TanStack Start 在服务端渲染请求的 locale,首次响应就已经是正确的。这就是扎根于代码库的基础设施与架在其上的插件之间的根本区别,也是 Weglot 这类运行时工具更适合旧 SPA 模式、而不适合新模式的原因。关于同步问题的更详细讨论,参见为什么 Lovable 的翻译会在每次推送时失效。
如何让基于 TanStack Start 的 Lovable 应用支持多语言?
把翻译移到服务端,并将语言目录保留在你的仓库中。具体来说,新技术栈上只需四步,而且都不需要手动编辑语言文件。
- 添加
lovable-i18nSkill,让 Lovable 接入 i18n。 在 Lovable 工作区中添加lovable-i18nSkill,然后提示 Lovable 配置国际化。它会安装 Lingui,将硬编码的 UI 字符串提取到消息目录中,并配置 provider。在编辑器之外,也可以用npx skills add globalize-now/globalize-skills安装同样的配置(加上--all即可为所有 Agent 安装)。 - 用 TanStack 的可选路径参数路由语言区域。 TanStack Router 使用
{-$locale}表示可选路径参数,因此定义为/{-$locale}/about的路由既能匹配默认语言的/about,也能匹配西班牙语的/es/about。这样每种语言都有独立且可被爬取的 URL,而不是一个文本在浏览器里被动态改写的 URL。 - 在服务端而不是
localStorage中确定 locale。 把当前语言存入 cookie,SSR 处理器就能从请求中读取。使用 Lingui 时,服务端在创建 router 之前调用setupLocaleFromRequest(),客户端 hydration 则在渲染前用服务端提供的 locale 调用dynamicActivate()。两端取值一致,就不会出现 hydration 不匹配,也不会闪烁。 - 将目录保留在仓库中,每次推送都自动同步。 PO 目录是提交到仓库的文件,而不是某个供应商的运行时。你在 Lovable 中持续开发时,新字符串会不断出现,需要重新提取和翻译,而手动维护恰恰最容易出问题。这正是 globalize.now 自动完成的工作,因此目录始终保持最新,无需手动导出。
// server: resolve locale before the router exists
const locale = getLocaleFromCookie(request) ?? "en";
await setupLocaleFromRequest(locale);
// client: activate the SAME locale before first render
await dynamicActivate(serverLocale);
这是一套有已提交产物的完整分步流程,所以它和标准的版本控制代码一样:可以在 PR 中评审、可以 diff,即使将来离开 Lovable 也能迁移。
globalize.now 在 TanStack Start 的 i18n 技术栈中处于什么位置?
它位于运行时库之下、翻译引擎之上。TanStack Start 和 Lingui 负责在运行时提供翻译;DeepL 或 LLM 负责产出译文本身。globalize.now 是介于两者之间的基础设施:它生成键和 PO 目录并保持同步,让运行时始终有正确的内容可渲染。
对 Lovable 开发者来说,实际效果是你不用再盯着语言文件了。安装 Skill,向 Lovable 发一次提示,之后每次推送都会提取新字符串、填充目录,并以普通 PR 的形式提交变更。无需往返控制台,无需重新导出,应用文案与目录内容之间也不会出现偏差。
定价只有一个套餐:每个工作区每月 €20,包含每月 €20 的翻译额度(约 200,000 词),超出部分按相同的单字符费率按 token 计费。不按席位收费,也不按语言收费,注册即送 €5 额度,无需绑卡。五种语言的典型 Lovable 应用完全在额度之内。如果你想了解开发者视角的细节,可以看 面向开发者的 globalize.now 和 面向 vibe coder 的 globalize.now 页面,产品概览 则介绍了技术栈的其余部分。
你的 Lovable 应用卡在英文,是因为翻译发生在了错误的位置:浏览器里,而此时服务端已经确定了语言。把翻译移进仓库,服务端在首次请求时就能渲染出正确的语言。提取和同步交给 globalize.now,配置一次,之后每次推送都保持最新。
globalize.now 把硬编码的应用文案转换为可直接翻译的语言文件,并在你持续发布时保持同步更新。
免费试用 globalize.now