Il modo migliore per localizzare un’app Lovable basata sul classico stack Vite è estrarre le stringhe hardcoded nei cataloghi PO di Lingui versionati, non aggiungere un widget di traduzione runtime. La tua app Lovable è una SPA React renderizzata sul client, quindi non c’è un rendering server a cui agganciarsi. L’opzione più solida è usare file di traduzione che vivono nel tuo repository e vengono inclusi nella build. globalize.now è un’infrastruttura di localizzazione basata su IA che esegue l’estrazione e mantiene sincronizzati i cataloghi a ogni push su Git: la configuri una volta e non devi più gestire a mano i file delle locale.
Su quale stack gira la tua app Lovable: Vite classico o TanStack Start?
Apri prima l’albero dei file, perché Lovable usa due stack diversi e ciascuno richiede una configurazione i18n diversa. Se vedi src/pages/Index.tsx, src/main.tsx e vite.config.ts, usi il classico stack Vite + React SPA, quello predefinito di Lovable. I progetti TanStack Start hanno invece src/routes/, src/router.tsx, src/routeTree.gen.ts e src/server.ts.
Lo stack viene scelto quando crei il progetto e non può essere cambiato in seguito, quindi questa decisione è già stata presa per te. Il classico stack Vite esegue tutto il rendering nel browser e, per impostazione predefinita, non recupera dati dal server. Questa guida tratta la SPA Vite classica. Se i tuoi file corrispondono alla struttura TanStack Start, segui invece la nostra guida i18n di TanStack Start per Lovable, perché il rendering server cambia il modo in cui vengono caricate le traduzioni.
Perché le app Lovable Vite SPA vengono trascurate dagli strumenti i18n?
Perché l’attenzione degli strumenti si è spostata sul nuovo default di Lovable, TanStack Start + SSR, lasciando scoperta la classica Vite SPA, anche se resta lo stack Lovable più diffuso. Negli ultimi mesi, gli strumenti di localizzazione rivolti a Lovable, tra cui Lovalingo, Intlayer e Paraglide, hanno tutti riscritto le proprie guide puntando su TanStack Start con rendering server-side.
Il risultato è un vuoto. Una SPA renderizzata sul client ha vincoli reali che le guide SSR ignorano: non c’è un rendering server che possa iniettare il markup tradotto, l’intero bundle viene caricato nel browser e qualsiasi script caricato in ritardo dipinge sopra una UI in inglese. La buona notizia è che lo stack classico ha una risposta pulita e ben supportata, di cui la maggior parte di chi costruisce app non sente mai parlare perché gli strumenti più rumorosi inseguono l’altro stack.
Qual è la differenza tra cataloghi versionati e un widget di traduzione runtime?
I cataloghi versionati sono file di traduzione inseriti nel repository e inclusi nella build, mentre un widget runtime è uno script di terze parti che sostituisce il testo nel browser dopo che la UI inglese è già stata caricata. Questa differenza determina tre aspetti importanti per una Vite SPA.
Primo: flash e layout shift. Un widget mostra l’inglese e poi lo riscrive, quindi l’utente vede uno scambio evidente e il layout può saltare. I cataloghi versionati renderizzano la lingua corretta già al primo paint. Secondo: indicizzabilità. Le stringhe incluse nella build fanno parte della sorgente, mentre il testo del widget viene iniettato in ritardo ed è più difficile da leggere per i crawler. Terzo: controllo. I cataloghi versionati sono file tuoi nel repository, quindi l’app non dipende da nulla di esterno per continuare a parlare tedesco o giapponese.
Come aggiungo l’i18n a un’app Lovable Vite con Lingui?
Aggiungi Lingui come layer i18n, racchiudi le stringhe e lascia che il plugin Vite compili i cataloghi. Lingui è un framework i18n leggero con un plugin Vite dedicato e un formato di catalogo basato su PO: esattamente ciò che serve a una SPA renderizzata sul client.
Per prima cosa, installa i pacchetti. Lingui separa la CLI, il plugin Vite e il runtime React:
npm install --save-dev @lingui/cli @lingui/vite-plugin @rolldown/plugin-babel
npm install @lingui/core @lingui/react
Poi registra il plugin in vite.config.ts e aggiungi un lingui.config.ts che punti alla cartella del codice sorgente e a quella delle locale:
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { lingui } from "@lingui/vite-plugin";
export default defineConfig({
plugins: [react(), lingui()],
});
// lingui.config.ts
import { defineConfig } from "@lingui/cli";
export default defineConfig({
locales: ["en", "de", "fr"],
sourceLocale: "en",
catalogs: [
{
path: "src/locales/{locale}/messages",
include: ["src"],
},
],
});
Quindi racchiudi il testo JSX hardcoded con la macro Trans invece di lasciare stringhe isolate:
// before
<h1>Create your account</h1>
// after
import { Trans } from "@lingui/react/macro";
<h1><Trans>Create your account</Trans></h1>
Ora esegui l’estrazione. La CLI analizza la directory src e scrive un catalogo PO per ogni locale, ad esempio src/locales/en/messages.po:
npx lingui extract
Compila i campi msgstr per ogni lingua oppure delega il passaggio a un layer automatizzato (vedi la sezione successiva). Non devi eseguire un comando di compilazione separato, perché @lingui/vite-plugin compila i cataloghi PO al volo durante lo sviluppo e la build.
Infine, aggiungi un selettore della lingua attivando una locale a runtime:
import { i18n } from "@lingui/core";
i18n.activate("de");
Questo è l’intero ciclo per il classico stack Vite: installa, racchiudi, estrai, traduci, cambia lingua. Nel repository vive tutto, tranne le traduzioni vere e proprie.
Come automatizza tutto questo globalize.now a ogni push?
globalize.now elimina i passaggi manuali di estrazione e compilazione monitorando il repository e svolgendoli per te a ogni push su Git. Trova le nuove stringhe hardcoded nella codebase Lovable, genera le chiavi e le entry PO richieste da Lingui, produce le traduzioni e fa commit dei cataloghi aggiornati, così la cartella src/locales è sempre aggiornata senza eseguire comandi.
Connetti una volta il repository a globalize.now e inizierà a monitorarlo. Per configurarlo direttamente dall’editor, installa le skill:
npx skills add globalize-now/globalize-skills
In Lovable, aggiungi la skill lovable-i18n al workspace, poi chiedi a Lovable di configurare l’i18n. Il runtime resta Lingui, quindi il modo in cui l’app esegue il rendering non cambia. Cambia il fatto che non devi più fare da babysitter ai file delle locale. È lo stesso modello «configura una volta, sincronizza a ogni push» su cui si basano il nostro workflow per vibe coder e la configurazione per sviluppatori.
Per chi costruisce da solo, il pricing è semplice: 20 € al mese per workspace, senza costi per seat o per lingua, più le traduzioni che usi davvero. I nuovi workspace ricevono 5 € di credito all’iscrizione, senza carta: abbastanza per tradurre da cima a fondo una piccola app.
Meglio usare invece un widget runtime? La lezione di Lovalingo
Non se vuoi che le traduzioni durino più di un singolo vendor. Un widget di traduzione runtime è comodo all’inizio, ma rende l’app dipendente dal fatto che i server di qualcun altro restino online. E questa dipendenza ha un vero punto di rottura.
Lovalingo, un widget runtime popolare tra chi costruisce app con Lovable, ha annunciato la chiusura per il 31 agosto 2026. Non accetta più nuove iscrizioni e non è stato indicato alcun successore. Le sue stesse istruzioni di migrazione invitano a passare a un’internazionalizzazione gestita dal progetto: esattamente l’approccio basato su cataloghi versionati descritto in questa guida. Quando il vendor di un widget chiude, le traduzioni iniettate smettono di funzionare e la UI torna in inglese. I file nel repository no. Se usi già un widget, la nostra guida alla migrazione dopo la chiusura di Lovalingo illustra il passaggio; il più ampio problema delle traduzioni che si rompono a ogni push spiega perché i cataloghi versionati sono la scelta giusta per le app costruite con IA.
globalize.now trasforma il testo hardcoded dell'app in file di localizzazione pronti e li mantiene aggiornati mentre rilasci.
Prova globalize.now gratis