Bonnes pratiques d'internationalisation multilingue Nextjs+next-intl (routeur APP)
Nextjs dispose de deux routeurs : le routeur APP et le routeur Page.
Il y a quelque temps, sous le routeur Page, nextjs a été internationalisé et résumé :
Mais le routeur Page sera le routeur progressivement supprimé par Nextjs. Par conséquent, récemment, Nextjs a été internationalisé sur la base du routeur APP.
1. Sélection de la solution d'internationalisation Nextjs
1. i18next + réagir-i18next + i18next-ressources-to-backend + next-i18n-router
Il semble que la plupart des gens l'utilisent. J'ai essayé et c'était assez compliqué. Je n'ai pas encore réussi, alors j'ai abandonné.
2. réaction-intl du routeur next-i18n
Cela avait l'air assez compliqué, mais à cause de l'ombre du 1, j'ai abandonné.
3. prochain-intl
next-intl est une solution d'internationalisation complète pour nextjs et ne nécessite pas d'autres progiciels. Et la configuration est relativement simple. Plus important encore, je l'ai configuré avec succès et je n'ai rencontré aucun problème inexplicable.
Alors c'est ça.
2. Structure du répertoire
|app ..[locale] ...layout.js ...page.js |components ..LangSwitcher.js |public ..locales ...en ....common.json ...es .... common.json |i18n.js |navigation.js |middleware.js |next.config.js
3. Routage international
1. navigation.js
Il s'agit d'un fichier de configuration et les éléments configurés dans ce fichier seront appelés dans d'autres fichiers.
importer { createSharedPathnamesNavigation } depuis 'next-intl/navigation' ; exporter const locales = ['en', 'de', 'es', 'ja','ko','it','pt'] ; exporter const localePrefix = 'selon les besoins'; export const defaultLocale= "en"; export const localeItems= [ { nom : "English", code : "en", iso : "en-US", dir : "ltr" }, { nom : "español",code: "es", iso: "es-ES", dir: "ltr" }, { nom: "中文",code: "zh_cn", iso: "zh-CN", dir: " ltr" }, { nom : "Deutsch",code : "de", iso : "de-DE", dir : "ltr" }, { nom : "Italiano",code : "it", iso : "it- IT", dir : "ltr" }, { nom : "日本语", code : "ja", iso : "ja-JP", dir : "ltr" }, { nom : "한국인", code : "ko ", iso : "ko-KR", dir : "ltr" }, { nom : "Português",code : "pt", iso : "pt-PT", dir : "ltr" }, ] export const { Lien , redirect, usePathname, useRouter } = createSharedPathnamesNavigation({ locales, localePrefix });
2. Répertoire [locales]
Tous les fichiers d'échange du répertoire app sont placés dans le répertoire [locale].
3. Intergiciel : middleware.js
illustrer:
Implémentez le style d'URL suivant
URL de la langue par défaut :
La page d'accueil est : www.xxx.com
La page intérieure est : www.xxx.com/about
URL dans d'autres langues : (Prenez l'espagnol comme exemple)
La page d'accueil est : www.xxx.com/es
La page intérieure est : www.xxx.com/es/about
De plus, si la langue par défaut est saisie dans l'URL, par exemple, la langue par défaut est l'anglais, l'utilisateur saisit l'URL : www.xxx.com/en
Ensuite, il ira automatiquement sur www.xxx.com
Code:
importer createMiddleware depuis "next-intl/middleware" ; importer { defaultLocale, localePrefix, locales } depuis '@/navigation' ; exporter default createMiddleware({ locales, localePrefix , defaultLocale, localeDetection: false, }); exporter const config = { / / Ignorer tous les chemins qui ne doivent pas être internationalisés. // Cela ignore les dossiers "api", "_next" et tous les fichiers // avec une extension (par exemple favicon.ico) matcher: ["/((?!api|_next| .*\\..*).*)"], };
4. Charger les fichiers de traduction
1. Traduire des fichiers
illustrer
Mes fichiers de traduction sont placés dans le répertoire "public", mais en fait, les fichiers de traduction peuvent également être placés dans d'autres répertoires, à condition que le chemin correspondant soit configuré dans le fichier i18n.js.
Le fichier de traduction est un fichier json, et le fichier json peut être dans un format imbriqué ou non. En fin de compte, les deux seront référencés de manière légèrement différente.
Code (non imbriqué)
{ "aaa": "salut", }
Code (imbriqué)
{ "bbb":{ "aaa": "salut", } }
2. Fichier i18n.js
illustrer:
Ce fichier permet d'importer des fichiers de traduction. L'essentiel est de configurer le chemin du fichier de traduction, qui doit être cohérent avec le chemin où se trouve votre fichier de traduction.
${locale} dans le chemin indique la langue.
code
import { getRequestConfig } from "next-intl/server" ; // Crée cette configuration une fois par requête et // la rend disponible à tous les composants du serveur. export default getRequestConfig(async ({ locale }) => ({ // Charger les traductions pour les paramètres régionaux actifs. messages : (await import(`./public/locales/${locale}/common.json`)).default, }));
3. Configuration de next.config.js
/** @type {import('next').NextConfig} */ const nextConfig = {} const withNextIntl = require("next-intl/plugin"))("./i18n.js"); module.exports =avecNextIntl (nextConfig)
5. Mettre en œuvre la traduction
Code dans layout.js :
importer "./globals.css"; importer { NextIntlClientProvider, useMessages } depuis 'next-intl'; importer { locales } depuis '@/navigation'; importer l'en-tête depuis '@/components/Header' importer le pied de page depuis '@/components /Footer' export default function RootLayout({ children, params: { locale } }) { if (!locales.includes(locale)) { notFound(); } const messages = useMessages(); return (
<html lang="{locale}">
<nextintlclientprovider locale="{locale}" messages="{messages}">
<body><header />{enfants}<footer /></body>
</nextintlclientprovider>
</html>
);
}
Code dans page.js :
Le paramètre locale représente la langue actuelle.
Si le fichier de traduction n'est pas imbriqué, alors const t = useTranslations();
Si le fichier de traduction est imbriqué, utilisez quelque chose comme : const t = useTranslations("bbb"); en fonction de la structure du fichier et des besoins réels.
importer { useTranslations } depuis 'next-intl'; importer { Link } depuis '@/navigation'; exporter la fonction par défaut Home({ params: { locale } }) { const t = useTranslations(); return (<>
<link href="{"/"}"><h1>{t("aaa")}</h1></Link>
</>)
6. Sélecteur de langue
1. Effet
Déroulez vers le bas pour sélectionner une langue et la page actuelle passe à la page dans la langue sélectionnée.
2. Coder
"use client";
import { useLocale } from "next-intl";
import { localeItems, useRouter, usePathname, defaultLocale } from '@/navigation';
export default function LangSwitcher() {
const locale = useLocale();
const router = useRouter();
const pathname = usePathname();
console.log(locale)
const handleChange = (e) => {
router.push(pathname, { locale: e.target.value });
};
return (
<div>
<select
value={locale}
onChange={handleChange}
className="h-8 m-2 p-1 rounded border-current"
>
<option value={locale} > {GetLangData(locale).name}</option>
{localeItems.map((item) => {
if (item.code === locale) return null
return (<option key={item.code} value={item.code}>
{item.name}
</option>)
})}
</select>
</div>
);
}
export function GetLangData(defaultLocale) {
var res = {}
{
localeItems.map(locale => {
if (locale.code === defaultLocale) {
console.log(locale)
res = locale
}
})
}
return res
}
7. Optimisé pour le référencement et les moteurs de recherche
1. Métadonnées
Le routeur Nextjs APP génère le titre et les métadonnées de la page. J'ai essayé trois méthodes :
La première façon : utilisez-le directement dans layout.js : expert const metadata={}
La deuxième façon : utiliser des métadonnées générées dynamiquement dans page.js
Pour référence:Optimisation : métadonnées | Next.js (nextjs.org)
De ces deux manières, j'ai échoué pour les titres multilingues et les métadonnées. Finalement, la troisième méthode a été utilisée, qui est également la méthode la plus simple et la plus directe.
La troisième façon : écrivez la balise titre et la balise Meta directement dans page.js.
Par conséquent, le code de page.js a été modifié comme suit :
importer { useTranslations } depuis 'next-intl'; importer { Link } depuis '@/navigation'; exporter la fonction par défaut Home({ params: { locale } }) { const t = useTranslations(); return (<>
<title>{t("nom du site")}</title>
<meta name="keyword" content="{t("site-name")}"></meta>
<meta name="description" content="{t("description du site")}"></meta>
<meta property="og:type" content="website"></meta>
<meta property="og:title" content="{t("nom du site")}"></meta>
<meta property="og:description" content="{t("description du site")}"></meta>
<meta property="og:site_name" content="{t("nom du site")}"></meta>
<meta property="og:image" content="/images/xxx.png"></meta>
<meta property="og:image:width" content="512"></meta>
<meta property="og:image:height" content="512"></meta>
<meta property="og:image:alt" content=""></meta>
<link href="{"/"}"><h1>{t("aaa")}</h1></Link>
</>)
2. Navigation multilingue : permettez aux moteurs de recherche de découvrir plus facilement les URL multilingues
illustrer
Le sélecteur de langue est rendu en front-end, j'ai donc ajouté une navigation multilingue rendue en back-end au bas de la page, qui est le composant Footer.js. En cliquant sur la langue correspondante, vous accéderez à la page d'accueil du site dans cette langue.
Le code Footer.js est le suivant :
import Link from 'next/link'
import { localeItems,defaultLocale } from '@/navigation';
export default function Footer(){
return (<>
<div className="divider"></div>
<footer className="footer footer-center p-10 bg-base-200 text-base-content rounded">
<nav className="flex flex-wrap gap-4">
{localeItems.map(locale => {
if (locale.code === defaultLocale) return(<Link className="link link-hover" href="/" key={locale.code}>{locale.name}</Link>)
const thehref="/"+locale.code
return (<Link className="link link-hover" href={thehref} key={locale.code}> {locale.name}</Link>)
})}
</nav>
<aside className='p-6 text-center'>
<p>Copyright © 2024 - All right reserved by xxx.com</p>
</aside>
</footer>
</>
)
}
8. Résumé
Routage international, structure et introduction des dossiers de traduction, et mise en œuvre de la traduction. Quel que soit le type de plan d'internationalisation, ces trois aspects seront impliqués. Bien que ce ne soit pas gênant, en général, next-intl est relativement simple.
9. Référence
Une plongée approfondie dans la localisation du routeur d'application Next.js avec next-intl
Un guide complet pour configurer next-intl avec l'App Router