2023 habe ich eine mehrsprachige E-Commerce-Website für einen Client aus Berlin veröffentlicht. Zwölf Sprachen, App Router, alles sah ordentlich aus. Drei Monate später rankten ihre deutschen Produktseiten in den UK-SERPs und ihre englischen Seiten wurden Nutzern in München angezeigt. Die hreflang-Tags waren technisch vorhanden. Sie waren nur falsch auf eine Weise, die mich einen beschämenden Nachmittag gekostet hat zu entwirren. Diese Erfahrung hat mir mehr über Next.js i18n beigebracht als jede Dokumentationsseite je gekonnt hätte.
Das ist kein „hier ist die offizielle Dokumentation zusammengefasst"-Post. Es ist, was ich beim Bau mehrsprachiger Websites bei Seahawk Media gelernt habe, wo Menschen wiederholt Probleme bekommen, und die konkreten Entscheidungen, die Rankings 2026 wirklich beeinflussen.
---
Der App Router hat alles verändert (und nicht alles zum Besseren)
Der Pages Router hatte eingebauten i18n-Support. Du packtest einen Block in next.config.js und Next.js kümmerte sich um Locale-Erkennung, Sub-Path-Routing und Locale-Wechsel der Link-Komponente fast automatisch. Es war nicht perfekt, aber es war eigensinnig, was weniger Fallstricke bedeutete.
Der App Router hat natives i18n-Routing vollständig entfernt. Kein i18n-Key in next.config.js. Keine automatische Locale-Erkennung. Du bist jetzt verantwortlich für die gesamte Routing-Logik, und genau diese Verantwortung ist es, wo die meisten Teams still und leise ein Durcheinander anrichten.
Der bewährte Ansatz 2026 ist ein [locale] Dynamic Segment im Root deines app/-Verzeichnisses. Etwa so: app/[locale]/page.tsx. Kombiniert mit next-intl oder i18next via react-i18next, eine Middleware-Datei, die Accept-Language-Header liest und entsprechend umleitet, und du hast eine funktionierende Grundlage.
Warum Middleware missverstanden wird
Die Middleware-Datei verrichtet zwei separate Aufgaben, die Leute vermischen. Erstens, Locale-Erkennung: den Accept-Language-Header lesen (oder ein Cookie, oder ein URL-Präfix) und entscheiden, welche Locale zu servieren ist. Zweitens, die URL umleiten oder neu schreiben, damit der Nutzer bei /de/produkte landet statt bei /produkte mit irgendeinem versteckten Locale-Zustand.
Beides muss passieren, bevor die Seite rendert. Das klingt offensichtlich. Aber ich habe Teams gesehen, die Locale-Erkennung in einen React Context Provider laufen lassen, was bedeutet, dass die initiale HTML an Googlebot kein Locale-Signal hat. Der Bot sieht eine Seite, indexiert sie unter der Root-URL, und plötzlich hast du ein kanonisches Chaos.
Halte Locale-Auflösung in Middleware. Immer.
---
Sub-Pfad vs Sub-Domain: Wähle eins und bleibe dabei
Die ewige Debatte. /en/about vs en.yoursite.com/about. Bei den meisten Projekten empfehle ich Sub-Pfad-Routing, und hier ist warum: Es konzentriert deine Domain Authority. Jeder Link, der auf deine .com zeigt, kommt allen Locales zugute. Mit Sub-Domains führst du effektiv separate Seiten aus Googles Sicht, was bedeutet, dass du Authority für jede unabhängig aufbauen musst.
Es gibt eine Ausnahme. Wenn du in einem Markt bist, wo die lokale Top-Level-Domain enorm für Vertrauen zählt (.de in Deutschland, .fr in Frankreich), schlägt eine Country-Code-TLD sowohl Sub-Pfade als auch Sub-Domains bei wahrgenommener lokaler Glaubwürdigkeit. Das ist keine SEO-Aussage, das ist eine Conversions-Aussage. Ich habe A/B-Tests gesehen, wo .de vs yourbrand.com/de Trust-Metriken sichtbar verschoben haben, selbst wenn Rankings identisch waren.
Aber du kannst ein ccTLD-Setup nicht einfach in einer einzigen Next.js-App betreiben. Also für 99% der Projekte: Sub-Pfade, eine App, eine Domain.
---
hreflang: Das Tag, das dich anlügt
Hier sehe ich die meisten Schäden. hreflang ist konzeptionell nicht schwer. Es teilt Suchmaschinen mit: „Diese Seite hat Äquivalente in anderen Sprachen, hier sind sie." In der Praxis gibt es drei spezifische Fehlermodi, auf die ich immer wieder stoße.
Fehlermodus 1: Die Tags sind nicht reziprok
Jede Seite in deinem hreflang-Set muss auf jede andere Seite verweisen, auch auf sich selbst. Wenn /en/about ein hreflang hat, das auf /de/about verweist, aber /de/about kein hreflang hat, das zurück auf /en/about verweist, ignoriert Google das gesamte Set. Nicht bestrafen. Ignorieren. Als würden die Tags nicht existieren.
Seahawk hatte letztes Jahr ein Fintech-Projekt, bei dem 40% der hreflang-Tags nicht reziprok waren, weil zwei Entwickler sie unabhängig voneinander in verschiedenen Komponenten implementiert hatten, ohne sich abzustimmen. Die Behebung dauerte eine Stunde. Die Ranking-Wiederherstellung dauerte zwei Monate.
Fehlermodus 2: Das x-default-Tag fehlt oder ist falsch platziert
x-default ist für Seiten, die keine spezifische Sprache oder Region anvisieren. Typischerweise deine Startseite / oder eine Sprachauswahl-Seite. Einige Teams setzen x-default auf ihre englische Seite, was in Ordnung ist, wenn Englisch wirklich dein Fallback für alle nicht zugeordneten Locales ist. Aber wenn du eine andere Seite für Nutzer bereitstellst, deren Sprache du nicht unterstützt, sollte x-default dorthin verweisen.
Ich habe gesehen, dass x-default komplett weggelassen wurde. Google wirft keinen Fehler. Es trifft einfach selbst eine Entscheidung darüber, welche Version für nicht zugeordnete Anfragen angezeigt werden soll, und diese Entscheidung ist oft falsch.
Fehlermodus 3: Trailing Slashes und kanonische Konflikte
Dein hreflang-Tag sagt https://yoursite.com/de/ueber-uns . Dein kanonischer Tag auf der gleichen Seite sagt https://yoursite.com/de/ueber-uns/ (beachte den Trailing Slash). Google behandelt diese als unterschiedliche URLs. Dein kanonischer Tag und hreflang zeigen nun auf verschiedene Dinge, und du hast einen Signalkonflikt erzeugt, der Rankings unauffällig unterdrückt, ohne einen sichtbaren Fehler in der Search Console zu hinterlassen.
Setze trailingSlash in next.config.js und sei konsistent überall. Überprüfe es. Überprüfe es wirklich, indem du deine eigenen URLs curlist und die Ausgabe liest.
Die Google Search Central-Dokumentation zu hreflang ist wirklich wert, vollständig gelesen zu werden. Das ist eine dieser seltenen offiziellen Dokumentationen, die spezifisch genug sind, um nützlich zu sein.
---
hreflang im großen Maßstab in Next.js generieren
Für eine 5-Sprachen-Website könntest du hreflang-Tags von Hand schreiben. Für 12 Locales über 3.000 Produktseiten brauchst du einen systematischen Ansatz.
Hier ist, was ich verwende:
- Definiere deine Locale-Liste einmal, in einer einzelnen Config-Datei. So etwas wie locales.config.ts, das ein Array exportiert:
['en', 'de', 'fr', 'es', 'nl'...]. - Baue eine Utility-Funktion
getHreflangAlternates(pathname: string), die einen locale-unabhängigen Pfad (/about) nimmt und ein Array von{ hreflang, href }Objekten für jedes Locale zurückgibt. - Rufen Sie diese Funktion in Ihrer root
layout.tsxauf und injizieren Sie die Ergebnisse über Next.js'smetadataAPI unter Verwendung desalternates.languagesFeldes. Dies wurde in Next.js 13.3 hinzugefügt und generiert automatisch die korrekten<link rel="alternate" hreflang="...">Tags im<head>. - Für Seiten mit dynamischen Inhalten (Blogposts, Produktseiten), bei denen nicht jedes Locale eine Übersetzung hat, übergeben Sie ein
supportedLocalesArray an Ihr Utility und generieren Sie Tags nur für Locales, bei denen der Inhalt tatsächlich existiert. Ein hreflang Tag, der auf eine Seite mit 404 zeigt, ist schlechter als kein hreflang Tag.
Der alternates.languages Ansatz in der metadata API ist die sauberste Lösung, die ich dafür gefunden habe. Kein Custom <Head> Jonglieren, keine Third-Party Pakete nur für die Tags.
---
Locale-Erkennung ohne lästig zu sein
Hier lauert eine UX-Falle, die auch SEO-Auswirkungen hat. Aggressive automatische Umleitung basierend auf dem Browser-Locale ist schlecht für beide.
Wenn ein Nutzer in Deutschland yoursite.com/en/article besucht und Ihre Middleware ihn ohne zu fragen auf /de/artikel hard-redirected, haben Sie gerade deren beabsichtigte Navigation zerstört. Sie haben möglicherweise auch das Teilen von Links beschädigt: Jemand teilt die englische URL, der Empfänger in Frankreich wird ins Französische umgeleitet, und der Inhalt, den er sehen sollte, existiert möglicherweise noch gar nicht auf Französisch.
Meine Regel: erkennen, vorschlagen, nicht erzwingen. Nutzen Sie den Accept-Language Header, um beim ersten Besuch einen sinnvollen Standard zu setzen (gespeichert in einem Cookie), aber lassen Sie Nutzer diesen manuell überschreiben und respektieren Sie diese Überschreibung bei jedem folgenden Besuch. Der Cookie hat Vorrang vor dem Header.
Spezifisch für SEO: Googlebot sendet keine aussagekräftigen Accept-Language Header. Es crawlt Ihre URLs so wie sie sind. Stellen Sie also sicher, dass jede Locale-URL direkt zugänglich ist ohne Umleitung, und dass Ihre Sitemap alle Locale-Varianten explizit enthält.
Die next-intl Middleware-Dokumentation behandelt diese Erkennungsstrategie gut, und das ist, wohin ich jeden mit einem neuen Projekt schicken würde.
---
Sitemaps für mehrsprachige Websites
Eine einzelne sitemap.xml, die jede Locale-Variante enthält, ist für kleinere Websites in Ordnung. Bei großen Websites (zehntausende URLs über mehrere Locales hinweg) teile ich das auf: einen Sitemap-Index unter /sitemap.xml, dann separate Sitemap-Dateien pro Locale unter /sitemaps/en.xml, /sitemaps/de.xml und so weiter.
Jeder URL-Eintrag sollte <xhtml:link rel="alternate">-Tags enthalten, die dein hreflang-Setup widerspiegeln. Das ist redundant zu den Tags im Seitenkopf, aber es hilft Googlebot, die Punkte auf Seiten zu verbinden, die es noch nicht gecrawlt hat.
In Next.js 14+ kannst du Sitemaps dynamisch über app/sitemap.ts generieren. Der Return-Type unterstützt alternates.languages in der gleichen Form wie die Metadata API. Verbinde es mit dem gleichen getHreflangAlternates Utility, das du früher gebaut hast, und du erhältst kostenlos Konsistenz.
Eine konkrete Zahl: Bei einem Projekt mit 8 Locales und 4.500 Produkten reduzierte die Aufteilung der Sitemaps die durchschnittliche Crawl-Zeit pro Locale basierend auf GSC-Crawl-Statistiken um etwa 30%. Nicht weltbewegend, aber bedeutsam.
---
Übersetzungsbibliotheken: Was ich wirklich nutze
Es gibt drei, die es wert sind zu kennen. next-intl ist mein Standard für App Router Projekte. Es hat First-Class-Unterstützung für Server Components, handhabt Pluralisierung ordnungsgemäß, und die API ist sauber. Ich habe es seit Mitte 2023 bei etwa 40 Projekten eingesetzt.
react-i18next ist kampferprobt und hat ein riesiges Ökosystem, aber sein mentales Modell wurde für Client Components gebaut und Server Component Unterstützung über den i18next Core hinzuzufügen fühlt sich im Vergleich zum nativen Ansatz von next-intl angeklebt an.
Lingui lohnt sich, wenn dein Translation-Workflow professionelle Übersetzer statt eines CMS umfasst. Seine Extraktions-Tools sind überlegen. Aber für die meisten Agency-Projekte, bei denen Content aus Contentful oder Sanity kommt, ist next-intl einfacher.
Was ich vermeiden würde: dein eigenes System bauen. Ich habe es 2020 einmal für ein Projekt gemacht, bei dem der Client darauf bestand, seine bestehenden PHP-Translationsdateien direkt wiederzuverwenden. Es funktionierte, kaum, und ich verbrachte zwei Jahre damit, etwas zu pflegen, das next-intl jetzt in einem einzigen useTranslations()-Call handhabt.
---
FAQ
Unterstützt Next.js App Router den alten `next.config.js` i18n Block?
Nein. Der i18n-Konfigurationsschlüssel war spezifisch für den Pages Router. Wenn du zu App Router migrierst, musst du das Routing über ein [locale] Dynamic Segment und eine Middleware-Datei implementieren. Der alte Config-Block wird in App Router-Projekten stillschweigend ignoriert.
Sollte ich `lang` im URL-Pfad verwenden oder mich auf Subdomains verlassen?
Für die meisten Projekte ist lang im URL-Pfad (Sub-Path Routing wie /de/) die richtige Wahl. Subdomains fragmentieren deine Domain Authority und erfordern separate DNS-Konfiguration. ccTLDs lohnen sich nur bei der Komplexität, wenn lokale Vertrauenssignale tatsächlich die Conversion Rates in deinen spezifischen Märkten bewegen.
Wie handhabt Googlebot JavaScript-gerenderte Locale-Inhalte?
Schlecht, manchmal. Wenn deine Locale-Erkennung rein clientseitig in einem React-Context läuft und das initiale HTML keinen Locale-Marker hat, kann Googlebot den Pre-Hydration-State indizieren. Löse Locale immer in Middleware auf und stelle sicher, dass das korrekte lang-Attribut auf dem <html>-Element im Server-gerenderten HTML ist. Überprüfe das, indem du die Quelle anschaust, nicht indem du Browser-DevTools verwendest (die den Post-Hydration-State zeigen).
Welcher `x-default` hreflang-Wert ist richtig für eine Website ohne Language-Selector-Seite?
Zeigen Sie auf die Homepage Ihres Standardsprachbereichs, meist /en/. So weiß Google, dass Englisch Ihr Fallback ist, wenn Sie die Sprache eines Nutzers nicht anbieten. Das bringt keine Nachteile mit sich. Es ist lediglich ein schwaches Signal, das Google möglicherweise berücksichtigt, aber nicht muss.
Kann ich meine hreflang-Implementierung ohne bezahltes SEO-Tool überprüfen?
Ja. Googles URL Inspection Tool in der Search Console zeigt Ihnen erkannte hreflang-Tags für jede indexierte URL. Es validiert Gegenseitigkeit nicht automatisch, aber Sie können manuell ein paar repräsentative Seiten überprüfen. Für Bulk-Validierung bietet Screaming Frog (kostenlos bis 500 URLs) Gegenseitigkeitsprüfungen im hreflang-Tab.
---
Multilinguales Next.js richtig hinzubekommen ist echte undankbare Arbeit. Es sind Config-Dateien, URL-Konsistenz und sicherzustellen, dass zwei Entwickler dieselbe Sache nicht zweimal in unterschiedlichen Komponenten implementiert haben. Aber auf den Websites, wo ich mir Zeit für eine ordentliche Umsetzung genommen habe, halten sich die Rankings über Regionen, und die, wo ich Abkürzungen genommen habe, haben mir die Lektionen beigebracht, die ich hier aufgeschrieben habe.
Der Berliner Kunde bekam übrigens seine deutschen Seiten schließlich in Deutschland zu ranken. Hat uns einen kompletten Crawl-Zyklus und viel Kaffee gekostet.
