Internationalisierung (i18n) Routing
Beispiele
Next.js bietet seit v10.0.0
integrierte Unterstützung für internationalisiertes (i18n) Routing. Sie können eine Liste von Locales, die Standard-Locale und domainspezifische Locales angeben, und Next.js übernimmt automatisch das Routing.
Die i18n-Routing-Unterstützung soll derzeit bestehende i18n-Bibliotheken wie react-intl
, react-i18next
, lingui
, rosetta
, next-intl
, next-translate
, next-multilingual
, tolgee
und andere ergänzen, indem es die Routen und Locale-Parsing vereinfacht.
Erste Schritte
Um zu beginnen, fügen Sie die i18n
-Konfiguration zu Ihrer next.config.js
-Datei hinzu.
Locales sind UTS Locale Identifiers, ein standardisiertes Format zur Definition von Locales.
Ein Locale-Identifier besteht im Allgemeinen aus einer Sprache, Region und Schrift, getrennt durch einen Bindestrich: Sprache-Region-Schrift
. Region und Schrift sind optional. Ein Beispiel:
en-US
- Englisch, wie in den USA gesprochennl-NL
- Niederländisch, wie in den Niederlanden gesprochennl
- Niederländisch, ohne spezifische Region
Wenn die Benutzer-Locale nl-BE
ist und nicht in Ihrer Konfiguration aufgeführt ist, werden Benutzer zu nl
weitergeleitet, falls verfügbar, oder andernfalls zur Standard-Locale.
Wenn Sie nicht alle Regionen eines Landes unterstützen möchten, ist es daher eine gute Praxis, Landes-Locales als Fallback einzubeziehen.
module.exports = {
i18n: {
// Dies sind alle Locales, die Sie in Ihrer Anwendung unterstützen möchten
locales: ['en-US', 'fr', 'nl-NL'],
// Dies ist die Standard-Locale, die verwendet werden soll, wenn ein Pfad ohne Locale-Präfix besucht wird, z.B. `/hello`
defaultLocale: 'en-US',
// Dies ist eine Liste von Locale-Domains und der Standard-Locale, die sie verarbeiten sollen (nur erforderlich bei Domain-Routing)
// Hinweis: Subdomains müssen im Domain-Wert enthalten sein, um erkannt zu werden, z.B. "fr.example.com".
domains: [
{
domain: 'example.com',
defaultLocale: 'en-US',
},
{
domain: 'example.nl',
defaultLocale: 'nl-NL',
},
{
domain: 'example.fr',
defaultLocale: 'fr',
// Ein optionales http-Feld kann auch verwendet werden, um Locale-Domains lokal mit http statt https zu testen
http: true,
},
],
},
}
Locale-Strategien
Es gibt zwei Strategien zur Locale-Behandlung: Sub-path Routing und Domain Routing.
Sub-path Routing
Sub-path Routing platziert die Locale im URL-Pfad.
module.exports = {
i18n: {
locales: ['en-US', 'fr', 'nl-NL'],
defaultLocale: 'en-US',
},
}
Mit der obigen Konfiguration sind en-US
, fr
und nl-NL
für das Routing verfügbar, und en-US
ist die Standard-Locale. Wenn Sie eine pages/blog.js
haben, wären folgende URLs verfügbar:
/blog
/fr/blog
/nl-nl/blog
Die Standard-Locale hat kein Präfix.
Domain Routing
Mit Domain Routing können Sie Locales so konfigurieren, dass sie von verschiedenen Domains aus bereitgestellt werden:
module.exports = {
i18n: {
locales: ['en-US', 'fr', 'nl-NL', 'nl-BE'],
defaultLocale: 'en-US',
domains: [
{
// Hinweis: Subdomains müssen im Domain-Wert enthalten sein, um erkannt zu werden
// z.B. www.example.com sollte verwendet werden, wenn dies der erwartete Hostname ist
domain: 'example.com',
defaultLocale: 'en-US',
},
{
domain: 'example.fr',
defaultLocale: 'fr',
},
{
domain: 'example.nl',
defaultLocale: 'nl-NL',
// andere Locales angeben, die zu dieser Domain weitergeleitet werden sollen
locales: ['nl-BE'],
},
],
},
}
Wenn Sie beispielsweise pages/blog.js
haben, wären folgende URLs verfügbar:
example.com/blog
www.example.com/blog
example.fr/blog
example.nl/blog
example.nl/nl-BE/blog
Automatische Locale-Erkennung
Wenn ein Benutzer den Anwendungsstamm (normalerweise /
) besucht, versucht Next.js automatisch zu erkennen, welche Locale der Benutzer bevorzugt, basierend auf dem Accept-Language
-Header und der aktuellen Domain.
Wenn eine andere Locale als die Standard-Locale erkannt wird, wird der Benutzer weitergeleitet zu:
- Bei Sub-path Routing: Dem mit der Locale präfixierten Pfad
- Bei Domain Routing: Der Domain, die diese Locale als Standard festgelegt hat
Bei Domain Routing wird ein Benutzer mit dem Accept-Language
-Header fr;q=0.9
, der example.com
besucht, zu example.fr
weitergeleitet, da diese Domain standardmäßig die fr
-Locale behandelt.
Bei Sub-path Routing würde der Benutzer zu /fr
weitergeleitet werden.
Präfix für die Standard-Locale
Mit Next.js 12 und Middleware können wir der Standard-Locale mit einem Workaround ein Präfix hinzufügen.
Hier ist beispielsweise eine next.config.js
-Datei mit Unterstützung für einige Sprachen. Beachten Sie, dass die "default"
-Locale absichtlich hinzugefügt wurde.
module.exports = {
i18n: {
locales: ['default', 'en', 'de', 'fr'],
defaultLocale: 'default',
localeDetection: false,
},
trailingSlash: true,
}
Als Nächstes können wir Middleware verwenden, um benutzerdefinierte Routing-Regeln hinzuzufügen:
import { NextRequest, NextResponse } from 'next/server'
const PUBLIC_FILE = /\.(.*)$/
export async function middleware(req: NextRequest) {
if (
req.nextUrl.pathname.startsWith('/_next') ||
req.nextUrl.pathname.includes('/api/') ||
PUBLIC_FILE.test(req.nextUrl.pathname)
) {
return
}
if (req.nextUrl.locale === 'default') {
const locale = req.cookies.get('NEXT_LOCALE')?.value || 'en'
return NextResponse.redirect(
new URL(`/${locale}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url)
)
}
}
Diese Middleware überspringt das Hinzufügen des Standard-Präfix zu API-Routen und öffentlichen Dateien wie Schriftarten oder Bildern. Wenn eine Anfrage an die Standard-Locale gestellt wird, leiten wir zu unserem Präfix /en
weiter.
Deaktivierung der automatischen Locale-Erkennung
Die automatische Locale-Erkennung kann deaktiviert werden mit:
module.exports = {
i18n: {
localeDetection: false,
},
}
Wenn localeDetection
auf false
gesetzt ist, leitet Next.js nicht mehr automatisch basierend auf der bevorzugten Locale des Benutzers weiter und stellt nur Locale-Informationen bereit, die entweder von der Locale-basierten Domain oder dem Locale-Pfad erkannt werden, wie oben beschrieben.
Zugriff auf die Locale-Informationen
Sie können über den Next.js-Router auf die Locale-Informationen zugreifen. Beispielsweise sind mit dem useRouter()
-Hook folgende Eigenschaften verfügbar:
locale
enthält die aktuell aktive Locale.locales
enthält alle konfigurierten Locales.defaultLocale
enthält die konfigurierte Standard-Locale.
Wenn Seiten mit getStaticProps
oder getServerSideProps
vorgerendert werden, werden die Locale-Informationen im Kontext bereitgestellt, der der Funktion übergeben wird.
Bei Verwendung von getStaticPaths
werden die konfigurierten Locales im Kontextparameter der Funktion unter locales
und die konfigurierte defaultLocale
unter defaultLocale
bereitgestellt.
Wechsel zwischen Locales
Sie können next/link
oder next/router
verwenden, um zwischen Locales zu wechseln.
Für next/link
kann eine locale
-Prop bereitgestellt werden, um zu einer anderen Locale als der aktuell aktiven zu wechseln. Wenn keine locale
-Prop bereitgestellt wird, wird die aktuell aktive locale
während Client-Übergängen verwendet. Beispiel:
import Link from 'next/link'
export default function IndexPage(props) {
return (
<Link href="/another" locale="fr">
Zu /fr/another
</Link>
)
}
Bei direkter Verwendung der next/router
-Methoden können Sie die zu verwendende locale
über die Übergangsoptionen angeben. Beispiel:
import { useRouter } from 'next/router'
export default function IndexPage(props) {
const router = useRouter()
return (
<div
onClick={() => {
router.push('/another', '/another', { locale: 'fr' })
}}
>
zu /fr/another
</div>
)
}
Hinweis: Um nur die locale
zu ändern und gleichzeitig alle Routing-Informationen wie dynamische Routen-Query-Werte oder versteckte href-Query-Werte beizubehalten, können Sie den href
-Parameter als Objekt bereitstellen:
import { useRouter } from 'next/router'
const router = useRouter()
const { pathname, asPath, query } = router
// Nur die Locale ändern und alle anderen Routing-Informationen einschließlich der href-Query beibehalten
router.push({ pathname, query }, asPath, { locale: nextLocale })
Weitere Informationen zur Objektstruktur für router.push
finden Sie hier.
Wenn Sie einen href
haben, der bereits die Locale enthält, können Sie die automatische Handhabung des Locale-Präfixes deaktivieren:
import Link from 'next/link'
export default function IndexPage(props) {
return (
<Link href="/fr/another" locale={false}>
Zu /fr/another
</Link>
)
}
Nutzung des NEXT_LOCALE
-Cookies
Next.js unterstützt das Überschreiben des Accept-Language
-Headers mit einem NEXT_LOCALE=the-locale
-Cookie. Dieser Cookie kann mit einem Sprachumschalter gesetzt werden, und wenn ein Benutzer zurück zur Seite kommt, wird die im Cookie angegebene Locale verwendet, wenn von /
zum korrekten Locale-Ort weitergeleitet wird.
Wenn ein Benutzer beispielsweise die Locale fr
in seinem Accept-Language
-Header bevorzugt, aber ein NEXT_LOCALE=en
-Cookie gesetzt ist, wird der Benutzer beim Besuch von /
zur en
-Locale weitergeleitet, bis der Cookie entfernt oder abgelaufen ist.
Suchmaschinenoptimierung
Da Next.js weiß, welche Sprache der Benutzer besucht, wird automatisch das lang
-Attribut zum <html>
-Tag hinzugefügt.
Next.js kennt keine Varianten einer Seite, daher liegt es an Ihnen, die hreflang
-Meta-Tags mit next/head
hinzuzufügen. Weitere Informationen zu hreflang
finden Sie in der Google Webmasters-Dokumentation.
Wie funktioniert dies mit statischer Generierung?
Hinweis: Internationalisiertes Routing ist nicht mit
output: 'export'
integriert, da es nicht auf der Next.js-Routing-Ebene basiert. Hybride Next.js-Anwendungen, dieoutput: 'export'
nicht verwenden, werden vollständig unterstützt.
Dynamische Routen und getStaticProps
-Seiten
Für Seiten, die getStaticProps
mit dynamischen Routen verwenden, müssen alle gewünschten Locale-Varianten der Seite aus getStaticPaths
zurückgegeben werden. Neben dem params
-Objekt, das für paths
zurückgegeben wird, können Sie auch ein locale
-Feld zurückgeben, das angibt, welche Locale gerendert werden soll. Beispiel:
export const getStaticPaths = ({ locales }) => {
return {
paths: [
// Wenn keine `locale` angegeben ist, wird nur die defaultLocale generiert
{ params: { slug: 'post-1' }, locale: 'en-US' },
{ params: { slug: 'post-1' }, locale: 'fr' },
],
fallback: true,
}
}
Für automatisch statisch optimierte und nicht-dynamische getStaticProps
-Seiten wird eine Version der Seite für jede Locale generiert. Dies ist wichtig zu beachten, da es die Build-Zeiten erhöhen kann, abhängig davon, wie viele Locales in getStaticProps
konfiguriert sind.
Wenn Sie beispielsweise 50 Locales mit 10 nicht-dynamischen Seiten konfiguriert haben, die getStaticProps
verwenden, bedeutet dies, dass getStaticProps
500 Mal aufgerufen wird. Bei jedem Build werden 50 Versionen der 10 Seiten generiert.
Um die Build-Zeit für dynamische Seiten mit getStaticProps
zu verringern, verwenden Sie einen fallback
-Modus. Dadurch können Sie nur die beliebtesten Pfade und Locales aus getStaticPaths
für die Vorrendering während des Builds zurückgeben. Next.js generiert dann die restlichen Seiten zur Laufzeit, wenn sie angefordert werden.
Automatisch statisch optimierte Seiten
Für Seiten, die automatisch statisch optimiert werden, wird eine Version der Seite für jede Locale generiert.
Nicht-dynamische getStaticProps
-Seiten
Für nicht-dynamische getStaticProps
-Seiten wird wie oben eine Version für jede Locale generiert. getStaticProps
wird mit jeder Locale aufgerufen, die gerendert wird. Wenn Sie eine bestimmte Locale vom Pre-Rendering ausschließen möchten, können Sie notFound: true
aus getStaticProps
zurückgeben, und diese Variante der Seite wird nicht generiert.
export async function getStaticProps({ locale }) {
// Rufen Sie einen externen API-Endpunkt ab, um Beiträge zu erhalten.
// Sie können jede Datenabfragebibliothek verwenden
const res = await fetch(`https://.../posts?locale=${locale}`)
const posts = await res.json()
if (posts.length === 0) {
return {
notFound: true,
}
}
// Durch die Rückgabe von { props: posts } erhält die Blog-Komponente
// `posts` als Prop zum Build-Zeitpunkt
return {
props: {
posts,
},
}
}
Grenzen der i18n-Konfiguration
locales
: 100 Locales insgesamtdomains
: 100 Locale-Domain-Einträge insgesamt
Gut zu wissen: Diese Grenzen wurden zunächst hinzugefügt, um potenzielle Performance-Probleme beim Build zu vermeiden. Sie können diese Grenzen mit benutzerdefiniertem Routing unter Verwendung von Middleware in Next.js 12 umgehen.