لماذا يحدث هذا
Replit بيئة عامة تشغّل لغات كثيرة، ووكيلها يختار الإطار حسب طلبك: قد يبني لك تطبيق Flask بقوالب Jinja، أو خادم Express مع قوالب EJS، أو واجهة React. هذا التنوع ميزة، لكنه يعني أن مكان إصلاح الاتجاه يختلف من مشروع لآخر، وأن الحل الذي قرأته لمشروع React قد لا يجد له ملفاً مطابقاً عندك.
في كل الحالات تقريباً يوجد قالب أساسي واحد تمر منه كل الصفحات، وهو الذي يحدد اللغة والاتجاه. إذا بقي على lang="en" بلا dir، يرسم المتصفح الصفحة من اليسار إلى اليمين. ثم يأتي ملف CSS مكتوب بخصائص مثل margin-left و float: right و text-align: left، وهذه لا تنقلب مع الاتجاه.
وفي المشاريع التي فيها خادم وقاعدة بيانات تظهر مشاكل عربية لا علاقة لها بالتصميم، ويخلط الناس بينها وبين مشكلة الاتجاه:
- حروف مشوّهة مثل
الرياضبدل «الرياض»: النص قُرئ بترميز غير UTF-8 في مكان ما بين قاعدة البيانات والمتصفح. - بحث لا يجد النتائج: العميل كتب «احمد» والاسم محفوظ «أحمد»، أو كتب «مكه» والمحفوظ «مكة».
- ملف CSV يفتح رموزاً في Excel: الملف سليم لكنه بلا علامة BOM، فيقرؤه Excel بترميز قديم.
- ترتيب أبجدي غريب: الأسماء التي تبدأ بهمزة تأتي في آخر القائمة لأن الترتيب يتم بالرموز لا باللغة.
كل واحدة من هذه لها إصلاح صغير ومستقل، والخطوات أدناه مرتبة من الواجهة إلى البيانات.
وفي المشاريع التي فيها واجهة منفصلة وخادم منفصل، يكون عندك أحياناً موضعان للاتجاه: صفحة الواجهة نفسها، وأي صفحات يولّدها الخادم مباشرة مثل صفحة تسجيل الدخول أو صفحة الخطأ 404 أو صفحة إعادة تعيين كلمة المرور. هذه الصفحات الثانوية تُنسى كثيراً، فيدخل العميل من رابط في بريده فيرى صفحة إنجليزية الاتجاه وسط موقع عربي. ابحث عن كل ملف فيه وسم <html في المشروع، لا عن الملف الرئيسي فقط.
الحل خطوة بخطوة في Replit
ابدأ بمعرفة القالب الأساسي في مشروعك. افتح شجرة الملفات في Replit وابحث عن أحد هذه الملفات حسب الإطار الذي اختاره الوكيل:
| الإطار | الملف الذي تعدّله | ماذا تبحث عنه |
|---|---|---|
| Flask / Jinja | templates/base.html أو layout.html | {% block content %} |
| Django | templates/base.html | {% block %} |
| Express / EJS | views/layout.ejs أو partials/head.ejs | <%- body %> |
| React / Vite | index.html في الجذر أو client/ | <div id="root"> |
| HTML بسيط | index.html | <body> |
اضبط اللغة والاتجاه والترميز في القالب
أضف السطرين معاً، فوسم
meta charsetيجب أن يكون أول ما فيheadحتى لا يقرأ المتصفح بداية الصفحة بترميز خطأ.code <!doctype html> <html lang="ar" dir="rtl"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{% block title %}صالون لمسة، جدة{% endblock %}</title>حوّل CSS إلى خصائص منطقية
إذا كان المشروع يستخدم CSS عادياً بلا Tailwind، فاستبدل الخصائص الفيزيائية بنظيراتها المنطقية. كلها مدعومة في المتصفحات الحديثة.
code /* قبل */ .card { margin-left: 16px; padding-right: 24px; text-align: left; border-left: 3px solid var(--accent); } .badge { position: absolute; right: 8px; } /* بعد */ .card { margin-inline-start: 16px; padding-inline-end: 24px; text-align: start; border-inline-start: 3px solid var(--accent); } .badge { position: absolute; inset-inline-end: 8px; }تحقق من ترميز قاعدة البيانات
قاعدة Postgres المدمجة في Replit تُدار عبر Neon، وترميزها الافتراضي UTF8 عادة، لكن تحقق بأمر واحد. وإن رأيت الحروف المشوّهة فالخلل غالباً في الاتصال أو في ملف أُدخل بترميز آخر، لا في القاعدة.
code SHOW server_encoding; -- المتوقع: UTF8 SHOW client_encoding; -- المتوقع: UTF8طبّع النص العربي قبل البحث
احفظ نسخة مطبّعة من الحقل الذي يُبحث فيه، وطبّع كلمة البحث بالطريقة نفسها. الدالة توحّد الهمزات والتاء المربوطة والألف المقصورة وتحذف التشكيل والتطويل.
code import re def normalize_ar(text: str) -> str: text = re.sub(r"[\u064B-\u0652\u0640]", "", text) # التشكيل والتطويل text = re.sub(r"[أإآ]", "ا", text) text = text.replace("ة", "ه").replace("ى", "ي") return text.strip() # عند الحفظ: customer.name_search = normalize_ar(customer.name) # عند البحث: WHERE name_search ILIKE %s مع f"%{normalize_ar(q)}%"صدّر CSV يفتح سليماً في Excel
أضف علامة BOM في بداية الملف. في Python يكفي اختيار الترميز
utf-8-sig، وفي Node أضف المحرف في أول النص.code # Python with open("orders.csv", "w", encoding="utf-8-sig", newline="") as f: csv.writer(f).writerows(rows) // Node / Express res.setHeader("Content-Type", "text/csv; charset=utf-8"); res.send("\uFEFF" + csvText);رتّب الأسماء ترتيباً عربياً
في الواجهة استخدم المقارنة حسب اللغة بدل المقارنة بالرموز، فتأتي «أحمد» مع الأسماء التي تبدأ بالألف.
code names.sort((a, b) => a.localeCompare(b, "ar"));
ولتطبيق كل ذلك عبر وكيل Replit، الصق هذا البرومبت كما هو، فهو يذكر الإطار بالاسم حتى لا يبحث الوكيل في ملفات خطأ:
المشروع واجهته عربية للسوق السعودي. أصلح التالي دون تغيير التصميم: 1. في القالب الأساسي لإطار المشروع (base.html أو layout.ejs أو index.html) اجعل <html lang="ar" dir="rtl"> وضع <meta charset="utf-8"> أول وسم في head. 2. حوّل كل خصائص CSS الفيزيائية إلى منطقية: margin-inline-start/end و padding-inline و inset-inline و text-align: start. 3. أضف حقلاً مطبّعاً للبحث في أسماء العملاء يوحّد أ إ آ إلى ا، و ة إلى ه، و ى إلى ي، ويحذف التشكيل، واستخدمه في البحث. 4. اجعل تصدير CSV بترميز UTF-8 مع BOM ليفتح في Excel بالعربي. 5. رتّب القوائم عبر localeCompare مع اللغة ar. اعرض لي قائمة الملفات التي غيّرتها.
إن كان مشروعك في Replit مبنياً على React و Tailwind، فخطوات الأصناف المنطقية وقلب الأيقونات مشروحة بالتفصيل في صفحة RTL في Lovable، وهي تنطبق كما هي.
وهناك مكان ينساه أغلب الناس: رسائل البريد التي يرسلها تطبيقك، مثل تأكيد الحجز أو إشعار الطلب. برامج البريد مثل Gmail و Outlook تتجاهل ملفات CSS الخارجية، فلا يصلها اتجاه موقعك. اجعل الاتجاه والخط داخل الرسالة نفسها:
<div dir="rtl" style="text-align:right; font-family:Tahoma, Arial, sans-serif; line-height:1.7;">
<p>أهلاً نورة،</p>
<p>تم تأكيد موعدك في صالون لمسة يوم الخميس الساعة 5 مساءً.</p>
<p>رقم الحجز: <span dir="ltr">BK-2207</span></p>
</div>استخدمنا هنا Tahoma لأنه متوفر في أغلب الأجهزة ويعرض العربية جيداً، فخطوط الويب لا تُحمَّل في كثير من برامج البريد. ولا تعتمد على اتجاه الموقع في أي نص يخرج منه: رسائل الجوال، ملفات PDF، والإشعارات كلها تحتاج ضبط اتجاه خاص بها.
وأخيراً، جرّب على النسخة المنشورة لا على المعاينة فقط. بعض المشاكل تظهر في الإنتاج وحده، مثل ملف CSS قديم محفوظ في ذاكرة المتصفح أو قالب يختلف بين التطوير والنشر. افتح الرابط العام من جوالك في نافذة خاصة، وأرسل لنفسك بريد تأكيد حقيقياً، وصدّر ملف CSV وافتحه في Excel. ثلاث تجارب في خمس دقائق تكشف ما لا تكشفه المعاينة.
الحل الأسرع: أوترا
في أوترا تبني بالعربية من البداية: الواجهة والمحتوى والاتجاه RTL جزء أصيل من التجربة، والمنصة تفهم طلبك بالفصحى أو اللهجة. وهي مثل Replit بيئة مفتوحة تقبل Python أو Node أو PHP أو غيرها، فلا تخسر حرية اختيار الإطار.
وحين يستخدم مشروعك قاعدة بيانات SQLite أو PostgreSQL أو MySQL، تعرض المنصة جداولها في معاينة «قاعدة البيانات»، فترى بعينك هل حُفظت الأسماء العربية سليمة دون أداة إضافية. وإن أردت نقل مشروع قائم، فاستورده من GitHub عبر خطوات نقل مشروعك من Replit.