Comment créer un composant de sélecteur de langue dans React Router v7
Changer de langue tout en restant sur la même page
Problème
Les utilisateurs s'attendent à ce que les sélecteurs de langue préservent leur contexte actuel. Lorsqu'ils consultent une page produit, un article d'aide ou les paramètres de compte, passer de l'anglais à l'espagnol devrait afficher cette même page en espagnol. Au lieu de cela, de nombreuses implémentations traitent la sélection de langue comme un événement de navigation qui redirige les utilisateurs vers la page d'accueil dans la nouvelle langue, les obligeant à revenir là où ils étaient. Cela interrompt le flux de l'utilisateur et crée de la frustration, en particulier dans les applications riches en contenu où les utilisateurs peuvent se trouver profondément dans une hiérarchie de navigation.
La cause principale est que les sélecteurs de langue utilisent souvent des URL de destination codées en dur plutôt que de construire dynamiquement des URL basées sur la page actuelle. Sans lire et transformer la structure de l'URL actuelle, le sélecteur ne peut pas maintenir la position de l'utilisateur dans l'application lors des changements de langue.
Solution
Créer un composant de sélecteur de langue qui lit l'URL actuelle et extrait à la fois le paramètre de locale actif et les segments de chemin restants. Pour chaque langue prise en charge, générer une nouvelle URL en remplaçant uniquement le segment de locale tout en conservant tous les autres segments de chemin et paramètres de requête intacts. Afficher ces URL sous forme de liens afin que les utilisateurs puissent changer de langue sans perdre leur position dans l'application.
Cette approche traite la locale comme un paramètre remplaçable dans la structure de l'URL plutôt que comme une destination de navigation, garantissant que le passage de /en/products/shoes à /es/products/shoes préserve le contexte de l'utilisateur.
Étapes
1. Créer une fonction utilitaire pour construire des URL tenant compte de la locale
Définissez une fonction qui prend le chemin actuel et une locale cible, puis construit un nouveau chemin en remplaçant le segment de locale.
export function buildLocalePath(
currentPath: string,
newLocale: string,
): string {
const segments = currentPath.split("/").filter(Boolean);
if (segments.length === 0) {
return `/${newLocale}`;
}
segments[0] = newLocale;
return `/${segments.join("/")}`;
}
Cette fonction divise le chemin en segments, remplace le premier segment par la locale cible et reconstruit le chemin. Elle gère les cas particuliers comme le chemin racine et garantit que la locale est toujours le premier segment.
2. Définissez vos locales prises en charge
Créez un objet de configuration qui répertorie toutes les langues prises en charge par votre application.
export const locales = [
{ code: "en", label: "English" },
{ code: "es", label: "Español" },
{ code: "fr", label: "Français" },
{ code: "de", label: "Deutsch" },
];
Cette configuration sert de source de vérité pour déterminer quelles langues afficher dans le sélecteur et fournit des libellés conviviaux pour chaque locale.
3. Créez le composant de sélecteur de langue
Créez un composant qui lit l'emplacement actuel, détermine la locale active et affiche des liens pour toutes les autres langues prises en charge.
import { Link, useLocation, useParams } from "react-router";
import { locales, buildLocalePath } from "./i18n-config";
export function LanguageSwitcher() {
const location = useLocation();
const params = useParams();
const currentLocale = params.locale || "en";
return (
<nav aria-label="Language switcher">
<ul>
{locales.map((locale) => {
const isActive = locale.code === currentLocale;
const newPath = buildLocalePath(location.pathname, locale.code);
return (
<li key={locale.code}>
{isActive ? (
<span aria-current="true">{locale.label}</span>
) : (
<Link to={newPath}>{locale.label}</Link>
)}
</li>
);
})}
</ul>
</nav>
);
}
Le composant utilise useLocation pour accéder au chemin actuel et useParams pour extraire la locale active de l'URL. Pour chaque locale prise en charge, il génère un nouveau chemin à l'aide de la fonction auxiliaire et affiche soit un lien, soit un élément non interactif pour la langue actuelle.
4. Préservez les paramètres de requête et les fragments de hachage
Étendez la fonction auxiliaire pour conserver les chaînes de requête et les fragments d'URL lors du changement de langue.
export function buildLocalePath(
currentPath: string,
search: string,
hash: string,
newLocale: string,
): string {
const segments = currentPath.split("/").filter(Boolean);
if (segments.length === 0) {
return `/${newLocale}${search}${hash}`;
}
segments[0] = newLocale;
return `/${segments.join("/")}${search}${hash}`;
}
Cette version mise à jour accepte les propriétés search et hash de l'objet location et les ajoute au chemin généré, garantissant que les filtres, les paramètres de tri et les liens d'ancrage survivent au changement de langue.
5. Mettez à jour le composant pour utiliser la fonction auxiliaire améliorée
Modifiez le sélecteur pour transmettre les informations complètes de localisation à la fonction auxiliaire.
import { Link, useLocation, useParams } from "react-router";
import { locales, buildLocalePath } from "./i18n-config";
export function LanguageSwitcher() {
const location = useLocation();
const params = useParams();
const currentLocale = params.locale || "en";
return (
<nav aria-label="Language switcher">
<ul>
{locales.map((locale) => {
const isActive = locale.code === currentLocale;
const newPath = buildLocalePath(
location.pathname,
location.search,
location.hash,
locale.code,
);
return (
<li key={locale.code}>
{isActive ? (
<span aria-current="true">{locale.label}</span>
) : (
<Link to={newPath}>{locale.label}</Link>
)}
</li>
);
})}
</ul>
</nav>
);
}
Le composant transmet maintenant location.search et location.hash à l'assistant, garantissant que les URL comme /en/products?category=shoes#reviews deviennent /es/products?category=shoes#reviews lors du passage à l'espagnol.