Changement de langue

Implémentez des sélecteurs de langue pour permettre aux utilisateurs de changer leur langue préférée.

Implémentation de base

Utilisez le hook useLingoContext pour obtenir la locale actuelle et une fonction pour la modifier :

"use client"; // For Next.js

import { useLingoContext } from "@lingo.dev/compiler/react";

export function LanguageSwitcher() {
  const { locale, setLocale } = useLingoContext();

  return (
    <select value={locale} onChange={(e) => setLocale(e.target.value)}>
      <option value="en">English</option>
      <option value="es">Español</option>
      <option value="de">Deutsch</option>
      <option value="fr">Français</option>
    </select>
  );
}

Lorsque setLocale() est appelé :

  1. La nouvelle langue est persistée (via un résolveur personnalisé ou le cookie par défaut)
  2. La page se recharge pour appliquer la nouvelle langue

Interface personnalisée

"use client";

import { useLingoContext } from "@lingo.dev/compiler/react";

const locales = [
  { code: "en", name: "English", flag: "🇺🇸" },
  { code: "es", name: "Español", flag: "🇪🇸" },
  { code: "de", name: "Deutsch", flag: "🇩🇪" },
  { code: "fr", name: "Français", flag: "🇫🇷" },
];

export function LanguageSwitcher() {
  const { locale: currentLocale, setLocale } = useLingoContext();

  return (
    <div className="relative">
      <select
        value={currentLocale}
        onChange={(e) => setLocale(e.target.value)}
        className="px-4 py-2 border rounded-md"
      >
        {locales.map((locale) => (
          <option key={locale.code} value={locale.code}>
            {locale.flag} {locale.name}
          </option>
        ))}
      </select>
    </div>
  );
}

Groupe de boutons

"use client";

import { useLingoContext } from "@lingo.dev/compiler/react";

export function LanguageSwitcher() {
  const { locale, setLocale } = useLingoContext();

  const locales = ["en", "es", "de", "fr"];

  return (
    <div className="flex gap-2">
      {locales.map((loc) => (
        <button
          key={loc}
          onClick={() => setLocale(loc)}
          className={`px-3 py-1 rounded ${
            locale === loc ? "bg-blue-500 text-white" : "bg-gray-200"
          }`}
        >
          {loc.toUpperCase()}
        </button>
      ))}
    </div>
  );
}
"use client";

import { useState } from "react";
import { useLingoContext } from "@lingo.dev/compiler/react";

