كيفية دعم اللغات من اليمين إلى اليسار (RTL) في TanStack Start v1
عكس التخطيطات للعربية والعبرية
المشكلة
تفترض معظم تخطيطات الويب أن النص يتدفق من اليسار إلى اليمين. تثبت قوائم التنقل على اليسار، وتظهر الأشرطة الجانبية على اليسار، ويُقرأ المحتوى من اليسار إلى اليمين. بالنسبة للغات مثل العربية والعبرية التي تُقرأ من اليمين إلى اليسار، يخلق هذا تجربة مربكة حيث يتعارض التدفق البصري مع اتجاه القراءة. يرى المستخدمون التنقل على الجانب الخطأ، والأيقونات موضوعة بشكل غريب، والتخطيطات التي تبدو معكوسة. بدون دعم RTL المناسب، تصبح الواجهة صعبة التنقل والفهم لمتحدثي اللغات من اليمين إلى اليسار.
الحل
تعيين اتجاه نص المستند ديناميكيًا بناءً على اللغة الحالية، مما يسمح للمتصفح بعكس التخطيط تلقائيًا للغات RTL. استخدام خصائص CSS المنطقية بدلاً من الخصائص الاتجاهية الفيزيائية بحيث تتكيف المسافات والموضع والمحاذاة مع اتجاه النص دون كود إضافي. يتيح هذا النهج للتخطيطات أن تظل محايدة الاتجاه: ما يظهر في "بداية" المحتوى بالإنجليزية سيظهر بشكل صحيح في "البداية" (الجانب الأيمن) بالعربية، مع قيام المتصفح بمعالجة التحويل.
الخطوات
1. تحديد اتجاه النص من اللغة
إنشاء دالة مساعدة تُرجع اتجاه النص للغة معينة باستخدام واجهة برمجة التطبيقات المدمجة للتدويل في المتصفح.
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";
}
تستخدم هذه الدالة Intl.Locale.getTextInfo() عندما تكون متاحة وتعود إلى قائمة باللغات RTL المعروفة. تُرجع إما 'ltr' أو 'rtl' بناءً على اللغة.
2. تعيين سمة dir على عنصر html
في المسار الجذري الخاص بك، استرجع اللغة المحلية الحالية وطبّق الاتجاه المقابل على عنصر <html> الخاص بالمستند.
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>
);
}
تخبر السمة dir على عنصر <html> المتصفح بعكس التخطيط للغات التي تُكتب من اليمين إلى اليسار. يتم عكس Flexbox وGrid والمحتوى المضمّن تلقائياً.
3. استبدل خصائص CSS الفيزيائية بالخصائص المنطقية
قم بتحديث أوراق الأنماط الخاصة بك لاستخدام الخصائص المنطقية التي تستجيب لاتجاه النص بدلاً من الاتجاهات الفيزيائية الثابتة.
.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;
}
الخصائص المنطقية مثل padding-inline-start تُطابق padding-left في اللغات التي تُكتب من اليسار إلى اليمين وpadding-right في اللغات التي تُكتب من اليمين إلى اليسار. يطبّق المتصفح الخاصية الفيزيائية الصحيحة بناءً على السمة dir، لذا تعمل أنماطك في كلا الاتجاهين دون تكرار.
4. استخدم قيم محاذاة مستقلة عن الاتجاه
استبدل كلمات المحاذاة الفيزيائية بكلمات منطقية في CSS والأنماط المضمّنة الخاصة بك.
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>
);
}
استخدام textAlign: 'end' بدلاً من 'right' يضمن محاذاة النص إلى نهاية اتجاه القراءة. خصائص Flexbox مثل justifyContent وalignItems تحترم تلقائياً الاتجاه المحدد بواسطة السمة dir.