Comment prendre en charge les langues de droite à gauche (RTL) dans TanStack Start v1
Inverser les mises en page pour l'arabe et l'hébreu
Problème
La plupart des mises en page web supposent que le texte s'écoule de gauche à droite. Les menus de navigation s'ancrent à gauche, les barres latérales apparaissent à gauche et le contenu se lit de gauche à droite. Pour les langues comme l'arabe et l'hébreu qui se lisent de droite à gauche, cela crée une expérience désorientante où le flux visuel contredit le sens de lecture. Les utilisateurs voient la navigation du mauvais côté, les icônes positionnées maladroitement et des mises en page qui semblent inversées. Sans prise en charge RTL appropriée, l'interface devient difficile à naviguer et à comprendre pour les locuteurs de langues RTL.
Solution
Définir dynamiquement la direction du texte du document en fonction de la locale actuelle, permettant au navigateur d'inverser automatiquement la mise en page pour les langues RTL. Utiliser les propriétés logiques CSS au lieu des propriétés directionnelles physiques afin que l'espacement, le positionnement et l'alignement s'adaptent à la direction du texte sans code supplémentaire. Cette approche permet aux mises en page de rester indépendantes de la direction : ce qui apparaît au "début" du contenu en anglais apparaîtra correctement au "début" (côté droit) en arabe, le navigateur gérant la transformation.
Étapes
1. Déterminer la direction du texte à partir de la locale
Créer une fonction utilitaire qui renvoie la direction du texte pour une locale donnée en utilisant l'API d'internationalisation intégrée du navigateur.
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";
}
Cette fonction utilise Intl.Locale.getTextInfo() lorsqu'elle est disponible et se replie sur une liste de langues RTL connues. Elle renvoie soit 'ltr' soit 'rtl' en fonction de la locale.
2. Définir l'attribut dir sur l'élément html
Dans votre route racine, récupérez la locale actuelle et appliquez la direction correspondante à l'élément <html> du document.
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>
);
}
L'attribut dir sur l'élément <html> indique au navigateur d'inverser la mise en page pour les langues RTL. Flexbox, grid et le contenu en ligne se reflètent automatiquement.
3. Remplacer les propriétés CSS physiques par des propriétés logiques
Mettez à jour vos feuilles de style pour utiliser des propriétés logiques qui répondent à la direction du texte au lieu de directions physiques fixes.
.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;
}
Les propriétés logiques comme padding-inline-start correspondent à padding-left en LTR et padding-right en RTL. Le navigateur applique la propriété physique correcte en fonction de l'attribut dir, de sorte que vos styles fonctionnent dans les deux directions sans duplication.
4. Utiliser des valeurs d'alignement indépendantes de la direction
Remplacez les mots-clés d'alignement physiques par des mots-clés logiques dans votre CSS et vos styles en ligne.
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>
);
}
L'utilisation de textAlign: 'end' au lieu de 'right' garantit que le texte s'aligne à la fin de la direction de lecture. Les propriétés Flexbox comme justifyContent et alignItems respectent automatiquement la direction définie par l'attribut dir.