IntlPull
Technical
18 min read

Next.js i18n Übersetzungen funktionieren nicht? Der komplette Troubleshooting-Guide (2026)

Behebe typische Next.js Internationalisierungsprobleme: Fehlende Übersetzungen, t() gibt Keys zurück, JSON-Dateifehler, Middleware-Probleme, Hydration-Mismatches und mehr. Debug-Guide für next-intl, react-i18next.

IntlPull Team
IntlPull Team
03 Feb 2026, 11:44 AM [PST]
On this page
Summary

Behebe typische Next.js Internationalisierungsprobleme: Fehlende Übersetzungen, t() gibt Keys zurück, JSON-Dateifehler, Middleware-Probleme, Hydration-Mismatches und mehr. Debug-Guide für next-intl, react-i18next.

Schnelle Antwort

Wenn deine Next.js Übersetzungen nicht funktionieren, prüfe der Reihe nach: (1) Übersetzungsschlüssel existiert in der JSON-Datei mit korrekter Verschachtelung, (2) JSON-Datei ist valide (keine Trailing Commas), (3) Locale wird korrekt in der Middleware erkannt, (4) Provider/Context umschließt deine Komponenten, (5) Richtiger Hook verwendet (Server vs. Client Component). 90% der Probleme sind Tippfehler in Keys oder fehlende JSON-Einträge.


Ich habe hunderte i18n-Setups in React- und Next.js-Projekten debuggt. Die gute Nachricht? Übersetzungsfehler fallen fast immer in eine von etwa 10 vorhersehbaren Kategorien. Die schlechte Nachricht? Sie können unglaublich frustrierend zu diagnostizieren sein, wenn man nicht weiß, wonach man suchen muss.

Dieser Guide behandelt jedes Übersetzungsproblem, das mir in Produktion begegnet ist, sortiert von häufig nach selten. Der Fokus liegt auf Next.js 14/15 mit App Router, aber das meiste gilt auch für den Pages Router.

Problem #1: Übersetzungsschlüssel wird statt Übersetzung angezeigt

Symptom: Du siehst common.buttons.submit auf dem Bildschirm statt "Absenden"

Das ist das häufigste Problem, und es bedeutet meistens eines der folgenden:

Der Key existiert nicht in deiner JSON

JSON
1// ❌ Dein Code verwendet: t('common.buttons.submit')
2// Aber deine en.json enthält:
3{
4  "common": {
5    "button": {  // Beachte: "button" nicht "buttons"
6      "submit": "Submit"
7    }
8  }
9}

Lösung: Prüfe deine JSON-Struktur sorgfältig. Nutze eine IDE mit JSON-Pfad-Vorschau oder ein Tool wie IntlPull, das Keys validiert.

Du verwendest den falschen Namespace

TSX
1// ❌ Falsch: sucht im Standard-Namespace
2const t = useTranslations();
3t('checkout.title');
4
5// ✅ Richtig: Namespace angeben
6const t = useTranslations('checkout');
7t('title');

Die JSON-Datei wird nicht geladen

Prüfe deine i18n-Konfiguration:

TypeScript
1// i18n/request.ts für next-intl
2import { getRequestConfig } from 'next-intl/server';
3
4export default getRequestConfig(async ({ locale }) => ({
5  messages: (await import(`../messages/${locale}.json`)).default
6}));

Stelle sicher, dass der Dateipfad korrekt ist. Ein häufiger Fehler ist, Messages in /public/locales abzulegen, während die Konfiguration /messages erwartet.


Problem #2: Ungültige JSON-Syntax

Symptom: App stürzt ab mit "Unexpected token" oder Übersetzungen scheitern still

JSON ist strikt. Folgendes macht alles kaputt:

JSON
1// ❌ Trailing Comma (am häufigsten)
2{
3  "welcome": "Hello",
4  "goodbye": "Bye",  // <-- Dieses Komma macht alles kaputt
5}
6
7// ❌ Einfache Anführungszeichen
8{
9  'welcome': 'Hello'  // Muss doppelte Anführungszeichen sein
10}
11
12// ❌ Nicht-escapte Anführungszeichen in Werten
13{
14  "message": "Klicke "hier" um fortzufahren"  // Muss escaped werden
15}
16
17// ✅ Korrekt
18{
19  "welcome": "Hello",
20  "goodbye": "Bye",
21  "message": "Klicke \"hier\" um fortzufahren"
22}

