Astro i18n Konfigurationsleitfaden: Mehrsprachige Website in 30 Minuten (inkl. Sprachumschalter)

Sie haben einen schönen Astro-Blog für den internationalen Markt vorbereitet – und stellen fest: Mehrsprachigkeit klappt nicht. locales, defaultLocale, prefixDefaultLocale wirken unverständlich, die Inhaltsorganisation ist unklar, Content Collections klingen abstrakt, und ein Sprachumschalter? Keine Ahnung, wo anfangen.
Astro i18n ist nicht so kompliziert – die offizielle Doku ist nur sehr technisch. Dieser Artikel führt Sie durch den gesamten Astro-i18n-Workflow: von der Basis-Konfiguration bis zum Sprachumschalter, mit vollständigem Code in jedem Schritt. In etwa 30 Minuten kann Ihre Website mehrere Sprachen bedienen.
Astro i18n Basis-Konfiguration (in 10 Minuten erledigt)
astro.config.mjs im Detail
Zuerst die wichtigste Datei – die Konfiguration. Ab Astro v4.0 ist i18n eingebaut und relativ einfach. Öffnen Sie astro.config.mjs und ergänzen Sie:
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
i18n: {
// Welche Sprachen Ihre Website unterstützt
locales: ['en', 'zh-cn', 'ja'],
// Standardsprache (muss in locales enthalten sein)
defaultLocale: 'en',
// Ob der Standardsprache ein URL-Präfix vorangestellt wird
prefixDefaultLocale: false,
}
});
Die einzelnen Optionen im Überblick:
locales – alle unterstützten Sprachen. Standard-Sprachcodes wie 'en' (Englisch), 'zh-cn' (vereinfachtes Chinesisch), 'ja' (Japanisch). Feinere Varianten sind möglich, z. B. 'en-US', 'en-GB'.
defaultLocale – die Sprache, die Besucher beim ersten Besuch sehen. Muss in der locales-Liste stehen, sonst meldet Astro einen Fehler.
prefixDefaultLocale – eine Option, über die viele lange nachdenken. Bei false hat die Standardsprache kein Sprachpräfix in der URL (z. B. /about), andere schon (/zh-cn/about, /ja/about). Bei true haben alle Sprachen ein Präfix (/en/about, /zh-cn/about).
In den meisten Fällen reicht false – die URL der Hauptsprache bleibt kurz. Bei starkem Fokus auf einheitliche URLs oder speziellen SEO-Anforderungen kann true sinnvoll sein.
Drei Routing-Strategien im Vergleich
Astro bietet drei i18n-Routing-Strategien. Die folgende Tabelle hilft bei der Wahl:
| Strategie | Konfiguration | URL-Beispiele | Einsatz | Vor- und Nachteile |
|---|---|---|---|---|
| Strategie 1: Standardsprache ohne Präfix | prefixDefaultLocale: false | /about/zh-cn/about/ja/about | Die meisten Websites (empfohlen) | ✅ Kurze URL für Standardsprache ❌ URLs nicht einheitlich formatiert |
| Strategie 2: Alle Sprachen mit Präfix | prefixDefaultLocale: true | /en/about/zh-cn/about/ja/about | Einheitliche URLs oder spezielle SEO-Anforderungen | ✅ Einheitliches URL-Schema ✅ Einfache Sprachumschalt-Logik ❌ Längere URL für Standardsprache |
| Strategie 3: Manueller Modus | routing: 'manual' | Vollständig anpassbar | Komplexe i18n-Anforderungen, volle Routing-Kontrolle | ✅ Sehr flexibel ❌ Aufwendige Konfiguration, viel eigene Logik nötig |
Für einfache Projekte (Blog, Dokumentation) reicht Strategie 1. Wer aufgeräumte URLs legt Wert, wählt Strategie 2. Strategie 3 eignet sich bei besonderen Anforderungen – z. B. dynamische Sprachwahl nach Nutzerverhalten oder verschiedene Sprachen auf Subdomains.
Für ein zweisprachiges Chinesisch-Englisch-Blog reicht es oft, die Konfiguration oben anzupassen: locales auf ['zh-cn', 'en'], defaultLocale auf 'zh-cn' (wenn Ihre Hauptzielgruppe chinesischsprachig ist) – fertig.
Astro i18n Mehrsprachigkeit konfigurieren
Vollständige Schritte zur mehrsprachigen Astro-Website in 30 Minuten
-
1
Step 1: astro.config.mjs konfigurieren
i18n in astro.config.mjs ergänzen: -
2
Step 2: Mehrsprachige Inhalte organisieren
Organisationsansatz wählen: -
3
Step 3: UI-Übersetzungswörterbuch anlegen
Übersetzungswörterbuch in src/i18n/ui.ts: -
4
Step 4: Sprachumschalter implementieren
Mit getRelativeLocaleUrl und Astro.currentLocale: -
5
Step 5: SEO optimieren
hreflang-Tags im Layout, Sitemap konfigurieren, Meta-Infos lokalisieren
Mehrsprachige Inhalte organisieren (zwei Ansätze)
Die Konfiguration steht – als Nächstes die Inhalte. Viele scheitern hier: Wo liegen die Dateien? Astro bietet zwei Wege.
Ansatz 1: Ordner pro Sprache (für Einsteiger empfohlen)
Der intuitivste Weg – pro Sprache ein Ordner:
src/pages/
├── about.astro # Standardsprache (z. B. Chinesisch)
├── blog.astro
├── index.astro
├── en/ # Englische Version
│ ├── about.astro
│ ├── blog.astro
│ └── index.astro
└── ja/ # Japanische Version
├── about.astro
├── blog.astro
└── index.astro
Bei prefixDefaultLocale: false liegen die Dateien der Standardsprache direkt unter pages/. Andere Sprachen bekommen Unterordner.
Vorteil: klare Struktur, Änderungen an einer Sprache beeinflussen andere nicht. Nachteil: bei vielen Seiten und Sprachen viel Duplikat – 20 Seiten × 5 Sprachen = 100 Dateien.
Ansatz 2: Dynamisches Routing (fortgeschritten empfohlen)
Weniger Dateien, eine Route für alle Sprachen:
src/pages/
└── [lang]/
└── [...slug].astro
In [...slug].astro Inhalt anhand von lang rendern:
---
// src/pages/[lang]/[...slug].astro
export function getStaticPaths() {
const locales = ['zh-cn', 'en', 'ja'];
const slugs = ['about', 'blog', 'contact'];
return locales.flatMap((lang) =>
slugs.map((slug) => ({
params: { lang, slug },
}))
);
}
const { lang, slug } = Astro.params;
// Inhalt anhand von lang und slug laden
---
Hohe Wiederverwendung, geringere Wartung – erfordert aber Verständnis für dynamisches Routing in Astro. Einsteiger starten besser mit Ansatz 1.
Content Collections für Mehrsprachigkeit (für Blogs unverzichtbar)
Für Blogs sind Content Collections zentral – Astros empfohlene Verwaltung für inhaltsstarke Sites.
Verzeichnisstruktur:
src/content/
└── blog/
├── en/
│ ├── post-1.md
│ └── post-2.md
├── zh-cn/
│ ├── post-1.md
│ └── post-2.md
└── ja/
├── post-1.md
└── post-2.md
Schema in src/content/config.ts:
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
schema: z.object({
title: z.string(),
author: z.string(),
date: z.date(),
lang: z.enum(['en', 'zh-cn', 'ja']), // Sprachfeld
}),
});
export const collections = {
blog: blogCollection,
};
Artikel der aktuellen Sprache laden:
---
// src/pages/blog/index.astro
import { getCollection } from 'astro:content';
const currentLang = Astro.currentLocale; // aktuelle Sprache
const posts = await getCollection('blog', ({ data }) => {
return data.lang === currentLang; // nur Artikel der aktuellen Sprache
});
---
So sehen Nutzer automatisch Artikel in ihrer gewählten Sprache. Die offizielle Astro-Doku nutzt diesen Ansatz – bewährt und zuverlässig.
UI-Übersetzungsdateien verwalten
Neben Inhalten brauchen Sie Übersetzungen für feste UI-Texte – Navigation, Buttons, Formularlabels. Ein zentrales Wörterbuch ist praktisch:
// src/i18n/ui.ts
export const ui = {
'en': {
'nav.home': 'Home',
'nav.about': 'About',
'nav.blog': 'Blog',
'btn.readMore': 'Read More',
},
'zh-cn': {
'nav.home': '首页',
'nav.about': '关于',
'nav.blog': '博客',
'btn.readMore': '阅读更多',
},
'ja': {
'nav.home': 'ホーム',
'nav.about': '概要',
'nav.blog': 'ブログ',
'btn.readMore': '続きを読む',
},
} as const;
Hilfsfunktionen:
// src/i18n/utils.ts
import { ui } from './ui';
// Sprache aus URL ermitteln
export function getLangFromUrl(url: URL) {
const [, lang] = url.pathname.split('/');
if (lang in ui) return lang as keyof typeof ui;
return 'zh-cn'; // Standardsprache
}
// Übersetzungsfunktion
export function useTranslations(lang: keyof typeof ui) {
return function t(key: keyof typeof ui[typeof lang]) {
return ui[lang][key] || ui['zh-cn'][key];
}
}
In Komponenten nutzen:
---
// Beispielkomponente
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
---
<nav>
<a href="/">{t('nav.home')}</a>
<a href="/about">{t('nav.about')}</a>
<a href="/blog">{t('nav.blog')}</a>
</nav>
Einfach und wartbar – alle UI-Übersetzungen an einem Ort. Bei sehr vielen Texten können Sie nach Modulen in mehrere JSON-Dateien aufteilen.
Sprachumschalter implementieren (mit vollständigem Code)
Konfiguration und Inhalte stehen – jetzt der Sprachumschalter. Mit den Astro-i18n-Helfern ist das überschaubar.
Astro-i18n-Helferfunktionen
getRelativeLocaleUrl(locale, path) – relativen Pfad für eine Sprache erzeugen.
import { getRelativeLocaleUrl } from 'astro:i18n';
// URL der englischen About-Seite
const url = getRelativeLocaleUrl('en', 'about');
// Ergebnis: '/en/about' oder '/about' (je nach Konfiguration)
getAbsoluteLocaleUrl(locale, path) – absolute URL inkl. Domain.
import { getAbsoluteLocaleUrl } from 'astro:i18n';
const url = getAbsoluteLocaleUrl('en', 'about');
// Ergebnis: 'https://example.com/en/about'
Astro.currentLocale – Sprache der aktuellen Seite.
---
const currentLang = Astro.currentLocale;
// z. B. 'zh-cn', 'en'
---
Astro.preferredLocale – bevorzugte Browsersprache (falls in locales unterstützt).
---
const browserLang = Astro.preferredLocale;
// Browsersprache, falls in locales enthalten
---
Sprachumschalt-Komponente
Eine einfache, direkt nutzbare Komponente:
---
// src/components/LanguageSwitcher.astro
import { getRelativeLocaleUrl } from 'astro:i18n';
// Unterstützte Sprachen (besser aus Config lesen; hier zur Demo fest codiert)
const locales = {
'zh-cn': '简体中文',
'en': 'English',
'ja': '日本語',
};
const currentLang = Astro.currentLocale || 'zh-cn';
const currentPath = Astro.url.pathname
.replace(`/${currentLang}/`, '/') // Sprachpräfix entfernen
.replace(/^\//, ''); // führenden Slash entfernen
---
<div class="language-switcher">
<button class="lang-button">
{locales[currentLang]} ▼
</button>
<div class="lang-dropdown">
{Object.entries(locales).map(([lang, label]) => {
const url = getRelativeLocaleUrl(lang, currentPath);
return (
<a
href={url}
class={lang === currentLang ? 'active' : ''}
>
{label}
</a>
);
})}
</div>
</div>
<style>
.language-switcher {
position: relative;
display: inline-block;
}
.lang-button {
padding: 8px 16px;
background: #f3f4f6;
border: 1px solid #d1d5db;
border-radius: 6px;
cursor: pointer;
}
.lang-button:hover {
background: #e5e7eb;
}
.lang-dropdown {
display: none;
position: absolute;
top: 100%;
right: 0;
margin-top: 4px;
background: white;
border: 1px solid #d1d5db;
border-radius: 6px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
min-width: 150px;
}
.language-switcher:hover .lang-dropdown {
display: block;
}
.lang-dropdown a {
display: block;
padding: 10px 16px;
color: #374151;
text-decoration: none;
transition: background 0.2s;
}
.lang-dropdown a:hover {
background: #f3f4f6;
}
.lang-dropdown a.active {
background: #dbeafe;
color: #1e40af;
font-weight: 500;
}
</style>
<script>
// Klick auf Mobilgeräten
document.querySelector('.lang-button')?.addEventListener('click', (e) => {
e.stopPropagation();
const dropdown = document.querySelector('.lang-dropdown');
dropdown?.classList.toggle('show');
});
document.addEventListener('click', () => {
document.querySelector('.lang-dropdown')?.classList.remove('show');
});
</script>
Im Layout oder in der Navigation einbinden:
---
// src/layouts/Layout.astro
import LanguageSwitcher from '@/components/LanguageSwitcher.astro';
---
<header>
<nav>
<!-- weitere Navigationspunkte -->
<LanguageSwitcher />
</nav>
</header>
Ablauf:
- Aktuelle Sprache und Pfad ermitteln
- URL für jede unterstützte Sprache erzeugen
- Aktuelle Sprache hervorheben
- Beim Klick zur entsprechenden Sprachversion wechseln
getRelativeLocaleUrl(lang, currentPath) sorgt dafür, dass Nutzer auf derselben Seite in einer anderen Sprache landen – nicht auf der Startseite.
Browser-Spracherkennung (optional, empfohlen)
Beim ersten Besuch zur Browsersprache weiterleiten – per Middleware:
// src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware((context, next) => {
const url = context.url;
const currentLocale = context.currentLocale;
const preferredLocale = context.preferredLocale;
// Root-Pfad: bei abweichender Browsersprache weiterleiten
if (url.pathname === '/' && preferredLocale && preferredLocale !== currentLocale) {
return context.redirect(`/${preferredLocale}/`);
}
return next();
});
Nicht bei jedem Besuch erzwingen – sonst überschreibt es manuelle Sprachwahl. Besser mit Cookie kombinieren:
// Verbesserte Middleware
export const onRequest = defineMiddleware((context, next) => {
const url = context.url;
const currentLocale = context.currentLocale;
const preferredLocale = context.preferredLocale;
const savedLang = context.cookies.get('user-lang')?.value;
// Gespeicherte Sprachpräferenz hat Vorrang
if (savedLang && savedLang !== currentLocale && url.pathname === '/') {
return context.redirect(`/${savedLang}/`);
}
// Sonst Browsersprache
if (!savedLang && url.pathname === '/' && preferredLocale && preferredLocale !== currentLocale) {
context.cookies.set('user-lang', preferredLocale, {
path: '/',
maxAge: 31536000, // 1 Jahr
});
return context.redirect(`/${preferredLocale}/`);
}
return next();
});
Beim Sprachwechsel Cookie setzen:
<script>
document.querySelectorAll('.lang-dropdown a').forEach((link) => {
link.addEventListener('click', (e) => {
const lang = e.target.getAttribute('data-lang');
document.cookie = `user-lang=${lang}; path=/; max-age=31536000`;
});
});
</script>
So bleibt die gewählte Sprache beim nächsten Besuch erhalten.
Fortgeschrittene Techniken (Fallback, Domain-Mapping, SEO)
Für einfache Projekte können Sie diesen Abschnitt überspringen und bei Bedarf zurückkommen.
Fallback-Strategie
Während der Übersetzung fehlen manche japanischen Seiten noch – Fallback zeigt stattdessen Englisch:
// astro.config.mjs
export default defineConfig({
i18n: {
locales: ['en', 'zh-cn', 'ja'],
defaultLocale: 'en',
fallback: {
ja: 'en', // Japanisch fehlt → Englisch
'zh-cn': 'en', // Chinesisch fehlt → Englisch
},
}
});
Existiert /ja/some-page nicht, liefert Astro /en/some-page statt 404 – praktisch während laufender Übersetzung.
Eigene Domain-Zuordnung
Manche Produkte nutzen Domains pro Sprache:
- Englisch:
example.com - Chinesisch:
example.cn - Japanisch:
example.jp
Astro unterstützt das – nur im SSR-Modus:
// astro.config.mjs
export default defineConfig({
output: 'server', // SSR erforderlich
adapter: node(), // Adapter konfigurieren
i18n: {
locales: ['en', 'zh-cn', 'ja'],
defaultLocale: 'en',
domains: {
'zh-cn': 'https://example.cn',
ja: 'https://example.jp',
},
}
});
Chinesische Inhalte landen auf example.cn, japanische auf example.jp. Im rein statischen Modus (Standard) ist Domain-Mapping nicht verfügbar.
SEO für mehrsprachige Sites
Suchmaschinen müssen wissen, welche Sprachversionen existieren – vor allem über hreflang.
Astro unterstützt i18n-SEO gut; einiges läuft automatisch. Folgendes sollten Sie manuell setzen:
1. hreflang-Tags im Layout
---
// src/layouts/Layout.astro
import { getAbsoluteLocaleUrl } from 'astro:i18n';
const locales = ['en', 'zh-cn', 'ja'];
const currentPath = Astro.url.pathname
.replace(/^\/(en|zh-cn|ja)\//, '')
.replace(/^\//, '');
---
<html>
<head>
{locales.map((lang) => (
<link
rel="alternate"
hreflang={lang}
href={getAbsoluteLocaleUrl(lang, currentPath)}
/>
))}
<link
rel="alternate"
hreflang="x-default"
href={getAbsoluteLocaleUrl('en', currentPath)}
/>
<meta name="description" content={description[currentLang]} />
<link rel="canonical" href={getAbsoluteLocaleUrl(currentLang, currentPath)} />
</head>
</html>
2. Mehrsprachige sitemap.xml
Mit @astrojs/sitemap wird pro Sprache eine Sitemap erzeugt – site in der Config setzen:
// astro.config.mjs
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://example.com', // erforderlich
integrations: [sitemap()],
});
3. Meta-Infos lokalisieren
title, description, keywords pro Sprache übersetzen:
---
const meta = {
'en': {
title: 'Welcome to My Blog',
description: 'A blog about web development',
},
'zh-cn': {
title: '欢迎来到我的博客',
description: '一个关于 Web 开发的博客',
},
};
const currentLang = Astro.currentLocale || 'en';
---
<head>
<title>{meta[currentLang].title}</title>
<meta name="description" content={meta[currentLang].description} />
</head>
Damit indexieren Suchmaschinen Ihre Sprachversionen korrekt.
Fazit
Kurz der Astro-i18n-Workflow im Überblick:
Schritt 1: astro.config.mjs (ca. 5 Minuten)
locales(unterstützte Sprachen)defaultLocale(Standardsprache)prefixDefaultLocalenach Bedarf
Schritt 2: Mehrsprachige Inhalte
- Einsteiger: Ordner pro Sprache
- Fortgeschritten: dynamisches Routing + Content Collections
- UI-Übersetzungswörterbuch nicht vergessen
Schritt 3: Sprachumschalter
getRelativeLocaleUrlfür URLsAstro.currentLocalefür die aktuelle Sprache- Optional: Browserspracherkennung und Cookie
Astro i18n ist in der Praxis angenehm: einfache Konfiguration, hilfreiche Helfer, gute Performance (Routen werden beim Build vorgeneriert). Für mehrsprachige Sites lohnt sich die eingebaute Lösung.
Legen Sie jetzt los und rüsten Sie Ihre Astro-Website auf Mehrsprachigkeit auf. Bei Fragen: offizielle Astro-i18n-Dokumentation mit detaillierter API-Referenz.
Erfahrungen oder Stolpersteine? Teilen Sie sie gerne in den Kommentaren – gemeinsam lernt es sich leichter.
FAQ
Wie lange dauert die Astro-i18n-Konfiguration?
• Einschließlich locales, defaultLocale und prefixDefaultLocale in astro.config.mjs
Eine vollständige mehrsprachige Website (inkl. Sprachumschalter und SEO) braucht etwa 30 Minuten.
Soll prefixDefaultLocale true oder false sein?
• Die URL der Standardsprache bleibt kurz (z. B. /about)
Bei einheitlichen URL-Formaten oder speziellen SEO-Anforderungen kann true sinnvoll sein (z. B. /en/about).
Wie organisiere ich mehrsprachige Inhalte?
Ansatz 1: Ordner pro Sprache (für Einsteiger empfohlen):
• Klare Struktur, aber mehr Dateien
Ansatz 2: Dynamisches Routing (für Fortgeschrittene empfohlen):
• Hohe Code-Wiederverwendung, geringere Wartungskosten
Für Blogs: Content Collections zur Verwaltung mehrsprachiger Artikel.
Wie implementiere ich einen Sprachumschalter?
Optional: Browser-Spracherkennung und Cookie zum Speichern der Sprachpräferenz – für bessere UX.
Wie optimiere ich SEO für mehrsprachige Websites?
• hreflang-Tags im Layout – Suchmaschinen über Sprachversionen informieren
• Sitemap-Plugin für automatische mehrsprachige Sitemap
• title, description und andere Meta-Infos lokalisieren
Astro unterstützt i18n-SEO gut – vieles läuft automatisch.
10 Min. Lesezeit · Veröffentlicht am: 2. Dez. 2025 · Aktualisiert am: 14. Juli 2026
Astro-Leitfaden
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
5 beste Astro-Blog-Themes mit Installations- und Konfigurationsanleitung
Schnell einen Blog starten, aber unsicher beim Theme? 5 praxiserprobte Astro-Blog-Themes (AstroPaper, Astro Air Blog u. a.) mit Installationsanleitung, FAQ und Lösungen – in 30 Minuten zum eigenen Blog.
Teil 5 von 18
Nächster
Astro-Website SEO: Vollständiger Leitfaden von Meta-Tags bis bessere Suchrankings
Schritt-für-Schritt-Anleitung zur vollständigen Astro-SEO-Konfiguration: Meta-Tags, Sitemap, robots.txt, JSON-LD-Strukturdaten. Kernsetup in 30 Minuten, bessere Google-Rankings – mit direkt nutzbaren Codebeispielen.
Teil 7 von 18
Ähnliche Beiträge
Was ist Astro? In 3 Minuten Zero JS, Islands Architecture und Content-First verstehen

Was ist Astro? In 3 Minuten Zero JS, Islands Architecture und Content-First verstehen
Astro-Blog von Grund auf: In 1 Stunde von der Startseite bis zum Deployment


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