हर language को अपना URL दें, फिर उन URLs को reciprocal hreflang tags से annotate करें। React state में strings बदलने वाला dropdown आपकी site पर पहले से मौजूद व्यक्ति के लिए interface का अनुवाद कर देता है, लेकिन search engine के लिए index करने योग्य कुछ नया नहीं बनाता। इसलिए आपके German और Spanish versions अदृश्य बने रहते हैं। globalize.now hardcoded strings को committed Lingui PO catalogs में निकालता है और हर Git push पर उन्हें sync रखता है। इसी वजह से per-locale routes को एक बार के झंझट के बजाय लगातार maintain करना व्यावहारिक बनता है।

यही वह चरण है जिसे Lovable के ज़्यादातर builders छोड़ देते हैं। ऐप का अनुवाद हो जाता है, switcher ब्राउज़र में काम करता है, लेकिन traffic कभी आता ही नहीं।


Google मेरे Lovable ऐप की दूसरी languages को index क्यों नहीं करता?

क्योंकि लगभग निश्चित रूप से उन languages के अपने addresses नहीं हैं।

AI builder का default pattern एक useState locale value और उसे set करने वाला dropdown होता है। हर language एक ही URL पर render होती है। उस URL का अनुरोध करने वाले crawler को एक ही response, एक ही language में मिलता है और वह एक ही page index करता है। उसके पास दूसरी languages खोजने के लिए कुछ नहीं होता, न ही कोई signal होता है कि उनके versions मौजूद हैं।

समाधान cosmetic नहीं, structural है। Localized versions पर Google की अपनी guidance स्पष्ट कहती है कि alternate language pages की पहचान URL से होती है और उन्हें जोड़ने वाले annotations set के हर page से लौटने चाहिए। अगर /de/pricing fetch किए जा सकने वाले address के रूप में मौजूद ही नहीं है, तो कोई भी markup उसे search में नहीं ला सकता।


एक वास्तविक language switcher को क्या करना चाहिए?

क्रम से तीन काम: URL बदलना, user को उसी page पर रखना और उसकी पसंद याद रखना।

Search के लिए URL बदलना सबसे महत्वपूर्ण हिस्सा है। User के लिए उसी page पर बने रहना महत्वपूर्ण है, और यहीं ज़्यादातर implementations विफल होती हैं: /en/pricing से switch करने पर /de/pricing पर पहुँचना चाहिए, /de/ पर नहीं। पसंद याद रखना सुविधा भर है और इसे URL में दिए गए explicit locale को कभी override नहीं करना चाहिए।

एक anti-pattern का नाम लेना ज़रूरी है: browser language के आधार पर automatic redirects। अगर United States में crawler /de/pricing का अनुरोध करे और उसे /en/pricing पर भेज दिया जाए, तो German page प्रभावी रूप से मौजूद ही नहीं है। Switch का विकल्प दें, उसे ज़बरदस्ती लागू न करें।


Lovable TanStack Start ऐप में locale routing कैसे जोड़ूँ?

Route tree के सबसे ऊपर locale segment जोड़ें और उसी से catalog activate करें।

Lovable ने मई 2026 में नए projects को TanStack Start पर server-side rendering में स्थानांतरित किया। इसलिए locale-prefixed route पहले response में पूरी तरह translated HTML लौटाता है—ठीक वही जो आप crawler को देना चाहते हैं।

एक dynamic segment बनाएँ, जो आपके बाकी routes को wrap करे:

src/routes/
  $locale/
    route.tsx
    index.tsx
    pricing.tsx

फिर children के render होने से पहले उस locale के लिए Lingui catalog activate करें:

// src/routes/$locale/route.tsx
import { createFileRoute, Outlet, notFound } from "@tanstack/react-router";
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";

const LOCALES = ["en", "de", "es", "fr"] as const;

export const Route = createFileRoute("/$locale")({
  loader: async ({ params }) => {
    if (!LOCALES.includes(params.locale as (typeof LOCALES)[number])) {
      throw notFound();
    }
    const { messages } = await import(
      `../../locales/${params.locale}/messages.po`
    );
    i18n.loadAndActivate({ locale: params.locale, messages });
    return { locale: params.locale };
  },
  component: LocaleLayout,
});