Lösung: Nutze einen JSON-Validator. VS Code hebt Syntaxfehler hervor. Führe cat en.json | python -m json.tool aus, um per CLI zu validieren.


Problem #3: Übersetzung fehlt für bestimmte Locale

Symptom: Englisch funktioniert, aber Spanisch/Deutsch/usw. zeigt Keys

Du hast den Key zu en.json hinzugefügt, aber die anderen Locales vergessen:

/messages
  en.json  ✅ Hat "checkout.newFeature": "Try our new feature"
  es.json  ❌ Dieser Key fehlt komplett
  de.json  ❌ Dieser Key fehlt komplett

Lösung: Nutze ein Übersetzungsmanagement-Tool wie IntlPull, das fehlende Übersetzungen über alle Locales hinweg trackt. Oder richte einen Fallback ein:

TypeScript
1// next-intl Konfiguration mit Fallback
2export default getRequestConfig(async ({ locale }) => ({
3  messages: {
4    ...(await import(`../messages/en.json`)).default, // Fallback
5    ...(await import(`../messages/${locale}.json`)).default
6  }
7}));

Problem #4: Middleware erkennt Locale nicht

Symptom: Zeigt immer Standardsprache an, URL-Locale wird ignoriert

TypeScript
1// ❌ Middleware läuft nicht auf deinen Routes
2export const config = {
3  matcher: ['/api/:path*']  // Matcht nur API-Routes!
4};
5
6// ✅ Korrekter Matcher für i18n
7export const config = {
8  matcher: ['/((?!api|_next|.*\\..*).*)']
9};

Stelle außerdem sicher, dass deine Middleware-Datei am richtigen Ort liegt – sie muss als middleware.ts im Projekt-Root sein, nicht in /app oder /src/app.

Locale-Erkennungslogik prüfen

TypeScript
1// middleware.ts
2import createMiddleware from 'next-intl/middleware';
3
4export default createMiddleware({
5  locales: ['en', 'es', 'de', 'fr'],
6  defaultLocale: 'en',
7  localePrefix: 'always'  // oder 'as-needed'
8});

Debug-Tipp: Füge console.log zur Middleware hinzu, um zu sehen, welche Locale erkannt wird:

TypeScript
1export default function middleware(request: NextRequest) {
2  console.log('Erkannte Locale:', request.nextUrl.pathname);
3  // ... Rest der Middleware
4}

Problem #5: Hydration Mismatch Fehler

Symptom: Konsole zeigt "Text content does not match server-rendered HTML"

Das passiert, wenn Server und Client unterschiedliche Übersetzungen rendern:

Ursache 1: Client Hook in Server Component verwenden

TSX
1// ❌ Server Component verwendet Client Hook
2// app/[locale]/page.tsx (Server Component standardmäßig)
3import { useTranslations } from 'next-intl';  // Das ist hier tatsächlich okay
4
5export default function Page() {
6  const t = useTranslations('home');
7  return <h1>{t('title')}</h1>;  // Funktioniert in next-intl!
8}

Moment, das funktioniert tatsächlich in next-intl, weil es den Context erkennt. Aber mit react-i18next:

TSX
1// ❌ Mit react-i18next in Server Component
2'use server';
3import { useTranslation } from 'react-i18next';  // Funktioniert nicht
4
5// ✅ Serverseitige Funktion verwenden
6import { getTranslations } from 'next-intl/server';
7
8export default async function Page() {
9  const t = await getTranslations('home');
10  return <h1>{t('title')}</h1>;
11}

Ursache 2: Datums-/Zeitformatierung ohne Zeitzone

TSX
1// ❌ Server könnte UTC sein, Client ist lokale Zeitzone
2{formatDate(new Date())}
3
4// ✅ Zeitzone immer explizit angeben
5import { format } from 'date-fns-tz';
6{format(new Date(), 'PPP', { timeZone: userTimezone })}

Problem #6: Provider umschließt Komponenten nicht

