دليل React Native للعربية (4): القوائم والتنقل والمكتبات

ضبط FlatList و React Navigation ومكونات الطرف الثالث في RTL دون قلب البيانات أو الاتجاه مرتين.

كل المقالات
دليل React Native للعربية (4): القوائم والتنقل والمكتبات

المكونات المركبة تكشف أخطاء RTL التي لا تظهر في بطاقة بسيطة. القائمة الأفقية لها ترتيب بيانات واتجاه تمرير. شريط التنقل له اتجاه حركة ومكان زر الرجوع. والمكتبة الخارجية قد تقرأ I18nManager بينما يعتمد التطبيق لغة داخلية مختلفة.

لا توجد إضافة واحدة تصلح كل هذه الحالات. عرّف السلوك المطلوب لكل مكون ثم اختبره بالعربية والإنجليزية.

FlatList العمودية

القائمة العمودية لا تحتاج إلى قلب البيانات بسبب العربية. احتفظ بترتيب المصدر، واضبط مكون الصف ليحترم اتجاه الشاشة:

<FlatList
  data={items}
  keyExtractor={(item) => item.id}
  extraData={direction}
  renderItem={({ item }) => <ResultRow item={item} direction={direction} />}
/>

FlatList مبنية على PureComponent. إذا كان renderItem يعتمد على قيمة خارج data مثل اللغة أو الاتجاه، مررها في extraData كي تعاد الصفوف عند تغييرها. استخدم مفتاحاً ثابتاً من البيانات، لا index إذا كان ترتيب العناصر يتغير.

داخل الصف، استخدم marginEnd وtextAlign: 'auto'. لا تضف row-reverse إلى القائمة وإلى الصف معاً.

القائمة الأفقية تحتاج قرار ترتيب

اسأل أولاً: هل أول عنصر في البيانات يجب أن يظهر عند بداية القراءة، أم أن القائمة تمثل محوراً مادياً ثابتاً مثل خط زمني من الأقدم إلى الأحدث؟ هذان سلوكان مختلفان.

لا تستخدم inverted كمرادف لـ RTL. توثيق FlatList يبين أن inverted يعكس اتجاه التمرير باستخدام transform، وقد يغير معنى الفهارس وعمليات scrollToIndex. استخدمه فقط عندما تكون القائمة معكوسة وظيفياً، مثل بعض واجهات المحادثة، وبعد اختبار الوصول والتمرير.

ابدأ بقائمة طبيعية واتجاه شاشة صحيح:

<FlatList
  horizontal
  data={categories}
  extraData={direction}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => <CategoryChip item={item} />}
  contentContainerStyle={styles.categoryList}
/>

إذا ظهر أول عنصر في الطرف الخطأ على نسخة محددة من React Native، أنشئ اختباراً صغيراً يثبت السلوك قبل إضافة شرط. لا تجمع بين عكس البيانات وinverted وrow-reverse; قد يبدو أول عنصر صحيحاً بينما يصبح التمرير وscrollToIndex خاطئين.

اختبر هذه العمليات صراحة:

  • موضع أول عنصر عند الفتح.
  • السحب في الاتجاهين.
  • scrollToIndex({ index: 0 }).
  • إضافة عنصر إلى البداية والنهاية.
  • استعادة الموضع بعد تغيير اللغة.

مرر الاتجاه إلى React Navigation

في React Navigation الحالية، يقبل NavigationContainer الخاصية direction. تستخدمها navigators لضبط المحتوى، ومنها مكان drawer:

import { NavigationContainer } from "@react-navigation/native";

const direction = language === "ar" ? "rtl" : "ltr";

export function RootNavigation() {
  return (
    <NavigationContainer direction={direction}>
      <RootStack />
    </NavigationContainer>
  );
}

هذه الخاصية تخبر React Navigation باتجاه التطبيق، لكنها لا تغير اتجاه كل مكون React Native بنفسها. يجب أن يستخدم جذر الواجهة والمكونات الاتجاه نفسه.

لا تثبت drawer على اليسار

