StartseiteSandboxShowcaseAppDokumentBlog
    • EnglishEnglisch
      EN
    • РусскийRussisch
      RU
    • 日本語Japanisch
      JA
    • françaisFranzösisch
      FR
    • 한국어Koreanisch
      KO
    • 中文Chinesisch
      ZH
    • EspañolSpanisch
      ES
    • DeutschDeutsch
      DE
    • العربيةArabisch
      AR
    • ItalianoItalienisch
      IT
    • British EnglishEnglisch (Vereinigtes Königreich)
      EN-GB
    • PortuguêsPortugiesisch
      PT
    • हिन्दीHindi
      HI
    • TürkçeTürkisch
      TR
    • polskiPolnisch
      PL
    • IndonesiaIndonesisch
      ID
    • Tiếng ViệtVietnamesisch
      VI
    • УкраїнськаUkrainisch
      UK
    /
    Alt+←
    Was ist Internationalisierung (i18n)?
    SEO und i18n
    Leitfaden
    • i18n mit next-i18next
    • i18n mit next-intl
    Verwenden Sie Intlayer in Ihrer Lösung
    • Automatisieren next-i18next
    • Automatisieren react-i18next
    • Automatisieren next-intl
    • Automatisieren react-intl
    • Automatisieren vue-i18n
    Vergleiche
    • next-i18next vs next-intl vs Intlayer
    • react-i18next vs react-intl vs Intlayer
    Dokumentation
    1. Blog
    2. Blog seo i18n nextjs
    Creation:2025-09-28Last update:2025-09-28
    Referenzieren Sie diese Dokumentation mit Ihrem bevorzugten AI-Assistenten
    ChatGPT
    Claude
    DeepSeek
    Google AI mode
    Gemini
    Perplexity
    Mistral
    Grok

    Stellen Sie Ihre Frage und erhalten Sie einen Resümee des Dokuments, indem Sie diese Seite und den AI-Anbieter Ihrer Wahl referenzieren

    Der Inhalt dieser Seite wurde mit einer KI übersetzt.

    Den englischen Originaltext ansehen
    Edit this doc

    If you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.

    GitHub link to the documentation
    Copy

    Copy doc Markdown to clipboard

    SEO und i18n in Next.js: Übersetzen allein reicht nicht aus

    Wenn Entwickler an Internationalisierung (i18n) denken, ist der erste Reflex oft: den Inhalt übersetzen. Aber oft wird vergessen, dass das Hauptziel der Internationalisierung darin besteht, Ihre Website für die Welt sichtbarer zu machen. Wenn Ihre mehrsprachige Next.js-App Suchmaschinen nicht mitteilt, wie sie Ihre verschiedenen Sprachversionen crawlen und verstehen sollen, kann ein Großteil Ihrer Mühe unbemerkt bleiben.

    In diesem Blog werden wir untersuchen, warum i18n eine SEO-Superkraft ist und wie man es in Next.js mit next-intl, next-i18next und Intlayer korrekt implementiert.


    Warum SEO und i18n

    Sprachen hinzuzufügen bedeutet nicht nur bessere Benutzererfahrung (UX). Es ist auch ein mächtiger Hebel für organische Sichtbarkeit. Hier ist der Grund:

    1. Bessere Auffindbarkeit: Suchmaschinen indexieren lokalisierte Versionen und ranken sie für Nutzer, die in ihrer Muttersprache suchen.
    2. Vermeidung von doppeltem Inhalt: Korrekte Canonical- und Alternate-Tags informieren Crawler darüber, welche Seite zu welcher Sprachversion gehört.
    3. Bessere UX: Besucher landen sofort auf der richtigen Version Ihrer Website.
    4. Wettbewerbsvorteil: Nur wenige Websites setzen mehrsprachiges SEO gut um, was bedeutet, dass Sie sich abheben können.

    Best Practices für mehrsprachiges SEO in Next.js

    Hier ist eine Checkliste, die jede mehrsprachige App umsetzen sollte:

    • Setzen Sie hreflang Meta-Tags im <head>
      Hilft Google zu verstehen, welche Versionen für jede Sprache existieren.

    • Listen Sie alle übersetzten Seiten in der sitemap.xml auf
      Verwenden Sie das xhtml-Schema, damit Crawler Alternativen leicht finden können.

    • Schließen Sie private/lokalisierte Routen in der robots.txt aus
      z.B. sollten /dashboard, /fr/dashboard, /es/dashboard nicht indexiert werden.

    • Verwenden Sie lokalisierte Links
      Beispiel: <a href="/fr/about">À propos</a> anstelle eines Links zur Standardseite /about.

    Dies sind einfache Schritte – aber das Überspringen kann Sie Sichtbarkeit kosten.


    Implementierungsbeispiele

    Entwickler vergessen oft, ihre Seiten über verschiedene Sprachversionen hinweg korrekt zu referenzieren. Schauen wir uns daher an, wie dies in der Praxis mit verschiedenen Bibliotheken funktioniert.

    next-intl

    src/app/[locale]/about/layout.tsx
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import type { Metadata } from "next";import { locales, defaultLocale } from "@/i18n";import { getTranslations, unstable_setRequestLocale } from "next-intl/server";// Funktion zur Lokalisierung des Pfads basierend auf der Sprachefunction localizedPath(locale: string, path: string) {return locale === defaultLocale ? path : `/${locale}${path}`;}export async function generateMetadata({params,}: {params: { locale: string };}): Promise<Metadata> {const { locale } = params;const t = await getTranslations({ locale, namespace: "about" });const url = "/about";const languages = Object.fromEntries(  locales.map((l) => [l, localizedPath(l, url)]));return {  title: t("title"),  description: t("description"),  alternates: {    canonical: localizedPath(locale, url),    languages: { ...languages, "x-default": url },  },};}// ... Rest des Seiten-Codes
    src/app/sitemap.ts
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";const formatterLocalizedPath = (locale: string, path: string) =>locale === defaultLocale ? `${origin}${path}` : `${origin}/${locale}${path}`;export default function sitemap(): MetadataRoute.Sitemap {const aboutLanguages = Object.fromEntries(  locales.map((l) => [l, formatterLocalizedPath(l, "/about")]));return [  {    url: formatterLocalizedPath(defaultLocale, "/about"),    lastModified: new Date(),    changeFrequency: "monatlich", // Häufigkeit der Änderung    priority: 0.7,    alternates: { languages: aboutLanguages },  },];}
    src/app/robots.ts
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";const withAllLocales = (path: string) => [path,...locales.filter((l) => l !== defaultLocale).map((l) => `/${l}${path}`),];export default function robots(): MetadataRoute.Robots {const disallow = [  ...withAllLocales("/dashboard"),  ...withAllLocales("/admin"),];return {  rules: { userAgent: "*", allow: ["/"], disallow },  host: origin,  sitemap: `${origin}/sitemap.xml`,};}

    next-i18next

    i18n.config.ts
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    export const locales = ["en", "fr"] as const;export type Locale = (typeof locales)[number];export const defaultLocale: Locale = "en";/** Pfad mit Locale voranstellen, außer es ist die Standard-Locale */export function localizedPath(locale: string, path: string) {return locale === defaultLocale ? path : `/${locale}${path}`;}/** Absolute URL-Hilfe */const ORIGIN = "https://example.com";export function abs(locale: string, path: string) {return `${ORIGIN}${localizedPath(locale, path)}`;}
    src/app/[locale]/about/layout.tsx
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import type { Metadata } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n.config";export async function generateMetadata({params,}: {params: { locale: string };}): Promise<Metadata> {const { locale } = params;// Dynamisch die korrekte JSON-Datei importierenconst messages = (await import(`@/../public/locales/${locale}/about.json`))  .default;const languages = Object.fromEntries(  locales.map((l) => [l, localizedPath(l, "/about")]));return {  title: messages.title,  description: messages.description,  alternates: {    canonical: localizedPath(locale, "/about"),    languages: { ...languages, "x-default": "/about" },  },};}export default async function AboutPage() {return <h1>Über</h1>;}
    src/app/sitemap.ts
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import type { MetadataRoute } from "next";import { locales, defaultLocale, abs } from "@/i18n.config";export default function sitemap(): MetadataRoute.Sitemap {const languages = Object.fromEntries(  locales.map((l) => [l, abs(l, "/about")]));return [  {    url: abs(defaultLocale, "/about"),    lastModified: new Date(),    changeFrequency: "monatlich", // Häufigkeit der Änderung    priority: 0.7,    alternates: { languages },  },];}
    src/app/robots.ts
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import type { MetadataRoute } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n.config";const ORIGIN = "https://example.com";const expandAllLocales = (path: string) => [localizedPath(defaultLocale, path),...locales  .filter((l) => l !== defaultLocale)  .map((l) => localizedPath(l, path)),];export default function robots(): MetadataRoute.Robots {const disallow = [  ...expandAllLocales("/dashboard"),  ...expandAllLocales("/admin"),];return {  rules: { userAgent: "*", allow: ["/"], disallow },  host: ORIGIN,  sitemap: `${ORIGIN}/sitemap.xml`,};}

    Intlayer

    src/app/[locale]/about/layout.tsx
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import { getIntlayer, getMultilingualUrls } from "intlayer";import type { Metadata } from "next";import type { LocalPromiseParams } from "next-intlayer";export const generateMetadata = async ({params,}: LocalPromiseParams): Promise<Metadata> => {const { locale } = await params;const metadata = getIntlayer("page-metadata", locale);/** * Generiert ein Objekt, das alle URLs für jede Locale enthält. * * Beispiel: * ```ts *  getMultilingualUrls('/about'); * *  // Gibt zurück *  // { *  //   en: '/about', *  //   fr: '/fr/about', *  //   es: '/es/about', *  // } * ``` */const multilingualUrls = getMultilingualUrls("/about");return {  ...metadata,  alternates: {    canonical: multilingualUrls[locale as keyof typeof multilingualUrls],    languages: { ...multilingualUrls, "x-default": "/about" },  },};};// ... Rest des Seiten-Codes
    src/app/sitemap.ts
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const sitemap = (): MetadataRoute.Sitemap => [{  url: "https://example.com/about",  alternates: {    languages: { ...getMultilingualUrls("https://example.com/about") },  },},];
    src/app/robots.ts
    Code kopieren

    Kopieren Sie den Code in die Zwischenablage

    import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const getAllMultilingualUrls = (urls: string[]) =>urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const robots = (): MetadataRoute.Robots => ({rules: {  userAgent: "*",  allow: ["/"],  disallow: getAllMultilingualUrls(["/dashboard"]),},host: "https://example.com",sitemap: `https://example.com/sitemap.xml`,});export default robots;
    Intlayer stellt eine Funktion getMultilingualUrls zur Verfügung, um mehrsprachige URLs für Ihre Sitemap zu generieren.

    Fazit

    i18n in Next.js richtig umzusetzen bedeutet nicht nur, Texte zu übersetzen, sondern sicherzustellen, dass Suchmaschinen und Nutzer genau wissen, welche Version Ihrer Inhalte angezeigt werden soll. Die Einrichtung von hreflang, Sitemaps und Robots-Regeln verwandelt Übersetzungen in echten SEO-Wert.

    Während next-intl und next-i18next solide Möglichkeiten bieten, dies zu realisieren, erfordern sie meist viel manuelle Einrichtung, um die Konsistenz über verschiedene Sprachen hinweg zu gewährleisten.

    Hier zeigt Intlayer seine Stärken:

    Es bietet integrierte Helfer wie getMultilingualUrls, die die Integration von hreflang, Sitemap und Robots nahezu mühelos machen.

    Metadaten bleiben zentralisiert, anstatt über JSON-Dateien oder benutzerdefinierte Hilfsprogramme verstreut zu sein.

    Es ist von Grund auf für Next.js konzipiert, sodass Sie weniger Zeit mit der Fehlerbehebung der Konfiguration verbringen und mehr Zeit mit der Auslieferung.

    Wenn Ihr Ziel nicht nur die Übersetzung, sondern die reibungslose Skalierung von mehrsprachigem SEO ist, bietet Intlayer Ihnen die sauberste und zukunftssicherste Lösung.

    Was ist Internationalisierung (i18n)?
    Alt+→

    Auf dieser Seite

      Diskussionen sind anonym und werden regelmäßig überprüft, um häufige Probleme zu behandeln. Teilen Sie gerne Feature-Ideen, Feedback zur Dokumentation oder alles rund um Intlayer, wir nutzen diese Eingaben, um unsere Roadmap zu gestalten und das Produkt zu verbessern.

      import type { Metadata } from "next";import { locales, defaultLocale } from "@/i18n";import { getTranslations, unstable_setRequestLocale } from "next-intl/server";// Funktion zur Lokalisierung des Pfads basierend auf der Sprachefunction localizedPath(locale: string, path: string) {return locale === defaultLocale ? path : `/${locale}${path}`;}export async function generateMetadata({params,}: {params: { locale: string };}): Promise<Metadata> {const { locale } = params;const t = await getTranslations({ locale, namespace: "about" });const url = "/about";const languages = Object.fromEntries(  locales.map((l) => [l, localizedPath(l, url)]));return {  title: t("title"),  description: t("description"),  alternates: {    canonical: localizedPath(locale, url),    languages: { ...languages, "x-default": url },  },};}// ... Rest des Seiten-Codes
      import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";const formatterLocalizedPath = (locale: string, path: string) =>locale === defaultLocale ? `${origin}${path}` : `${origin}/${locale}${path}`;export default function sitemap(): MetadataRoute.Sitemap {const aboutLanguages = Object.fromEntries(  locales.map((l) => [l, formatterLocalizedPath(l, "/about")]));return [  {    url: formatterLocalizedPath(defaultLocale, "/about"),    lastModified: new Date(),    changeFrequency: "monatlich", // Häufigkeit der Änderung    priority: 0.7,    alternates: { languages: aboutLanguages },  },];}
      import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";const withAllLocales = (path: string) => [path,...locales.filter((l) => l !== defaultLocale).map((l) => `/${l}${path}`),];export default function robots(): MetadataRoute.Robots {const disallow = [  ...withAllLocales("/dashboard"),  ...withAllLocales("/admin"),];return {  rules: { userAgent: "*", allow: ["/"], disallow },  host: origin,  sitemap: `${origin}/sitemap.xml`,};}
      export const locales = ["en", "fr"] as const;export type Locale = (typeof locales)[number];export const defaultLocale: Locale = "en";/** Pfad mit Locale voranstellen, außer es ist die Standard-Locale */export function localizedPath(locale: string, path: string) {return locale === defaultLocale ? path : `/${locale}${path}`;}/** Absolute URL-Hilfe */const ORIGIN = "https://example.com";export function abs(locale: string, path: string) {return `${ORIGIN}${localizedPath(locale, path)}`;}
      import type { Metadata } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n.config";export async function generateMetadata({params,}: {params: { locale: string };}): Promise<Metadata> {const { locale } = params;// Dynamisch die korrekte JSON-Datei importierenconst messages = (await import(`@/../public/locales/${locale}/about.json`))  .default;const languages = Object.fromEntries(  locales.map((l) => [l, localizedPath(l, "/about")]));return {  title: messages.title,  description: messages.description,  alternates: {    canonical: localizedPath(locale, "/about"),    languages: { ...languages, "x-default": "/about" },  },};}export default async function AboutPage() {return <h1>Über</h1>;}
      import type { MetadataRoute } from "next";import { locales, defaultLocale, abs } from "@/i18n.config";export default function sitemap(): MetadataRoute.Sitemap {const languages = Object.fromEntries(  locales.map((l) => [l, abs(l, "/about")]));return [  {    url: abs(defaultLocale, "/about"),    lastModified: new Date(),    changeFrequency: "monatlich", // Häufigkeit der Änderung    priority: 0.7,    alternates: { languages },  },];}
      import type { MetadataRoute } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n.config";const ORIGIN = "https://example.com";const expandAllLocales = (path: string) => [localizedPath(defaultLocale, path),...locales  .filter((l) => l !== defaultLocale)  .map((l) => localizedPath(l, path)),];export default function robots(): MetadataRoute.Robots {const disallow = [  ...expandAllLocales("/dashboard"),  ...expandAllLocales("/admin"),];return {  rules: { userAgent: "*", allow: ["/"], disallow },  host: ORIGIN,  sitemap: `${ORIGIN}/sitemap.xml`,};}
      import { getIntlayer, getMultilingualUrls } from "intlayer";import type { Metadata } from "next";import type { LocalPromiseParams } from "next-intlayer";export const generateMetadata = async ({params,}: LocalPromiseParams): Promise<Metadata> => {const { locale } = await params;const metadata = getIntlayer("page-metadata", locale);/** * Generiert ein Objekt, das alle URLs für jede Locale enthält. * * Beispiel: * ```ts *  getMultilingualUrls('/about'); * *  // Gibt zurück *  // { *  //   en: '/about', *  //   fr: '/fr/about', *  //   es: '/es/about', *  // } * ``` */const multilingualUrls = getMultilingualUrls("/about");return {  ...metadata,  alternates: {    canonical: multilingualUrls[locale as keyof typeof multilingualUrls],    languages: { ...multilingualUrls, "x-default": "/about" },  },};};// ... Rest des Seiten-Codes
      import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const sitemap = (): MetadataRoute.Sitemap => [{  url: "https://example.com/about",  alternates: {    languages: { ...getMultilingualUrls("https://example.com/about") },  },},];
      import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const getAllMultilingualUrls = (urls: string[]) =>urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const robots = (): MetadataRoute.Robots => ({rules: {  userAgent: "*",  allow: ["/"],  disallow: getAllMultilingualUrls(["/dashboard"]),},host: "https://example.com",sitemap: `https://example.com/sitemap.xml`,});export default robots;