Symptom: "Could not find IntlProvider" oder ähnliche Context-Fehler

TSX
1// ❌ Provider fehlt im Layout
2// app/[locale]/layout.tsx
3export default function Layout({ children }) {
4  return <html><body>{children}</body></html>;
5}
6
7// ✅ Mit Provider
8import { NextIntlClientProvider } from 'next-intl';
9import { getMessages } from 'next-intl/server';
10
11export default async function Layout({ children, params: { locale } }) {
12  const messages = await getMessages();
13  return (
14    <html lang={locale}>
15      <body>
16        <NextIntlClientProvider messages={messages}>
17          {children}
18        </NextIntlClientProvider>
19      </body>
20    </html>
21  );
22}

Problem #7: Dynamische Keys funktionieren nicht

Symptom: t(status.${status}) gibt den Key zurück

TSX
1// ❌ Dynamisch konstruierte Keys
2const key = `status.${order.status}`;
3t(key);  // Manche Bundler können das nicht optimieren
4
5// ✅ Explizites Mapping verwenden
6const statusMessages = {
7  pending: t('status.pending'),
8  shipped: t('status.shipped'),
9  delivered: t('status.delivered')
10};
11return statusMessages[order.status];
12
13// ✅ Oder t.raw() für dynamische Keys in next-intl
14t(`status.${order.status}`);  // Das funktioniert tatsächlich in next-intl

Problem #8: Pluralisierung funktioniert nicht

Symptom: Zeigt "{count, plural, one {# item} other {# items}}" wörtlich an

Du verwendest ICU-Format, aber die Library parst es nicht:

JSON
1// Deine JSON
2{
3  "items": "{count, plural, one {# Artikel} other {# Artikel}}"
4}
TSX
1// ❌ Variable nicht übergeben
2t('items');
3
4// ✅ Count-Variable übergeben
5t('items', { count: 5 });  // "5 Artikel"

Prüfe, ob deine Library ICU unterstützt

  • next-intl: Volle ICU-Unterstützung ✅
  • react-i18next: Benötigt i18next-icu Plugin
  • next-translate: Nur einfache Pluralisierung

Problem #9: Umgebungs-/Build-Probleme

Keys funktionieren im Dev, brechen in Produktion

TypeScript
1// ❌ Dynamische Imports könnten zur Build-Zeit fehlschlagen
2const messages = await import(`@/messages/${locale}.json`);
3
4// ✅ Sicherstellen, dass alle Locales statisch bekannt sind
5import en from '@/messages/en.json';
6import es from '@/messages/es.json';
7
8const messages = { en, es };
9export const getMessages = (locale: string) => messages[locale];

"Module not found" nach Hinzufügen neuer Locale

Nach dem Hinzufügen einer neuen Locale-Datei den Dev-Server neu starten. Next.js cached die Modul-Auflösung.

Terminal
rm -rf .next && npm run dev

Symptom: Klick auf interne Links setzt auf Standardsprache zurück

TSX
1// ❌ Normaler Link verliert Locale
2import Link from 'next/link';
3<Link href="/about">Über uns</Link>
4
5// ✅ Navigation von next-intl verwenden
6import { Link } from '@/i18n/navigation';  // Deine konfigurierte Navigation
7<Link href="/about">Über uns</Link>  // Behält Locale automatisch bei
8
9// ✅ Oder Locale manuell einbinden
10import { useLocale } from 'next-intl';
11const locale = useLocale();
12<Link href={`/${locale}/about`}>Über uns</Link>

Debugging-Checkliste

Wenn Übersetzungen nicht funktionieren, geh diese Checkliste durch:

