So unterstützen Sie Rechts-nach-Links-Sprachen (RTL) in TanStack Start v1

Layouts für Arabisch und Hebräisch spiegeln

Problem

Die meisten Web-Layouts gehen davon aus, dass Text von links nach rechts fließt. Navigationsmenüs sind links verankert, Seitenleisten erscheinen links und Inhalte werden von links nach rechts gelesen. Für Sprachen wie Arabisch und Hebräisch, die von rechts nach links gelesen werden, entsteht dadurch eine desorientierte Erfahrung, bei der der visuelle Fluss der Leserichtung widerspricht. Benutzer sehen die Navigation auf der falschen Seite, Icons sind ungünstig positioniert und Layouts wirken rückwärts. Ohne ordnungsgemäße RTL-Unterstützung wird die Benutzeroberfläche für RTL-Sprachsprecher schwer zu navigieren und zu verstehen.

Lösung

Legen Sie die Textrichtung des Dokuments dynamisch basierend auf der aktuellen Locale fest, sodass der Browser das Layout für RTL-Sprachen automatisch spiegelt. Verwenden Sie logische CSS-Eigenschaften anstelle von physischen Richtungseigenschaften, damit sich Abstände, Positionierung und Ausrichtung an die Textrichtung anpassen, ohne zusätzlichen Code zu benötigen. Dieser Ansatz ermöglicht es Layouts, richtungsunabhängig zu bleiben: Was am "Anfang" des Inhalts auf Englisch erscheint, wird korrekt am "Anfang" (rechte Seite) auf Arabisch erscheinen, wobei der Browser die Transformation übernimmt.

Schritte

1. Textrichtung aus Locale bestimmen

Erstellen Sie eine Hilfsfunktion, die die Textrichtung für eine gegebene Locale mithilfe der integrierten Internationalisierungs-API des Browsers zurückgibt.

export function getTextDirection(locale: string): "ltr" | "rtl" {
  try {
    const localeObj = new Intl.Locale(locale);
    if (
      "getTextInfo" in localeObj &&
      typeof localeObj.getTextInfo === "function"
    ) {
      return localeObj.getTextInfo().direction;
    }
  } catch (e) {
    console.warn(`Could not determine direction for locale: ${locale}`);
  }

  const rtlLocales = ["ar", "he", "fa", "ur"];
  const lang = locale.split("-")[0];
  return rtlLocales.includes(lang) ? "rtl" : "ltr";
}

Diese Funktion verwendet Intl.Locale.getTextInfo(), wenn verfügbar, und greift auf eine Liste bekannter RTL-Sprachen zurück. Sie gibt entweder 'ltr' oder 'rtl' basierend auf der Locale zurück.

2. Das dir-Attribut auf dem html-Element setzen

Rufen Sie in Ihrer Root-Route das aktuelle Locale ab und wenden Sie die entsprechende Richtung auf das <html>-Element des Dokuments an.

import {
  createRootRoute,
  Outlet,
  Scripts,
  HeadContent,
} from "@tanstack/react-router";
import { useIntl } from "react-intl";
import { getTextDirection } from "~/utils/text-direction";

export const Route = createRootRoute({
  component: RootComponent,
});

function RootComponent() {
  return (
    <RootDocument>
      <Outlet />
    </RootDocument>
  );
}

function RootDocument({ children }: { children: React.ReactNode }) {
  const intl = useIntl();
  const dir = getTextDirection(intl.locale);

  return (
    <html lang={intl.locale} dir={dir}>
      <head>
        <HeadContent />
      </head>
      <body>
        {children}
        <Scripts />
      </body>
    </html>
  );
}

Das dir-Attribut am <html>-Element weist den Browser an, das Layout für RTL-Sprachen umzukehren. Flexbox, Grid und Inline-Inhalte werden automatisch gespiegelt.

3. Physische CSS-Eigenschaften durch logische Eigenschaften ersetzen

Aktualisieren Sie Ihre Stylesheets, um logische Eigenschaften zu verwenden, die auf die Textrichtung reagieren, anstatt feste physische Richtungen zu verwenden.

.sidebar {
  padding-inline-start: 1rem;
  margin-inline-end: 2rem;
  border-inline-start: 1px solid #ccc;
}

.icon {
  margin-inline-end: 0.5rem;
}

.card {
  inset-inline-start: 0;
  text-align: start;
}

Logische Eigenschaften wie padding-inline-start werden in LTR auf padding-left und in RTL auf padding-right abgebildet. Der Browser wendet die korrekte physische Eigenschaft basierend auf dem dir-Attribut an, sodass Ihre Styles in beiden Richtungen ohne Duplizierung funktionieren.

4. Richtungsunabhängige Ausrichtungswerte verwenden

Ersetzen Sie physische Ausrichtungs-Keywords durch logische in Ihrem CSS und Inline-Styles.

export function Header() {
  return (
    <header
      style={{
        display: "flex",
        justifyContent: "space-between",
        alignItems: "center",
      }}
    >
      <nav style={{ display: "flex", gap: "1rem" }}>
        <a href="/">Home</a>
        <a href="/about">About</a>
      </nav>
      <div style={{ textAlign: "end" }}>
        <button>Menu</button>
      </div>
    </header>
  );
}

Die Verwendung von textAlign: 'end' anstelle von 'right' stellt sicher, dass Text am Ende der Leserichtung ausgerichtet wird. Flexbox-Eigenschaften wie justifyContent und alignItems respektieren automatisch die durch das dir-Attribut festgelegte Richtung.