Next.js Mehrsprachige SEO: Vollständiger Leitfaden – Suchmaschinen indexieren jede Sprache korrekt

Sie haben eine mehrsprachige Website sorgfältig aufgebaut – und trotzdem zeigt die Suche die falsche Sprachversion. Nutzer suchen auf Chinesisch, landen aber auf der englischen Seite. Verschiedene Sprachversionen konkurrieren in den Suchergebnissen miteinander und drücken das Gesamtranking.
Typische Symptome einer schlecht konfigurierten Mehrsprach-SEO. Laut Google-Statistiken haben über 60 % der mehrsprachigen Websites hreflang-Konfigurationsfehler – mit spürbaren Auswirkungen auf Internationalisierung und Nutzererfahrung.
Dieser Artikel zeigt, wie Sie Mehrsprach-SEO in Next.js korrekt umsetzen:
- hreflang-Tags richtig konfigurieren – Sprachversionen nicht verwechseln
- Mehrsprachige Sitemaps generieren – Indexierung beschleunigen
- URL-Struktur best practices – die optimale Internationalisierungsstrategie wählen
- Typische Fehler finden und beheben – Probleme schnell lokalisieren
Ob Pages Router oder App Router – für beide finden Sie passende Lösungen.
1. Kernkonzepte der Mehrsprach-SEO
1.1 Was ist hreflang?
hreflang ist ein HTML-Attribut, das Suchmaschinen Zielsprache und -region einer Seite mitteilt. Hauptfunktionen:
- Duplicate-Content-Strafe vermeiden – Suchmaschinen erkennen: verschiedene Sprachversionen sind Übersetzungen desselben Inhalts, kein Duplicate Content
- Nutzer präzise matchen – passende Sprachversion je nach Sprache und Region des Nutzers
- UX verbessern – Nutzer sehen nicht die falsche Sprache
1.2 Wie Google Mehrsprach-Inhalte verarbeitet
Beim Crawlen einer mehrsprachigen Website geht Google so vor:
- Sprache erkennen (HTML-lang, hreflang, Inhaltsanalyse)
- hreflang-Tags auswerten und Beziehungen zwischen Sprachversionen verstehen
- passende Version in den Suchergebnissen anzeigen
- SEO-Signale der Sprachversionen bündeln (statt gegeneinander konkurrieren zu lassen)
1.3 Typische SEO-Fehler
Fehler 1: Fehlende hreflang-Tags
<!-- ❌ Fehler: keine hreflang-Tags -->
<head>
<title>My Website</title>
<link rel="canonical" href="https://example.com/en/about" />
</head>
Folge: Suchmaschinen erkennen die Sprachbeziehungen nicht – falsche Sprachversionen können in den Ergebnissen erscheinen.
Fehler 2: Asymmetrische hreflang-Konfiguration
<!-- Englische Seite -->
<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="zh" href="https://example.com/zh/about" />
<!-- ❌ Chinesische Seite – Fehler: hreflang fehlt -->
<!-- Auf jeder Sprachversion müssen vollständige hreflang-Tags stehen -->
Folge: Google verlangt symmetrische hreflang-Konfiguration – einseitige Angaben werden ignoriert.
Fehler 3: Falsche Sprachcodes
<!-- ❌ Fehler: ungültige Sprachcodes -->
<link rel="alternate" hreflang="cn" href="..." /> <!-- korrekt: zh -->
<link rel="alternate" hreflang="en-us" href="..." /> <!-- korrekt: en-US, Groß-/Kleinschreibung beachten -->
Folge: Suchmaschinen erkennen die Codes nicht – hreflang wirkt nicht.
2. URL-Strategie wählen
Vor der Umsetzung eine passende URL-Strategie festlegen – sie beeinflusst SEO, UX und technische Implementierung.
2.1 Drei gängige URL-Strategien im Vergleich
| Strategie | Beispiel | SEO-Auswirkung | Implementierung | Empfehlung |
|---|---|---|---|---|
| Unterverzeichnis | example.com/en/ example.com/zh/ | ⭐⭐⭐⭐⭐ Beste | ⭐⭐⭐ Mittel | ⭐⭐⭐⭐⭐ |
| Subdomain | en.example.com zh.example.com | ⭐⭐⭐ Mittel | ⭐⭐⭐⭐ Komplex | ⭐⭐⭐ |
| URL-Parameter | example.com?lang=en | ⭐⭐ Schwach | ⭐⭐⭐⭐⭐ Einfach | ⭐⭐ |
2.2 Strategien im Detail
Option 1: Unterverzeichnis (empfohlen)
Vorteile:
- SEO-Signale bündeln sich auf der Hauptdomain – besseres Gesamtranking
- Einfache Konfiguration, keine extra Domains oder SSL-Zertifikate
- Wartbar und skalierbar, einheitliches Deployment
- Native Next.js-Unterstützung
Nachteile:
- Alle Sprachen teilen sich eine Domain – kein DNS-Tuning pro Markt
Next.js-Implementierung:
// next.config.js
module.exports = {
i18n: {
locales: ['en', 'zh', 'ja', 'de'],
defaultLocale: 'en',
localeDetection: true // Nutzersprache automatisch erkennen
}
}
Option 2: Subdomain
Vorteile:
- Pro Markt eigener Server möglich (z. B. China separat)
- Technologie-Stack pro Subdomain unabhängig
- CDN- und Geo-Optimierung einfacher
Nachteile:
- SEO-Signale verteilen sich – jede Subdomain braucht eigenes Ranking
- Extra Domain- und SSL-Verwaltung
- Höhere Implementierungs- und Wartungskosten
Option 3: URL-Parameter (nicht empfohlen)
Vorteile:
- Am einfachsten umzusetzen
Nachteile:
- Schlechteste SEO-Wirkung – Parameter werden oft ignoriert
- Schlechte UX, URLs wenig sprechend
- CDN-Caching schwierig
- Sprachversionen in der Suche schwer unterscheidbar
Fazit:
Für die meisten Projekte: Unterverzeichnis-Strategie. Bestes Gleichgewicht aus SEO, Aufwand und Wartung.
3. hreflang im Detail
3.1 Aufgabe der hreflang-Tags
hreflang teilt Suchmaschinen mit:
- welche Sprachversionen es gibt
- die vollständige URL jeder Version
- Sprach- und Regionscode pro Version
3.2 hreflang im Next.js App Router
Methode 1: Metadata API (empfohlen)
Next.js 13+ App Router mit schlanker Metadata API:
// app/[lang]/about/page.tsx
import { Metadata } from 'next'
type Props = {
params: { lang: string }
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { lang } = params
// Unterstützte Sprachen
const languages = ['en', 'zh', 'ja', 'de']
// Alternate-Links für alle Sprachen
const alternates = {
canonical: `https://example.com/${lang}/about`,
languages: languages.reduce((acc, locale) => {
acc[locale] = `https://example.com/${locale}/about`
return acc
}, {} as Record<string, string>)
}
return {
title: 'About Us',
alternates,
// x-default für nicht gematchte Sprachen
other: {
'x-default': 'https://example.com/en/about'
}
}
}
export default function AboutPage({ params }: Props) {
return <div>About page in {params.lang}</div>
}
Methode 2: Eigene Head-Komponente
Für mehr Kontrolle:
// components/I18nHead.tsx
import Head from 'next/head'
interface I18nHeadProps {
currentLang: string
pathname: string
languages?: string[]
}
export default function I18nHead({
currentLang,
pathname,
languages = ['en', 'zh', 'ja', 'de']
}: I18nHeadProps) {
const baseUrl = 'https://example.com'
return (
<Head>
{/* Canonical der aktuellen Seite */}
<link rel="canonical" href={`${baseUrl}/${currentLang}${pathname}`} />
{/* hreflang für alle Sprachversionen */}
{languages.map(lang => (
<link
key={lang}
rel="alternate"
hrefLang={lang}
href={`${baseUrl}/${lang}${pathname}`}
/>
))}
{/* x-default auf Standardsprache */}
<link
rel="alternate"
hrefLang="x-default"
href={`${baseUrl}/en${pathname}`}
/>
</Head>
)
}
Verwendung:
// app/[lang]/about/page.tsx
import I18nHead from '@/components/I18nHead'
export default function AboutPage({ params }: { params: { lang: string } }) {
return (
<>
<I18nHead
currentLang={params.lang}
pathname="/about"
/>
<div>About page content</div>
</>
)
}
3.3 hreflang im Next.js Pages Router
Pages Router nutzt andere APIs:
// pages/about.tsx
import { GetStaticProps } from 'next'
import Head from 'next/head'
import { useRouter } from 'next/router'
export default function AboutPage() {
const router = useRouter()
const { locale, locales, asPath } = router
const baseUrl = 'https://example.com'
return (
<>
<Head>
{/* Canonical der aktuellen Seite */}
<link rel="canonical" href={`${baseUrl}/${locale}${asPath}`} />
{/* hreflang für alle Sprachversionen */}
{locales?.map(loc => (
<link
key={loc}
rel="alternate"
hrefLang={loc}
href={`${baseUrl}/${loc}${asPath}`}
/>
))}
{/* x-default Standardsprache */}
<link
rel="alternate"
hrefLang="x-default"
href={`${baseUrl}/en${asPath}`}
/>
</Head>
<div>About page content</div>
</>
)
}
export const getStaticProps: GetStaticProps = async ({ locale }) => {
return {
props: {
messages: (await import(`../locales/${locale}.json`)).default
}
}
}
3.4 Regionale Codes (language-REGION)
Für länderspezifische Inhalte das Format language-REGION:
// Englisch für verschiedene Regionen
const hreflangConfig = {
'en-US': 'https://example.com/en-us/about', // US-Englisch
'en-GB': 'https://example.com/en-gb/about', // UK-Englisch
'en-AU': 'https://example.com/en-au/about', // Australien
'zh-CN': 'https://example.com/zh-cn/about', // Festlandchina vereinfachtes Chinesisch
'zh-TW': 'https://example.com/zh-tw/about', // Taiwan traditionelles Chinesisch
'zh-HK': 'https://example.com/zh-hk/about', // Hongkong traditionelles Chinesisch
}
Regionales Routing in Next.js:
// next.config.js
module.exports = {
i18n: {
locales: ['en-US', 'en-GB', 'en-AU', 'zh-CN', 'zh-TW', 'zh-HK'],
defaultLocale: 'en-US',
}
}
3.5 Typische Konfigurationsfehler und Fixes
Fehler 1: Fehlende Selbstreferenz
<!-- ❌ Fehler: aktuelle Seite referenziert sich nicht selbst -->
<link rel="alternate" hreflang="zh" href="https://example.com/zh/about" />
<!-- ✅ Korrekt: Selbstreferenz erforderlich -->
<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="zh" href="https://example.com/zh/about" />
Warum Selbstreferenz?
Google verlangt symmetrische hreflang – jede Sprachversion muss alle anderen inklusive sich selbst referenzieren.
Fehler 2: Fehlendes x-default
<!-- ✅ Empfohlen: x-default als Fallback -->
<link rel="alternate" hreflang="x-default" href="https://example.com/en/about" />
x-default liefert die Standardversion für nicht unterstützte Sprachen, z. B.:
- Nutzer mit arabischer Browser-Sprache, Website ohne Arabisch
- Suchmaschine liefert die unter x-default angegebene Seite
Fehler 3: hreflang und canonical im Konflikt
<!-- ❌ Fehler: canonical zeigt auf andere Sprachversion -->
<link rel="canonical" href="https://example.com/en/about" />
<link rel="alternate" hreflang="zh" href="https://example.com/zh/about" />
<!-- ✅ Korrekt: canonical zeigt auf die aktuelle Sprachversion -->
<link rel="canonical" href="https://example.com/zh/about" />
<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="zh" href="https://example.com/zh/about" />
Grundregel: canonical muss die URL der aktuellen Seite sein – nie eine andere Sprachversion.
4. Mehrsprachige Sitemap
Sitemaps helfen Suchmaschinen, Seiten zu finden und zu indexieren. Bei mehrsprachigen Sites ist die richtige Sitemap-Konfiguration entscheidend.
4.1 Warum eine mehrsprachige Sitemap?
Drei Vorteile:
- Schnellere Indexierung – alle Sprachversionen aktiv melden, statt auf den Crawler zu warten
- Vollständigkeit – keine Sprachversion übersehen, besonders bei tiefen Linkstrukturen
- hreflang in der Sitemap – Sprachbeziehungen zusätzlich verstärken
4.2 Sitemap-Strategie
Je nach Site-Größe:
Option 1: Eine Sitemap (kleine Sites)
Alle Sprach-URLs in einer sitemap.xml – geeignet bis ca. 5.000 Seiten:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<!-- Englische Version -->
<url>
<loc>https://example.com/en/about</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about"/>
<xhtml:link rel="alternate" hreflang="zh" href="https://example.com/zh/about"/>
<xhtml:link rel="alternate" hreflang="ja" href="https://example.com/ja/about"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/about"/>
</url>
<!-- Chinesische Version -->
<url>
<loc>https://example.com/zh/about</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about"/>
<xhtml:link rel="alternate" hreflang="zh" href="https://example.com/zh/about"/>
<xhtml:link rel="alternate" hreflang="ja" href="https://example.com/ja/about"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/about"/>
</url>
</urlset>
Option 2: Sitemap pro Sprache (große Sites)
Pro Sprache eine Sitemap, gebündelt per Sitemap-Index – ab ca. 5.000 Seiten oder vielen Sprachen:
<!-- sitemap-index.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://example.com/sitemap-en.xml</loc>
<lastmod>2025-01-01</lastmod>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-zh.xml</loc>
<lastmod>2025-01-01</lastmod>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-ja.xml</loc>
<lastmod>2025-01-01</lastmod>
</sitemap>
</sitemapindex>
4.3 Sitemap im Next.js App Router
Next.js 13+ mit eingebauter Sitemap-Generierung:
// app/sitemap.ts
import { MetadataRoute } from 'next'
const languages = ['en', 'zh', 'ja', 'de']
const routes = ['', '/about', '/blog', '/contact']
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://example.com'
const sitemap: MetadataRoute.Sitemap = []
routes.forEach(route => {
languages.forEach(lang => {
const url = `${baseUrl}/${lang}${route}`
sitemap.push({
url,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: route === '' ? 1 : 0.8,
alternates: {
languages: languages.reduce((acc, l) => {
acc[l] = `${baseUrl}/${l}${route}`
return acc
}, {} as Record<string, string>)
}
})
})
})
return sitemap
}
4.4 Sitemap für dynamische Inhalte
Bei Blog-Artikeln oder Produkten aus DB/CMS:
// app/sitemap.ts
import { MetadataRoute } from 'next'
const languages = ['en', 'zh', 'ja']
const baseUrl = 'https://example.com'
async function getArticles() {
return [
{ slug: 'getting-started', lastModified: '2025-01-01' },
{ slug: 'advanced-guide', lastModified: '2025-01-15' },
]
}
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const sitemap: MetadataRoute.Sitemap = []
const staticPages = ['', '/about', '/contact']
staticPages.forEach(page => {
languages.forEach(lang => {
sitemap.push({
url: `${baseUrl}/${lang}${page}`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: page === '' ? 1 : 0.8,
alternates: {
languages: languages.reduce((acc, l) => {
acc[l] = `${baseUrl}/${l}${page}`
return acc
}, {} as Record<string, string>)
}
})
})
})
const articles = await getArticles()
articles.forEach(article => {
languages.forEach(lang => {
sitemap.push({
url: `${baseUrl}/${lang}/blog/${article.slug}`,
lastModified: new Date(article.lastModified),
changeFrequency: 'weekly',
priority: 0.6,
alternates: {
languages: languages.reduce((acc, l) => {
acc[l] = `${baseUrl}/${l}/blog/${article.slug}`
return acc
}, {} as Record<string, string>)
}
})
})
})
return sitemap
}
4.5 Sitemap im Pages Router
Manuell über API-Route:
// pages/api/sitemap.xml.ts
import { NextApiRequest, NextApiResponse } from 'next'
const baseUrl = 'https://example.com'
const languages = ['en', 'zh', 'ja']
function generateSiteMap(pages: string[]) {
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
${pages.map(page => {
return languages.map(lang => {
const url = `${baseUrl}/${lang}${page}`
const alternates = languages.map(l =>
` <xhtml:link rel="alternate" hreflang="${l}" href="${baseUrl}/${l}${page}"/>`
).join('\n')
return ` <url>
<loc>${url}</loc>
<lastmod>${new Date().toISOString()}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
${alternates}
<xhtml:link rel="alternate" hreflang="x-default" href="${baseUrl}/en${page}"/>
</url>`
}).join('\n')
}).join('\n')}
</urlset>`
}
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const pages = ['', '/about', '/blog', '/contact']
const sitemap = generateSiteMap(pages)
res.setHeader('Content-Type', 'text/xml')
res.write(sitemap)
res.end()
}
4.6 Sitemap bei Suchmaschinen einreichen
Nach der Generierung aktiv einreichen:
Methode 1: In robots.txt deklarieren
Einfachste Variante – Crawler lesen automatisch:
# public/robots.txt
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap.xml
Methode 2: Google Search Console
Manuelles Einreichen beschleunigt die Indexierung:
- Google Search Console öffnen
- Property auswählen
- Menü „Sitemaps“
- URL der sitemap.xml eingeben
- „Senden“ klicken
Methode 3: Bing Webmaster Tools
Bing hat relevanten Marktanteil:
- Bing Webmaster Tools öffnen
- Website hinzufügen
- Sitemap im Bereich „Sitemaps“ einreichen
4.7 Sitemap validieren
Validierungstools:
- XML Sitemap Validator: https://www.xml-sitemaps.com/validate-xml-sitemap.html
- Google Search Console: Indexstatus und Fehler nach Einreichung
- Online-XML-Validator: Standardkonformität prüfen
5. Best Practices und Hinweise
5.1 Qualität der Übersetzungen
Google erkennt minderwertige Übersetzungen – das beeinflusst das Ranking.
Vermeiden:
- ❌ Automatische Übersetzung (Google Translate) direkt veröffentlichen
- ❌ Nur Navigation und Titel übersetzen, Body in einer Sprache lassen
- ❌ Starke inhaltliche Unterschiede zwischen Sprachversionen
Empfohlen:
- ✅ Professionelle Übersetzer oder Muttersprachler
- ✅ Lokalisierung statt reiner Übersetzung (Kultur, Ausdruck)
- ✅ Einheitliche Struktur und Qualität aller Sprachversionen
5.2 SEO-Risiko automatischer Client-Übersetzung
Clientseitige Auto-Übersetzung wirkt für SEO nicht – Crawler sehen den Originalinhalt:
// ❌ Nicht empfohlen: Client-Auto-Übersetzung (nicht indexierbar)
import GoogleTranslate from 'google-translate-api'
export default function Page() {
const [content, setContent] = useState('')
useEffect(() => {
GoogleTranslate(originalText, { to: 'zh' })
.then(res => setContent(res.text))
}, [])
return <div>{content}</div>
}
// ✅ Empfohlen: SSR mit echten Übersetzungen
export default function Page({ params }: { params: { lang: string } }) {
const content = await getTranslatedContent(params.lang)
return <div>{content}</div>
}
5.3 Performance
Mehrsprachige Sites erreichen Nutzer weltweit – Performance zählt.
1. CDN für mehrere Regionen
// next.config.js
module.exports = {
images: {
domains: ['cdn.example.com'],
},
compress: true,
}
2. Sprachpakete lazy laden
Nicht alle Übersetzungsdateien auf einmal laden:
const messages = await import(`@/locales/${lang}.json`)
3. Cache-Strategie
// app/[lang]/layout.tsx
export const revalidate = 3600 // stündliche Revalidierung
5.4 Monitoring und Wartung
Mehrsprach-SEO ist kein Einmal-Task.
1. hreflang-Fehler prüfen
Google Search Console, Bericht „Internationale Ausrichtung“:
- hreflang-Fehler und Warnungen
- Indexstatus pro Sprache
- Suchperformance und Klickrate pro Sprache
2. Empfohlene Tools
- Google Search Console – Pflicht, kostenlos
- Ahrefs Site Audit – hreflang im Bulk prüfen
- Screaming Frog – lokaler Vollständigkeits-Crawl
- hreflang Tags Testing Tool – https://www.aleydasolis.com/english/international-seo-tools/hreflang-tags-generator/
3. Monitoring-Skript
Automatisierte hreflang-Prüfung:
// scripts/check-hreflang.ts
import { JSDOM } from 'jsdom'
async function checkHreflang(url: string) {
const response = await fetch(url)
const html = await response.text()
const dom = new JSDOM(html)
const document = dom.window.document
const hreflangLinks = document.querySelectorAll('link[rel="alternate"][hreflang]')
console.log(`Found ${hreflangLinks.length} hreflang links on ${url}`)
hreflangLinks.forEach(link => {
const hreflang = link.getAttribute('hreflang')
const href = link.getAttribute('href')
console.log(` ${hreflang}: ${href}`)
})
const currentUrl = new URL(url).href
const hasSelfReference = Array.from(hreflangLinks).some(
link => link.getAttribute('href') === currentUrl
)
if (!hasSelfReference) {
console.warn('⚠️ Warning: Missing self-reference hreflang tag')
}
const hasXDefault = Array.from(hreflangLinks).some(
link => link.getAttribute('hreflang') === 'x-default'
)
if (!hasXDefault) {
console.warn('⚠️ Warning: Missing x-default hreflang tag')
}
}
checkHreflang('https://example.com/en/about')
checkHreflang('https://example.com/zh/about')
6. Praxisbeispiel: vollständiges Projekt
So setzen Sie Mehrsprach-SEO in einem Next.js App Router-Projekt um.
6.1 Projektstruktur
my-i18n-site/
├── app/
│ ├── [lang]/
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ ├── about/
│ │ │ └── page.tsx
│ │ └── blog/
│ │ ├── page.tsx
│ │ └── [slug]/
│ │ └── page.tsx
│ ├── sitemap.ts
│ └── robots.ts
├── components/
│ └── I18nMetadata.tsx
├── lib/
│ ├── i18n.ts
│ └── articles.ts
├── locales/
│ ├── en.json
│ ├── zh.json
│ └── ja.json
└── next.config.js
6.2 Konfiguration
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// App Router nutzt i18n in next.config nicht – Routing manuell
}
module.exports = nextConfig
// lib/i18n.ts
export const languages = ['en', 'zh', 'ja'] as const
export type Language = (typeof languages)[number]
export const defaultLanguage: Language = 'en'
export const languageNames: Record<Language, string> = {
en: 'English',
zh: '中文',
ja: '日本語',
}
export function isValidLanguage(lang: string): lang is Language {
return languages.includes(lang as Language)
}
6.3 Layout-Komponente
// app/[lang]/layout.tsx
import { languages, isValidLanguage } from '@/lib/i18n'
import { notFound } from 'next/navigation'
export async function generateStaticParams() {
return languages.map(lang => ({ lang }))
}
export default function LangLayout({
children,
params,
}: {
children: React.ReactNode
params: { lang: string }
}) {
if (!isValidLanguage(params.lang)) {
notFound()
}
return (
<html lang={params.lang}>
<body>{children}</body>
</html>
)
}
6.4 Seite mit Metadata
// app/[lang]/about/page.tsx
import { Metadata } from 'next'
import { languages, Language } from '@/lib/i18n'
type Props = {
params: { lang: Language }
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { lang } = params
const baseUrl = 'https://example.com'
const pathname = '/about'
const alternates = {
canonical: `${baseUrl}/${lang}${pathname}`,
languages: languages.reduce((acc, locale) => {
acc[locale] = `${baseUrl}/${locale}${pathname}`
return acc
}, {} as Record<string, string>)
}
const titles: Record<Language, string> = {
en: 'About Us - Learn More About Our Company',
zh: '关于我们 - 了解更多关于我们公司的信息',
ja: '私たちについて - 当社についてもっと知る',
}
const descriptions: Record<Language, string> = {
en: 'Learn about our mission, values, and the team behind our success.',
zh: '了解我们的使命、价值观以及我们成功背后的团队。',
ja: '私たちの使命、価値観、そして成功を支えるチームについて学びます。',
}
return {
title: titles[lang],
description: descriptions[lang],
alternates,
openGraph: {
title: titles[lang],
description: descriptions[lang],
url: `${baseUrl}/${lang}${pathname}`,
siteName: 'Example Site',
locale: lang,
type: 'website',
},
}
}
export default function AboutPage({ params }: Props) {
const content = {
en: 'About us content in English...',
zh: '关于我们的中文内容...',
ja: '私たちについての日本語コンテンツ...',
}
return (
<div>
<h1>About Us</h1>
<p>{content[params.lang]}</p>
</div>
)
}
6.5 Dynamische Route mit hreflang
// app/[lang]/blog/[slug]/page.tsx
import { Metadata } from 'next'
import { languages, Language } from '@/lib/i18n'
import { getArticle, getAllArticles } from '@/lib/articles'
import { notFound } from 'next/navigation'
type Props = {
params: { lang: Language; slug: string }
}
export async function generateStaticParams() {
const articles = await getAllArticles()
return languages.flatMap(lang =>
articles.map(article => ({
lang,
slug: article.slug,
}))
)
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { lang, slug } = params
const article = await getArticle(slug, lang)
if (!article) {
return {}
}
const baseUrl = 'https://example.com'
const pathname = `/blog/${slug}`
const alternates = {
canonical: `${baseUrl}/${lang}${pathname}`,
languages: languages.reduce((acc, locale) => {
acc[locale] = `${baseUrl}/${locale}${pathname}`
return acc
}, {} as Record<string, string>)
}
return {
title: article.title,
description: article.excerpt,
alternates,
openGraph: {
title: article.title,
description: article.excerpt,
url: `${baseUrl}/${lang}${pathname}`,
type: 'article',
publishedTime: article.publishedAt,
authors: [article.author],
},
}
}
export default async function BlogArticle({ params }: Props) {
const { lang, slug } = params
const article = await getArticle(slug, lang)
if (!article) {
notFound()
}
return (
<article>
<h1>{article.title}</h1>
<p>{article.content}</p>
</article>
)
}
6.6 Sitemap-Generierung
// app/sitemap.ts
import { MetadataRoute } from 'next'
import { languages } from '@/lib/i18n'
import { getAllArticles } from '@/lib/articles'
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = 'https://example.com'
const sitemap: MetadataRoute.Sitemap = []
const staticPages = ['', '/about', '/contact']
staticPages.forEach(page => {
languages.forEach(lang => {
sitemap.push({
url: `${baseUrl}/${lang}${page}`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: page === '' ? 1 : 0.8,
alternates: {
languages: languages.reduce((acc, l) => {
acc[l] = `${baseUrl}/${l}${page}`
return acc
}, {} as Record<string, string>)
}
})
})
})
const articles = await getAllArticles()
articles.forEach(article => {
languages.forEach(lang => {
sitemap.push({
url: `${baseUrl}/${lang}/blog/${article.slug}`,
lastModified: new Date(article.updatedAt),
changeFrequency: 'weekly',
priority: 0.6,
alternates: {
languages: languages.reduce((acc, l) => {
acc[l] = `${baseUrl}/${l}/blog/${article.slug}`
return acc
}, {} as Record<string, string>)
}
})
})
})
return sitemap
}
6.7 Robots.txt
// app/robots.ts
import { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
},
sitemap: 'https://example.com/sitemap.xml',
}
}
7. Validierung und Tests
7.1 Lokale Checkliste
Vor dem Produktions-Deploy:
-
<html lang="...">auf allen Seiten korrekt - Vollständige hreflang-Tags auf jeder Seite (alle Sprachversionen)
- Selbstreferenz in hreflang vorhanden
-
x-defaultzeigt auf Standardsprache - canonical zeigt auf die aktuelle Sprachversion
- Sitemap enthält alle Sprach-URLs
- robots.txt verweist auf sitemap.xml
- Einheitliche Übersetzungsqualität aller Sprachversionen
7.2 Google Rich Results Test
- Seiten-URL eingeben
- Auf Crawl und Analyse warten
- Fehler und Warnungen prüfen
- hreflang-Erkennung verifizieren
7.3 hreflang-Prüftools
- Aleyda Solis hreflang Generator: https://www.aleydasolis.com/english/international-seo-tools/hreflang-tags-generator/
- Merkle hreflang Checker: https://technicalseo.com/tools/hreflang/
Funktionen:
- Bulk-Prüfung mehrerer Seiten
- Symmetrie-Probleme erkennen
- Sprachcode-Fehler finden
7.4 Google Search Console
Nach dem Deploy:
- Sitemap in Search Console einreichen
- 1–2 Wochen auf erste Indexierung warten
- „Internationale Ausrichtung“ > „Sprache“ prüfen
- hreflang-Fehler und Warnungen beheben
- Suchperformance pro Sprache überwachen
8. Häufige Fragen
F1: Unterschied zwischen hreflang und canonical?
- canonical – kanonische URL der Seite, gegen Duplicate Content
- hreflang – verfügbare Sprachversionen, für Sprach-Targeting
Beides kombinierbar. canonical pro Sprachversion auf sich selbst, hreflang auf alle Versionen.
F2: hreflang auf jeder Seite Pflicht?
Ja. Auf jeder Sprachversion, symmetrisch (gegenseitige Referenz). Nur auf der englischen Seite reicht nicht – Google ignoriert das.
F3: Wohin zeigt x-default?
Meist Standardsprache oder allgemeinste Version:
- Hauptpublikum Englisch → englische Version
- Globale Site → internationales Englisch (en-US)
- Regionale Site → Hauptsprache der Region
F4: Unterverzeichnis vs. Subdomain?
Unterverzeichnis (empfohlen):
- SEO auf Hauptdomain
- Einfache Implementierung
- Für die meisten Projekte
Subdomain:
- Eigener Server pro Markt
- Große internationale Sites mit eigenem Markt-Betrieb
- Extra Domain-Kosten
Fazit: Ohne Spezialbedarf → Unterverzeichnis.
F5: Maschinell übersetzte Inhalte?
Nicht empfohlen für SEO:
- Google erkennt schwache Übersetzungen
- Geringerer Content-Wert
- Schlechte UX, hohe Absprungrate
Bei knappem Budget:
- Kernseiten zuerst (Startseite, Hauptprodukte, Top-Traffic)
- MT + menschliches Lektorat
- Qualität schrittweise verbessern
F6: Wie lange bis zur Indexierung?
Typischer Zeitplan:
- Nach Sitemap-Einreichung 1–2 Wochen erste Indexierung
- Vollständige Indexierung 1–2 Monate
- SEO-Signale 3–6 Monate
Beschleunigen:
- Korrekte Sitemap + Einreichung
- Hohe Content-Qualität und Updates
- Qualitative Backlinks
- Indexierung wichtiger Seiten in Search Console anfordern
9. Zusammenfassung
Mehrsprach-SEO ist Schlüssel zum internationalen Erfolg. Kernpunkte:
9.1 Kernpunkte
-
URL-Strategie
- Unterverzeichnis empfohlen (example.com/en/, example.com/zh/)
- Klare, konsistente URL-Struktur
-
hreflang
- Vollständige Tags auf jeder Seite
- Selbstreferenz Pflicht
- x-default auf Standardsprache
- ISO-639-1-Sprachcodes
-
Sitemap
- Alle Sprachversionen enthalten
- Optional hreflang in der Sitemap
- Regelmäßig aktualisieren und einreichen
-
Content-Qualität
- Keine rohe MT-Veröffentlichung
- Konsistenz und Professionalität
- Lokalisierung, nicht nur Übersetzung
-
Monitoring
- Google Search Console
- Regelmäßige hreflang-Prüfung
- Performance pro Sprache tracken
9.2 Aktionsliste
- URL-Strategie wählen und umsetzen (Unterverzeichnis empfohlen)
- Vollständige hreflang-Tags auf allen Seiten
- Korrekte canonical-Tags
- Mehrsprachige Sitemap generieren
- robots.txt mit Sitemap-Verweis
- Sitemap an Google Search Console und Bing einreichen
- hreflang mit Validierungstools prüfen
- Übersetzungsqualität sichern
- Monitoring und regelmäßige Reviews einrichten
9.3 Weiterführend
- Google: Mehrsprachige und mehrsregionale Sites
- Google: hreflang-Leitfaden
- Next.js: Internationalisierung
- Schema.org: Mehrsprach-Markup
Korrekte Mehrsprach-SEO braucht Zeit – lohnt sich: besseres Ranking, präzisere Nutzer, höhere Conversion. Mit diesen Best Practices performt Ihre Site in der Suche deutlich besser.
Bei Fragen zur Umsetzung – gerne in den Kommentaren diskutieren!
Next.js Mehrsprach-SEO: Vollständiger Konfigurationsablauf
Von hreflang-Tags über mehrsprachige Sitemaps bis zur URL-Strategie – Schritt für Schritt
⏱️ Estimated time: 2 hr
- 1
Step 1: hreflang-Tags konfigurieren
In Metadata konfigurieren:
```tsx
// app/[locale]/about/page.tsx
export async function generateMetadata({ params }): Promise<Metadata> {
const { locale } = params
return {
title: 'About Us',
alternates: {
languages: {
'zh': '/zh/about',
'en': '/en/about',
'x-default': '/en/about', // Standardsprache
},
},
}
}
```
Wichtig:
• Alle Sprachversionen enthalten
• x-default auf Standardsprache
• Auf jeder Seite konfigurieren
HTML-Ausgabe:
```html
<link rel="alternate" hreflang="zh" href="https://example.com/zh/about" />
<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/about" />
```
Wirkung:
• Zielsprache für Suchmaschinen
• Duplicate-Content-Strafe vermeiden
• Nutzer präzise matchen - 2
Step 2: Mehrsprachige Sitemap generieren
Methode 1: Pro Sprache eigene Sitemap
```tsx
// app/[locale]/sitemap.ts
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = 'https://example.com'
const locale = params.locale
return [
{
url: `${baseUrl}/${locale}`,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
]
}
```
Methode 2: Sitemap-Index
```tsx
// app/sitemap.ts
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const locales = ['zh', 'en']
const baseUrl = 'https://example.com'
return locales.flatMap(locale => [
{
url: `${baseUrl}/${locale}`,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
])
}
```
Wichtig:
• Alle Sprachversionen enthalten
• Korrektes URL-Format
• In Google Search Console einreichen - 3
Step 3: URL-Strategie wählen
Option 1: Unterverzeichnis (empfohlen)
• URL: /zh/about, /en/about
• Einfache Konfiguration
• SEO-freundlich
• Für die meisten Projekte
Option 2: Subdomain
• URL: zh.example.com, en.example.com
• Mehrere Domains nötig
• Professioneller Eindruck
• Große Projekte
Option 3: Cookie
• Sprache per Cookie
• Kein Sprachpräfix in der URL
• SEO-unfreundlich
• Nicht empfohlen
Empfehlung:
• Meiste Projekte → Unterverzeichnis
• Große Projekte → Subdomain
• Vermeiden → Cookie
Unterverzeichnis ist SEO-technisch am besten. - 4
Step 4: Validieren und testen
Validierungstools:
1. Google Search Console:
• Mehrsprachige Sitemap einreichen
• hreflang-Tags prüfen
• Indexstatus ansehen
2. hreflang-Testtools:
• https://www.aleydasolis.com/en/english-tools/international-seo-tools/hreflang-tags-validator/
• hreflang-Konfiguration verifizieren
3. Mehrsprach-Sitemap:
• Sitemap-Format prüfen
• Alle Sprachversionen enthalten
• URLs korrekt
Typische Fehler:
• Fehlende hreflang-Tags
• Falsches x-default
• Sitemap ohne alle Sprachen
• Inkonsistente URL-Formate
Tipp: Direkt nach der Konfiguration validieren.
FAQ
Was sind hreflang-Tags? Warum braucht man sie?
Hauptfunktionen:
1. Duplicate-Content-Strafe vermeiden – verschiedene Sprachen sind Übersetzungen, kein Duplicate
2. Nutzer präzise matchen – passende Sprachversion in der Suche
3. UX verbessern – keine falsche Sprache
Konfiguration:
```tsx
export async function generateMetadata({ params }): Promise<Metadata> {
return {
alternates: {
languages: {
'zh': '/zh/about',
'en': '/en/about',
'x-default': '/en/about',
},
},
}
}
```
Wichtig:
• Alle Sprachversionen
• x-default auf Standardsprache
• Auf jeder Seite
Laut Google haben über 60 % der mehrsprachigen Websites hreflang-Fehler.
Wie konfiguriere ich hreflang-Tags?
```tsx
// app/[locale]/about/page.tsx
export async function generateMetadata({ params }): Promise<Metadata> {
const { locale } = params
return {
title: 'About Us',
alternates: {
languages: {
'zh': '/zh/about',
'en': '/en/about',
'x-default': '/en/about',
},
},
}
}
```
HTML-Ausgabe:
```html
<link rel="alternate" hreflang="zh" href="https://example.com/zh/about" />
<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/about" />
```
Wichtig:
• Alle Sprachversionen inkl. aktueller Seite
• x-default auf Standardsprache
• Absolute URLs verwenden
Wie generiere ich eine mehrsprachige Sitemap?
```tsx
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = 'https://example.com'
const locale = params.locale
return [
{
url: `${baseUrl}/${locale}`,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
]
}
```
Methode 2: Sitemap-Index
```tsx
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const locales = ['zh', 'en']
const baseUrl = 'https://example.com'
return locales.flatMap(locale => [
{
url: `${baseUrl}/${locale}`,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
])
}
```
Wichtig:
• Alle Sprachversionen
• Korrektes URL-Format
• In Google Search Console einreichen
Empfehlung: Sitemap-Index für Flexibilität.
Welche URL-Strategie für mehrsprachige Websites?
Option 1: Unterverzeichnis (empfohlen)
• /zh/about, /en/about
• Einfach, SEO-freundlich
• Meiste Projekte
Option 2: Subdomain
• zh.example.com, en.example.com
• Mehr Domains, professioneller
• Große Projekte
Option 3: Cookie
• Sprache per Cookie, kein URL-Präfix
• SEO-unfreundlich – vermeiden
Empfehlung: Meiste Projekte → Unterverzeichnis.
Wichtig: hreflang-URLs müssen zur gewählten Strategie passen.
Wie validiere ich die Mehrsprach-SEO-Konfiguration?
1. Google Search Console:
• Mehrsprachige Sitemap einreichen
• hreflang prüfen
• Indexstatus überwachen
2. hreflang-Validator:
• https://www.aleydasolis.com/en/english-tools/international-seo-tools/hreflang-tags-validator/
3. Sitemap-Validierung:
• Format, alle Sprachen, korrekte URLs
Typische Fehler:
• Fehlende hreflang
• Falsches x-default
• Unvollständige Sitemap
• Inkonsistente URLs
Empfehlung: Nach Konfiguration sofort prüfen, regelmäßig Indexstatus kontrollieren.
Welche typischen Mehrsprach-SEO-Fehler gibt es?
1. Fehlende hreflang-Tags
• Suchmaschine kennt Sprache nicht
• Falsche Sprache in Ergebnissen
2. Falsches x-default
• Nicht gesetzt oder falsche Sprache
3. Unvollständige Sitemap
• Nur Teil der Sprachversionen eingereicht
4. Inkonsistente URL-Formate
• hreflang-URLs passen nicht zur Strategie
5. Duplicate Content
• hreflang fehlt – Sprachversionen gelten als Duplikate
Lösung:
• hreflang auf allen Seiten
• Alle Sprachversionen referenzieren
• Korrekte URLs und vollständige Sitemap
Best Practices aus diesem Artikel befolgen.
16 Min. Lesezeit · Veröffentlicht am: 25. Dez. 2025 · Aktualisiert am: 14. Juli 2026
Next.js Komplettleitfaden
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
Next.js Internationalisierung und statische Generierung: SSG-Mehrsprachen-Website in der Praxis
Vom Build-Fehler bis zur Performance-Optimierung: Schritt für Schritt mehrsprachige statische Generierung mit dem App Router – inkl. Codebeispielen, generateStaticParams und Build-Zeit-Tipps.
Teil 16 von 51
Nächster
Next.js API Routes – Komplettguide: Von Route Handlers bis zu Best Practices für Fehlerbehandlung
Komplettguide zu Next.js API Routes: Route Handlers erstellen, Requests verarbeiten, Fehlerbehandlung und Response-Design – damit Sie Backend-Schnittstellen mit Next.js sicher entwickeln.
Teil 18 von 51
Ähnliche Beiträge
Next.js App Router Einstieg: Kernkonzepte und Grundlagen im Überblick

Next.js App Router Einstieg: Kernkonzepte und Grundlagen im Überblick
Next.js 15 in der Praxis: Wie ich an einem Wochenende ein produktionsreifes Blog-System aufgebaut habe


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen