Use Cases (Aktualisiert: 2.6.2026)

i18n mit Claude Code implementieren: Next.js Praxisleitfaden

Praxisnaher Workflow für Next.js i18n mit Claude Code, next-intl, Übersetzungschecks, Use Cases und typischen Fehlern.

i18n mit Claude Code implementieren: Next.js Praxisleitfaden

i18n ist zuerst eine Architekturentscheidung

i18n steht für Internationalisierung: Eine Anwendung wird so vorbereitet, dass sie mehrere Sprachen, Regionen und Formate sauber unterstützt. In einem produktiven Projekt bedeutet das mehr als übersetzte JSON-Dateien. Du musst URL-Struktur, Locale-Erkennung, SEO-Metadaten, Datums- und Währungsformatierung, Pluralregeln, interne Links und Prüfungen für fehlende Übersetzungen berücksichtigen. Claude Code ist dafür stark, weil es den Codebestand lesen, mehrere Dateien ändern, Befehle ausführen und Restrisiken zusammenfassen kann. Ohne klare Vorgabe produziert es aber leicht nur Textdateien statt einer belastbaren i18n-Struktur.

Masa hat bei Content-Sites und SaaS-Seiten vor allem einen Fehler gesehen: Man bittet zu früh um “alles übersetzen”. Die erste Version sieht vollständig aus, aber später fehlen CTA-Texte, Preise, description oder kanonische Links in einzelnen Sprachen. Besser ist ein Auftrag an Claude Code, der die komplette Arbeitskette enthält: Routing-Fundament, Message-Dateien, Migration der Seiten, Prüfscripts und Review-Regeln.

Dieser Leitfaden nutzt Next.js App Router mit next-intl. Prüfe die Ausgabe gegen die offiziellen Quellen: Claude Code Dokumentation, next-intl Routing Setup, Next.js Internationalization Guide und die Intl Referenz von MDN. Das ist besonders wichtig, weil aktuelle Next.js-Versionen proxy.ts verwenden, während ältere Projekte noch middleware.ts nutzen.

flowchart LR
  A[Anforderungen] --> B[Routing]
  B --> C[Message JSON]
  C --> D[Seiten und Metadata]
  D --> E[Checks]
  E --> F[SEO und Release]

Minimale Struktur mit Next.js und next-intl

Das Beispiel verwendet ja als Standardsprache und ergänzt en und de. Die Struktur trennt Routing, Navigation und Messages, damit Reviews klein bleiben.

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

In routing.ts werden Sprachen und lokalisierte Pfade zentral definiert. Dadurch muss Claude Code nicht in Komponenten nach verstreuten Strings suchen.

// 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];

Navigation sollte über die Wrapper von next-intl laufen. So verwenden Links, Redirects und Locale-Wechsel dieselbe Konfiguration.

// 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 lädt die Messages für die erkannte Sprache. Nicht unterstützte Locales fallen auf die Standardsprache zurück.

// 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,
  };
});

Für Next.js 16 ist proxy.ts der passende Dateiname. Bei älteren Projekten sollte Claude Code prüfen, ob middleware.ts erwartet wird.

// 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|.*\\..*).*)',
};

Übersetzungsschlüssel in echte Seiten bringen

Lege nicht alle Texte in common ab. Diese Datei sollte nur wirklich gemeinsame Elemente enthalten: Navigation, Sprachauswahl, Standardbuttons. Seitenspezifische Texte gehören in Namespaces wie HomePage, PricingPage oder DocsPage. Ein Namespace ist einfach eine Gruppe zusammengehöriger Übersetzungsschlüssel.

{
  "common": {
    "language": {
      "label": "Anzeigesprache",
      "ja": "日本語",
      "en": "English",
      "de": "Deutsch"
    },
    "nav": {
      "docs": "Dokumentation",
      "pricing": "Preise"
    }
  },
  "HomePage": {
    "title": "Teamwissen in mehreren Sprachen bereitstellen",
    "lead": "{count} Artikel in der Sprache des Lesers anzeigen.",
    "cta": "Beratung buchen"
  }
}

In einer App-Router-Seite ist getTranslations praktisch, weil es in Server Components und später auch für generateMetadata funktioniert.

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

Ein Sprachumschalter sollte den aktuellen Pfad beibehalten und nur die Locale ändern. Manuelle String-Ersetzung kann Pfade wie /enquiry beschädigen.

Fehlende Übersetzungen in CI stoppen

Wenn Claude Code Message-Dateien generiert, erkennt ein Mensch oft schlechte Formulierungen, übersieht aber fehlende Keys. Das folgende Script vergleicht die Basissprache mit allen anderen Sprachen.

// 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.`);

Das Script bewertet nicht, ob die Übersetzung elegant klingt. Es stellt nur sicher, dass die Key-Struktur vollständig ist. Genau diese mechanische Prüfung ist ideal für CI.

Drei reale Use Cases

Der erste Use Case ist eine SaaS-Preisseite. Dort hängen Währung, Steuerhinweise, Abrechnungsperiode und Plannamen zusammen. String-Konkatenation ist riskant; Claude Code sollte Intl.NumberFormat oder Formatter von next-intl verwenden. Danach muss ein Mensch prüfen, ob Satzstellung und Kaufkontext natürlich wirken.

Der zweite Use Case ist eine technische Dokumentation. Begriffe wie middleware, proxy, locale und namespace sollten nicht zwanghaft übersetzt werden. Erkläre sie beim ersten Auftreten kurz auf Deutsch und behalte danach den Originalbegriff bei, damit Leser offizielle Dokumentation wiederfinden.

Der dritte Use Case ist ein Admin-Panel. Hier geht es weniger um SEO als um Fehlbedienung. Labels wie “löschen”, “deaktivieren” und “Einladung widerrufen” müssen präzise sein. Buttons, Bestätigungsdialoge, Toasts und Audit-Logs gehören in dasselbe Key-System.

Für Blogs und Medienseiten reicht der Artikeltext nicht aus. Title, description, canonical, alternate links, OGP-Bild und interne Links müssen zusammen geprüft werden. Diese Regel gehört in CLAUDE.md Best Practices, damit Claude Code bei jeder Aktualisierung konsistent arbeitet.

Typische Fehler und verifiziertes Ergebnis

FehlerAuswirkungGegenmaßnahme
URL-Design zu spätRedirects und indexierte Seiten werden unübersichtlichPrefix, Subdomain oder Domain zuerst wählen
Vage Key-Namentitle2 und text3 sind kaum reviewbarNach Seite und Bedeutung benennen
Zu viel FallbackFehlende Übersetzungen bleiben verborgenCI bei fehlenden Keys fehlschlagen lassen
Datum und Währung verkettenReihenfolge und Trenner sind falschIntl oder Formatter verwenden
Metadata vergessenSuchergebnisse bleiben in der StandardspracheAuch generateMetadata übersetzen

Ich habe das Prüfscript mit einem kleinen Message-Set getestet und HomePage.cta aus der englischen Datei entfernt. Das Script schlug fehl und meldete den fehlenden Key. Es kann aber nicht entscheiden, ob “Beratung buchen” in jedem Markt der richtige CTA ist. Die sinnvolle Arbeitsteilung lautet daher: Claude Code und CI finden mechanische Lücken, Menschen prüfen Ton, Preise, Rechtstexte und kulturelle Passung. Für den nächsten Schritt kombiniere diesen Ablauf mit der Claude Code Review Workflow Checklist oder der ClaudeCodeLab Beratung.

#Claude Code #i18n #Internationalisierung #Next.js #next-intl
Kostenlos

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.