Comment mémoriser la sélection de langue entre les sessions dans React Router v7
Stocker le choix de langue explicite de l'utilisateur
Problème
Lorsqu'un utilisateur sélectionne explicitement une langue, ce choix reflète sa préférence et doit prévaloir sur toute détection automatique. Sans persistance, cette sélection disparaît lorsque le navigateur se ferme ou que la session se termine. Lors de la visite suivante, l'application repart de zéro, obligeant l'utilisateur à sélectionner à nouveau sa langue. Cette répétition signale que l'application ne respecte pas ses préférences, créant des frictions et diminuant la confiance.
Solution
Stocker le choix de langue de l'utilisateur dans un emplacement persistant tel qu'un cookie lorsqu'il effectue une sélection. Lors des visites suivantes, vérifier cette préférence stockée avant de recourir aux en-têtes du navigateur ou à d'autres méthodes de détection. Si une langue stockée valide est trouvée, rediriger automatiquement l'utilisateur vers la route de cette langue. Cela garantit que son choix explicite est prioritaire et persiste entre les sessions.
Étapes
1. Créer un cookie pour stocker la préférence de langue
Définir un cookie qui contiendra la langue sélectionnée par l'utilisateur avec une durée d'expiration longue.
import { createCookie } from "react-router";
export const languagePreference = createCookie("language-preference", {
maxAge: 31536000,
httpOnly: false,
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
});
Ce cookie persiste pendant un an et est accessible au code côté client pour lire la préférence.
2. Ajouter une action pour stocker la sélection de langue
Créer une action qui gère les soumissions de formulaire de sélection de langue et stocke le choix dans le cookie.
import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";
export async function action({ request }: Route.ActionArgs) {
const formData = await request.formData();
const selectedLanguage = formData.get("language");
if (typeof selectedLanguage === "string") {
return redirect(`/${selectedLanguage}`, {
headers: {
"Set-Cookie": await languagePreference.serialize(selectedLanguage),
},
});
}
return redirect("/");
}
Lorsque l'utilisateur soumet son choix de langue, cette action le stocke dans le cookie et le redirige vers la route de langue appropriée.
3. Créer un composant de sélection de langue
Construire un composant de formulaire qui permet aux utilisateurs de choisir leur langue préférée.
import { Form } from "react-router";
export function LanguageSelector({
currentLanguage,
}: {
currentLanguage: string;
}) {
return (
<Form method="post">
<select
name="language"
defaultValue={currentLanguage}
onChange={(e) => e.currentTarget.form?.requestSubmit()}
>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
<option value="de">Deutsch</option>
</select>
</Form>
);
}
Ce composant se soumet automatiquement lorsque l'utilisateur modifie la sélection, déclenchant l'action qui enregistre la préférence.
4. Vérifier la préférence stockée dans le loader racine
Ajoutez une logique au loader de la route racine qui vérifie la présence d'une préférence linguistique stockée et redirige en conséquence.
import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
const cookieHeader = request.headers.get("Cookie");
const storedLanguage = await languagePreference.parse(cookieHeader);
if (url.pathname === "/" && storedLanguage) {
return redirect(`/${storedLanguage}`);
}
return null;
}
Lorsqu'un utilisateur visite le chemin racine, ce loader vérifie la présence d'une préférence linguistique stockée et le redirige vers la route de langue choisie si elle existe.
5. Valider la langue stockée par rapport aux locales prises en charge
Assurez-vous que la préférence stockée est valide avant de l'utiliser pour la redirection.
import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";
const SUPPORTED_LANGUAGES = ["en", "es", "fr", "de"];
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
const cookieHeader = request.headers.get("Cookie");
const storedLanguage = await languagePreference.parse(cookieHeader);
if (
url.pathname === "/" &&
storedLanguage &&
SUPPORTED_LANGUAGES.includes(storedLanguage)
) {
return redirect(`/${storedLanguage}`);
}
return null;
}
Cette validation empêche la redirection vers des routes linguistiques invalides ou non prises en charge si la valeur du cookie a été modifiée ou si les langues prises en charge ont changé depuis l'enregistrement de la préférence.