مقدمة
يبدو بناء موقع يعمل بالعربية والإنجليزية أمرًا بسيطًا حتى تجربه فعليًا. تغيير اللغة سهل. أما قلب اتجاه التخطيط بالكامل — مع الحفاظ على سلاسة الحركات واتجاه الصور الصحيح وسلوك مكوّنات الواجهة بشكل طبيعي — فهنا يتعثر كثير من المطورين.
يوثّق هذا الدليل بالضبط كيف نفّذت دعم RTL وLTR في Dywan Dev، منصة ويب fullstack مبنية بـ React وVite وi18next. بلا نظريات طويلة: ما يعمل فقط.
1. إعداد i18next في تطبيق React + Vite
ثبّت الحزم المطلوبة أولًا:
npm install i18next react-i18next i18next-browser-languagedetector
أنشئ ملفات الترجمة:
src/
locales/
en/translation.json
fr/translation.json
ar/translation.json
هيّئ i18next في ملف مخصّص src/i18n.js:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import en from './locales/en/translation.json';
import fr from './locales/fr/translation.json';
import ar from './locales/ar/translation.json';
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: { en: { translation: en }, fr: { translation: fr }, ar: { translation: ar } },
fallbackLng: 'en',
interpolation: { escapeValue: false }
});
export default i18n;
استورده مرة واحدة في أعلى main.jsx:
import './i18n';
2. التعامل مع تبديل الاتجاه — الطريقة الصحيحة
وهنا تتوقف أغلب الشروحات مبكرًا جدًا. تغيير اللغة لا يكفي: يجب تحديث خاصيتَي HTML dir وlang ديناميكيًا في كل مرة تتغيّر فيها اللغة.
أنشئ خطافًا مخصصًا useDirection.js:
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
const RTL_LANGUAGES = ['ar'];
export const useDirection = () => {
const { i18n } = useTranslation();
useEffect(() => {
const isRTL = RTL_LANGUAGES.includes(i18n.language);
document.documentElement.dir = isRTL ? 'rtl' : 'ltr';
document.documentElement.lang = i18n.language;
}, [i18n.language]);
};
استدعِ هذا الخطاف مرة واحدة في جذر App.jsx:
import { useDirection } from './hooks/useDirection';
function App() {
useDirection();
return (...);
}
بهذا تستجيب واجهتك بالكامل تلقائيًا لتغيّرات اللغة.
3. الجزء الأصعب — الحركات والصور في RTL
قليل من المقالات تتناول هذا. عند التبديل إلى RTL، يتولى CSS النص وأجزاء كبيرة من التخطيط تلقائيًا. لكن الحركات والصور لا تتبع ذلك دائمًا.
الحركات
إذا كنت تستخدم Framer Motion، فيجب أن تحترم الحركات الاتجاهية الاتجاه الحالي. بدل تثبيت قيمة x: 100، اقرأ الاتجاه ديناميكيًا:
import { useTranslation } from 'react-i18next';
const { i18n } = useTranslation();
const isRTL = i18n.language === 'ar';
const slideVariant = {
hidden: { x: isRTL ? -100 : 100, opacity: 0 },
visible: { x: 0, opacity: 1 }
};
الصور
الصور الزخرفية ذات الاتجاه — أسهم، شخصيات تواجه جهةً ما، رسوم واجهة — قد تحتاج إلى انعكاس في RTL. استخدم صنف CSS مشروطًا:
.mirror-rtl {
transform: scaleX(-1);
}
<img
src={arrow}
className={isRTL ? 'mirror-rtl' : ''}
alt="direction indicator"
/>
طبّق ذلك فقط على الصور التي يكون للاتجاه فيها معنى بصري. ليست كل الصور بحاجة للانعكاس — فقط التي توحي باتجاه بصريًا.
4. Tailwind CSS وRTL
يدعم Tailwind من الإصدار 3 فما فوق RTL بشكل مدمج. فعّله في tailwind.config.js (مسارات content الافتراضية تكفي عادةً)؛ ثم استخدم متغيّرات ltr: وrtl: للأدوات الاتجاهية:
<div class="ltr:pl-4 rtl:pr-4">
Content
</div>
هذا يحافظ على تخطيط نظيف دون كتابة أنماط RTL منفصلة.
5. مكوّن تبديل اللغة
فيما يلي مبدّل لغة بسيط وواضح يحدّث كلًا من اللغة والاتجاه:
import { useTranslation } from 'react-i18next';
const languages = [
{ code: 'en', label: 'EN' },
{ code: 'fr', label: 'FR' },
{ code: 'ar', label: 'ع' }
];
export const LanguageSwitcher = () => {
const { i18n } = useTranslation();
return (
<div className="flex gap-2">
{languages.map(({ code, label }) => (
<button
key={code}
onClick={() => i18n.changeLanguage(code)}
className={
i18n.language === code
? 'px-3 py-1 rounded bg-primary text-white'
: 'px-3 py-1 rounded bg-transparent'
}
>
{label}
</button>
))}
</div>
);
};
الخاتمة
دعم RTL ليس مجرد مسألة ترجمة — إنه أيضًا تخطيط وحركة وتجربة مستخدم. الجمع بين i18next للمحتوى، وخطاف للاتجاه لخصائص HTML، ومنطق شرطي للحركات يغطي نحو 95٪ من الحالات العملية.
إن كنت تبني لأسواق ناطقة بالعربية — أو لأي جمهور ثنائي اللغة — فالإحكام من البداية يوفر عليك إعادة هيكلة كبيرة لاحقًا.
Dywan Dev مبني على هذا النموذج نفسه: منصة متعددة اللغات جاهزة لـ RTL ومصممة للوصول العالمي. إذا احتجت موقعًا يتحدث لغة جمهورك حرفيًا، تواصل معي.
