Comment mémoriser la sélection de langue entre les sessions dans Next.js (Pages Router) v16

Stocker le choix explicite de langue de l'utilisateur

Problème

Lorsqu'un utilisateur sélectionne explicitement une langue, ce choix reflète sa préférence et devrait prévaloir sur la détection automatique basée sur les en-têtes du navigateur ou la géolocalisation. Sans persistance, cette préférence est perdue à la fermeture du navigateur ou à la fin de la session. Lors de la visite suivante, l'application redémarre à zéro, obligeant l'utilisateur à sélectionner à nouveau sa langue. Cette répétition signale que l'application ne respecte pas les préférences de l'utilisateur, créant ainsi des frictions et diminuant la confiance.

Le défi est double : capturer le choix explicite de l'utilisateur au moment de la sélection et récupérer ce choix lors des visites ultérieures avant que toute logique de détection automatique ne s'exécute. Si la préférence enregistrée n'est pas vérifiée tôt dans le cycle de vie de la requête, l'utilisateur peut être redirigé en fonction des paramètres du navigateur plutôt que de son choix explicite, ce qui diminue l'intérêt d'avoir fait une sélection en premier lieu.

Solution

Stocker la sélection de langue de l'utilisateur dans un cookie persistant lorsqu'il choisit explicitement une langue. Lors des futures visites à la racine de l'application, vérifier ce cookie avant de recourir à la détection de locale basée sur le navigateur. Si une locale valide est trouvée, rediriger l'utilisateur vers le chemin racine de cette locale, garantissant ainsi que sa préférence est respectée immédiatement.

Cette approche sépare le choix explicite de l'utilisateur de la détection automatique. Le cookie agit comme un signal durable d'intention qui survit aux redémarrages du navigateur et prend priorité sur les signaux transitoires comme l'en-tête Accept-Language. En vérifiant le cookie côté serveur pendant la requête initiale, la redirection se produit avant le rendu de la page, offrant une expérience fluide.

Étapes

Lorsqu'un utilisateur sélectionne une langue, stockez son choix dans un cookie qui persiste entre les sessions.

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

Cette fonction écrit un cookie nommé NEXT_LOCALE avec la locale choisie, valide pendant un an. Le path=/ garantit qu'il est disponible dans toute l'application, et SameSite=Lax fournit une protection CSRF raisonnable tout en permettant l'envoi du cookie lors de la navigation de premier niveau.

2. Appelez l'assistant lorsque l'utilisateur sélectionne une langue

Intégrez l'assistant dans votre composant de sélection de langue afin que la préférence soit enregistrée immédiatement après la sélection.

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>
  );
}

Lorsque l'utilisateur change la sélection, le cookie est défini et le routeur navigue vers la même page dans la nouvelle locale. Le cookie sera disponible pour toutes les requêtes suivantes.

3. Vérifiez la préférence stockée sur la page racine

Dans le getServerSideProps de la page racine, lisez le cookie et redirigez vers la locale stockée si elle existe et est valide.

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;
}

Ceci vérifie si le cookie NEXT_LOCALE existe et contient une locale valide de la liste configurée de l'application. Si la locale stockée n'est pas celle par défaut, l'utilisateur est redirigé vers la racine de cette locale. Sinon, il est redirigé vers la locale par défaut. La redirection se produit côté serveur avant le rendu, garantissant que l'utilisateur arrive immédiatement sur la locale correcte.

4. Configurer le routage des locales dans Next.js

Assurez-vous que votre next.config.js définit les locales prises en charge afin que la logique de redirection puisse valider la préférence enregistrée.

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

Cette configuration active le routage i18n intégré de Next.js et rend les locales et defaultLocale disponibles dans getServerSideProps. La logique de la page racine utilise ces valeurs pour valider le cookie stocké et construire la destination de redirection correcte.