Cómo recordar la selección de idioma entre sesiones en Next.js (Pages Router) v16

Almacenar la elección explícita de idioma del usuario

Problema

Cuando un usuario selecciona explícitamente un idioma, esa elección refleja su preferencia y debe tener prioridad sobre la detección automática de los encabezados del navegador o la geolocalización. Sin persistencia, esta preferencia se pierde cuando el navegador se cierra o la sesión termina. En la siguiente visita, la aplicación comienza de nuevo, obligando al usuario a seleccionar su idioma otra vez. Esta repetición indica que la aplicación no respeta las preferencias del usuario, creando fricción y disminuyendo la confianza.

El desafío es doble: capturar la elección explícita del usuario en el momento de la selección y recuperar esa elección en visitas posteriores antes de que se ejecute cualquier lógica de detección automática. Si la preferencia almacenada no se verifica temprano en el ciclo de vida de la solicitud, el usuario puede ser redirigido según la configuración del navegador en lugar de su elección explícita, socavando el valor de haber realizado una selección en primer lugar.

Solución

Almacenar la selección de idioma del usuario en una cookie persistente cuando eligen explícitamente un idioma. En futuras visitas a la raíz de la aplicación, verificar esta cookie antes de recurrir a la detección de idioma basada en el navegador. Si se encuentra un idioma almacenado válido, redirigir al usuario a la ruta raíz de ese idioma, asegurando que su preferencia sea respetada inmediatamente.

Este enfoque separa la elección explícita del usuario de la detección automática. La cookie actúa como una señal duradera de intención que sobrevive a los reinicios del navegador y tiene prioridad sobre señales transitorias como el encabezado Accept-Language. Al verificar la cookie del lado del servidor durante la solicitud inicial, la redirección ocurre antes de que la página se renderice, proporcionando una experiencia fluida.

Pasos

Cuando un usuario selecciona un idioma, almacena su elección en una cookie que persiste a través de las sesiones.

export function setLocalePreference(locale: string) {
  const maxAge = 60 * 60 * 24 * 365;
  document.cookie = `NEXT_LOCALE=${locale}; path=/; max-age=${maxAge}; SameSite=Lax`;
}

Esta función escribe una cookie llamada NEXT_LOCALE con el idioma elegido, válida por un año. El path=/ asegura que esté disponible en toda la aplicación, y SameSite=Lax proporciona una protección CSRF razonable mientras permite que la cookie se envíe en la navegación de nivel superior.

2. Llama al helper cuando el usuario selecciona un idioma

Integra el helper en tu componente de selector de idioma para que la preferencia se guarde inmediatamente tras la selección.

import { useRouter } from "next/router";
import { setLocalePreference } from "@/lib/locale";

export default function LanguageSwitcher() {
  const router = useRouter();
  const { locales, locale: currentLocale } = router;

  const handleLocaleChange = (newLocale: string) => {
    setLocalePreference(newLocale);
    router.push(router.pathname, router.asPath, { locale: newLocale });
  };

  return (
    <select
      value={currentLocale}
      onChange={(e) => handleLocaleChange(e.target.value)}
    >
      {locales?.map((loc) => (
        <option key={loc} value={loc}>
          {loc.toUpperCase()}
        </option>
      ))}
    </select>
  );
}

Cuando el usuario cambia la selección, la cookie se establece y el router navega a la misma página en el nuevo idioma. La cookie estará disponible en todas las solicitudes posteriores.

3. Verifica la preferencia almacenada en la página raíz

En el getServerSideProps de la página raíz, lee la cookie y redirige al idioma almacenado si existe y es válido.

import { GetServerSideProps } from "next";

export const getServerSideProps: GetServerSideProps = async (context) => {
  const storedLocale = context.req.cookies.NEXT_LOCALE;
  const { locales, defaultLocale } = context;

  if (
    storedLocale &&
    locales?.includes(storedLocale) &&
    storedLocale !== defaultLocale
  ) {
    return {
      redirect: {
        destination: `/${storedLocale}`,
        permanent: false,
      },
    };
  }

  return {
    redirect: {
      destination: `/${defaultLocale}`,
      permanent: false,
    },
  };
};

export default function RootPage() {
  return null;
}

Esto verifica si la cookie NEXT_LOCALE existe y contiene un idioma válido de la lista configurada en la aplicación. Si el idioma almacenado no es el predeterminado, el usuario es redirigido a la raíz de ese idioma. De lo contrario, son redirigidos al idioma predeterminado. La redirección ocurre del lado del servidor antes del renderizado, asegurando que el usuario llegue al idioma correcto inmediatamente.

4. Configurar el enrutamiento de localización en Next.js

Asegúrate de que tu next.config.js defina los idiomas soportados para que la lógica de redirección pueda validar la preferencia almacenada.

module.exports = {
  i18n: {
    locales: ["en", "fr", "de", "es"],
    defaultLocale: "en",
  },
};

Esta configuración habilita el enrutamiento i18n integrado de Next.js y hace que locales y defaultLocale estén disponibles en getServerSideProps. La lógica de la página raíz utiliza estos valores para validar la cookie almacenada y construir el destino de redirección correcto.