function LocaleLayout() {
  return (
    <I18nProvider i18n={i18n}>
      <Outlet />
    </I18nProvider>
  );
}

यहाँ दो बातें वास्तविक काम करती हैं। Unknown locales को notFound() से reject करने पर crawler द्वारा आज़माए गए हर बेकार path के लिए /xx/pricing soft 200 लौटाना बंद हो जाता है। Route loader में catalog load करने से activation server पर, HTML serialize होने से पहले हो जाता है।

अगर आप पुराने stack पर हैं, तो URL shape वही रहेगी, लेकिन render path अलग होगा। Lovable Vite i18n walkthrough उस मामले को कवर करती है, जबकि TanStack Start setup guide SSR वाले हिस्से को अधिक विस्तार से समझाती है।


Language switcher component कैसे बनाऊँ?

अलग locale parameter के साथ उसी route पर navigate करें और हर option को वास्तविक link के रूप में render करें।

// src/components/LanguageSwitcher.tsx
import { Link, useLocation, useParams } from "@tanstack/react-router";

const LOCALES = {
  en: "English",
  de: "Deutsch",
  es: "Español",
  fr: "Français",
} as const;

export function LanguageSwitcher() {
  const { locale } = useParams({ from: "/$locale" });
  const { pathname } = useLocation();
  const rest = pathname.replace(`/${locale}`, "") || "/";

  return (
    <nav aria-label="Language">
      <ul>
        {Object.entries(LOCALES).map(([code, label]) => (
          <li key={code}>
            <Link
              to={`/${code}${rest}`}
              hrefLang={code}
              aria-current={code === locale ? "true" : undefined}
            >
              {label}
            </Link>
          </li>
        ))}
      </ul>
    </nav>
  );
}

Options को router call से जुड़े buttons के बजाय anchors के रूप में render करें। Anchors crawlable होते हैं, इसलिए sitemap के अलावा search engines को आपके locale routes खोजने का दूसरा रास्ता मिलता है। हर option को उसी language में label करें, flag से नहीं: flags देशों को दर्शाते हैं, और Spanish कोई देश नहीं है।


Hreflang tags सही तरीके से कैसे emit करूँ?

Set के हर page पर हर locale के लिए एक annotation emit करें, जिसमें self-reference भी शामिल हो, साथ ही एक x-default।

Google जाँचता है कि alternate URLs वापस एक-दूसरे से link हों, और ऐसे annotations को नज़रअंदाज़ करता है जो reciprocal न हों या page के अपने canonical से बाहर point करते हों। इसलिए इन्हें programmatically generate करना ही समझदारी है—चार languages और बीस pages के set में हाथ से consistent रखने के लिए 320 annotations होंगे।

TanStack Start में इन्हें route के head में बनाएँ:

// src/routes/$locale/route.tsx (excerpt)
const SITE = "https://example.com";
const LOCALES = ["en", "de", "es", "fr"] as const;

export const Route = createFileRoute("/$locale")({
  head: ({ params, location }) => {
    const rest = location.pathname.replace(`/${params.locale}`, "") || "/";
    return {
      links: [
        { rel: "canonical", href: `${SITE}/${params.locale}${rest}` },
        ...LOCALES.map((code) => ({
          rel: "alternate",
          hrefLang: code,
          href: `${SITE}/${code}${rest}`,
        })),
        { rel: "alternate", hrefLang: "x-default", href: `${SITE}/en${rest}` },
      ],
    };
  },
});

क्योंकि annotations उसी LOCALES array से बनते हैं जिसका router इस्तेमाल करता है, language जोड़ने पर routes, switcher और hreflang set एक साथ update हो जाते हैं। यही वह property है जिसे सुरक्षित रखना चाहिए: एक list, तीन consumers।

