Wie man Rechts-nach-Links (RTL) Sprachen in TanStack Start v1 unterstützt
Spiegelung von Layouts für Arabisch und Hebräisch
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 verwirrende Erfahrung, bei der der visuelle Fluss der Leserichtung widerspricht. Benutzer sehen die Navigation auf der falschen Seite, unbeholfen positionierte Icons und Layouts, die sich rückwärts anfühlen. Ohne ordnungsgemäße RTL-Unterstützung wird die Benutzeroberfläche für RTL-Sprachsprecher schwer zu navigieren und zu verstehen.
Lösung
Setzen Sie die Textrichtung des Dokuments dynamisch basierend auf dem aktuellen Gebietsschema, sodass der Browser das Layout für RTL-Sprachen automatisch spiegeln kann. Verwenden Sie CSS-logische Eigenschaften anstelle von physischen Richtungseigenschaften, damit sich Abstände, Positionierung und Ausrichtung ohne zusätzlichen Code an die Textrichtung anpassen. Dieser Ansatz ermöglicht es Layouts, richtungsunabhängig zu bleiben: Was im Englischen am "Anfang" des Inhalts erscheint, wird korrekt am "Anfang" (rechte Seite) im Arabischen erscheinen, wobei der Browser die Transformation übernimmt.
Schritte
1. Textrichtung aus dem Gebietsschema bestimmen
Erstellen Sie eine Hilfsfunktion, die die Textrichtung für ein bestimmtes Gebietsschema 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 andernfalls auf eine Liste bekannter RTL-Sprachen zurück. Sie gibt entweder 'ltr' oder 'rtl' basierend auf dem Gebietsschema zurück.
2. Setzen Sie das dir-Attribut auf dem html-Element
In Ihrer Root-Route rufen Sie das aktuelle Gebietsschema ab und wenden 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 auf dem <html>-Element weist den Browser an, das Layout für RTL-Sprachen umzukehren. Flexbox, Grid und Inline-Inhalte werden automatisch gespiegelt.
3. Ersetzen Sie physische CSS-Eigenschaften durch logische Eigenschaften
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 zu padding-left und in RTL zu padding-right. Der Browser wendet die korrekte physische Eigenschaft basierend auf dem dir-Attribut an, sodass Ihre Stile in beiden Richtungen ohne Duplizierung funktionieren.
4. Verwenden Sie richtungsunabhängige Ausrichtungswerte
Ersetzen Sie physische Ausrichtungsschlüsselwörter durch logische in Ihren CSS- und Inline-Stilen.
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 der Text am Ende der Leserichtung ausgerichtet wird. Flexbox-Eigenschaften wie justifyContent und alignItems respektieren automatisch die durch das dir-Attribut festgelegte Richtung.