يوضح توثيق Drawer Navigator أن drawerPosition افتراضياً left في LTR وright في RTL. إذا كان اتجاه NavigationContainer صحيحاً، ابدأ من الإعداد الافتراضي:

<Drawer.Navigator>
  <Drawer.Screen name="Home" component={HomeScreen} />
</Drawer.Navigator>

إذا كان للمنتج سبب يفرض جانباً ثابتاً، اجعله صريحاً:

<Drawer.Navigator
  screenOptions={{
    drawerPosition: direction === "rtl" ? "right" : "left",
  }}
>
  <Drawer.Screen name="Home" component={HomeScreen} />
</Drawer.Navigator>

لا تثبت drawerPosition على الجهة اليسرى ثم تتوقع من المكتبة أن تقلب القيمة. القيمة الصريحة تعني الجانب الذي كتبته.

اختبر أيضاً إيماءة الفتح، زر الرجوع، انتقالات stack، والعنوان الطويل. بعض القيود في دعم RTL تخص navigator أو المنصة أو نسخة المكتبة، لذلك لا يكفي أن تفتح الشاشة الرئيسية بشكل صحيح.

ScrollView والحاويات

style ينسق إطار ScrollView، بينما contentContainerStyle ينسق الحاوية الداخلية للمحتوى. ضع المسافات المنطقية في المكان الذي تقصده:

<ScrollView
  contentContainerStyle={{
    paddingStart: 16,
    paddingEnd: 16,
    paddingBottom: 24,
  }}
>
  {children}
</ScrollView>

في نموذج طويل، اختبر انتقال التركيز إلى الحقل الذي يحمل خطأ وظهوره فوق لوحة المفاتيح. الاتجاه الصحيح لا يعالج تلقائياً حجب الحقل أو ترتيب التركيز.

قيّم مكتبة الطرف الثالث قبل اعتمادها

عبارة “تدعم RTL” في README لا تكفي. أنشئ شاشة تجريبية صغيرة وافحص:

  1. هل تقرأ المكتبة I18nManager مرة واحدة عند الاستيراد أم تستجيب لتغير اللغة؟
  2. هل تستخدم left وright في التموضع أو الحركة؟
  3. هل ينقلب ترتيب البيانات أم العرض فقط؟
  4. هل تعمل الإيماءات من الحافة الصحيحة؟
  5. هل أسماء الوصول وترتيب التركيز صحيحان؟
  6. هل النسخة المستخدمة ما زالت مدعومة ومتوافقة مع نسخة React Native؟

إذا احتجت patch، احتفظ به في المستودع مع تعليق يذكر نسخة المكتبة ورابط المشكلة واختباراً يمنع رجوع الخطأ. افحص patch بعد كل ترقية. لا تجعل patch-package بديلاً دائماً عن تقييم مكتبة مهجورة.

الحوارات والتنبيهات والبوابات

قد تعرض بعض المكتبات الحوار أو toast في جذر منفصل عن الشاشة، فيفقد الاتجاه الموروث. مرر direction أو isRTL إلى provider نفسه إن كانت المكتبة تدعم ذلك. اختبر النص العربي داخل:

  • Modal و bottom sheet.
  • Toast ورسالة الخطأ.
  • Date picker و time picker.
  • قائمة الاختيار والبحث.
  • WebView إن كان جزءاً من المسار.

لا تنس حالة فتح المكون أثناء تغيير اللغة. قد يكون القرار الصحيح إغلاق overlay وإعادة فتحه بعد اكتمال التغيير بدلاً من إبقاء نسخة نصفها بالاتجاه القديم.

اختبار قبول المكونات

لكل مكون معقد، سجل نتيجة على iOS و Android في اللغتين:

  • موضع البداية والنهاية.
  • ترتيب البيانات المرئي.
  • اتجاه الإيماءة والحركة.
  • زر الرجوع ومكان drawer.
  • التركيز وقارئ الشاشة.
  • النص الطويل وتكبير الخط.
  • إعادة الرسم بعد تغيير اللغة.

إذا كانت النتيجة تعتمد على صدفة في نسخة بعينها، ثبت النسخة واكتب اختباراً قبل ترقيتها.

المراجع الرسمية