Internationalisierung (i18n) Routing
Beispiele
Next.js bietet seit Version v10.0.0
integrierte Unterstützung für internationalisiertes (i18n) Routing. Sie können eine Liste von Locales, das Standard-Locale und domainspezifische Locales bereitstellen, 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
, typesafe-i18n
, 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: language-region-script
. 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 das Benutzer-Locale nl-BE
ist und nicht in Ihrer Konfiguration aufgeführt ist, wird der Benutzer zu nl
weitergeleitet, falls verfügbar, oder andernfalls zum Standard-Locale.
Wenn Sie nicht alle Regionen eines Landes unterstützen möchten, ist es daher eine gute Praxis, Landes-Locales einzubeziehen, die als Fallback dienen.
module.exports = {
i18n: {
// Dies sind alle Locales, die Sie in Ihrer Anwendung unterstützen möchten
locales: ['en-US', 'fr', 'nl-NL'],
// Dies ist das Standard-Locale, das 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 das Standard-Locale, das sie verarbeiten sollen
// (nur erforderlich bei der Einrichtung von 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 das 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
verfügbar, und en-US
ist das Standard-Locale. Wenn Sie eine pages/blog.js
haben, wären folgende URLs verfügbar:
/blog
/fr/blog
/nl-nl/blog
Das Standard-Locale hat kein Präfix.
Domain Routing
Mit Domain Routing können Sie Locales von verschiedenen Domains aus bereitstellen:
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 Anwendungsroot (normalerweise /
) besucht, versucht Next.js automatisch zu erkennen, welches Locale der Benutzer bevorzugt, basierend auf dem Accept-Language
-Header und der aktuellen Domain.
Wenn ein anderes Locale als das Standard-Locale erkannt wird, wird der Benutzer weitergeleitet zu:
- Bei Sub-path Routing: Dem mit dem Locale präfixierten Pfad
- Bei Domain Routing: Der Domain, die dieses 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 das fr
-Locale bedient.
Bei Sub-path Routing würde der Benutzer zu /fr
weitergeleitet werden.
Präfix für das Standard-Locale
Mit Next.js 12 und Middleware können wir dem 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 das "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 das 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 dem 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 das aktuell aktive Locale.locales
enthält alle konfigurierten Locales.defaultLocale
enthält das konfigurierte Standard-Locale.
Wenn Seiten mit getStaticProps
oder getServerSideProps
pre-rendered 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 das 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 einem anderen Locale als dem aktuell aktiven zu wechseln. Wenn keine locale
-Prop bereitgestellt wird, wird das 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 das 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 das 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 das 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 das 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 das im Cookie angegebene Locale verwendet, wenn von /
zum korrekten Locale-Ort weitergeleitet wird.
Wenn ein Benutzer beispielsweise das Locale fr
in seinem Accept-Language-Header bevorzugt, aber ein NEXT_LOCALE=en
-Cookie gesetzt ist, wird der Benutzer beim Besuch von /
zum en
-Locale-Ort 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 Static Generation?
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, welches Locale gerendert werden soll. Beispiel:
export const getStaticPaths = ({ locales }) => {
return {
paths: [
// Wenn kein `locale` angegeben ist, wird nur das 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 jedes Locale generiert. Dies ist wichtig zu beachten, da es die Build-Zeiten erhöhen kann, je nachdem, 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. 50 Versionen der 10 Seiten werden während jedes Builds generiert.
Um die Build-Zeit dynamischer Seiten mit getStaticProps
zu verringern, verwenden Sie einen fallback
-Modus. Dies ermöglicht es Ihnen, nur die beliebtesten Pfade und Locales aus getStaticPaths
für das Pre-Rendering während des Builds zurückzugeben. Next.js baut dann die verbleibenden 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 jedes Locale generiert.
Nicht-dynamische getStaticProps
-Seiten
Für nicht-dynamische getStaticProps
-Seiten wird wie oben eine Version für jedes Locale generiert. getStaticProps
wird mit jedem Locale aufgerufen, das gerendert wird. Wenn Sie bestimmte Locales 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 auf, um Beiträge abzurufen.
// Sie können jede Datenabrufbibliothek 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 zur Build-Zeit
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 zur Build-Zeit zu vermeiden. Sie können diese Grenzen mit benutzerdefiniertem Routing unter Verwendung von Middleware in Next.js 12 umgehen.