export function LanguageSwitcher() {
  const { locale, setLocale } = useLingoContext();
  const [isOpen, setIsOpen] = useState(false);

  const locales = [
    { code: "en", name: "English" },
    { code: "es", name: "Español" },
    { code: "de", name: "Deutsch" },
    { code: "fr", name: "Français" },
  ];

  const currentLocaleName = locales.find((l) => l.code === locale)?.name;

  return (
    <div className="relative">
      <button
        onClick={() => setIsOpen(!isOpen)}
        className="px-4 py-2 border rounded-md flex items-center gap-2"
      >
        <span>{currentLocaleName}</span>
        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
        </svg>
      </button>

      {isOpen && (
        <div className="absolute top-full mt-2 bg-white border rounded-md shadow-lg">
          {locales.map((loc) => (
            <button
              key={loc.code}
              onClick={() => {
                setLocale(loc.code);
                setIsOpen(false);
              }}
              className={`block w-full text-left px-4 py-2 hover:bg-gray-100 ${
                locale === loc.code ? "bg-blue-50" : ""
              }`}
            >
              {loc.name}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

Persistance

Par défaut, setLocale() utilise votre persistance de langue configurée (cookie par défaut).

Persistance personnalisée

Implémentez une persistance personnalisée via les résolveurs de langue personnalisés :

// .lingo/locale-resolver.client.ts
export function persistLocale(locale: string): void {
  // Custom logic: localStorage, URL params, API call, etc.
  localStorage.setItem("locale", locale);
  window.location.reload();
}

setLocale() appelle automatiquement votre fonction persistLocale().

Éviter le rechargement de page

Par défaut, setLocale() recharge la page pour appliquer la nouvelle langue. Pour éviter le rechargement :

  1. Utilisez la gestion d'état côté client
  2. Préchargez les traductions pour toutes les langues
  3. Changez les traductions sans recharger la page

Remarque : cela nécessite une implémentation personnalisée — le comportement par défaut du compilateur recharge la page par simplicité.

Changement de langue basé sur l'URL

Pour le routage de langue basé sur l'URL (/en/about, /es/about) :

"use client";

import { useRouter, usePathname } from "next/navigation";

export function LanguageSwitcher() {
  const router = useRouter();
  const pathname = usePathname();

  // Extract current locale from path: /es/about → es
  const currentLocale = pathname.split("/")[1];

  function switchLocale(newLocale: string) {
    // Replace locale in path: /es/about → /de/about
    const newPath = pathname.replace(`/${currentLocale}`, `/${newLocale}`);
    router.push(newPath);
  }

  return (
    <select value={currentLocale} onChange={(e) => switchLocale(e.target.value)}>
      <option value="en">English</option>
      <option value="es">Español</option>
      <option value="de">Deutsch</option>
    </select>
  );
}

Changement basé sur le sous-domaine

Pour le routage basé sur le sous-domaine (es.example.com) :

"use client";

export function LanguageSwitcher() {
  const currentLocale = window.location.hostname.split(".")[0];

  function switchLocale(newLocale: string) {
    const host = window.location.hostname;
    const domain = host.split(".").slice(1).join(".");
    const newHost = `${newLocale}.${domain}`;

    window.location.href = `${window.location.protocol}//${newHost}${window.location.pathname}`;
  }

  return (
    <select value={currentLocale} onChange={(e) => switchLocale(e.target.value)}>
      <option value="en">English</option>
      <option value="es">Español</option>
      <option value="de">Deutsch</option>
    </select>
  );
}

Noms de langues natifs

Affichez les noms de langues dans leur langue native pour une meilleure expérience utilisateur :

const locales = [
  { code: "en", name: "English" },
  { code: "es", name: "Español" },
  { code: "de", name: "Deutsch" },
  { code: "fr", name: "Français" },
  { code: "ja", name: "日本語" },
  { code: "zh", name: "中文" },
  { code: "ar", name: "العربية" },
  { code: "ru", name: "Русский" },
];

Accessibilité

Rendez votre sélecteur de langue accessible :

const { locale, setLocale } = useLingoContext();

<div role="group" aria-label="Language selector">
  <label htmlFor="language-select" className="sr-only">
    Choose language
  </label>
  <select
    id="language-select"
    value={locale}
    onChange={(e) => setLocale(e.target.value)}
    aria-label="Select language"
  >
    {locales.map((loc) => (
      <option key={loc.code} value={loc.code}>
        {loc.name}
      </option>
    ))}
  </select>
</div>

Modèles courants

Intégration dans la barre de navigation

export function Navbar() {
  return (
    <nav className="flex items-center justify-between p-4">
      <Logo />
      <div className="flex items-center gap-4">
        <NavLinks />
        <LanguageSwitcher />
      </div>
    </nav>
  );
}

Intégration dans le pied de page

export function Footer() {
  return (
    <footer className="p-4 border-t">
      <div className="flex justify-between items-center">
        <p>© 2024 Your Company</p>
        <LanguageSwitcher />
      </div>
    </footer>
  );
}
export function MobileMenu() {
  return (
    <div className="mobile-menu">
      <NavLinks />
      <div className="border-t pt-4 mt-4">
        <p className="text-sm text-gray-500 mb-2">Language</p>
        <LanguageSwitcher />
      </div>
    </div>
  );
}

Tests

Testez le changement de langue en développement :

  1. Ajoutez le composant de sélecteur de langue
  2. Lancez le serveur de développement
  3. Cliquez pour changer de langue
  4. Vérifiez que la page se recharge avec la nouvelle langue
  5. Vérifiez que les traductions sont mises à jour

Avec le pseudotraducteur activé, vous verrez immédiatement des fausses traductions.

Questions fréquentes

Pourquoi la page se recharge-t-elle ? Le compilateur recharge la page pour appliquer la nouvelle langue. Cela garantit que tous les composants serveur et les métadonnées sont correctement mis à jour.

Puis-je éviter le rechargement ? Oui, mais cela nécessite une implémentation personnalisée. Préchargez toutes les traductions et gérez l'état côté client manuellement.

Dois-je envelopper LanguageSwitcher dans Suspense ? Non. useLingoContext est synchrone — aucun suspense n'est nécessaire.

Puis-je détecter automatiquement la langue du navigateur de l'utilisateur ? Oui. Implémentez dans Résolveurs de locale personnalisés :

export function getClientLocale(): string {
  return navigator.language.split("-")[0] || "en";
}

Dois-je afficher toutes les locales prises en charge ou seulement quelques-unes ? Affichez toutes dans un menu déroulant. Si de nombreuses locales, regroupez par région ou utilisez une interface de recherche/filtrage.

Prochaines étapes