आपका Lovable ऐप पूरी तरह अनुवादित होने के बाद भी "5 элемент" कह सकता है, या किसी जर्मन उपयोगकर्ता को कीमत "1,234.50" के रूप में दिखा सकता है। इसकी वजह वह प्लुरल और फ़ॉर्मैट लॉजिक है जो अंग्रेज़ी के लिए लिखा गया था और आपके कंपोनेंट में रह गया। globalize.now AI-संचालित स्थानीयकरण इन्फ़्रास्ट्रक्चर है, जो आपकी स्ट्रिंग्स को कमिट किए गए कैटलॉग में रखता है। नीचे दिया गया समाधान प्लुरल के नियम आपके कोड की जगह उन्हीं कैटलॉग में रखता है।

Lovable द्वारा ऐप का अनुवाद करने पर प्लुरल क्यों टूट जाते हैं?

क्योंकि प्लुरल का नियम कंपोनेंट में रहता है, अनुवाद में नहीं। जनरेट किया गया एक आम पैटर्न कुछ ऐसा दिखता है:

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

वह पंक्ति अंग्रेज़ी व्याकरण को कोड में बाँध देती है। अनुवादक शब्द बदल सकता है, पर === 1 वाली जाँच नहीं, और शब्दों का क्रम भी तय रहता है, जिसमें संख्या हमेशा पहले आती है। अंग्रेज़ी में दो रूप होते हैं। रूसी में चार रूप होते हैं, इसलिए "1 элемент", "2 элемента", "5 элементов" और "1,5 элемента" सबके अंत अलग-अलग होने चाहिए।

यदि आपने पहले रूटिंग सेट की है (देखें Lovable ऐप को बहुभाषी कैसे बनाएँ), तो प्लुरल अगली गड़बड़ी है जो उपयोगकर्ताओं को दिखती है, क्योंकि कुछ क्रैश नहीं होता। बस वाक्य ग़लत होता है।

चरण 1: मैं ऐसा प्लुरल कैसे लिखूँ जिसे अनुवादक बदल सकें?

ICU प्लुरल मैसेज का उपयोग करें, ताकि नियम अनुवाद में चला जाए। Lingui में Plural कंपोनेंट और plural macro, दोनों ऐसा मैसेज बनाते हैं।

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

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

JSX के बाहर की स्ट्रिंग्स के लिए core पैकेज का macro उपयोग करें:

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

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

# की जगह संख्या आ जाती है। Lingui के दस्तावेज़ों के अनुसार, आप केवल वही रूप लिखते हैं जो आपकी स्रोत भाषा को चाहिए, और other अनिवार्य है। _0="Your cart is empty" जैसे सटीक मिलान अंग्रेज़ी में अलग शाखा के बिना शून्य वाला मामला सँभाल लेते हैं।

Lovable के डिफ़ॉल्ट स्टैक सेटअप में अलग हैं, पर इस API में नहीं, इसलिए वही कंपोनेंट Vite SPA और TanStack Start प्रोजेक्ट, दोनों में काम करता है।

प्लुरल एक्सट्रैक्ट होने के बाद कैटलॉग कैसा दिखता है?

हर स्ट्रिंग के लिए एक मैसेज, मानक ICU सिंटैक्स में, आपकी रिपॉज़िटरी में PO फ़ाइल के रूप में सहेजा हुआ। अनुवादक, चाहे इंसान हो या AI, अपनी भाषा के लिए ज़रूरी रूप ख़ुद देता है।

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

रूसी का other रूप 1,5 जैसे भिन्नों को भी कवर करता है, इसीलिए यह संबंध कारक (genitive) के एकवचन जैसा होता है। चूँकि कैटलॉग कमिट की गई फ़ाइल है, आप प्लुरल में बदलाव की समीक्षा किसी भी अन्य कोड की तरह pull request में करते हैं। सिंटैक्स के बारे में जानने के लिए देखें ICU MessageFormat क्या है।

किन भाषाओं को one और other से अधिक रूप चाहिए?

Unicode CLDR छह प्लुरल श्रेणियाँ परिभाषित करता है: zero, one, two, few, many और other। हर भाषा इनमें से कुछ का उपयोग करती है, और other हर जगह अनिवार्य है।

भाषाउपयोग की जाने वाली श्रेणियाँ
जापानी, चीनीother
अंग्रेजीone, other
रूसीone, few, many, other
अरबीzero, one, two, few, many, other

