Détection de la langue préférée de l'utilisateur
Redirection des nouveaux visiteurs vers leur langue la plus probable
Problème
Lorsqu'un utilisateur visite pour la première fois la racine d'une application (par exemple, /), celle-ci affiche une langue par défaut, comme l'anglais. Cela crée une friction immédiate pour les utilisateurs qui parlent d'autres langues, les obligeant à trouver manuellement un sélecteur de langue, alors que leur navigateur communique déjà leur préférence.
Solution
Utilisez un middleware pour intercepter les requêtes vers le chemin racine (/). Vérifiez l'en-tête HTTP Accept-Language de l'utilisateur pour trouver sa langue préférée. Si cette langue est prise en charge par l'application, redirigez l'utilisateur vers la racine de cette langue (par exemple, /fr). Sinon, redirigez-le vers une langue par défaut (par exemple, /en).
Étapes
1. Installer un analyseur de langue
L'en-tête Accept-Language peut être complexe (par exemple, fr-CH, fr;q=0.9, en;q=0.8). Une petite bibliothèque aide à analyser cet en-tête et à trouver la meilleure correspondance dans notre liste de langues prises en charge.
Exécutez cette commande dans votre terminal :
npm install accept-language-parser
2. Définir vos langues et la langue par défaut
Créez un fichier de configuration central pour stocker votre liste de langues prises en charge et définir une langue par défaut. Cette langue par défaut sera utilisée si les préférences du navigateur de l'utilisateur ne correspondent à aucune langue que vous prenez en charge.
// i18n.config.ts
export const locales = ['en', 'es', 'fr'];
export const defaultLocale = 'en';
3. Créer le middleware
Créez un fichier middleware.ts à la racine de votre projet. Ce fichier s'exécutera sur les requêtes entrantes, vous permettant de vérifier le chemin et les en-têtes.
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import parser from 'accept-language-parser';
import { locales, defaultLocale } from './i18n.config';
// Fonction auxiliaire pour trouver la meilleure correspondance de langue
function getBestLocale(acceptLangHeader: string | null) {
if (!acceptLangHeader) {
return defaultLocale;
}
// Utiliser l'analyseur pour trouver la meilleure langue prise en charge
const bestMatch = parser.pick(locales, acceptLangHeader, {
loose: true,
});
return bestMatch || defaultLocale;
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// 1. Vérifier si la requête concerne le chemin racine
if (pathname === '/') {
// Obtenir la langue préférée de l'utilisateur
const acceptLang = request.headers.get('Accept-Language');
const bestLocale = getBestLocale(acceptLang);
// Rediriger vers le chemin de la langue la mieux adaptée
request.nextUrl.pathname = `/${bestLocale}`;
return NextResponse.redirect(request.nextUrl);
}
// 2. Pour tous les autres chemins, continuer normalement
return NextResponse.next();
}
export const config = {
matcher: [
// Ignorer tous les chemins qui commencent par :
// - api (routes API)
// - _next/static (fichiers statiques)
// - _next/image (fichiers d'optimisation d'image)
// - favicon.ico (fichier favicon)
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
Ce code n'exécute la logique que pour le chemin racine (/). Si un utilisateur visite /, il vérifie son en-tête Accept-Language, trouve la meilleure correspondance (par exemple, es), et le redirige vers /es. Toutes les autres requêtes, comme /en/about, sont ignorées par cette logique et passent à travers.