La tua app Lovable può essere tradotta per intero e dire comunque «5 элемент» o mostrare un prezzo come «1,234.50» a un utente tedesco. La causa è la logica di plurali e formattazione scritta per l'inglese e rimasta nei tuoi componenti. globalize.now è un'infrastruttura di localizzazione basata su IA che tiene le stringhe in catalog versionati: la correzione qui sotto sposta le regole di plurale in quei catalog invece che nel codice.
Perché i plurali si rompono quando Lovable traduce la mia app?
Perché la regola di plurale si trova nel componente, non nella traduzione. Un pattern generato molto comune è questo:
<p>{count} {count === 1 ? "item" : "items"} in your cart</p>
Quella riga codifica la grammatica inglese. Chi traduce può cambiare le parole ma non il test === 1, e anche l'ordine delle parole è fisso, con il numero sempre per primo. L'inglese ha due forme. Il russo ne ha quattro, quindi «1 элемент», «2 элемента», «5 элементов» e «1,5 элемента» richiedono tutti desinenze diverse.
Se hai configurato prima il routing (vedi come rendere multilingue un'app Lovable), i plurali sono il prossimo bug che gli utenti notano, perché non si blocca nulla. La frase è semplicemente sbagliata.
Passaggio 1: come scrivo un plurale che chi traduce può modificare?
Usa un messaggio plurale ICU, così la regola passa nella traduzione. Con Lingui, sia il componente Plural sia la macro plural ne producono uno.
import { Plural } from "@lingui/react/macro";
<p>
<Plural value={count} one="# item in your cart" other="# items in your cart" />
</p>
Per le stringhe fuori da JSX, usa la macro del pacchetto core:
import { plural } from "@lingui/core/macro";
const label = plural(count, { one: "# file", other: "# files" });
# viene sostituito dal numero. Come indicato nella documentazione di Lingui, scrivi solo le forme che servono alla lingua sorgente, e other è obbligatorio. Le corrispondenze esatte come _0="Your cart is empty" gestiscono il caso zero in inglese senza un ramo separato.
Gli stack predefiniti di Lovable differiscono nel setup ma non in questa API, quindi lo stesso componente funziona sia nel Vite SPA sia nei progetti TanStack Start.
Che aspetto ha il catalog dopo l'estrazione dei plurali?
Un messaggio per stringa, in sintassi ICU standard, salvato come file PO nel tuo repository. Chi traduce, umano o IA, fornisce le forme necessarie alla propria lingua.
msgid "{count, plural, one {# item in your cart} other {# items in your cart}}"
msgstr "{count, plural, one {# товар в корзине} few {# товара в корзине} many {# товаров в корзине} other {# товара в корзине}}"
La forma russa other copre anche le frazioni come 1,5, ed è per questo che coincide con il genitivo singolare. Poiché il catalog è un file versionato, rivedi le modifiche ai plurali in una pull request come qualsiasi altro codice. Per la sintassi in sé, vedi cos'è ICU MessageFormat.
Quali lingue hanno bisogno di più di one e other?
Unicode CLDR definisce sei categorie di plurale: zero, one, two, few, many e other. Ogni lingua ne usa un sottoinsieme, e other è obbligatoria ovunque.
| Lingua | Categorie usate |
|---|---|
| giapponese, cinese | other |
| Inglese | one, other |
| Russo | one, few, many, other |
| Arabo | zero, one, two, few, many, other |
La specifica CLDR indica che anche il gallese le usa tutte e sei. Non serve memorizzarle. Serve un formato di catalog in cui ogni lingua compila le proprie forme, ed è quello che offre PO con messaggi ICU.
Come evito che Lovable riscriva i plurali con i ternari?
Metti la regola dove Lovable legge le istruzioni. Lovable rigenera i componenti quando gli chiedi nuove feature, e una feature scritta senza la regola riporta il ternario.
Aggiungi questo a Knowledge o a AGENTS.md:
Never hand-build plurals or number formats. Use the Lingui Plural component
or plural() macro for every count. Use Intl with the active locale for every
date, number and price.
La skill lovable-i18n scrive regole di questo tipo al posto tuo. Come lo fa è spiegato in cosa fa la skill Lovable i18n. Dopo la prossima feature generata, cerca nel diff === 1 e !== 1 per verificare che la regola abbia tenuto.
Passaggio 2: come formatto date e valuta in base al locale?
Usa Intl con il locale attivo. L'oggetto i18n di Lingui offre anche i18n.date() e i18n.number(), ma chiamare Intl direttamente con i18n.locale mantiene le opzioni di formattazione visibili nel tuo codice.
import { useLingui } from "@lingui/react";
export function Price({ amount, currency }: { amount: number; currency: string }) {
const { i18n } = useLingui();
return (
<span>
{new Intl.NumberFormat(i18n.locale, { style: "currency", currency }).format(amount)}
</span>
);
}
export function OrderDate({ date }: { date: Date }) {
const { i18n } = useLingui();
return <time>{new Intl.DateTimeFormat(i18n.locale, { dateStyle: "long" }).format(date)}</time>;
}
Gli stessi 1234,5 euro vengono resi come una stringa diversa in ogni locale, con separatori e posizione del simbolo propri. La formattazione non converte mai il denaro. Un prezzo salvato in euro resta in euro in ogni lingua, quindi tieni il codice valuta accanto a ogni prezzo nel database.
Passaggio 3: come testo ogni categoria di plurale prima del rilascio?
Chiedi al browser in quale categoria rientra un numero, poi verifica che ognuna abbia una forma.
const ru = new Intl.PluralRules("ru");
[1, 2, 5, 21, 1.5].map((n) => ru.select(n));
// ["one", "few", "many", "one", "other"]
const ar = new Intl.PluralRules("ar");
[0, 1, 2, 3, 11, 100].map((n) => ar.select(n));
// ["zero", "one", "two", "few", "many", "other"]
Aggiungi un test per ogni lingua che rilasci: renderizza il componente con un numero di ciascuna categoria e verifica che nessuno ricada su una forma mancante. Poi leggi una volta le pagine in russo e arabo nel browser. Un few mancante in un catalog si manifesta come desinenza sbagliata, non come errore.
Cosa cambia se prima usavo un widget runtime?
I widget runtime traducono il testo renderizzato dopo il caricamento, quindi non vedono una regola di plurale nel tuo codice. È parte del motivo per cui spostare le traduzioni nel repository conta. Lovalingo ha chiuso il 31 agosto 2026; la guida alla migrazione e la pagina di confronto spiegano cosa cambia quando i catalog stanno nel tuo repo.
Con globalize.now connetti il repository una volta sola e la codebase viene convertita nell'app. Da lì, i job di push traducono le nuove unità del catalog e il risultato arriva come pull request. Lovable si sincronizza da GitHub, quindi le forme plurali arrivano nella tua app come qualsiasi altra modifica. Il setup è nella pagina di integrazione con Lovable, e il workflow senza dashboard è in localizza un'app Lovable senza dashboard.
globalize.now trasforma il testo hardcoded dell'app in file di localizzazione pronti e li mantiene aggiornati mentre rilasci.
Prova globalize.now gratis