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 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
| Fehler | Auswirkung | Gegenmaßnahme |
|---|---|---|
| URL-Design zu spät | Redirects und indexierte Seiten werden unübersichtlich | Prefix, Subdomain oder Domain zuerst wählen |
| Vage Key-Namen | title2 und text3 sind kaum reviewbar | Nach Seite und Bedeutung benennen |
| Zu viel Fallback | Fehlende Übersetzungen bleiben verborgen | CI bei fehlenden Keys fehlschlagen lassen |
| Datum und Währung verketten | Reihenfolge und Trenner sind falsch | Intl oder Formatter verwenden |
| Metadata vergessen | Suchergebnisse bleiben in der Standardsprache | Auch 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.
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.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Workflow von Obsidian zu CLAUDE.md
Obsidian-Arbeitsnotizen in CLAUDE.md-Betriebsnotizen verwandeln und Kontext nicht ständig neu erklären.
Claude Code Revenue CTA Routing: Artikel zu PDF, Gumroad und Beratung führen
Ein Claude-Code-Ablauf, der Leser nach Absicht zu Gratis-PDF, Gumroad oder Beratung führt.
Claude-Code-Team-Handoff-Regeln: Belege, Berechtigungen, Rollback und Umsatzpfade
Ein praktisches Claude-Code-Handoff für Review-Belege, Berechtigungen, Rollback, Gratis-PDF, Gumroad und Beratung.