PrüfungBefehl/Aktion
JSON-Syntax valide`cat messages/en.json
Key existiertExakten Key in JSON-Datei suchen
Locale-Datei existiertls messages/
Middleware läuftconsole.log hinzufügen, Server-Output prüfen
Provider vorhandenlayout.tsx auf IntlProvider prüfen
Korrekter ImportServer: getTranslations, Client: useTranslations
Cache geleertrm -rf .next && npm run dev

Häufige Fehlermeldungen erklärt

FehlerBedeutungLösung
Missing message: "key"Key nicht in JSONKey zu allen Locale-Dateien hinzufügen
Unable to find next-intl localeMiddleware setzt Locale nichtmiddleware.ts Platzierung und Konfiguration prüfen
Hydration failedServer/Client MismatchKorrekten Hook für Component-Typ verwenden
Cannot read property 't' of undefinedProvider fehltMit IntlClientProvider umschließen
ENOENT: no such fileDateipfad falschMessages-Ordner-Pfad in Konfiguration prüfen

Prävention: Diese Probleme komplett vermeiden

1. TypeScript für typsichere Keys verwenden

TypeScript
1// Types aus deiner JSON generieren
2// Mit next-intl eine Types-Datei erstellen:
3type Messages = typeof import('./messages/en.json');
4declare global {
5  interface IntlMessages extends Messages {}
6}

Jetzt meldet TypeScript einen Fehler bei ungültigen Keys.

2. Ein Übersetzungsmanagement-System nutzen

Tools wie IntlPull machen automatisch:

  • JSON-Syntax validieren
  • Fehlende Übersetzungen pro Locale tracken
  • Key-Tippfehler durch Autocomplete verhindern
  • Keys über alle Locales synchronisieren

3. CI-Checks hinzufügen

YAML
1# .github/workflows/i18n-check.yml
2- name: JSON-Dateien validieren
3  run: |
4    for f in messages/*.json; do
5      python -m json.tool "$f" > /dev/null || exit 1
6    done
7
8- name: Auf fehlende Keys prüfen
9  run: npx intlpull check --config intlpull.config.json

4. Integrationstests für kritische Pfade

TypeScript
1// e2e/i18n.spec.ts
2test('Checkout-Seite rendert in allen Locales', async ({ page }) => {
3  for (const locale of ['en', 'es', 'de']) {
4    await page.goto(`/${locale}/checkout`);
5    // Sollte keine rohen Übersetzungskeys enthalten
6    await expect(page.locator('body')).not.toContainText('checkout.');
7  }
8});

Wann man Übersetzungsmanagement nutzen sollte

Wenn du diese Probleme wiederholt erlebst, denk über ein TMS nach:

SzenarioDIY JSON-DateienÜbersetzungsmanagement
< 50 Keys, 1-2 Entwickler✅ FunktioniertOverkill
> 200 Keys, mehrere Entwickler❌ Merge-Konflikte✅ Single Source of Truth
> 3 Sprachen❌ Schwer zu synchronisieren✅ Erkennung fehlender Keys
Externe Übersetzer❌ JSON-Übergabe-Albträume✅ Eingebauter Workflow

IntlPull (kleine Eigenwerbung) ist genau dafür gebaut. Es integriert sich in deinen Git-Workflow, erkennt fehlende Übersetzungen in CI, und unterstützt OTA-Updates, damit du für Übersetzungsfixes nicht neu deployen musst.


Häufig gestellte Fragen

Warum gibt meine t()-Funktion den Key statt der Übersetzung zurück?

Dein Übersetzungsschlüssel existiert nicht in der JSON-Datei oder im Namespace. Prüfe auf Tippfehler im Key, stelle sicher, dass die JSON-Struktur zum erwarteten Pfad im Code passt, prüfe ob du den richtigen Namespace verwendest, und validiere, dass die JSON-Datei geladen wird. Das ist das häufigste i18n-Problem.

Warum funktionieren meine Übersetzungen auf Englisch, aber nicht in anderen Sprachen?

Der Übersetzungsschlüssel fehlt in anderen Locale-Dateien. Wenn du einen neuen Key zu en.json hinzufügst, musst du ihn auch zu es.json, de.json usw. hinzufügen. Nutze ein TMS wie IntlPull um fehlende Übersetzungen automatisch zu erkennen, oder richte Fallback-Locales in deiner Konfiguration ein.

Wie behebe ich Next.js i18n Hydration Mismatch Fehler?

Server und Client rendern unterschiedlichen Content. Das passiert meistens bei Datums-/Zeitformatierung (Server ist UTC, Client lokal), Verwendung von Client Hooks in Server Components, oder Locale-Mismatch zwischen Server und Client. Gib Zeitzonen explizit an, verwende korrekte Hooks für den Component-Typ, und stelle sicher, dass die Locale korrekt übergeben wird.

Warum erkennt meine Next.js Middleware die Locale nicht?

Dein Middleware Matcher-Pattern matcht deine Routes nicht. Stelle sicher, dass middleware.ts im Projekt-Root liegt (nicht in /app), dein Matcher die benötigten Routes einschließt, und das locales-Array deinen unterstützten Sprachen entspricht. Füge console.log zur Middleware hinzu, um zu debuggen, was erkannt wird.

Wie debugge ich "Could not find IntlProvider" Fehler?

Deine Komponente ist nicht vom i18n-Provider umschlossen. Prüfe, dass NextIntlClientProvider (oder der Provider deiner Library) in deiner app/[locale]/layout.tsx ist und alle Kind-Komponenten umschließt. Der Provider muss Messages und die aktuelle Locale erhalten.

Warum verursacht meine JSON-Datei "Unexpected token" Fehler?

Deine JSON-Syntax ist ungültig. Häufige Probleme: Trailing Commas, einfache statt doppelte Anführungszeichen, nicht-escapte Anführungszeichen in Werten, oder fehlende Kommas. Lass deine JSON durch einen Validator wie python -m json.tool laufen, um die genaue Fehlerstelle zu finden.

Wie bringe ich Übersetzungen in Next.js Server Components zum Laufen?

Verwende serverseitige Übersetzungsfunktionen. In next-intl nutze getTranslations() aus next-intl/server in Server Components. Der normale useTranslations() Hook funktioniert in next-intl durch Context-Erkennung, aber für react-i18next brauchst du explizite serverseitige Funktionen.

Warum brechen meine Übersetzungen in Produktion, funktionieren aber in Development?

Dynamische Imports können zur Build-Zeit fehlschlagen. Stelle sicher, dass alle Locale-Dateien vor dem Build existieren, verwende statische Imports oder verifizierte dynamische Imports, und leere den .next Cache vor dem Bauen. Produktions-Builds optimieren Imports anders als der Dev-Modus.

Wie verhindere ich, dass die Locale beim Navigieren verloren geht?

Verwende die Link-Komponente deiner i18n-Library statt Next.js Link. In next-intl konfiguriere Navigation-Exports in i18n/navigation.ts und importiere Link von dort. Alternativ füge die Locale manuell in href ein: /${locale}/about.

Wie teste ich, ob alle Übersetzungen existieren?

Füge CI-Checks hinzu, die JSON validieren und fehlende Keys erkennen. Validiere JSON-Syntax mit einem Linter, vergleiche Keys über Locale-Dateien hinweg, und führe Integrationstests aus, die verifizieren, dass Seiten keine rohen Übersetzungskeys anzeigen. IntlPulls CLI bietet automatische Erkennung fehlender Übersetzungen.


Zusammenfassung

Die meisten Next.js i18n-Probleme fallen in vorhersehbare Kategorien:

  1. Key-Tippfehler → TypeScript-Types und Autocomplete nutzen
  2. Ungültige JSON → In CI validieren
  3. Fehlende Locale-Daten → TMS mit Sync-Prüfung nutzen
  4. Falscher Hook/Context → Server vs. Client Component Regeln befolgen
  5. Middleware-Probleme → Datei-Platzierung und Matcher-Konfiguration prüfen

Das Ökosystem ist deutlich besser geworden. Mit App Router und modernen Libraries wie next-intl ist i18n wesentlich zuverlässiger als mit dem Pages Router. Aber es ist immer noch Code, und Code hat Bugs.

Programmiere defensiv: typsichere Keys, CI-Validierung und gutes Tooling sparen dir Stunden beim Debugging.


Brauchst du Hilfe beim Verwalten von Übersetzungen im großen Maßstab? Starte kostenlos mit IntlPull — automatische Erkennung fehlender Übersetzungen, KI-Übersetzung und nahtlose next-intl-Integration.

Tags
nextjs
i18n
troubleshooting
debugging
next-intl
react-i18next
localization
2026
IntlPull Team
IntlPull Team
Engineering

Building tools to help teams ship products globally. Follow us for more insights on localization and i18n.