Deine Lovable-App kann vollständig übersetzt sein und trotzdem „5 элемент“ sagen oder einem deutschen User einen Preis als „1,234.50“ anzeigen. Die Ursache ist Plural- und Formatierungslogik, die für Englisch geschrieben und in deinen Komponenten stehen geblieben ist. globalize.now ist KI-gestützte Lokalisierungsinfrastruktur, die deine Strings in committeten Katalogen hält. Der Fix unten legt die Pluralregeln in diese Kataloge statt in deinen Code.

Warum brechen Plurale, wenn Lovable meine App übersetzt?

Weil die Pluralregel in der Komponente steckt und nicht in der Übersetzung. Ein typisches generiertes Pattern sieht so aus:

<p>{count} {count === 1 ? "item" : "items"} in your cart</p>

Diese Zeile codiert englische Grammatik hart. Übersetzer:innen können die Wörter ändern, aber nicht den === 1-Test, und auch die Wortstellung ist fix, mit der Zahl immer vorn. Englisch hat zwei Formen. Russisch hat vier, also brauchen „1 элемент“, „2 элемента“, „5 элементов“ und „1,5 элемента“ jeweils andere Endungen.

Wenn du zuerst das Routing eingerichtet hast (siehe So machst du eine Lovable-App mehrsprachig), sind Plurale der nächste Bug, den User bemerken – denn nichts stürzt ab. Der Satz ist einfach falsch.

Schritt 1: Wie schreibe ich einen Plural, den Übersetzer:innen ändern können?

Nutze eine ICU-Plural-Message, damit die Regel in die Übersetzung wandert. Mit Lingui erzeugen die Plural-Komponente und das plural-Macro jeweils eine.

import { Plural } from "@lingui/react/macro";

<p>
  <Plural value={count} one="# item in your cart" other="# items in your cart" />
</p>

Für Strings außerhalb von JSX nimmst du das Macro aus dem Core-Paket:

import { plural } from "@lingui/core/macro";

const label = plural(count, { one: "# file", other: "# files" });

# wird durch die Zahl ersetzt. Laut Lingui-Doku schreibst du nur die Formen, die deine Quellsprache braucht, und other ist Pflicht. Exakte Treffer wie _0="Your cart is empty" decken in Englisch den Null-Fall ohne separaten Branch ab.

Die Default-Stacks von Lovable unterscheiden sich im Setup, nicht in dieser API – dieselbe Komponente funktioniert also im Vite-SPA und in den TanStack-Start-Projekten.

Wie sieht der Katalog aus, sobald die Plurale extrahiert sind?

Eine Message pro String in Standard-ICU-Syntax, gespeichert als PO-Datei in deinem Repository. Die Übersetzung – ob von Menschen oder KI – liefert die Formen, die ihre Sprache braucht.

msgid "{count, plural, one {# item in your cart} other {# items in your cart}}"
msgstr "{count, plural, one {# товар в корзине} few {# товара в корзине} many {# товаров в корзине} other {# товара в корзине}}"

Die russische other-Form deckt Brüche wie 1,5 ab, deshalb entspricht sie dem Genitiv Singular. Da der Katalog eine committete Datei ist, prüfst du Plural-Änderungen wie jeden anderen Code im Pull Request. Zur Syntax selbst siehe Was ICU MessageFormat ist.

Welche Sprachen brauchen mehr als one und other?

Unicode CLDR definiert sechs Plural-Kategorien: zero, one, two, few, many und other. Jede Sprache nutzt eine Teilmenge, und other ist überall Pflicht.

SpracheVerwendete Kategorien
Japanisch, Chinesischother
Englischone, other
Russischone, few, many, other
Arabischzero, one, two, few, many, other

Laut CLDR-Spec nutzt auch Walisisch alle sechs. Das musst du dir nicht merken. Du brauchst ein Katalogformat, in dem jede Sprache ihre eigenen Formen füllt – und das leistet PO mit ICU-Messages.

Wie verhindere ich, dass Lovable wieder Ternary-Plurale schreibt?

Leg die Regel dorthin, wo Lovable Anweisungen liest. Lovable generiert Komponenten neu, sobald du neue Features promptest, und ein Feature, das ohne die Regel entsteht, bringt das Ternary zurück.

Füge das in deine Knowledge oder AGENTS.md ein:

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.

Der Skill lovable-i18n schreibt solche Regeln für dich. Wie das funktioniert, steht in Was der Lovable-i18n-Skill macht. Durchsuche nach deinem nächsten generierten Feature den Diff nach === 1 und !== 1, um zu prüfen, ob die Regel gehalten hat.

Schritt 2: Wie formatiere ich Datum und Währung je nach Locale?

Nutze Intl mit der aktiven Locale. Das i18n-Objekt von Lingui bietet auch i18n.date() und i18n.number(), aber wenn du Intl direkt mit i18n.locale aufrufst, bleiben die Formatierungsoptionen in deinem eigenen Code sichtbar.

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>;
}

Dieselben 1234,5 Euro werden in jeder Locale als anderer String gerendert, mit eigenen Trennzeichen und Symbolposition. Formatierung rechnet nie Geld um. Ein Preis in Euro bleibt in jeder Sprache ein Preis in Euro, also speichere den Währungscode neben jedem Preis in deiner Datenbank.

Schritt 3: Wie teste ich jede Plural-Kategorie vor dem Release?

Frag den Browser, in welche Kategorie eine Zahl fällt, und prüfe dann, ob jede Kategorie eine Form hat.

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"]

Schreib pro ausgelieferter Sprache einen Test: Rendere die Komponente mit einer Zahl aus jeder Kategorie und prüfe, dass keine auf eine fehlende Form zurückfällt. Lies danach die russischen und arabischen Seiten einmal im Browser durch. Ein fehlendes few im Katalog zeigt sich als falsche Endung, nicht als Fehler.

Was ändert sich, wenn ich vorher ein Runtime-Widget genutzt habe?

Runtime-Widgets übersetzen den gerenderten Text nach dem Laden und sehen deshalb keine Pluralregel in deinem Code. Das ist ein Grund, warum es sich lohnt, Übersetzungen ins Repository zu holen. Lovalingo wurde am 31. August 2026 eingestellt; der Migrationsguide und die Vergleichsseite zeigen, was sich ändert, wenn die Kataloge in deinem Repo liegen.

Mit globalize.now verbindest du das Repository einmal, und die Codebase wird in der App konvertiert. Danach übersetzen Push-Jobs neue Katalog-Einheiten, und das Ergebnis kommt als Pull Request zurück. Lovable synchronisiert von GitHub, die Pluralformen erreichen deine App also wie jede andere Änderung. Das Setup findest du auf der Lovable-Integrationsseite, den Workflow ohne Dashboard unter Eine Lovable-App ohne Dashboard lokalisieren.

globalize.now konvertiert hartcodierte App-Texte in übersetzungsreife Locale-Dateien und hält sie aktuell, während Sie veröffentlichen.

Probiere globalize.now kostenlos