उन्हीं URLs को xhtml:link alternates के साथ अपने sitemap में जोड़ें और सुनिश्चित करें कि आपका <html lang> attribute active locale से match करता हो। lang attribute hreflang को प्रभावित नहीं करता, लेकिन screen readers और browser translation prompts पर असर डालता है।


Runtime translation widget ऐसा क्यों नहीं कर सकता?

क्योंकि widget page के English में serve हो जाने के बाद अनुवाद करता है।

Runtime widget अपनी script load होने के बाद ब्राउज़र में text बदलता है। Crawler को मिलने वाला पहला response English DOM होता है और translated version केवल client-side JavaScript चलने के बाद मौजूद होता है। कुछ widgets generated hreflang के साथ subdomain या subdirectory modes देते हैं, लेकिन तब URL structure और annotations आपकी repository के नहीं, vendor के infrastructure के होते हैं।

इस dependency की एक वास्तविक कीमत है। Lovable builders के बीच लोकप्रिय translation widget Lovalingo 31 अगस्त 2026 को बंद हो रहा है और उसकी अपनी guidance users को project-owned internationalization पर जाने को कहती है। Widget हटने पर उसके बनाए language URLs भी चले जाते हैं और site फिर English पर लौट आती है। आपकी अपनी codebase में defined committed catalogs और routes पर ऐसा कोई switch नहीं होता। इस migration का व्यावहारिक विवरण हमने Lovalingo alternatives comparison में लिखा है।


Classic Vite SPA stack के बारे में क्या?

URL structure वही है, rendering नहीं।

TanStack Start पर switch से पहले बनाए गए Lovable projects Vite और React वाले single-page apps हैं, जो static files के रूप में serve होते हैं और ब्राउज़र में render होते हैं। आप अब भी /:locale पर route कर सकते हैं, hreflang emit कर सकते हैं और catalogs को repo में रख सकते हैं। लेकिन crawler के पहले byte में translated content होने की गारंटी नहीं रहती।

अगर SEO ही localization का मुख्य कारण है, तो locale routes के लिए prerendering जोड़ें ताकि हर route वास्तविक HTML के साथ ship हो, या server-rendered stack पर जाने की योजना बनाएँ। Client-rendered app के ऊपर runtime widget जोड़कर समस्या हल न करें; इससे दो client-side render passes जुड़ते हैं और हर language में first meaningful paint खराब होता है।


ऐप बदलते रहने पर चार locales को drift होने से कैसे रोकें?

Extraction को automate करें और catalogs को source code की तरह treat करें।

Per-locale routing छोड़ने की वजह routing नहीं होती। समस्या यह है कि हर नया feature ऐसी English strings जोड़ता है जिन्हें कोई extract नहीं करता। धीरे-धीरे /de/ English fragments से भर जाता है और बिना German के रहने से भी बदतर दिखने लगता है। globalize.now इस layer को संभालता है: अपने Lovable workspace में lovable-i18n skill जोड़ें और Lovable को i18n सेट अप करने के लिए prompt करें, या skills को locally इंस्टॉल करें:

npx skills add globalize-now/globalize-skills

हर agent के लिए इंस्टॉल करने हेतु --all जोड़ें। नई strings extract होंगी, keys generate होंगी, catalogs translate होंगे और updated PO files हर Git push पर वापस commit हो जाएँगी।

Pricing प्रति workspace €20/माह है, जिसमें हर महीने €20 का translation credit (लगभग 200,000 words) शामिल है; इसके बाद उसी per-character rate पर token-based usage लागू होता है। Per-seat या per-language शुल्क नहीं हैं, इसलिए पाँचवाँ locale जोड़ने से आपका routing config बदलेगा, bill नहीं। Signup पर €5 का translation credit मिलता है और कार्ड की आवश्यकता नहीं होती। Developers और AI-built apps ship करने वाले लोगों के लिए अधिक विवरण उपलब्ध है।

Routing और hreflang एक दोपहर में हो जाने वाला काम है। ऐप बदलते समय चार catalogs को पूरा बनाए रखना वह हिस्सा है जिसका कभी अंत नहीं होता—और यही हिस्सा globalize.now automate करता है।

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

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