अगर आपका Next.js ऐप अनुवादित है, पर ब्राउज़र टैब, 404 पेज, फ़ॉर्म एरर और लिंक प्रीव्यू अब भी अंग्रेज़ी में हैं, तो कारण लगभग हमेशा एक ही होता है: ये स्ट्रिंग्स किसी कंपोनेंट के बाहर बनती हैं, इसलिए useTranslations कॉल ने उन्हें कभी छुआ ही नहीं। globalize.now AI-संचालित स्थानीयकरण इन्फ्रास्ट्रक्चर है, और जब कोई AI एजेंट किसी App Router प्रोजेक्ट में i18n जोड़ता है तो यही वह परत है जो हमें अक्सर अधूरी छूटी मिलती है: दिखने वाला पेज बदल जाता है, बाकी सतह नहीं।

नीचे बताया गया है कि इनमें से हर स्ट्रिंग कहाँ रहती है और उसे संभालने वाला next-intl कॉल कौन-सा है। हर उदाहरण next-intl के मौजूदा दस्तावेज़ों के अनुसार है, जिन्हें 2026-10-28 को देखा गया।

App Router ऐप में अनुवाद-रहित स्ट्रिंग्स कहाँ छिपी रहती हैं?

वे छह ऐसी जगहों पर छिपी रहती हैं जो टेक्स्ट रेंडर करने वाले React कंपोनेंट नहीं हैं। जो कोडिंग एजेंट आपके कंपोनेंट्स से गुज़रकर i18n जोड़ता है, वह दिखने वाले UI को तो बदल देता है और इन जगहों को छोड़कर आगे बढ़ जाता है:

  1. generateMetadata में पेज टाइटल और विवरण।
  2. Server Actions में वैलिडेशन एरर और नतीजे के संदेश।
  3. not-found.tsx, यानी 404 पेज।
  4. error.tsx, यानी रनटाइम एरर पेज।
  5. opengraph-image.tsx, manifest.ts और sitemap.ts जैसी जनरेट की गई फ़ाइलें।
  6. टेक्स्ट लौटाने वाले Route Handlers।

इन सबमें समानता यह है कि इनमें से कोई भी आपके [locale] लेआउट ट्री के भीतर सामान्य तरीके से रेंडर नहीं होता, इसलिए locale इन्हें अलग से देना पड़ता है या अलग तरीके से पढ़ना पड़ता है। Next.js 16 रूटिंग वाली पोस्ट में रूटिंग की वायरिंग समझाई गई है; यह लेख उन जगहों के बारे में है जहाँ वह वायरिंग नहीं पहुँचती।

पेज टाइटल और विवरण का अनुवाद कैसे करें?

generateMetadata के भीतर next-intl/server से getTranslations को कॉल करें। यह फ़ंक्शन किसी पेज या लेआउट से export किया जा सकता है और async है, इसलिए awaitable API ही सही विकल्प है:

// app/[locale]/page.tsx
import {getTranslations} from 'next-intl/server';

export async function generateMetadata() {
  const t = await getTranslations('Metadata');
  return {title: t('title'), description: t('description')};
}

असली समस्या स्टैटिक रूप में है। एजेंट अक्सर छोटा होने के कारण export const metadata = {title: 'Dashboard'} लिख देते हैं, पर एक कॉन्स्टेंट अनुवाद फ़ंक्शन को कॉल नहीं कर सकता। इसे फ़ंक्शन रूप में बदलें और हर locale के कैटलॉग में वही keys जोड़ें। यही टेक्स्ट सर्च में भी दिखता है, इसीलिए मेटाडेटा का अनुवाद किए बिना ऐप का अनुवाद करने से रैंकिंग पर बहुत कम असर पड़ता है।

Server Action और वैलिडेशन संदेशों का अनुवाद कैसे करें?

action को locale पास करें और getTranslations को नेमस्पेस और उस locale, दोनों के साथ कॉल करें। Server Action को पता नहीं होता कि पेज किस भाषा में है, इसलिए next-intl के दस्तावेज़ उसे स्वयं देने को कहते हैं, जैसे आर्ग्युमेंट के रूप में:

'use server';
import {getTranslations} from 'next-intl/server';

export async function subscribe(locale: string, formData: FormData) {
  const t = await getTranslations({locale, namespace: 'Subscribe'});
  // ...validate, then return t('success') or t('invalidEmail')
}

