Use Cases (अपडेट: 2/6/2026)

Claude Code से i18n लागू करें: Next.js के लिए व्यावहारिक गाइड

Claude Code, Next.js और next-intl से i18n लागू करने का व्यावहारिक तरीका, translation checks और आम गलतियों सहित।

Claude Code से i18n लागू करें: Next.js के लिए व्यावहारिक गाइड

i18n को पहले architecture की तरह सोचें

i18n का अर्थ internationalization है, यानी app को कई भाषाओं और क्षेत्रों के लिए तैयार करना। यह सिर्फ JSON में translated text भरना नहीं है। Production में URL structure, language detection, SEO metadata, date और currency format, plural rules, internal links और missing translation checks सब साथ आते हैं। Claude Code इस काम में उपयोगी है क्योंकि यह project पढ़ सकता है, कई files बदल सकता है, command चला सकता है और risk summary दे सकता है। लेकिन अगर prompt सिर्फ “translate this app” है, तो result अक्सर अधूरा रहता है।

Masa के अनुभव में सबसे बेहतर तरीका है Claude Code से पूरा workflow बनवाना: routing foundation, message files, page migration, verification script और review checklist। Foundation से मतलब वह आधार है जिस पर multi-language app खड़ा रहता है। आधार साफ हो तो बाद में English, German या Indonesian जोड़ना सिर्फ content work बनता है, architecture rewrite नहीं।

इस guide में Next.js App Router और next-intl का उदाहरण है। Review करते समय official references देखें: Claude Code docs, next-intl routing setup, Next.js internationalization guide, और MDN का Intl reference। नई Next.js versions में proxy.ts दिखता है, जबकि पुराने projects में middleware.ts हो सकता है।

flowchart LR
  A[Requirements] --> B[Routing]
  B --> C[Message JSON]
  C --> D[Pages and metadata]
  D --> E[Checks]
  E --> F[SEO and release]

Next.js और next-intl की basic setup

यह उदाहरण ja को default locale मानता है और en, de जोड़ता है। Claude Code को पहले package version पढ़ने दें, फिर तय करें कि proxy.ts बनाना है या पुराने project में middleware.ts

src/
  app/
    [locale]/
      layout.tsx
      page.tsx
  i18n/
    navigation.ts
    request.ts
    routing.ts
  messages/
    ja.json
    en.json
    de.json
  proxy.ts

routing.ts supported locales और localized paths को एक जगह रखता है। इससे URL policy review करना आसान होता है।

// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';

export const routing = defineRouting({
  locales: ['ja', 'en', 'de'],
  defaultLocale: 'ja',
  pathnames: {
    '/': '/',
    '/pricing': {
      ja: '/pricing',
      en: '/pricing',
      de: '/preise',
    },
    '/docs': {
      ja: '/docs',
      en: '/docs',
      de: '/dokumentation',
    },
  },
});

export type Locale = (typeof routing.locales)[number];
// src/i18n/navigation.ts
import { createNavigation } from 'next-intl/navigation';
import { routing } from './routing';

export const { Link, redirect, usePathname, useRouter, getPathname } =
  createNavigation(routing);

request.ts हर request में locale पढ़ता है। Unsupported locale आए तो default locale पर लौटना सुरक्षित है।

// src/i18n/request.ts
import { hasLocale } from 'next-intl';
import { getRequestConfig } from 'next-intl/server';
import { routing } from './routing';

export default getRequestConfig(async ({ requestLocale }) => {
  const requested = await requestLocale;
  const locale = hasLocale(routing.locales, requested)
    ? requested
    : routing.defaultLocale;

  return {
    locale,
    messages: (await import(`../messages/${locale}.json`)).default,
  };
});
// src/proxy.ts
import createMiddleware from 'next-intl/middleware';
import { routing } from './i18n/routing';

export default createMiddleware(routing);

export const config = {
  matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
};

Translation keys को real pages में इस्तेमाल करें

सभी text को common में मत डालें। common में navigation, language selector और सच में shared buttons रखें। Page-specific text को HomePage, PricingPage, DocsPage जैसे namespace में रखें। Namespace का मतलब related translation keys का group है।

{
  "common": {
    "language": {
      "label": "Display language",
      "ja": "日本語",
      "en": "English",
      "de": "Deutsch"
    },
    "nav": {
      "docs": "Docs",
      "pricing": "Pricing"
    }
  },
  "HomePage": {
    "title": "Deliver team knowledge in multiple languages",
    "lead": "Show {count} articles in the reader's language.",
    "cta": "Book a consultation"
  }
}

Server Component में getTranslations साफ रहता है और बाद में translated metadata के लिए भी काम आता है।

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

type Props = {
  params: Promise<{ locale: string }>;
};

