If your Lovable app renders in English no matter what language you add, the cause is the stack change: since mid-May 2026, new Lovable projects ship on TanStack Start with server-side rendering, not the old React and Vite single-page app. globalize.now is AI-powered localization infrastructure that fits this new stack by extracting your strings into committed Lingui PO catalogs, so the correct language renders on the server instead of getting swapped in the browser. The fix is not another widget. It is moving translation into your repo, where the server can render it and search engines can index it.
Why did localizing your Lovable app suddenly get harder?
Because the ground moved under the old advice. Most "translate your Lovable app" guides assume a client-rendered single-page app, where a widget can rewrite the DOM after load and no one notices. That assumption is now wrong for new projects.
Lovable switched new projects to TanStack Start with SSR so that crawlers receive fully rendered HTML on the first request, with no JavaScript execution required. That is a real SEO win, but it inverts how translation has to work. When the first response is already rendered, translating it afterward in the browser is too late.
If you built your app in the last couple of months and dropped in a runtime translation widget, you are seeing the symptom: a flash of English, then the swap. The Lovable integration for globalize.now exists precisely to handle this at the layer where it belongs.
What actually changed in Lovable's TanStack Start switch?
The rendering model changed from client-side to server-side. Previously Lovable generated single-page apps built with React and Vite, deployed as static files and rendered entirely in the browser. Now the base is TanStack Start, a full-stack React framework with per-route SSR, SSG, and CSR, plus server functions colocated with components.
For localization, three things matter. First, HTML is produced on the server before it reaches the browser, so the language is decided server-side. Second, routing now supports real per-locale URLs. Third, anything that depends on browser-only APIs to pick a language runs after the server has already committed to one.
That third point is where most broken setups live. A locale saved in localStorage is invisible to the server, so the server renders the default language and the client corrects it a beat later.
Why do runtime translation widgets flash English on SSR?
Because they translate after the server has already sent English. On the new stack the sequence is: the server renders HTML in the default language, the browser paints it, then the widget's JavaScript loads and rewrites the text. The gap between paint and rewrite is the flash of English, and it is now structural, not a tuning problem.
The SEO cost is worse than the flash. A crawler reads the first response and moves on. If the translated text only appears after client-side JavaScript runs, the crawler indexes English for every locale, and you get no per-language pages to rank. The whole reason Lovable moved to SSR, indexable HTML, is undone by translating in the browser.
Committed catalogs avoid this by design. When the translation strings live in your repo, TanStack Start renders the requested locale on the server, so the first response is already correct. This is the durable difference between infrastructure that lives in your codebase and a widget that runs on top of it, and it is why runtime tools like Weglot fit the old SPA model better than the new one. For a longer treatment of the sync problem, see why Lovable translations break on every push.
How do you make a TanStack Start Lovable app multilingual?
Move translation to the server and keep the catalogs in your repo. Concretely, that is four steps on the new stack, and none of them require you to hand-edit locale files.
- Add the
lovable-i18nskill and let Lovable wire i18n. In your Lovable workspace, add thelovable-i18nskill, then prompt Lovable to set up internationalization. It installs Lingui, extracts your hardcoded UI strings into message catalogs, and configures the provider. Outside the editor the same setup installs withnpx skills add globalize-now/globalize-skills(add--allto install for all agents). - Route locales with TanStack's optional path param. TanStack Router uses
{-$locale}for optional path parameters, so a route defined as/{-$locale}/aboutmatches both/aboutfor your default language and/es/aboutfor Spanish. That gives every language a distinct, crawlable URL instead of one URL whose text mutates in the browser. - Resolve the locale on the server, not in
localStorage. Store the active language in a cookie so the SSR handler can read it from the request. With Lingui, the server callssetupLocaleFromRequest()before creating the router, and the client hydration callsdynamicActivate()with the server-provided locale before rendering. Same value on both sides means no hydration mismatch and no flash. - Keep catalogs in your repo, synced on every push. The PO catalogs are committed files, not a vendor's runtime. As you keep building in Lovable and new strings appear, they need extracting and translating again, and that is the part that rots by hand. This is the job globalize.now does automatically, so the catalogs stay current without a manual export step.
// 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);Because this is a real step-by-step procedure with committed output, it behaves like standard version-controlled code: reviewable in a pull request, diffable, and portable if you ever move off Lovable.
Where does globalize.now fit in the TanStack Start i18n stack?
It sits one layer below the runtime library and above the translation engine. TanStack Start and Lingui serve translations at runtime; DeepL or an LLM produces the translations themselves. globalize.now is the infrastructure in between: it generates the keys and the PO catalogs and keeps them in sync, so the runtime always has something correct to render.
The practical effect for a Lovable builder is that you stop babysitting locale files. You install the skill, prompt Lovable once, and every subsequent push extracts new strings, fills the catalogs, and opens the change as a normal PR. No dashboard round-trip, no re-export, no drift between what your app says and what your catalogs contain.
Pricing is one plan: €20/month per workspace, including over 4,000,000 characters (about 600,000 words) per month, then token-based usage at the same per-character rate. There are no per-seat and no per-language charges, and signup comes with a €5 credit and no card. A typical Lovable app across five locales lands comfortably inside that. If you want the developer-side detail, the globalize.now for developers and vibe coders pages go deeper, and the product overview covers the rest of the stack.
Your Lovable app is stuck in English because the translation is happening in the wrong place, the browser, after the server already committed to a language. Move it into your repo and the server renders the right language on the first request. globalize.now handles the extraction and sync so you set it up once and it stays current on every push.
globalize.now turns hardcoded app copy into translation-ready locale files and keeps them updated as you ship.
Try globalize.now free