उसी दस्तावेज़ से एक सावधानी: सोचिए कि अगर action का संदेश स्क्रीन पर रहते हुए विज़िटर भाषा बदल ले तो क्या होगा। URL में [locale] सेगमेंट हो तो यह अपने-आप संभल जाता है, क्योंकि रूट बदल जाता है। न हो, तो आपको संदेश खुद हटाना पड़ सकता है, जैसे कंपोनेंट को key={locale} देकर ताकि उसकी state रीसेट हो जाए।

Zod के साथ फ़ॉर्म वैलिडेशन के लिए दस्तावेज़ों में बताया गया तरीका error map है। Zod हर safeParse कॉल पर एक map स्वीकार करता है, और वह map getTranslations को कॉल कर सकता है। इसे एक async हेल्पर में रखें और हर parse में उसका नतीजा error ऑप्शन के रूप में पास करें। तब आपके स्कीमा में नियम रहेंगे, अंग्रेज़ी वाक्य नहीं, और AI से बने फ़ॉर्म लातवियाई पेज में "Invalid email" भेजना बंद कर देंगे।

404 और एरर पेजों का अनुवाद कैसे करें?

not-found.tsx को app/[locale]/ के भीतर रखें, फिर एक catch-all जोड़ें ताकि वह सचमुच चले। Next.js यह फ़ाइल तब रेंडर करता है जब कोई सेगमेंट notFound() को कॉल करे, और कोई अज्ञात URL यह कॉल अपने आप नहीं करता:

// app/[locale]/[...rest]/page.tsx
import {notFound} from 'next/navigation';

export default function CatchAllPage() {
  notFound();
}

जिन रिक्वेस्ट से next-intl middleware मैच नहीं करता, उनमें locale होता ही नहीं, इसलिए [locale] वाला 404 उन पर कभी लागू नहीं होता। दस्तावेज़ों का जवाब app/global-not-found.tsx है, जिसे Next.js ने experimental बताया है और जो अपने ही html और body रेंडर करता है। किसी अज्ञात [locale] मान के लिए दस्तावेज़ notFound() को कॉल करने को कहते हैं, आमतौर पर i18n/request.ts में।

error.tsx अलग है। Next.js इसे Client Component होने की शर्त पर चलाता है, और यह आपके लेआउट के अंतर्गत रेंडर होता है, इसलिए इसे कम-से-कम Error नेमस्पेस वाला NextIntlClientProvider चाहिए। पूरा कैटलॉग देने के बजाय केवल वही संदेश पास करें:

// app/[locale]/layout.tsx (excerpt)
const messages = await getMessages();
// ...
<NextIntlClientProvider locale={locale} messages={pick(messages, 'Error')}>

इसके बाद error.tsx के भीतर useTranslations('Error') काम करने लगता है। यह पेज global-error को कवर नहीं करता, इसलिए अगर आपके पास वह फ़ाइल है तो उसे हाथ से जाँच लें।

शेयर इमेज, manifest और sitemap का क्या?

इन सबमें locale अलग से देना पड़ता है, क्योंकि ये लेआउट ट्री के बाहर रहते हैं। opengraph-image.tsx के लिए params से locale पढ़ें और getTranslations({locale, namespace}) को कॉल करें। कस्टमाइज़ किए गए localePrefix के साथ दस्तावेज़ चेतावनी देते हैं कि जनरेट किया गया रूट पहुँच से बाहर हो सकता है, क्योंकि Next.js को proxy (middleware) rewrites दिखाई नहीं देते; समाधान यह है कि matcher opengraph-image पर समाप्त होने वाले पाथ को छोड़ दे।

app/manifest.ts [locale] के बाहर रहता है, इसलिए next-intl पाथ से locale का अनुमान नहीं लगा सकता। कोई प्रतिनिधि locale चुनें, आमतौर पर डिफ़ॉल्ट, और उसे स्पष्ट रूप से पास करें। sitemap.ts के लिए alternates.languages एंट्री जोड़ें और हर URL को अपने navigation मॉड्यूल के async getPathname({locale, href}) से बनाएँ, आगे होस्ट जोड़कर। next-intl डिफ़ॉल्ट रूप से एक link रिस्पॉन्स हेडर भी भेजता है जो भाषा संस्करणों की जानकारी देता है; CMS से चलने वाले slugs पर नियंत्रण चाहिए तो sitemap बेहतर विकल्प है।