export default async function HomePage({ params }: Props) {
  const { locale } = await params;
  setRequestLocale(locale);
  const t = await getTranslations({ locale, namespace: 'HomePage' });

  return (
    <main>
      <h1>{t('title')}</h1>
      <p>{t('lead', { count: 42 })}</p>
      <a href={`/${locale}/pricing`}>{t('cta')}</a>
    </main>
  );
}

Language switcher बनाते समय current path रखें और सिर्फ locale बदलें। Manual string replace से /enquiry जैसी route टूट सकती है।

CI में missing translations रोकें

Claude Code जब message files बनाता है, reviewer wording देख लेता है लेकिन key drift छूट जाता है। Key drift का मतलब एक language में HomePage.cta है और दूसरी में नहीं। नीचे script base language और बाकी files compare करता है।

// scripts/check-translations.mjs
import { readdir, readFile } from 'node:fs/promises';

const messagesDir = new URL('../src/messages/', import.meta.url);
const baseLocale = 'ja';

function flattenKeys(value, prefix = '') {
  if (value === null || typeof value !== 'object' || Array.isArray(value)) {
    return [prefix];
  }

  return Object.entries(value).flatMap(([key, child]) => {
    const nextPrefix = prefix ? `${prefix}.${key}` : key;
    return flattenKeys(child, nextPrefix);
  });
}

async function readMessages(locale) {
  const file = new URL(`${locale}.json`, messagesDir);
  return JSON.parse(await readFile(file, 'utf8'));
}

const files = await readdir(messagesDir);
const locales = files.filter((file) => file.endsWith('.json')).map((file) => file.replace(/\.json$/, ''));
const baseKeys = new Set(flattenKeys(await readMessages(baseLocale)));
let hasError = false;

for (const locale of locales.filter((item) => item !== baseLocale)) {
  const targetKeys = new Set(flattenKeys(await readMessages(locale)));
  const missing = [...baseKeys].filter((key) => !targetKeys.has(key));
  const extra = [...targetKeys].filter((key) => !baseKeys.has(key));

  if (missing.length || extra.length) {
    hasError = true;
    console.error(`\n${locale}.json has translation key drift`);
    if (missing.length) console.error('Missing:', missing.join(', '));
    if (extra.length) console.error('Extra:', extra.join(', '));
  }
}

if (hasError) process.exit(1);
console.log(`Translation keys are aligned for ${locales.length} locales.`);

यह script translation quality नहीं बताता। यह केवल structure complete है या नहीं बताता है। फिर भी यह production में missing button या missing metadata जैसी गलती रोक देता है।

तीन practical use cases

पहला use case SaaS pricing page है। Currency, tax, billing period और plan names अलग-अलग market में बदलते हैं। Claude Code से कहें कि Intl.NumberFormat या next-intl formatter इस्तेमाल करे, string concatenation नहीं।

दूसरा use case documentation site है। middleware, proxy, locale, namespace जैसे terms को हर बार translate करना ठीक नहीं। पहली बार आसान भाषा में समझाएँ, फिर original term रखें ताकि developer official docs खोज सके।

तीसरा use case admin dashboard है। यहाँ SEO से ज़्यादा operation safety महत्वपूर्ण है। “delete”, “disable”, “revoke invitation” जैसे actions गलत translate हुए तो user गलती कर सकता है। Button, confirmation modal, toast और audit log को एक ही key system में रखें।

Blog या media site में body translation काफी नहीं है। Title, description, canonical, alternate links, OGP image और internal links भी साथ update होने चाहिए। इस rule को CLAUDE.md best practices में लिखना अच्छा है।

Pitfalls और verified result

PitfallProblemFix
URL design बाद मेंRedirect और indexed pages उलझते हैंPrefix, subdomain या domain पहले तय करें
Key name vaguetitle2 review नहीं होताScreen और meaning से name दें
Fallback पर भरोसाMissing translation छिप जाती हैCI में missing key fail करें
Date और currency जोड़नाWord order गलत होता हैIntl या formatter इस्तेमाल करें
Metadata भूलनाSearch result default language में रहता हैgenerateMetadata translate करें

मैंने छोटे message set में English file से HomePage.cta हटाकर script आजमाया। Script ने missing key सही पकड़ी। लेकिन यह decide नहीं कर सकता कि “Book a consultation” हर market के लिए सही CTA है या नहीं। Practical split यही है: Claude Code और CI mechanical gaps पकड़ें, human reviewer CTA, pricing, legal copy और cultural nuance देखें। अगला कदम है इस workflow को Claude Code review checklist और ClaudeCodeLab consultation से जोड़ना।

#Claude Code #i18n #internationalization #Next.js #next-intl
मुफ़्त

मुफ़्त PDF: Claude Code cheatsheet

Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.

हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.

Masa

लेखक के बारे में

Masa

Claude Code workflow और team adoption पर काम करने वाला engineer.