Wie man Rechts-nach-Links (RTL) Sprachen in React Router v7 unterstützt
Layouts für Arabisch und Hebräisch spiegeln
Problem
Die meisten Design-Systeme gehen davon aus, dass Text von links nach rechts fließt. Die Navigation beginnt links, Seitenleisten verankern sich links und Inhalte werden von links nach rechts gelesen. Arabisch und Hebräisch werden jedoch von rechts nach links gelesen, und ihre Layouts sollten entsprechend gespiegelt werden – was für Englisch links erscheint, sollte für Arabisch rechts erscheinen. Ohne diese Spiegelung fühlt sich die gesamte Benutzeroberfläche rückwärts an. Der visuelle Fluss widerspricht der Leserichtung und schafft eine desorientierte Erfahrung, bei der Benutzer gegen das Layout kämpfen müssen, um natürlich zu lesen.
Die Herausforderung geht über einfache Textausrichtung hinaus. Ränder, Padding, Rahmen und Positionierung müssen sich alle anpassen. Ein Button mit linkem Rand im Englischen sollte im Arabischen einen rechten Rand haben. Symbole, die nach rechts zeigen, sollten nach links zeigen. Die gesamte räumliche Logik der Benutzeroberfläche muss umgedreht werden, um der Leserichtung zu entsprechen.
Lösung
Setzen Sie das dir-Attribut auf dem <html>-Element des Dokuments, um die Textrichtung für die aktuelle Sprache anzugeben. Verwenden Sie ltr für Sprachen von links nach rechts wie Englisch und rtl für Sprachen von rechts nach links wie Arabisch und Hebräisch. Dieses einzelne Attribut veranlasst Browser, viele Layout-Verhaltensweisen automatisch zu spiegeln.
Entwerfen Sie Layouts mit CSS-logischen Eigenschaften wie margin-inline-start anstelle von physischen Eigenschaften wie margin-left, damit sich Abstände automatisch anpassen, wenn sich die Textrichtung ändert. Logische Eigenschaften sind richtungsunabhängig – sie definieren Abstände relativ zum Textfluss und nicht zu festen Bildschirmpositionen. Wenn die Dokumentrichtung RTL ist, wird margin-inline-start zu margin-right, und das Layout spiegelt sich selbst ohne zusätzlichen Code.
Schritte
1. Erkennen der Textrichtung des aktuellen Gebietsschemas
React Router 7 erfordert eine Root-Route in app/root.tsx, die das HTML-Dokument rendert. Erstellen Sie eine Hilfsfunktion, die Gebietsschema-Codes ihrer Textrichtung zuordnet.
const locales = {
en: { dir: "ltr" },
ar: { dir: "rtl" },
he: { dir: "rtl" },
es: { dir: "ltr" },
};
function getTextDirection(locale: string): "ltr" | "rtl" {
return locales[locale as keyof typeof locales]?.dir || "ltr";
}
Diese Funktion gibt die entsprechende Richtung für jedes unterstützte Gebietsschema zurück und verwendet standardmäßig links-nach-rechts für unbekannte Gebietsschemata.
2. Setzen Sie das dir-Attribut auf dem html-Element
In Ihrem Root-Layout rufen Sie das aktuelle Gebietsschema ab und wenden die entsprechende Richtung auf das Dokument an.
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router";
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" dir="ltr">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
export default function Root() {
return <Outlet />;
}
Ersetzen Sie das fest codierte dir="ltr" durch einen dynamischen Wert, der auf Ihrem Mechanismus zur Erkennung des Gebietsschemas basiert. Wenn Ihre App das aktuelle Gebietsschema in einem Loader oder Kontext speichert, lesen Sie es hier und übergeben Sie es an getTextDirection.
3. Verwenden Sie logische Eigenschaften für Abstände
Ersetzen Sie physische CSS-Eigenschaften durch ihre logischen Äquivalente in Ihren Komponenten und Stylesheets.
export default function Card({
title,
children,
}: {
title: string;
children: React.ReactNode;
}) {
return (
<div
style={{
paddingInlineStart: "1rem",
paddingInlineEnd: "1rem",
marginInlineStart: "auto",
borderInlineStart: "4px solid blue",
}}
>
<h2>{title}</h2>
{children}
</div>
);
}
Wenn dir="rtl" gesetzt ist, wird paddingInlineStart auf die rechte Seite und paddingInlineEnd auf die linke Seite angewendet, wodurch das Layout automatisch gespiegelt wird. Die gleiche Komponente funktioniert sowohl in LTR- als auch in RTL-Kontexten korrekt ohne bedingte Logik.
4. Wenden Sie logische Eigenschaften auf Layout-Container an
Verwenden Sie logische Eigenschaften für gängige Layout-Muster wie Navigationsleisten und Content-Grids.
export default function Navigation() {
return (
<nav
style={{
display: "flex",
gap: "1rem",
paddingInline: "2rem",
borderBlockEnd: "1px solid #ccc",
}}
>
<a href="/" style={{ marginInlineEnd: "auto" }}>
Home
</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
);
}
paddingInline setzt Padding auf beiden Inline-Seiten, und marginInlineEnd: "auto" schiebt den Inhalt an den Inline-Start-Rand, der sich von links nach rechts ändert, wenn sich die Richtung ändert. Das Navigationslayout wird für RTL-Sprachen automatisch gespiegelt.
5. Icons und Richtungsgrafiken verarbeiten
Für Icons, die Richtung oder Fluss darstellen, sollten sie basierend auf der Textrichtung bedingt gespiegelt werden.
function BackButton() {
const dir = document.documentElement.dir;
const iconStyle = {
transform: dir === "rtl" ? "scaleX(-1)" : "none",
marginInlineEnd: "0.5rem",
};
return (
<button>
<span style={iconStyle}>←</span>
Back
</button>
);
}
Dies spiegelt das Pfeil-Icon im RTL-Modus horizontal, während der Text und die Abstände durch logische Eigenschaften richtungsbewusst bleiben. Nicht alle Icons müssen gespiegelt werden – nur diejenigen, die Richtung oder Bewegung anzeigen.