Route Handlers को कैसे संभालें?

locale को search param, किसी सेगमेंट या accept-language हेडर से लें, hasLocale(routing.locales, locale) से उसकी वैधता जाँचें, और जाँच विफल हो तो 400 लौटाएँ। फिर getTranslations({locale, namespace}) को कॉल करें। वैलिडेशन छोड़ने पर कोई भी मनमानी स्ट्रिंग आपके कैटलॉग लुकअप तक पहुँच जाती है।

आपके एजेंट के पीछे छूटी अंग्रेज़ी कैसे ढूँढें?

इन्हें प्रोजेक्ट रूट से चलाएँ। ये जान-बूझकर मोटे तौर के हैं; मकसद पढ़ने के लिए एक सूची पाना है, कोई स्कोर नहीं।

# 1. Static metadata that cannot be translated
grep -rn "export const metadata" app

# 2. Titles and descriptions already in generateMetadata
grep -rn "title:" app --include=page.tsx --include=layout.tsx

# 3. Server Actions with literal return messages
grep -rln "use server" app src 2>/dev/null | xargs grep -n "message:\|error:"

# 4. Zod schemas with inline messages
grep -rn "message:\s*['\"]" app src 2>/dev/null

# 5. 404 and error files, and whether a catch-all exists
ls app/\[locale\]/not-found.tsx app/\[locale\]/error.tsx "app/[locale]/[...rest]/page.tsx" 2>&1

पहले चार नतीजों में जो भी सादा अंग्रेज़ी लिटरल हो, वह कैटलॉग में जाना चाहिए। एजेंट हार्डकोडेड स्ट्रिंग्स क्यों जोड़ते रहते हैं में बताया गया है कि यह बार-बार क्यों होता है: एजेंट सामने दिखने वाले पैटर्न का अनुसरण करता है और वह पैटर्न कंपोनेंट ही होता है। अगर आप Copilot इस्तेमाल करते हैं, तो Copilot के लिए instruction-file की सीमाएँ यहाँ भी लागू होती हैं।

इससे आपके कैटलॉग में क्या बदलता है?

इससे नई keys जुड़ती हैं, और drift की शुरुआत keys से ही होती है। ऊपर की हर बात कैटलॉग में नई एंट्री लाती है, जैसे Metadata, Error, Subscribe और वैलिडेशन संदेश, और हर एक का अनुवाद आपके हर शिप किए गए locale में चाहिए। जो प्रोजेक्ट अपने कंपोनेंट्स का अनुवाद एक बार करके बाद में कोई Server Action या नया पेज टाइटल जोड़ता है, वह वही प्रोजेक्ट है जिसका ज़िक्र अनुवाद फ़ाइलें सिंक से बाहर क्यों हो जाती हैं में है।

next-intl रनटाइम पर अनुवाद परोसता है और हम उसकी जगह नहीं लेते। globalize.now उससे एक परत ऊपर काम करता है: आप ऐप में रिपॉज़िटरी कनेक्ट करते हैं, कोडबेस एक बार कैटलॉग में बदल दिया जाता है, और फिर push jobs नए कैटलॉग यूनिट्स के आते ही उनका अनुवाद करती हैं, जो आपको समीक्षा योग्य बदलावों के रूप में मिलते हैं। Next.js इंटीग्रेशन में सेटअप का विवरण है, और मौजूदा i18n सेटअप में हम क्या छूते हैं और क्या नहीं उस स्थिति को कवर करता है जहाँ next-intl पहले से हाथ से जुड़ा हो।

कहाँ से शुरुआत करें

पाँचों grep चलाएँ, कोई भी स्टैटिक metadata export बदलें, catch-all रूट जोड़ें, और error.tsx को उसका provider दें। फिर कैटलॉग में हर locale के नए नेमस्पेस जाँच लें। अगर आपने AI से बना ऐप शिप किया है और चाहते हैं कि कन्वर्ज़न और अनुवाद आपके बजाय कोई और संभाले, तो vibe coders पेज में पूरा परिचय है, डेवलपर रेफ़रेंस में एजेंट सेटअप हैं, और प्राइसिंग का अलग पेज है।

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

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