CLDR स्पेसिफ़िकेशन के अनुसार वेल्श भाषा भी सभी छह श्रेणियों का उपयोग करती है। इसे याद रखने की ज़रूरत नहीं है। आपको ऐसा कैटलॉग फ़ॉर्मैट चाहिए जो हर भाषा को अपने रूप भरने दे, और ICU मैसेज वाला PO यही करता है।

मैं Lovable को दोबारा ternary प्लुरल लिखने से कैसे रोकूँ?

नियम वहाँ रखें जहाँ Lovable निर्देश पढ़ता है। जब आप नई फ़ीचर के लिए प्रॉम्प्ट देते हैं, तो Lovable कंपोनेंट दोबारा जनरेट करता है, और बिना इस नियम के लिखी गई नई फ़ीचर ternary को वापस ले आती है।

इसे अपनी Knowledge या 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.

lovable-i18n स्किल इसी तरह के नियम आपके लिए लिखती है। यह कैसे होता है, इसकी जानकारी Lovable i18n स्किल क्या करती है में है। अगली जनरेट की गई फ़ीचर के बाद, diff में === 1 और !== 1 खोजकर जाँच लें कि नियम का पालन हुआ।

चरण 2: मैं locale के अनुसार तारीख़ें और करेंसी कैसे फ़ॉर्मैट करूँ?

सक्रिय locale के साथ Intl का उपयोग करें। Lingui का i18n ऑब्जेक्ट i18n.date() और i18n.number() भी देता है, लेकिन i18n.locale के साथ सीधे Intl को कॉल करने से फ़ॉर्मैटिंग विकल्प आपके अपने कोड में दिखते रहते हैं।

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

वही 1234.5 यूरो हर locale में अलग स्ट्रिंग के रूप में दिखता है, अपने विभाजक चिह्नों और सिंबल की जगह के साथ। फ़ॉर्मैटिंग कभी पैसे का रूपांतरण नहीं करती। यूरो में सहेजी गई कीमत हर भाषा में यूरो ही रहती है, इसलिए अपने डेटाबेस में हर कीमत के साथ करेंसी कोड रखें।

चरण 3: शिप करने से पहले हर प्लुरल श्रेणी की जाँच कैसे करूँ?

ब्राउज़र से पूछें कि कोई संख्या किस श्रेणी में आती है, फिर जाँचें कि हर श्रेणी का एक रूप मौजूद है।

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

आप जितनी भाषाएँ शिप करते हैं, हर एक के लिए एक टेस्ट जोड़ें: हर श्रेणी की एक संख्या के साथ कंपोनेंट रेंडर करें और जाँचें कि कोई भी संख्या छूटे हुए रूप पर फ़ॉलबैक न करे। फिर रूसी और अरबी पेज ब्राउज़र में एक बार पढ़ लें। कैटलॉग में few छूट जाए तो वह एरर के रूप में नहीं, ग़लत अंत के रूप में दिखता है।

यदि पहले मैं रनटाइम विजेट का उपयोग करता था, तो क्या बदलेगा?

रनटाइम विजेट पेज लोड होने के बाद रेंडर किए गए टेक्स्ट का अनुवाद करते हैं, इसलिए वे आपके कोड में प्लुरल का नियम नहीं देख सकते। अनुवादों को रिपॉज़िटरी में ले जाना इसी कारण से भी मायने रखता है। Lovalingo 2026-08-31 को बंद हो गया; जब कैटलॉग आपकी रिपॉज़िटरी में रहते हैं तो क्या बदलता है, यह माइग्रेशन गाइड और तुलना पेज में बताया गया है।

globalize.now के साथ आप रिपॉज़िटरी एक बार कनेक्ट करते हैं और कोडबेस ऐप में ही कन्वर्ट हो जाता है। उसके बाद पुश जॉब्स नई कैटलॉग यूनिट्स का अनुवाद करते हैं और नतीजा पुल रिक्वेस्ट के रूप में आता है। Lovable GitHub से सिंक होता है, इसलिए प्लुरल रूप आपके ऐप तक उसी तरह पहुँचते हैं जैसे कोई भी अन्य बदलाव। सेटअप Lovable इंटीग्रेशन पेज पर है, और बिना डैशबोर्ड वाला वर्कफ़्लो डैशबोर्ड के बिना Lovable ऐप का स्थानीयकरण में है।

globalize.now आपके ऐप्लिकेशन की हार्डकोडेड कॉपी को अनुवाद-तैयार locale फ़ाइलों में बदल देता है और जैसे-जैसे आप नई रिलीज़ करते हैं, उन्हें अपडेट रखता है।

globalize.now को निःशुल्क आजमाएं