معظم مشاكل التعريب في تطبيقات Flutter ليست في الترجمة بل في الاتجاه: قائمة تنزلق من الجهة الخاطئة، أيقونة سهم تشير عكس المسار، حشوة تلتصق بالحافة الخطأ. هذه أخطاء تجعل التطبيق يبدو مترجماً لا مصمَّماً للعربية.
هذا الدليل تقني موجّه للمطورين، ويغطي ما يجب فعله فعلياً في الكود.
تبحث عن الصورة الأوسع؟ هذا الدليل يغطي Flutter تحديداً. أما للنطاق الكامل للتعريب — الطباعة والأرقام وتكييف المحتوى والتكلفة — فابدأ بـالدليل الكامل لتعريب التطبيقات والمواقع.
القاعدة الحاكمة: التعريب قرار معماري يُتخذ في اليوم الأول، لا طبقة تُضاف قبل الإطلاق. إضافته لاحقاً تكلف أضعاف مراعاته من البداية — راجع دليل تكلفة تطوير التطبيقات في الخليج.
1. الودجات الاتجاهية — الأساس كله
هذا أهم قسم في الدليل. القاعدة بسيطة: لا تستخدم left وright أبداً؛ استخدم start وend التي تنعكس تلقائياً مع اتجاه اللغة.
| بدلاً من | استخدم |
|---|---|
EdgeInsets.only(left: 16) | EdgeInsetsDirectional.only(start: 16) |
Alignment.centerLeft | AlignmentDirectional.centerStart |
BorderRadius.only(topLeft: ...) | BorderRadiusDirectional.only(topStart: ...) |
Positioned(left: 0) | PositionedDirectional(start: 0) |
Icons.arrow_back | Icons.arrow_back مع انعكاس (انظر أدناه) |
مثال:
// ❌ يلتصق باليسار دائماً — خطأ في العربية
Padding(
padding: EdgeInsets.only(left: 16),
child: Text('مرحباً'),
)
// ✅ يلتصق ببداية السطر — يمين في العربية، يسار في الإنجليزية
Padding(
padding: EdgeInsetsDirectional.only(start: 16),
child: Text('مرحباً'),
)
نصيحة عملية: امنع EdgeInsets.only بقاعدة lint في مشروعك. هذا يحوّل خطأ يُكتشف بالمراجعة البصرية إلى خطأ يُكتشف عند الكتابة.
2. إعداد اللغات والاتجاه
Flutter يتولى الاتجاه تلقائياً حين تُضبط اللغات بشكل صحيح (راجع توثيق Flutter الرسمي للتدويل):
MaterialApp(
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [Locale('ar'), Locale('en')],
locale: const Locale('ar'),
)
GlobalWidgetsLocalizations هو ما يضبط اتجاه النص تلقائياً. نسيانه يعني أن التطبيق يبقى LTR رغم اختيار العربية — وهذا أشيع خطأ في الإعداد.
لفرض اتجاه على جزء محدد (لعرض كود أو رقم هاتف مثلاً):
Directionality(
textDirection: TextDirection.ltr,
child: Text('+966 5X XXX XXXX'),
)
3. الخطوط العربية
لا تعتمد على الخط الافتراضي. الخطوط الافتراضية على أندرويد تعرض العربية بجودة متفاوتة بين الأجهزة.
ThemeData(
fontFamily: 'IBMPlexSansArabic',
textTheme: const TextTheme(/* ... */),
)
ما يجب مراعاته:
- ارتفاع السطر. العربية تحتاج
heightأكبر من الإنجليزية بسبب النقاط والمدّات. ابدأ بـ1.5وعدّل بصرياً. - أوزان الخط. تأكد أن الخط يوفّر الأوزان التي تستخدمها فعلاً؛ الوزن المفقود يُحاكى برداءة.
- حجم الملف. الخطوط العربية أثقل من اللاتينية — استخدم صيغة
woff2وحمّل الأوزان المستخدمة فقط.
4. الأرقام — نقطة تُغفل دائماً
العربية تُكتب بنمطين للأرقام: الهندية (٠١٢٣) والعربية (0123). الاختيار بينهما قرار منتج لا تقني.
// تنسيق حسب اللغة
final formatter = NumberFormat.decimalPattern('ar');
formatter.format(1234.5); // ١٬٢٣٤٫٥
// لفرض الأرقام اللاتينية في سياق عربي
final latin = NumberFormat.decimalPattern('ar_SA');
قاعدة عملية: استخدم الأرقام اللاتينية للأسعار وأرقام الهواتف وأرقام الطلبات — جمهور الخليج معتاد عليها في هذه السياقات. واستخدم الهندية إن كان جمهورك يفضّلها في المحتوى النصي. الأهم: اتساق واحد عبر التطبيق كله.
5. الأيقونات والحركات
الأيقونات الاتجاهية يجب أن تنعكس: أسهم الرجوع والتقدّم، أيقونات الإرسال، مؤشرات التقدّم.
Transform.flip(
flipX: Directionality.of(context) == TextDirection.rtl,
child: const Icon(Icons.arrow_back),
)
الأيقونات غير الاتجاهية لا تنعكس أبداً: الساعة، الكاميرا، الإعدادات، أي شعار. انعكاسها يبدو خطأً واضحاً.
الحركات تنعكس أيضاً: القائمة الجانبية تنزلق من اليمين، والانتقال بين الصفحات يتجه عكسياً، وشريط التقدّم يمتلئ من اليمين. Flutter يتولى معظم هذا تلقائياً في ودجات Material، لكن حركاتك المخصصة تحتاج معالجة يدوية.
6. النص المختلط (عربي + إنجليزي)
أكثر مصادر الأخطاء البصرية: جملة عربية تحوي كلمة إنجليزية أو رقماً.
الخوارزمية ثنائية الاتجاه (Bidi) تتولى هذا تلقائياً في معظم الحالات، لكن تظهر مشاكل مع علامات الترقيم في نهاية الجملة:
// قد يضع علامة التعجب في المكان الخطأ
Text('مرحباً بك في Flutter!')
// حل صريح عند الحاجة
Text.rich(
TextSpan(children: [
const TextSpan(text: 'مرحباً بك في '),
TextSpan(text: 'Flutter', style: ltrStyle),
const TextSpan(text: '!'),
]),
)
اختبر دائماً بنصوص حقيقية مختلطة لا بنص عربي نقي — الأخطاء تظهر عند الخلط.
7. المكتبات الخارجية — أكثر ما يكسر التعريب
هذه أشيع مصدر للمفاجآت: مكتبة تعمل بامتياز ثم تكسر التخطيط عند تفعيل RTL.
قبل اعتماد أي مكتبة، تحقّق من:
- هل تستخدم الودجات الاتجاهية داخلياً؟
- هل توجد قضايا مفتوحة تخص RTL في مستودعها؟
- متى كان آخر تحديث؟
اختبرها بالعربية قبل بنائها في مشروعك، لا بعده. استبدال مكتبة بعد ربط نصف التطبيق بها مكلف.
قائمة اختبار قبل الإطلاق
مرّ على هذه بنفسك على جهاز حقيقي بالعربية:
- كل الحشوات والهوامش تستخدم
Directional. - القائمة الجانبية تنزلق من اليمين.
- أسهم الرجوع تشير لليمين.
- الأيقونات غير الاتجاهية لم تنعكس.
- النص المختلط يظهر بترتيب صحيح مع علامات الترقيم.
- الأرقام بنمط واحد متسق عبر التطبيق.
- حقول الإدخال تبدأ الكتابة من اليمين.
- رسائل الخطأ والتنبيهات معرّبة ومحاذاة صحيحاً.
- التمرير الأفقي يبدأ من الجهة الصحيحة.
- التبديل بين اللغتين لا يكسر التخطيط ولا يفقد الحالة.
- الشاشات الطويلة — مرّر كامل الصفحة لا الجزء العلوي فقط.
- أحجام شاشات مختلفة — الأخطاء تظهر على الشاشات الصغيرة.
اقرأ أيضاً
- التواريخ الهجرية في التطبيقات — الجانب الآخر من التعريب.
- معمارية Clean Architecture — فصل المنطق يسهّل دعم اللغتين.
- اختبار تطبيقات الجوال — قائمة اختبار RTL قبل الإصدار.
الأسئلة الشائعة
هل Flutter أفضل من React Native لدعم العربية؟
نعم بفارق ملموس. دعم RTL في Flutter مدمج بعمق ويعكس التخطيط والحشوات والحركات تلقائياً عبر الودجات الاتجاهية. React Native يدعم RTL عبر I18nManager لكنه يحتاج ضبطاً يدوياً أكثر، وبعض المكتبات الخارجية تتجاهل RTL. راجع المقارنة الكاملة.
كم يضيف دعم العربية على تكلفة التطبيق؟
2,000$–8,000$ إن رُوعي من مرحلة التصميم. الرقم يرتفع كثيراً — أحياناً للضعف — إن أُضيف بعد اكتمال الواجهات، لأنه يعني مراجعة كل شاشة وكل حشوة.
هل أحتاج ملفين للتصميم، عربي وإنجليزي؟
لا. التصميم الواحد المبني بمبدأ start/end يعمل بالاتجاهين. ما تحتاجه هو مراجعة بصرية للنسخة العربية للتأكد من أن الانعكاس منطقي — خصوصاً في الشاشات المعقدة.
كيف أختبر RTL أثناء التطوير؟
بدّل لغة التطبيق أثناء التشغيل ولا تعتمد على إعداد الجهاز فقط. أضف مبدّل لغة في وضع التطوير لتنتقل بين الاتجاهين بضغطة واحدة — هذا يجعل اختبار كل شاشة عادة لا مهمة منفصلة.
ماذا عن التواريخ الهجرية؟
مسألة منفصلة عن الاتجاه. Flutter لا يدعم التقويم الهجري افتراضياً وتحتاج مكتبة متخصصة. القرار الأهم أن تخزّن التواريخ دائماً بالميلادي في قاعدة البيانات وتحوّلها عند العرض فقط.
هل تنعكس الصور والرسوم؟
الصور الفوتوغرافية لا تنعكس. الرسوم التوضيحية التي تحمل اتجاهاً (شخص يشير، سهم ضمن الرسم) قد تحتاج نسخة معكوسة. القاعدة: انعكس ما يحمل معنى اتجاهياً، واترك ما عداه.
الخلاصة
استخدم الودجات الاتجاهية حصرياً — EdgeInsetsDirectional وAlignmentDirectional وPositionedDirectional. هذه وحدها تحل معظم المشاكل.
اضبط GlobalWidgetsLocalizations — نسيانه يبقي التطبيق LTR رغم اختيار العربية.
اختبر المكتبات الخارجية بالعربية قبل الاعتماد — أشيع مصدر للمفاجآت المتأخرة.
وراعِ التعريب من اليوم الأول — إضافته لاحقاً تكلف أضعافاً.
تبني تطبيقاً عربياً؟ تواصل معنا للحصول على تقييم نطاق مجاني. اطّلع على خدمات تطوير التطبيقات وأعمالنا السابقة.