Persistencia de la elección de idioma del usuario
Uso de una cookie para recordar una selección
Problema
Un usuario selecciona manualmente 'Francés' en un sitio. Cuando cierra su navegador y posteriormente escribe la dirección principal del sitio (por ejemplo, example.com), la aplicación vuelve a su configuración predeterminada (por ejemplo, inglés) o al idioma detectado automáticamente. Este fallo al recordar su elección obliga al usuario a encontrar el selector de idioma y volver a seleccionar su idioma cada vez que inicia una nueva sesión.
Solución
Cuando un usuario selecciona un idioma, almacena esa elección en una cookie. En el middleware, cuando un usuario visita la ruta raíz (/), verifica esta cookie antes de comprobar el encabezado Accept-Language. Si se encuentra una cookie válida, redirige al usuario a la raíz de su idioma elegido (por ejemplo, /fr), anulando cualquier configuración predeterminada del navegador.
Pasos
1. Definir la configuración de idioma
Crea un archivo de configuración central para almacenar tus idiomas compatibles, un idioma predeterminado y el nombre de la cookie que utilizarás para almacenar la preferencia del usuario.
// i18n.config.ts
export const locales = ['en', 'es', 'fr'];
export const defaultLocale = 'en';
export const localeCookieName = 'NEXT_LOCALE';
2. Instalar un analizador de idioma
Todavía necesitas un analizador para el encabezado Accept-Language, que se utilizará como respaldo si no se establece ninguna cookie.
npm install accept-language-parser
3. Crear el middleware
Crea un archivo middleware.ts en la raíz de tu proyecto. Este middleware verificará primero la cookie NEXT_LOCALE. Si no se encuentra, recurrirá a verificar el encabezado Accept-Language. Esta lógica solo se aplicará a las solicitudes para la ruta raíz (/).
// 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. Verificar la cookie
const cookie = request.cookies.get(localeCookieName);
if (cookie) {
const locale = cookie.value;
if (locales.includes(locale)) {
return locale;
}
}
// 2. Verificar el encabezado Accept-Language
const acceptLang = request.headers.get('Accept-Language');
if (acceptLang) {
const bestMatch = parser.pick(locales, acceptLang, {
loose: true,
});
if (bestMatch) {
return bestMatch;
}
}
// 3. Devolver el valor predeterminado
return defaultLocale;
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// 1. Verificar si la solicitud es para la ruta raíz
if (pathname === '/') {
// Obtener el idioma preferido del usuario (de la cookie o encabezado)
const bestLocale = getPreferredLocale(request);
// Redirigir a la ruta del idioma mejor coincidente
request.nextUrl.pathname = `/${bestLocale}`;
return NextResponse.redirect(request.nextUrl);
}
// 2. Para todas las demás rutas, continuar normalmente
return NextResponse.next();
}
export const config = {
matcher: [
// Solo queremos ejecutar esto en la ruta raíz por ahora
'/',
// También necesitamos coincidir con rutas no raíz para dejarlas pasar
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
La lógica de este middleware ahora prioriza correctamente la elección explícita del usuario (la cookie) sobre su preferencia implícita (el encabezado del navegador) cuando visitan la raíz del sitio.