So erstellen Sie eine Sprachumschaltungskomponente in React Router v7

Sprachen wechseln und dabei auf derselben Seite bleiben

Problem

Benutzer erwarten, dass Sprachumschaltungen ihren aktuellen Kontext beibehalten. Beim Durchsuchen einer Produktseite, eines Hilfeartikels oder der Kontoeinstellungen sollte der Wechsel von Englisch zu Spanisch dieselbe Seite auf Spanisch anzeigen. Stattdessen behandeln viele Implementierungen die Sprachauswahl als Navigationsereignis, das Benutzer zur Startseite in der neuen Sprache weiterleitet und sie zwingt, zurück zu navigieren, wo sie waren. Dies unterbricht den Arbeitsablauf des Benutzers und führt zu Frustration, insbesondere in inhaltsreichen Anwendungen, in denen sich Benutzer möglicherweise tief in einer Navigationshierarchie befinden.

Die Grundursache liegt darin, dass Sprachumschaltungen häufig fest codierte Ziel-URLs verwenden, anstatt URLs dynamisch basierend auf der aktuellen Seite zu konstruieren. Ohne das Lesen und Transformieren der aktuellen URL-Struktur kann die Umschaltung die Position des Benutzers in der Anwendung über Sprachwechsel hinweg nicht beibehalten.

Lösung

Erstellen Sie eine Sprachumschaltungskomponente, die die aktuelle URL liest und sowohl den aktiven Locale-Parameter als auch die verbleibenden Pfadsegmente extrahiert. Generieren Sie für jede unterstützte Sprache eine neue URL, indem Sie nur das Locale-Segment ersetzen und dabei alle anderen Pfadsegmente und Query-Parameter intakt lassen. Rendern Sie diese URLs als Links, damit Benutzer die Sprache wechseln können, ohne ihre Position in der Anwendung zu verlieren.

Dieser Ansatz behandelt die Locale als austauschbaren Parameter in der URL-Struktur und nicht als Navigationsziel, wodurch sichergestellt wird, dass der Wechsel von /en/products/shoes zu /es/products/shoes den Kontext des Benutzers beibehält.

Schritte

1. Erstellen Sie eine Hilfsfunktion zum Erstellen von Locale-bewussten URLs

Definieren Sie eine Funktion, die den aktuellen Pfadnamen und eine Ziel-Locale entgegennimmt und dann einen neuen Pfad erstellt, indem sie das Locale-Segment ersetzt.

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("/")}`;
}

Diese Funktion teilt den Pfadnamen in Segmente auf, ersetzt das erste Segment durch die Ziel-Locale und rekonstruiert den Pfad. Sie behandelt Sonderfälle wie den Root-Pfad und stellt sicher, dass die Locale immer das erste Segment ist.

2. Definieren Sie Ihre unterstützten Locales

Erstellen Sie ein Konfigurationsobjekt, das alle Sprachen auflistet, die Ihre Anwendung unterstützt.

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

Diese Konfiguration dient als Single Source of Truth dafür, welche Sprachen im Switcher angezeigt werden sollen, und stellt benutzerfreundliche Labels für jede Locale bereit.

3. Erstellen Sie die Sprachumschaltungs-Komponente

Erstellen Sie eine Komponente, die den aktuellen Standort ausliest, die aktive Locale ermittelt und Links für alle anderen unterstützten Sprachen rendert.

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

Die Komponente verwendet useLocation, um auf den aktuellen Pfadnamen zuzugreifen, und useParams, um die aktive Locale aus der URL zu extrahieren. Für jede unterstützte Locale generiert sie einen neuen Pfad mithilfe der Hilfsfunktion und rendert entweder einen Link oder ein nicht-interaktives Element für die aktuelle Sprache.

4. Query-Parameter und Hash-Fragmente beibehalten

Erweitern Sie die Hilfsfunktion, um Query-Strings und URL-Fragmente beim Sprachwechsel beizubehalten.

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

Diese aktualisierte Version akzeptiert die search- und hash-Properties aus dem location-Objekt und hängt sie an den generierten Pfad an, wodurch sichergestellt wird, dass Filter, Sortierparameter und Anker-Links den Sprachwechsel überstehen.

5. Aktualisieren Sie die Komponente zur Verwendung der erweiterten Hilfsfunktion

Modifizieren Sie den Switcher, um die vollständigen Location-Informationen an die Hilfsfunktion zu übergeben.

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

Die Komponente übergibt nun location.search und location.hash an den Helper und stellt sicher, dass URLs wie /en/products?category=shoes#reviews zu /es/products?category=shoes#reviews werden, wenn auf Spanisch umgeschaltet wird.