Aufgrund von Fokus und Prioritäten können wir dieses Paket nicht mehr verwalten. Es erhält keine Updates, Fehlerbehebungen oder neue Funktionen und kann im Laufe der Zeit inkompatibel werden. Wir empfehlen, zu Paketen zu wechseln, die das neueste Next.js App -Verzeichnis unterstützen.
next-multilingual ist eine Meinung von End-to-End-Lösung für Next.js-Anwendungen ✱, für die mehrere Sprachen erforderlich sind.
Schauen Sie sich unsere Demo -App an!
✱ funktioniert next-multilingual mit? pages . Wir bügeln immer noch unsere Lösung, um die Neuen zu unterstützen? app -Verzeichnis Da die Internationalisierung nicht mehr Teil der Konfiguration von Next.js ist.
npm install next-multilingual
useMessages -Hook, der die Injektion von MessageFormat und JSX in der ICU unterstützt./en-us/contact-us für uns Englisch und /fr-ca/nous-joindre für kanadisches Französisch) ✱ . ✱ Ihre Standard-Gebietsschalen-Slugs müssen mit dem pages Verzeichnisdateisystem übereinstimmen (z. B. eine Schnecke für "Über uns" sollte sich in einem about-us -Verzeichnis befinden). Wenn das Standard -Gebietsschema, das Sie benötigen, Zeichen verwendet, die über die vom Dateisystem unterstützten Personen hinausgehen, wurde es nicht getestet und wird wahrscheinlich nicht funktionieren. Anfragen sind willkommen?
next-multilingual hat sich viel Mühe gegeben, Tsdoc zu allen APIs hinzuzufügen. Bitte überprüfen Sie direkt in Ihrer IDE, wenn Sie sich nicht sicher sind, wie bestimmte APIs in unseren Beispielen verwendet werden sollen.
Außerdem ist es keine leichte Aufgabe, eine Meinung zu "Best Practices" zu haben. Aus diesem Grund haben wir unsere Entwurfsentscheidungen in einem speziellen Dokument dokumentiert, das hier konsultiert werden kann. Wenn Sie der Meinung sind, dass einige unserer APIs nicht das anbieten, was Sie erwarten würden, konsultieren Sie dieses Dokument, bevor Sie ein Problem eröffnen.
Für diejenigen, die es vorziehen, direkt in die Aktion zu springen, suchen Sie im example nach einer End-to-End-Implementierung von next-multilingual . Für den Rest enthält der folgende Abschnitt einen vollständigen, Schritt -für -Schritt -Konfigurationshandbuch.
Es gibt viele Optionen, die Sie in Next.js konfigurieren können, um unsere Ziele zu erreichen. next-multilingual erinnert sich hauptsächlich um:
Wir bieten zwei APIs an, um diesen Schritt zu vereinfachen:
getConfig (einfache Konfiguration) Diese Funktion generiert eine Next.js -Konfiguration, die die meisten Anwendungsfälle entspricht. getConfig nimmt die folgenden Argumente ein:
applicationId - Die eindeutige Anwendungskennung, die als Meldungsschlüsselpräfix verwendet wird.locales - die Orte Ihrer Bewerbung.defaultLocale - Das Standardgebiet Ihrer Anwendung (es muss auch in locales enthalten sein)❗ Nur BCP 47 Sprach -Tags folgen der
language-countrywerden akzeptiert. Weitere Informationen zum Warum finden Sie im Dokument für Entwurfsentscheidungen.
options (optional) - Optionen Teil eines nächsten.js -Konfigurationsobjekts. getConfig gibt ein Next.js -Konfigurationsobjekt zurück.
Um es zu verwenden, fügen Sie einfach den folgenden Code in next.config.js Ihrer Anwendung hinzu.config.js:
const { getConfig } = require ( 'next-multilingual/config' )
const config = getConfig ( 'exampleApp' , [ 'en-US' , 'fr-CA' ] , 'en-US' , {
// Put your optional options below.
poweredByHeader : false ,
} )
module . exports = config Nicht alle Konfigurationsoptionen werden nicht durch getConfig unterstützt. Wenn Sie jemals eine verwenden, verweist Sie direkt auf den nächsten Abschnitt: Erweiterte Konfiguration.
Config (erweiterte Konfiguration) Wenn Sie fortgeschrittenere Anforderungen haben, können Sie das Config direkt verwenden und die Konfiguration einfügen, die von next-multilingual direkt in einem vorhandenen next.config.js erforderlich ist. Die Argumente der Config sind nahezu identisch mit getConfig (abzüglich der options ) - Details in Ihrer IDE (TSDOC) untersuchen. Hier ist ein Beispiel dafür, wie es verwendet werden kann:
const { Config , webpackConfigurationHandler } = require ( 'next-multilingual/config' )
const config = new Config ( 'exampleApp' , [ 'en-US' , 'fr-CA' ] , 'en-US' )
module . exports = {
reactStrictMode : true ,
i18n : {
locales : config . getUrlLocalePrefixes ( ) ,
defaultLocale : config . getDefaultUrlLocalePrefix ( ) ,
localeDetection : false ,
} ,
poweredByHeader : false ,
webpack : webpackConfigurationHandler ,
}Wenn Sie Ihre eigene Webpack -Konfiguration anpassen müssen, empfehlen wir, unseren Handler wie folgt zu erweitern:
import Webpack from 'webpack'
import { webpackConfigurationHandler , WebpackContext } from 'next-multilingual/config'
export const myWebpackConfigurationHandler = (
config : Webpack . Configuration ,
context : WebpackContext
) : Webpack . Configuration => {
const myConfig = webpackConfigurationHandler ( config , context )
// Do stuff here.
return myConfig
} Oder direkt in next.config.js :
// Webpack handler wrapping next-multilingual's handler.
const webpack = ( config , context ) => {
config = webpackConfigurationHandler ( config , context )
// Do stuff here.
return config
} next-multilingual/config führt 2 Dinge durch, die Next.JS 'aktuelle Routing-Fähigkeit nutzen:
next-multilingual/config übernimmt außerdem die spezielle Webpack-Konfiguration, die für die Server-Seite von lokalisierten URLs erforderlich ist, indem sie next-multilingual/link/ssr für Link und next-multilingual/head/ssr für kanonische und alternative Links in der Head für kanonische und alternative Links erhalten.
Weitere Informationen zur Implementierung, z. B. warum wir UTF-8-Zeichen verwenden, finden Sie im Dokument für Entwurfsentscheidungen.
next-multilingual/messages/babel-plugin Um lokalisierte Nachrichten mit dem useMessages() Hook anzuzeigen, müssen wir unser benutzerdefiniertes Babel -Plugin konfigurieren, das automatisch Zeichenfolgen in Seiten und Komponenten injiziert. Die empfohlene Möglichkeit, dies zu tun, besteht darin, einen .babelrc am Fuße Ihrer Bewerbung aufzunehmen:
{
"presets" : [ " next/babel " ],
"plugins" : [ " next-multilingual/messages/babel-plugin " ]
} Wenn Sie das Plugin nicht konfigurieren, erhalten Sie einen Fehler, wenn Sie versuchen, useMessages zu verwenden.
App ( _app.tsx ) Wir müssen eine benutzerdefinierte App erstellen, indem wir _app.tsx im pages -Verzeichnis hinzufügen:
import { useActualLocale } from 'next-multilingual'
import type { AppProps } from 'next/app'
const ExampleApp : React . FC < AppProps > = ( { Component , pageProps } ) => {
useActualLocale ( ) // Forces Next.js to use the actual (proper) locale.
return < Component { ... pageProps } / >
}
export default ExampleAppDies macht im Grunde zwei Dinge, wie in den Kommentaren erwähnt:
/ ) treffen. Wenn Sie nicht die Erkennung von next-multilingual -Gebietsschema verwenden möchten, können Sie stattdessen useActualLocale(false) verwenden.Document ( _document.tsx ) Wir müssen auch ein benutzerdefiniertes Document erstellen, indem wir _document.tsx im pages hinzufügen:
import { getHtmlLang } from 'next-multilingual'
import { DocumentProps , Head , Html , Main , NextScript } from 'next/document'
const Document : React . FC < DocumentProps > = ( documentProps ) => {
return (
< Html lang = { getHtmlLang ( documentProps ) } translate = "no" className = "notranslate" >
< Head >
< meta name = "google" content = "notranslate" / >
< / Head >
< body >
< Main / >
< NextScript / >
< / body >
< / Html >
)
}
export default Document Dies dient nur 1 Zweck: Zeigen Sie das richtige Server -Seiten -Gebietsschema im <html> -Tag an. Da wir ein "gefälschtes" Standardgebietsschema verwenden, ist es wichtig, das richtige SSR -Aufschlag zu halten, insbesondere wenn ein dynamisches Gebietsschema auf / auflöst.
next-multilingual/head bietet eine <Head> -Komponente, die automatisch einen kanonischen Link und alternative Links im Header erstellt. Dies ist etwas, das von Next.js.
NEXT_PUBLIC_ORIGIN hinzu Laut Google müssen alternative Links vollständig qualifiziert sein, einschließlich der Transportmethode (HTTP/HTTPS). Da Next.js nicht weiß, welche URL zum Zeitpunkt der Erstellung verwendet wird, müssen wir die absolute URL in einer Umgebungsvariablen angeben. Erstellen Sie beispielsweise für die Entwicklungsumgebung eine .env.development -Datei zum Stamm Ihrer Anwendung mit der folgenden Variablen (basierend auf Ihrem Setup anpassen):
NEXT_PUBLIC_ORIGIN =http://localhost:3000 Unabhängig von der Umgebung sucht next-multilingual eine Variable namens NEXT_PUBLIC_ORIGIN , um vollqualifizierte URLs zu generieren. Wenn Sie basePath von Next.js verwenden, wird es automatisch zur Basis -URL hinzugefügt.
NEXT_PUBLIC_ORIGIN akzeptiert nur vollständig qualifizierte Domänen (z. B. http://example.com ) ohne Wege.
next-multilingual ? Jetzt, da alles konfiguriert wurde, können wir uns darauf konzentrieren, als next-multilingual aufzutragen!
Um next-multilingual zu arbeiten, um wie entworfen zu arbeiten, mussten wir Lösungen für 2 Probleme finden:
undefined Werte: Da Next.js Websites ohne Orte unterstützt, ermöglichen die nativen Typen undefined Werte, die für unseren Fall eher ein Ärger sind und zusätzliches Casting erfordert.next-multilingual ein Standard-Gebietsschema erstellen, das wir nie verwenden. Dies bedeutet, dass wir uns nicht auf die APIs von Next.js verlassen können.Wir haben die folgenden APIs erstellt, um konsistente Lokalwerte in Ihrer Anwendung zu ermöglichen:
useRouter Dies ist ein einfacher Wrapper auf useRouter von NEXT.JS, der beide die richtigen Orte bietet, aber auch nie undefined zurückgibt.
import { NextPage } from 'next'
import { useRouter } from 'next-multilingual/router'
const Page : NextPage = ( ) => {
const router = useRouter ( )
return < > { router . locale } < / >
}
export default Page getStaticPropsLocales import { getStaticPropsLocales } from 'next-multilingual'
export const getStaticProps : GetStaticProps = async ( context ) => {
const { locale , locales , defaultLocale } = getStaticPropsLocales ( context )
// do stuff
return { props : { } }
} getStaticPathsLocales import { getStaticPathsLocales } from 'next-multilingual'
export const getStaticPaths : GetStaticProps = async ( context ) => {
const { locales , defaultLocale } = getStaticPathsLocales ( context )
// do stuff
return { props : { } }
} getServerSidePropsLocales import { getServerSidePropsLocales } from 'next-multilingual'
export const getServerSideProps : GetServerSideProps = async ( context ) => {
const { locale , locales , defaultLocale } = getServerSidePropsLocales ( context )
// do stuff
return { props : { } }
}
Euen Beachten Sie, dass wir zwar empfehlen, die Erkennung intelligenter Gebietsschema zu verwenden, um die Homepage dynamisch zu rendern, dies jedoch vollständig optional ist. Durch die Verwendung einer erweiterten Konfiguration mitlocaleDetection: truewerden Sie das Verhalten von Standard.JS -Verhalten wiederherstellen, ohne dassgetServerSidePropsverwendet werden muss.
Die Homepage ist etwas komplexer als andere Seiten, da wir aus dem folgenden Grund eine dynamische Erkennung von Gebietsschema (und Anzeigen) implementieren müssen:
/ kann sich negativ auf die SEO auswirken und ist nicht die beste Benutzererfahrung.next-multilingual verfügt über eine getPreferredLocale -API, die eine intelligentere automatische Erkennung anbietet als die Standard-Implementierung von Standard.js.Im Beispiel finden Sie eine vollständige Implementierung, aber hier ist eine abgespeckte Version:
import type { GetServerSideProps , NextPage } from 'next'
import { ResolvedLocaleServerSideProps , resolveLocale , useResolvedLocale } from 'next-multilingual'
import { useRouter } from 'next-multilingual/router'
const Homepage : NextPage < ResolvedLocaleServerSideProps > = ( { resolvedLocale } ) => {
// Force Next.js to use a locale that was resolved dynamically on the homepage (this must be the first action on the homepage).
useResolvedLocale ( resolvedLocale )
const { locale } = useRouter ( )
return < h1 > { locale } </ h1 >
}
export default Homepage
export const getServerSideProps : GetServerSideProps < ResolvedLocaleServerSideProps > = async (
context
) => {
return {
props : {
resolvedLocale : resolveLocale ( context ) ,
} ,
}
}Kurz gesagt, das passiert:
next-multilingual erhältlich ist.useResolvedLocale , um diese Dynamik in der Anwendung zu machen. Jedes Mal, wenn Sie eine tsx , ts , jsx oder js -Datei (kompilierbar) erstellen und lokalisierte Nachrichten benötigen, können Sie einfach eine Nachrichtendatei in Ihren unterstützten Orten erstellen, die nur von diesen Dateien verwendet werden können. Genau wie bei den CSS -Modulen können Sie Nachrichtendateien mit dem lokalen Bereich einer anderen Datei zugeordnet haben. Dies hat den Vorteil, dass Nachrichten modularer gestaltet werden, und vermeidet auch, dass Nachrichten über verschiedene Kontexte hinweg freigegeben werden (weitere Details im Entwurfsentscheidungen dokumentieren, warum dies schlecht ist).
Nachrichtendateien haben 2 Hauptanwendungsfälle:
pages können Sie ein lokalisiertes URL -Segment (Teil einer URL zwischen / oder am Ende des Pfades) unter Verwendung der slug -Kenner angeben. Weitere Details dazu unten.useMessages Hook verfügbar sein. Stellen Sie sich CSS vor, aber für lokalisierbare Saiten.Zusammenfassen:
Das Erstellen und Verwalten dieser Dateien ist so einfach wie das Erstellen eines Stilblatts, aber hier sind die wichtigen Details:
.properties -Dateien. Ja, Sie fragen sich vielleicht warum, aber es gibt gute Gründe, die im Entwurfsentscheidungsdokument dokumentiert sind.UTF-8 festgelegt ist. Dies ersetzt Nicht-Latin-Zeichen durch �.properties Dateien zu nutzen, folgen wir einer strikten Namenskonvention: <PageFilename>.<locale>.properties<applicationId>.<context>.<id> Wobei:next-multilingual/config festgelegtfooterComponent der aboutUsPage zugeordnet ist, z. Jede Datei kann nur 1 Kontext enthalten und der Kontext sollte nicht in vielen Dateien verwendet werden, da dies zu einer "Schlüsselkollision" (nicht eindeutige Schlüssel) führen kann.. und kann nur zwischen 1 und 50 alphanumerischen Zeichen enthalten - wir empfehlen, Camel -Fall für die Lesbarkeit zu verwenden.slug -Kennung einfügen.title einen Schlüssel hinzu.getTitle API, die in next-multilingual/messages bereitgestellt wird, um automatisch zwischen dem title und slug Tasten zu fallen.useMessages -Hook verwenden.Überprüfen Sie außerdem Ihr Konsolenprotokoll auf Warnungen vor potenziellen Problemen mit Ihren Nachrichten. Es kann schwierig sein, sich daran zu gewöhnen, wie es zuerst funktioniert, aber wir haben versucht, Probleme zu erkennen und zu beheben. Beachten Sie, dass diese Protokolle nur in Nichtproduktionsumgebungen angezeigt werden.
Es ist nicht ungewöhnlich, lokalisierte Nachrichten zu benötigen, ohne Hooks zu verwenden. Ein Beispiel wäre die Verwendung eines der Kernfunktionen von Next.js ist die gebaute API -Unterstützung. In diesem Zusammenhang können wir, anstatt useMessage zu verwenden, einfach getMessages verwenden, während wir das Argument locale angeben.
Wie bereits erwähnt, gibt es einen speziellen Schlüssel für pages , bei denen die id der slug ist. Im Gegensatz zu herkömmlichen Schlägen, die wie this-is-a-page aussehen, bitten wir Sie, die Schnecke als normalen und menschlichen lesbaren Satz zu schreiben, damit er wie jede andere Zeichenfolge übersetzt werden kann. Dies vermeidet spezielle Prozesse für Schnecken, die in mehreren Sprachen kostspielig und komplex sein können.
Grundsätzlich ist die slug die menschliche lesbare "kurze Beschreibung" Ihrer Seite und stellt ein Segment (Teil zwischen / oder am Ende des Pfades) einer URL dar. Bei Verwendung als URL -Segment wird die folgende Transformation angewendet:
- ersetzt - Zum Beispiel werden About Us about-us hinaus.
Für die Homepage wird die URL immer / was bedeutet, dass slug -Tasten nicht verwendet werden, um lokalisierte URL -Segmente zu erstellen.
Vergessen Sie nicht, dass die Schnecken als normale kurze Beschreibung geschrieben werden müssen, was bedeutet, dass das Überspringen von Wörtern, damit es für SEO kürzer ist, entmutigt wird. Der Hauptgrund dafür ist, dass ein Linguist, der mit SEO nicht vertraut ist, diese Nachricht möglicherweise schwer zu übersetzen kann, wenn Sie "eine Reihe von Schlüsselwörtern" schreiben. SEO -Spezialisten in vielen Sprachen zu haben, wäre auch sehr kostspielig und schwierig zu skalieren. In einem idealen Szenario sollten marktspezifische SEO-Seiten wahrscheinlich in den Muttersprachen verfasst und optimiert werden, dies ist jedoch nicht mehr Teil des Übersetzungsprozesses. Der Schwerpunkt von next-multilingual liegt auf einer einfachen, optimierten Lösung zur Lokalisierung von URLs in vielen Sprachen.
Der slug -Schlüssel wird auch als Fallback des title verwendet, wenn die getTitle -API in next-multilingual/messages bereitgestellt wird. Diese API erleichtert es einfach, Titel anzupassen, wenn sich eine Schnecke nicht ausreicht.
Euen Beachten Sie, dass sich die Änderung einesslugbedeutet, dass sich eine URL ändert. Da diese Änderungen innext.config.jsvorliegen, wie bei jeder nächsten Änderung der Konfiguration, muss der Server neu gestartet werden, um die Änderungen zu erkennen. Gleiches gilt, wenn Sie die Ordnerstruktur ändern, da die zugrunde liegende Konfiguration darauf abhängt.
Wenn Sie ein Verzeichnis ohne Seiten haben möchten, können Sie es dennoch lokalisieren locale indem Sie einen index.<locale>.properties Obwohl diese Option unterstützt wird, empfehlen wir nicht, sie zu verwenden, da sie URL -Pfade länger macht, was gegen die Best Practice der SEO verstößt.
Standardmäßig schließt next-multilingual einige Dateien wie benutzerdefinierte Fehlerseiten oder API-Routen im Verzeichnis /api aus. Sie können immer slug -Tasten verwenden, wenn Sie Nachrichten für diese Dateien verwenden, sie werden jedoch nicht zum Erstellen lokalisierter URLs verwendet.
Sie können immer das Beispiel untersuchen, um Nachrichtendateien in Aktion anzuzeigen. Hier ist jedoch ein Beispiel, das auf der Homepage verwendet werden kann:
# Homepage title
exampleApp.homepage.title = Homepage
# Homepage headline
exampleApp.homepage.headline = Welcome to the homepage Nachdem wir nun gelernt haben, wie man die Homepage und einige Details darüber erstellt, wie die Dinge funktionieren, können wir problemlos andere Seiten erstellen. Wir erstellen viele Seiten im Beispiel, aber hier ist ein Beispiel davon, wie about-us.jsx aussehen könnte:
import { NextPage } from 'next'
import { getTitle , useMessages } from 'next-multilingual/messages'
import Layout from '@/layout'
import styles from './index.module.css'
const AboutUs : NextPage = ( ) => {
const messages = useMessages ( )
const title = getTitle ( messages )
return (
< Layout title = { title } >
< h1 className = { styles . headline } > { title } </ h1 >
< p > { messages . format ( 'details' ) } </ p >
</ Layout >
)
}
export default AboutUs Und natürlich hätten Sie diese Nachrichtendatei about-us.en-US.properties :
# Page localized URL segment (slug) in (translatable) human readable format.
# This key will be "slugified" (e.g, "About Us" will become "about-us"). All non-alphanumeric characters will be replaced by "-".
exampleApp.aboutUsPage.slug = About Us
# Page details.
exampleApp.aboutUsPage.details = This is just some english boilerplate text. next-multilingual verfügt über eine eigene <Link> -Komponente, mit der die Client-Seite und die Serverseite der lokalisierten URL rendern können. Die Verwendung ist einfach, es funktioniert genau wie Next.js ' <Link> .
Das einzig Wichtigste, an das Sie sich erinnern sollten, ist, dass das href -Attribut immer die nächste.JS -URL enthalten sollte. Das heißt, die Dateistruktur im Ordner der pages sollte das verwendet werden, was verwendet wird, und nicht die lokalisierten Versionen.
Mit anderen Worten, die Dateistruktur wird als "nicht lokalisierte" URL-Darstellung angesehen, und <Link> kümmert sich um das Ersetzen der URLs durch die lokalisierten Versionen (aus den Nachrichtendateien), wenn sie sich von der Struktur unterscheiden.
Die API ist unter next-multilingual/link verfügbar und Sie können sie so verwenden:
import Link from 'next-multilingual/link'
import { useMessages } from 'next-multilingual/messages'
const Menu : React . FC = ( ) => {
const messages = useMessages ( )
return (
< nav >
< Link href = "/" >
< a > { messages . format ( 'home' ) } </ a >
</ Link >
< Link href = "/about-us" >
< a > { messages . format ( 'aboutUs' ) } </ a >
</ Link >
< Link href = "/contact-us" >
< a > { messages . format ( 'contactUs' ) } </ a >
</ Link >
</ nav >
)
}
export default Menu Jede dieser Links wird automatisch lokalisiert, wenn die slug -Taste in der Nachrichtendatei dieser Seite angegeben ist. Zum Beispiel ist in US-Englisch den "Kontakt uns" -RURL-Pfad /en-us/contact-us /fr-ca/nous-joindre es in kanadischem Französisch es ist.
Da die Daten für diese Zuordnung während des Renders nicht sofort verfügbar sind, kümmert sich next-multilingual/link/ssr um das Server-Side-Rendering (SSR). Durch die Nutzung von getConfig von next-multilingual/config wird die Webpack-Konfiguration automatisch hinzugefügt. Wenn Sie die erweiterte Config verwenden, wird erläutert, warum die spezielle Webpack -Konfiguration in dem vorgesehenen Beispiel vorgelegt ist.
Nicht alle lokalisierten URLs verwenden die <Link> -Komponente, und dies ist auch der Grund, warum Next.js die Methode für router.push -Methoden hat, die von vielen anderen Anwendungsfällen verwendet werden kann. next-multilingual kann diese Anwendungsfälle mit dem useLocalizedUrl Haken unterstützen, der eine lokalisierte URL zurückgibt, die von Komponenten verwendet werden kann. Hier ist ein Beispiel, wie es genutzt werden kann:
import { NextPage } from 'next'
import { useMessages } from 'next-multilingual/messages'
import { useLocalizedUrl } from 'next-multilingual/url'
import router from 'next/router'
const Tests : NextPage = ( ) => {
const messages = useMessages ( )
const localizedUrl = useLocalizedUrl ( '/about-us' )
return < button onClick = { ( ) => router . push ( localizedUrl ) } > { messages . format ( 'clickMe' ) } </ button >
}
export default Tests Wenn Sie es vorziehen, Ihre URLs -Inline zu definieren, anstatt an der Spitze der Komponente, oder wenn Sie fortgeschrittenere URL -Manipulationen durchführen müssen, können Sie auch den useGetLocalizedUrl -Hook verwenden, der eine Funktion zurückgibt, um URLs zu erhalten:
import { NextPage } from 'next'
import { useMessages } from 'next-multilingual/messages'
import { useGetLocalizedUrl } from 'next-multilingual/url'
import router from 'next/router'
const Tests : NextPage = ( ) => {
const messages = useMessages ( )
const { getLocalizedUrl } = useGetLocalizedUrl ( )
return (
< button onClick = { ( ) => router . push ( getLocalizedUrl ( '/about-us' ) ) } >
{ messages . format ( 'clickMe' ) }
</ button >
)
}
export default TestsSeien Sie vorsichtig, wenn Sie den Stringwert der URL in React-Elementen verwenden möchten, haben Sie Fehler, da sich die URLs zwischen Vorrendern und Browser unterscheiden. Der Grund dafür ist, dass bei dem Client bei First Render.js auf dem Client keinen Zugriff auf die Umschreibungsdaten hat und daher "semi-lokalisierte" URL-Pfade (z. B.
/fr-ca/about-us) verwendet. Da dies ein natives Verhalten von Next.js ist, besteht der einfachste Weg, dies vorerst umzuarbeiten, indem Sie Ihr ElementsuppressHydrationWarning={true}. Um dies zu umgehen, gibtuseGetLocalizedUrlauch eineisLoading-Eigenschaft zurück, mit der die lokalisierten URLs für den Client verfügbar sind.
Möglicherweise stoßen Sie auf eine Situation, in der Sie auch eine lokalisierte URL erhalten müssen, aber die Verwendung eines Hakens ist keine Option. Hier kommt getLocalizedUrl in next-multilingual/url ins Spiel. Es fungiert genauso wie useLocalizedUrl , aber sein Argument locale ist obligatorisch.
Stellen Sie sich vor, Sie verwenden die API von Next.js, um Transaktions-E-Mails zu senden und die lokalisierten URLs von next-multilingual zu nutzen, ohne sie in einer Konfiguration festzuhalten. Hier ist ein Beispiel dafür, wie es verwendet werden kann:
import type { NextApiRequest , NextApiResponse } from 'next'
import { isLocale } from 'next-multilingual'
import { getMessages } from 'next-multilingual/messages'
import { getLocalizedUrl } from 'next-multilingual/url'
import { sendEmail } from 'send-email'
/**
* The "/api/send-email" handler.
*/
const handler = ( request : NextApiRequest , response : NextApiResponse ) : Promise < void > => {
const locale = request . headers [ 'accept-language' ]
let emailAddress = ''
try {
emailAddress = JSON . parse ( request . body ) . emailAddress
} catch ( error ) {
response . status ( 400 )
return
}
if ( locale === undefined || ! isLocale ( locale ) || ! emailAddress . length ) {
response . status ( 400 )
return
}
const messages = getMessages ( locale )
sendEmail (
emailAddress ,
messages . format ( 'welcome' , { loginUrl : await getLocalizedUrl ( '/login' , locale , true ) } )
)
response . status ( 200 )
}
export default handler Das Erstellen von Komponenten entspricht den Seiten, aber sie leben außerhalb des pages . Außerdem hat der slug -Schlüssel (falls verwendet) keine Auswirkungen auf URLs. Wir haben einige Beispielkomponenten, die selbsterklärend sein sollten, aber hier ist ein Beispiel für eine Footer.tsx -Komponente:
import { useMessages } from 'next-multilingual/messages'
const Footer : React . FC = ( ) => {
const messages = useMessages ( )
return < footer > { messages . format ( 'footerMessage' ) } </ footer >
}
export default FooterUnd seine Nachrichtendatei:
# This is the message in the footer at the bottom of pages
exampleApp.footerComponent.footerMessage = © FooterSchauen Sie sich auch das Beispiel für Sprachschalterkomponenten an, das in allen mehrsprachigen Anwendungen ein Muss ist.
Wir waren klar, dass das Teilen von Nachrichten von Anfang an eine schlechte Praxis ist. Worüber sprechen wir hier? Tatsächlich ist das Teilen von Nachrichten selbst nicht schlecht. Was zu Problemen führen kann, ist, wenn Sie Nachrichten in verschiedenen Kontexten freigeben. Zum noButton sind Sie möglicherweise versucht, eine Button.ts zu erstellen yesButton In vielen Sprachen können einfache Wörter wie "Ja" und "Nein" je nach Kontext unterschiedliche Schreibweisen haben, auch wenn es sich um eine Taste handelt.
Wann ist es gut, Nachrichten zu teilen? Für Listen von Elementen.
Um Ihren Lokalisierungsprozess beispielsweise einfach zu halten, möchten Sie vermeiden, lokalisierbare Zeichenfolgen in Ihrer Datenbank zu speichern (weitere Details, warum im Entwurfsentscheidungsdokument). In Ihrer Datenbank identifizieren Sie den Kontext anhand eindeutiger Bezeichner und speichern Ihre Nachrichten in gemeinsam genutzten Nachrichtendateien, in denen die Kennungen Ihres Schlüssels mit den aus der Datenbank übereinstimmenden Bezeichnungen übereinstimmen.
Um dies zu veranschaulichen, haben wir ein Beispiel mit Früchten erstellt. Alles, was Sie tun müssen, ist, einen Haken zu erstellen, in dem useMessages :
export { useMessages as useFruitsMessages } from 'next-multilingual/messages'❗ Wenn Sie auf Ihre Nachrichten außerhalb von Hooks zugreifen müssen, müssen Sie auch
getMessagesexportieren.
Natürlich haben Sie Ihre Nachrichtendateien im selben Verzeichnis:
exampleApp.fruits.banana = Banana
exampleApp.fruits.apple = Apple
exampleApp.fruits.strawberry = Strawberry
exampleApp.fruits.grape = Grape
exampleApp.fruits.orange = Orange
exampleApp.fruits.watermelon = Watermelon
exampleApp.fruits.blueberry = Blueberry
exampleApp.fruits.lemon = LemonUnd um ihn zu verwenden, importieren Sie diesen Haken einfach von jedem Ort aus, an dem Sie möglicherweise die folgenden Werte benötigen:
import { useFruitsMessages } from '../messages/useFruitsMessages'
const FruitList : React . FC ( ) => {
const fruitsMessages = useFruitsMessages ( )
return (
< >
{ fruitsMessages
. getAll ( )
. map ( ( message ) => message . format ( ) )
. join ( ', ' ) }
</ >
)
}
export default FruitListSie können auch einzelne Nachrichten wie diese aufrufen:
fruitsMessages . format ( 'banana' )Die Idee, diese Elementlisten zu teilen, ist, dass Sie eine einheitliche Erfahrung in verschiedenen Komponenten in verschiedenen Komponenten haben können. Stellen Sie sich eine Dropdown-Liste mit einer Liste von Früchten auf einer Seite und auf einer anderen Seite vor einer automatischen Eingabe. Der wichtige Teil, an den man sich erinnern sollte, ist jedoch, dass die Liste immer im selben Kontext verwendet werden muss, um einige der Nachrichten nicht in einem anderen Kontext wiederzuverwenden.
Die Verwendung von Platzhaltern in Nachrichten ist eine kritische Funktionalität, da nicht alle Nachrichten einen statischen Text enthalten. next-multilingual unterstützt die ICU MessageFormat-Syntax außerhalb des Feldes, was bedeutet, dass Sie die folgende Nachricht verwenden können:
exampleApp.homepage.welcome = Hello {name}!Und injizieren Sie die Werte mit:
messages . format ( 'welcome' , { name : 'John Doe' } ) format Es gibt einige einfache Regeln, die Sie bei der Verwendung format beachten sollten:
values bei der Formatierung der Nachricht nicht angeben, wird die Nachricht einfach als statischer Text ausgegeben.values beim Formatieren der Nachricht angeben, müssen Sie die Werte aller Platzhalter in Ihrer Nachricht mit der {placeholder} -Syntax einbeziehen. Andernfalls wird die Nachricht nicht angezeigt.values angeben, die nicht in Ihrer Nachricht enthalten sind, werden sie stillschweigend ignoriert. Einer der Hauptvorteile von ICU MessageFormat besteht darin, die Werkzeuge und Standards von Unicode zu verwenden, um die Anwendungen zu ermöglichen, die die meisten Sprachen fließend zu klingen. Viele Ingenieure könnten glauben, dass durch 2 Botschaften eine für Singular und eine für Plural ausreicht, um alle Sprachen fließend zu halten. Tatsächlich dokumentierte Unicode die Pluralregeln von über 200 Sprachen, und einige Sprachen wie Arabisch können bis zu 6 Pluralformen haben.
Um sicherzustellen, dass Ihr Satz alle Sprachen fließend bleibt, können Sie die folgende Nachricht verwenden:
exampleApp.homepage.mfPlural = {count, plural, =0 {No candy left.} one {Got # candy left.} other {Got # candies left.}}Und die richtige Pluralform wird unter Verwendung der von Unicode definierten korrekten Pluralkategorien ausgewählt:
messages . format ( 'mfPlural' , { count } )Es gibt viel zu diesem Thema zu lernen. Lesen Sie die Unicode-Dokumentation durch und versuchen Sie es mit der Syntax selbst, um sich mit dieser unterbezogenen I18N-Fähigkeit vertraut zu machen.
In einem seltenen Ereignis, bei dem Sie beide Platzhalter verwenden müssten, die die Syntax {placeholder} verwenden, und die { und } Zeichen in einer Nachricht anzeigen müssen, müssen Sie sie durch die { (für { ) und } (für } ) HTML -Entitäten, die durch Übersetzungswerkzeuge wie folgt erkannt werden:
exampleApp.debuggingPage.variableInfo = Your variable contains the following values: & # x7b;{values}} Wenn Sie eine Nachricht ohne Werte (Platzhalter) haben, ist es nicht erforderlich, { und } mit HTML -Entitäten zu entkommen, und zeigt Entitäten als statischer Text an.
Es ist eine sehr häufige Situation, in der wir in einer einzigen Nachricht Inline -HTML benötigen. Eine Möglichkeit, dies zu tun, wäre:
# Bad example, do not ever do this!
exampleApp.homepage.createAccount1 = Please
exampleApp.homepage.createAccount2 = create your account
exampleApp.homepage.createAccount3 = today for free.Und dann:
< div >
{ messages . format ( 'createAccount1' ) }
< Link href = "/sign-up" > { messages . format ( 'createAccount2' ) } </ Link >
{ messages . format ( 'createAccount3' ) }
</ div >Es gibt 2 Probleme mit diesem Ansatz:
Dies ist eigentlich ein Anti-Muster namens Verkettung und sollte immer vermieden werden. Dies ist der richtige Weg, um dies mit formatJsx zu tun:
exampleApp.homepage.createAccount = Please <link>create your account</link> today for free.Und dann:
< div > { messages . formatJsx ( 'createAccount' , { link : < Link href = "/sign-up" > </ Link > } ) } </ div > formatJsx verwendet formatJsx unterstützt sowohl Platzhalter als auch JSX -Elemente als values was bedeutet, dass Sie von den format (z. B. Pluralen) profitieren können, während Sie JSX -Elemente injizieren.
Es gibt einige einfache Regeln, die Sie bei der Verwendung format beachten sollten:
formatJsx übergeben.<link> XML -Tag das JSX -Element mit link: <Link href="/"></Link> bereitgestellt werden.<i> in einem Satz verwenden, einzigartige Tags wie <i1> , <i2> usw. erstellen und ihre Werte in Argument als JSX -Elemente übergeben müssen.Hello <name>{name}</name> ) nicht unterstützt..properties enthalten sein.<Link href="/contact-us><a id="test"></a></Link> ist gültig, aber <div><span1></span1><span2></span2></div> ist ungültig. Stattdessen müssen Sie das XML-Mark-Mark-Mark-Markus in der .properties gleichniveau und nicht als JSX-Argument verwenden. > < Bei Verwendung formatJsx müssen Sie noch lockige Klammern entkommen, wenn Sie sie als Text anzeigen möchten. Da wir XML in den formatJsx -Nachrichten verwenden, gelten ähnliche Regeln für < > die zur Identifizierung von Tags verwendet werden.
In einem seltenen Ereignis, bei dem Sie JSX mit der Syntax <element></element> (XML) in eine Nachricht injizieren müssen, und die < und > Zeichen in einer Nachricht anzeigen müssen Sie sie durch die < (für < ) und > (für > ) HTML -Entitäten, die durch Übersetzungswerkzeuge wie folgt erkannt werden:
exampleApp.statsPage.targetAchieved = You achieved your weekly target (& # x3c;5) and are eligible for a <link>reward</link>.Ankerlinks sind Links, die Sie zu einem bestimmten Ort in einem Dokument und nicht an der Spitze bringen.
Eine der Kernfunktionen von next-multilingual ist die Unterstützung lokalisierter URLs. Unser Design wurde mit normalen Sätzen gebaut, die leicht zu lokalisieren sind und dann in SEO-freundliche Schnecken verwandelt werden. Wir können dieselbe Funktion verwenden, um Ankerlinks zu schlugen, sodass Sie anstatt /fr-ca/nous-joindre#our-team zu haben können, können Sie /fr-ca/nous-joindre#notre-équipe haben.
Es gibt zwei Arten von Ankerlinks:
Wenn sich die Ankerlinks auf derselben Seite befinden und auf anderen Seiten nicht verwiesen werden, können Sie sie einfach in der Datei .properties mit dieser Seite wie folgt hinzufügen:
# Table of content header
exampleApp.longPage.tableOfContent = Table of Content
# This key will be used both as content and "slugified". Make sure when translating that its value is unique.
exampleApp.longPage.p1Header = Paragraph 1
# "Lorem ipsum" text to make the (long) page scroll
exampleApp.longPage.p1 = Lorem ipsum dolor sit amet... Und dann kann die Seite die slugify -Funktion verwenden, um mit dem eindeutigen Kennung zu verknüpfen, das dem Element zugeordnet ist, das das URL -Fragment verweisen möchte:
import { NextPage } from 'next'
import Link from 'next-multilingual/link'
import { slugify , useMessages } from 'next-multilingual/messages'
import { useRouter } from 'next/router'
const LongPage : NextPage = ( ) => {
const messages = useMessages ( )
const { locale } = useRouter ( )
return (
< div >
< div >
< h2 > { messages . format ( 'tableOfContent' ) } </ h2 >
< ul >
< li >
< Link href = { `# ${ slugify ( messages . format ( 'p1Header' ) , locale ) } ` } >
{ messages . format ( 'p1Header' ) }
</ Link >
</ li >
</ ul >
</ div >
< div >
< h2 id = { slugify ( messages . format ( 'p1Header' ) , locale ) } > { messages . format ( 'p1Header' ) } </ h2 >
< p > { messages . format ( 'p1' ) } </ p >
</ div >
</ div >
)
}
export default LongPage Es ist auch üblich, Ankerlinks über Seiten hinweg zu verwenden. Wenn Sie auf einen Link klicken, wird Ihr Browser den entsprechenden Inhalt auf dieser Seite direkt angezeigt. Dazu müssen Sie die Nachricht Ihrer Seite auf andere Seiten zur Verfügung stellen, indem Sie diesen einfachen Export hinzufügen, der genau wie "gemeinsam genutzte Nachrichten" wirkt:
export const useLongPageMessages = useMessagesUnd dann können Sie diesen Haken von einer anderen Seite wie folgt verwenden:
import { NextPage } from 'next'
import Link from 'next-multilingual/link'
import { slugify , useMessages } from 'next-multilingual/messages'
import { useRouter } from 'next/router'
import { useLongPageMessages } from './long-page'
const AnchorLinks : NextPage = ( ) => {
const messages = useMessages ( )
const { locale , pathname } = useRouter ( )
const longPageMessages = useLongPageMessages ( )
return (
< div >
< div >
< Link
href = { ` ${ pathname } /long-page# ${ slugify ( longPageMessages . format ( 'p3Header' ) , locale ) } ` }
>
{ messages . format ( 'linkAction' ) }
</ Link >
</ div >
</ div >
)
}
export default AnchorLinksDieses Muster funktioniert auch für Komponenten. Der Vorteil davon besteht darin, dass die damit verbundenen Ankerlinks, wenn Sie die Seite löschen oder die Seite umarbeiten, immer auf der Seite bleiben.
Sie können eine separate gemeinsame Nachrichtenkomponente nur für die Ankerlinks erstellen, dies würde jedoch das Proximity -Prinzip brechen.
Ein vollständiges Beispiel für Ankerlinks finden Sie in der Beispielanwendung.
Eine Funktion, die bei Next.js fehlt. Wir haben die <Head> -Komponente hinzugefügt, um mit zwei sehr wichtigen Tags umzugehen, die in der HTML <head> leben:
<link rel=canonical> ): Dies sagt Suchmaschinen, dass die Quelle der Wahrheit für die durchgebrannte Seite diese URL ist. Sehr wichtig, um nicht für doppelte Inhalte bestraft zu werden, zumal URLs unempfindlich sind, aber Google behandelt sie als Fallempfindlichkeit.<link rel=alternate> ): Dies gibt Suchmaschinen mit, dass die durchgebrannte Seite auch in anderen Sprachen verfügbar ist und das Kriechen der Website erleichtert. Die API ist unter next-multilingual/head erhältlich und Sie können sie so importieren:
import Head from 'next-multilingual/head' Genau wie <Link> soll <Head> ein Drop-In-Ersatz für Next.js ' <Head> -Komponente sein. In unserem Beispiel verwenden wir es in der Layoutkomponente wie folgt:
< Head >
< title > { title } </ title >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" > </ meta >
</ Head > All dies macht die kanonischen und alternativen Links ein, damit Suchmaschinen Ihre Anwendung besser kriechen können. Wenn Sie beispielsweise auf der Seite /en-us/about-us sind, wird das folgende HTML automatisch unter Ihrem HTML <head> -Tag hinzugefügt:
< link rel =" canonical " href =" http://localhost:3000/en-us/about-us " />
< link rel =" alternate " href =" http://localhost:3000/en-us/about-us " hreflang =" en-US " />
< link rel =" alternate " href =" http://localhost:3000/fr-ca/%C3%A0-propos-de-nous " hreflang =" fr-CA " /> Um vollständig vom SEO -Markup zu profitieren, muss <Head> auf allen Seiten enthalten sein. Es gibt mehrere Möglichkeiten, dies zu erreichen, aber im Beispiel haben wir eine <Layout> -Komponente erstellt, die auf allen Seiten verwendet wird.
Wie die meisten Websites möchten Sie die benutzerdefinierten Fehlerseiten von Next.js nutzen. Mit useMessages() ist es genauso einfach wie das Erstellen anderer Seiten. Zum Beispiel können Sie für einen 404 -Fehler Ihre 404.tsx erstellen:
import { NextPage } from 'next'
import Link from 'next-multilingual/link'
import { getTitle , useMessages } from 'next-multilingual/messages'
import Layout from '@/layout'
const Error404 : NextPage = ( ) => {
const messages = useMessages ( )
const title = getTitle ( messages )
return (
< Layout title = { title } >
< h1 > { title } </ h1 >
< Link href = "/" >
< a > { messages . format ( 'goBack' ) } </ a >
</ Link >
</ Layout >
)
}
export default Error404 Und natürlich Ihre Nachrichten, zum Beispiel 404.en-US.properties :
# Page title
exampleApp.pageNotFoundError.title = 404 - Page Not Found
# Go back link text
exampleApp.pageNotFoundError.goBack = Go back homeAPIs müssen oft lokalisiert werden. Hier ist ein "Hallo -API" -Beispiel:
import type { NextApiRequest , NextApiResponse } from 'next'
import { getMessages } from 'next-multilingual/messages'
/**
* Example API schema.
*/
type Schema = {
message : string
}
/**
* The "hello API" handler.
*/
const handler = ( request : NextApiRequest , response : NextApiResponse < Schema > ) : void => {
const locale = request . headers [ 'accept-language' ]
if ( locale === undefined || ! isLocale ( locale ) ) {
response . status ( 400 )
return
}
const messages = getMessages ( locale )
response . status ( 200 ) . json ( { message : messages . format ( 'message' ) } )
} Dies ist der in der Beispielanwendung implementierten API sehr ähnlich. Wir verwenden den Accept-Language HTTP-Header, um die API zu sagen, in welchem Gebietsschema ihre Antwort sein soll. Im Gegensatz zu dem useMessages -Haken, der den Kontext des aktuellen Gebietsschemas hat, müssen wir getMessages mitteilen, in welchem Gebietsschema Nachrichten zurückgegeben werden sollen.
Nachrichtendateien verhalten sich genauso wie bei den useMessages , die Sie lediglich neben der Datei der API-Route erstellen müssen, in unserem Fall hello.en-US.properties :
# API message
exampleApp.helloApi.message = Hello, from API.Sie können dies auf allen Seiten implementieren, genau wie bei jedem anderen React-basierten API-Aufruf wie folgt:
const SomePage : NextPage = ( ) => {
const [ apiError , setApiError ] = useState ( null )
const [ isApiLoaded , setApiIsLoaded ] = useState ( false )
const [ apiMessage , setApiMessage ] = useState ( '' )
useEffect ( ( ) => {
setApiIsLoaded ( false )
const requestHeaders : HeadersInit = new Headers ( )
requestHeaders . set ( 'Accept-Language' , normalizeLocale ( router . locale as string ) )
fetch ( '/api/hello' , { headers : requestHeaders } )
. then ( ( result ) => result . json ( ) )
. then (
( result ) => {
setApiIsLoaded ( true )
setApiMessage ( result . message )
} ,
( apiError ) => {
setApiIsLoaded ( true )
setApiError ( apiError )
}
)
} , [ router . locale ] )
const showApiMessage : React . FC = ( ) => {
if ( apiError ) {
return (
< >
{ messages . format ( 'apiError' ) }
{ ( apiError as Error ) . message }
</ >
)
} else if ( ! isApiLoaded ) {
return < > { messages . format ( 'apiLoading' ) } </ >
} else {
return < > { apiMessage } </ >
}
}
return (
< div >
< h2 > { messages . format ( 'apiHeader' ) } </ h2 >
< div > { showApiMessage ( { } ) } </ div >
</ div >
)
} Die normalizeLocale ist nicht obligatorisch, sondern eine empfohlene ISO 3166 -Konvention. Da Next.js die Orte als URL-Präfixe verwendet, sind sie in der Konfiguration niedriger und können nach Bedarf neu anormalisiert werden.
❗ Dynamische Routen sind komplex und die Lokalisierung fügt noch mehr Komplexität hinzu. Stellen Sie sicher, dass Sie mit der Funktionsweise dieser Nächsten.js -Funktion vertraut sind, bevor Sie versuchen, die Lokalisierung hinzuzufügen.
Dynamische Routen sind sehr häufig und werden von Next.js. Seit Version 3.0 bietet next-multilingual die gleichen Supports wie Next.js in Bezug auf dynamische Routen. Damit dynamische Routen mit next-multilingual funktionieren, haben wir ein paar Muster, die folgen müssen:
href -Attribut des <Link> und das useLocalizedUrl url -Argument von useGetLocalizedUrl / getLocalizedUrl akzeptiert nur String -URLs.<Link> component which accepts a UrlObject , we preferred to streamline our types since urlObject.href can easily be used instead.userRouter().asPath (most common scenario) by providing localized parameters directly in the URL. By using asPath you are using the localized URL which means that the URL you will use will be fully localized.userRouter().pathname is conjunction with hydrateRouteParameters by providing localized parameters. By using pathname you are using the non-localized URL which means that the URL you will use might be a mix of non-localized segments plus the localized parameters. This can be useful in cases where you have nested dynamic routes.We provided several examples of on on to use dynamic routes in our dynamic route test pages.
The main challenge with dynamic routes, is that if the value of the parameter needs to be localized, we need to keep a relation between languages so that we can correctly switch languages. next-multilingual solves this problem with its getLocalizedRouteParameters API that creates a LocalizedRouteParameters object used as a page props. This can work both with getStaticProps and getServerSideProps .
getStaticProps First you need to tell Next.js which predefined paths will be valid by using getStaticPaths (all imports are added in the first example):
import { getCitiesMessages } from '@/messages/cities/citiesMessages'
import { GetStaticPaths } from 'next'
import { slugify } from 'next-multilingual/messages'
export const getStaticPaths : GetStaticPaths = async ( context ) => {
const paths : MultilingualStaticPath [ ] = [ ]
const { locales } = getStaticPathsLocales ( context )
locales . forEach ( ( locale ) => {
const citiesMessages = getCitiesMessages ( locale )
citiesMessages . getAll ( ) . forEach ( ( cityMessage ) => {
paths . push ( {
params : {
city : slugify ( cityMessage . format ( ) , locale ) ,
} ,
locale ,
} )
} )
} )
return {
paths ,
fallback : false ,
}
} Then you have to pre-compute the localized route parameters and return them as props using getStaticProps and getLocalizedRouteParameters :
export type CityPageProps = { localizedRouteParameters : LocalizedRouteParameters }
export const getStaticProps : GetStaticProps < CityPageProps > = async ( context ) => {
const localizedRouteParameters = getLocalizedRouteParameters (
context ,
{
city : getCitiesMessages ,
} ,
import . meta . url
)
return { props : { localizedRouteParameters } }
}If you are using a catch-all dynamic route, you will need to pass your parameters as an array, for each URL segment that you want to support. For example, if you want to support 2 levels:
const localizedRouteParameters = getLocalizedRouteParameters ( context , {
city : [ getCitiesMessages , getCitiesMessages ] ,
} ) Note that since we need to use the getMessages API instead of the useMessages hook, you will also need to export it in the message file:
export {
getMessages as getCitiesMessages ,
useMessages as useCitiesMessages ,
} from 'next-multilingual/messages'Finally you have to pass down your localized route parameters down to your language switcher component when you create your page:
const CityPage : NextPage < CityPageProps > = ( { localizedRouteParameters } ) => {
const messages = useMessages ( )
const title = getTitle ( messages )
const { query } = useRouter ( )
return (
< Layout title = { title } localizedRouteParameters = { localizedRouteParameters } >
< h1 > { query [ 'city' ] } < / h1>
< / Layout>
)
}
export default CityPage The only part missing now is the language switcher which needs to leverage the localized route parameters by using getLanguageSwitcherUrl :
import { normalizeLocale , setCookieLocale } from 'next-multilingual'
import Link from 'next-multilingual/link'
import { KeyValueObject } from 'next-multilingual/messages'
import { LocalizedRouteParameters , useRouter } from 'next-multilingual/router'
import { getLanguageSwitcherUrl } from 'next-multilingual/url'
import { ReactElement } from 'react'
// Locales don't need to be localized.
const localeStrings : KeyValueObject = {
'en-US' : 'English (United States)' ,
'fr-CA' : 'Français (Canada)' ,
}
type LanguageSwitcherProps = {
/** Route parameters, if the page is using a dynamic route. */
localizedRouteParameters ?: LocalizedRouteParameters
}
export const LanguageSwitcher : React . FC < LanguageSwitcherProps > = ( { localizedRouteParameters } ) => {
const router = useRouter ( )
const { pathname , locale : currentLocale , locales , defaultLocale , query } = useRouter ( )
const href = getLanguageSwitcherUrl ( router , localizedRouteParameters )
return (
< div id = "language-switcher" >
< ul >
{ locales
. filter ( ( locale ) => locale !== currentLocale )
. map ( ( locale ) => {
return (
< li key = { locale } >
< Link href = { href } locale = { locale } >
< a
onClick = { ( ) => {
setCookieLocale ( locale )
} }
lang = { normalizeLocale ( locale ) }
>
{ localeStrings [ normalizeLocale ( locale ) ] }
< / a>
< / Link>
< / li >
)
} ) }
< / ul>
< / div >
)
}Check out our fully working examples:
Our ideal translation process is one where you send the modified files to your localization vendor (while working in a branch), and get back the translated files, with the correct locale in the filenames. Once you get the files back you basically submit them back in your branch which means localization becomes an integral part of the development process. Basically, the idea is:
We don't have any "export/import" tool to help as at the time of writing this document.
next-multilingual ? ?️Why did we put so much effort into these details? Because our hypothesis is that it can have a major impact on:
More details can be found on the implementation and design decision in the individual README files of each API and in the documentation directory.