Conserver le choix de langue d'un utilisateur
Utiliser un cookie pour mémoriser une sélection
Problème
Un utilisateur sélectionne manuellement « Français » sur un site. Lorsqu'il ferme son navigateur et saisit plus tard l'adresse principale du site (par exemple, example.com), l'application revient à sa langue par défaut (par exemple, l'anglais) ou à la langue détectée automatiquement. Cette incapacité à mémoriser son choix oblige l'utilisateur à rechercher le sélecteur de langue et à resélectionner sa langue à chaque nouvelle session.
Solution
Lorsqu'un utilisateur sélectionne une langue, stockez ce choix dans un cookie. Dans le middleware, lorsqu'un utilisateur visite le chemin racine (/), vérifiez ce cookie avant de vérifier l'en-tête Accept-Language. Si un cookie valide est trouvé, redirigez l'utilisateur vers la racine de sa langue choisie (par exemple, /fr), en remplaçant tout paramètre par défaut du navigateur.
Étapes
1. Définir la configuration des langues
Créez un fichier de configuration central pour stocker vos langues prises en charge, une langue par défaut et le nom du cookie que vous utiliserez pour stocker la préférence de l'utilisateur.
// i18n.config.ts
export const locales = ['en', 'es', 'fr'];
export const defaultLocale = 'en';
export const localeCookieName = 'NEXT_LOCALE';
2. Installer un analyseur de langue
Vous avez toujours besoin d'un analyseur pour l'en-tête Accept-Language, qui sera utilisé comme solution de secours si aucun cookie n'est défini.
npm install accept-language-parser
3. Créer le middleware
Créez un fichier middleware.ts à la racine de votre projet. Ce middleware vérifiera d'abord le cookie NEXT_LOCALE. S'il n'est pas trouvé, il se rabattra sur la vérification de l'en-tête Accept-Language. Cette logique s'appliquera uniquement aux requêtes pour le chemin racine (/).
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import parser from 'accept-language-parser';
import {
locales,
defaultLocale,
localeCookieName,
} from './i18n.config';
function getPreferredLocale(request: NextRequest) {
// 1. Check for the cookie
const cookie = request.cookies.get(localeCookieName);
if (cookie) {
const locale = cookie.value;
if (locales.includes(locale)) {
return locale;
}
}
// 2. Check the Accept-Language header
const acceptLang = request.headers.get('Accept-Language');
if (acceptLang) {
const bestMatch = parser.pick(locales, acceptLang, {
loose: true,
});
if (bestMatch) {
return bestMatch;
}
}
// 3. Return the default
return defaultLocale;
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// 1. Check if the request is for the root path
if (pathname === '/') {
// Get the user's preferred language (from cookie or header)
const bestLocale = getPreferredLocale(request);
// Redirect to the best-matched language path
request.nextUrl.pathname = `/${bestLocale}`;
return NextResponse.redirect(request.nextUrl);
}
// 2. For all other paths, continue as normal
return NextResponse.next();
}
export const config = {
matcher: [
// We only want to run this on the root path for now
'/',
// We also need to match non-root paths to let them pass
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
La logique de ce middleware priorise désormais correctement le choix explicite de l'utilisateur (le cookie) par rapport à sa préférence implicite (l'en-tête du navigateur) lorsqu'il visite la racine du site.