الأرقام هي التفصيل الذي يشي بغربة الواجهة بصمت. قد يكون كل شيء آخر صحيحاً — الترجمة والتخطيط والخطوط — ويبقى سعر معروض بـSAR 1,234.00 بجوار رقم طلب بـ١٢٣٤ يُقرأ كمنتج غير مكتمل.
الإجابة المختصرة: اختر نظام أرقام واحداً بوعي وطبّقه باتساق. استخدم Intl.NumberFormat لا معالجة النصوص. ولا تعكس أرقام الهواتف أو الآيبان أو البطاقات مهما كان اختيارك.
هذا الدليل يغطي الأرقام والعملات وأخطاء الاتجاه التي تسببها. أما للنطاق الأوسع، فراجع الدليل الكامل لتعريب التطبيقات والمواقع.
نظامان رقميان، قرار واحد
تستخدم العربية مجموعتي أرقام متداولتين:
| الأرقام | شائعة في | |
|---|---|---|
العربية الغربية (latn) | 0 1 2 3 4 5 6 7 8 9 | الخليج، خصوصاً السياقات التجارية والتقنية |
العربية الشرقية (arab) | ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ | مصر والشام، والسياقات الرسمية والمطبوعة |
كلاهما عربي صحيح. والتسمية مربكة — فالأرقام «العربية الغربية» هي التي تستخدمها الإنجليزية، لأن أوروبا أخذتها عن الرياضيات العربية.
كيف تختار:
- المنتجات التجارية الخليجية — الأرقام الغربية الخيار الأسلم. يقرأها المستخدمون بطلاقة، وتتفادى الالتباس في الأسعار والمراجع.
- مصر والشام، أو السياقات الرسمية والتحريرية — الأرقام الشرقية تبدو أقرب للأصالة.
- خدمة المنطقة كاملة — الأرقام الغربية أقل مخاطرة؛ فهي مقروءة للجميع، بينما تبدو الشرقية غير مألوفة لبعض مستخدمي الخليج في السياق التجاري.
- المنتجات الحكومية والمؤسسية — اتبع عرف الجهة التي تعمل معها.
والخطأ الحقيقي ليس في الاختيار بل في عدم الاتساق. الخلط بينهما في واجهة واحدة هو ما يجعل المنتج يبدو غير مكتمل. قرّر مرة واحدة، وضع القرار في إعدادات اللغة، ولا تكتب رقماً داخل الكود أبداً.
استخدم Intl لا الاستبدال النصي
الغريزة الأولى كتابة دالة تبدّل الأرقام. لا تفعل — ستخطئ في الفواصل العشرية وفواصل الآلاف والأرقام السالبة.
كل بيئة تشغيل حديثة توفّر هذا داخلياً:
// أرقام غربية
new Intl.NumberFormat("ar-SA-u-nu-latn").format(1234.5); // "1,234.5"
// أرقام شرقية
new Intl.NumberFormat("ar-SA-u-nu-arab").format(1234.5); // "١٬٢٣٤٫٥"
امتداد -u-nu- يحدد نظام الترقيم صراحةً، وهذا ما يجعل السلوك متوقعاً — فالاعتماد على الافتراضي يختلف بين المنصات وإصدارات بيئة التشغيل.
والعملة تعمل بالطريقة نفسها:
new Intl.NumberFormat("ar-SA-u-nu-latn", {
style: "currency",
currency: "SAR",
}).format(1234.5);
ولاحظ أن العربية تستخدم فواصل مختلفة مع الأرقام الشرقية: ٬ للآلاف و٫ للعشرية، لا الفاصلة والنقطة. وهذا تحديداً ما يخطئ فيه أي محوّل مكتوب يدوياً ويصيبه Intl.
وفي Flutter، توفّر حزمة intl صنف NumberFormat بالسلوك نفسه المبني على اللغة.
العملة: الموضع والرموز التي يخطئ فيها الناس
تنسيق العملة بالعربية ليس مجرد رمز مترجم.
| العملة | الرمز العربي | الرمز الدولي |
|---|---|---|
| الريال السعودي | ر.س | SAR |
| الدرهم الإماراتي | د.إ | AED |
| الريال القطري | ر.ق | QAR |
| الدينار الكويتي | د.ك | KWD |
ثلاث نقاط عملية:
الموضع قاعدة لغوية لا تفضيل. يضع Intl الرمز بعد المبلغ في ar-SA ويحيط الناتج بعلامات اتجاه ليُعرض صحيحاً في سياق ثنائي الاتجاه — فاستدعاء Intl.NumberFormat("ar-SA-u-nu-latn", { style: "currency", currency: "SAR" }).format(1234.5) ينتج 1,234.50 ر.س. مع تلك العلامات. وهذا تحديداً ما تخطئ فيه النصوص المبنية يدوياً: دمج الرمز مع الرقم بنفسك يُسقط علامات العزل، وهكذا ينتهي الرمز في الجهة الخاطئة بصرياً.
وعدد المنازل العشرية يختلف بين العملات. الدينار الكويتي والبحريني والعُماني تستخدم ثلاث منازل عشرية لا اثنتين. والنظام المكتوب فيه منزلتان بشكل ثابت سيعرضها خطأً، بل قد يحسبها خطأً. Intl يعرف هذا، وtoFixed(2) المكتوبة يدوياً لا تعرفه.
ولا تخزّن العملة منسّقة أبداً. خزّن مبلغاً رقمياً ورمز عملة، ونسّق عند العرض. تخزين "ر.س ١٢٣" في قاعدة بيانات قرار ستندم عليه أول مرة تحتاج فيها جمع عمود.
أرقام الهواتف والآيبان وما يجب ألا ينقلب
هذه تحتوي أرقاماً لكنها ليست أعداداً — ترتيب محارفها يحمل معنى، ومعالجة الاتجاه يجب أن تتركها وشأنها.
- أرقام الهواتف (
+966 50 123 4567) - الآيبان (
SA03 8000 0000 6080 1016 7519) - أرقام بطاقات الائتمان
- أرقام الإصدارات (
2.14.3) - مراجع الطلبات والشحنات
- الإحداثيات
والخطأ الذي ينتج عن ذلك: رقم هاتف يُعرض ومفتاح الدولة في الطرف الخطأ، أو آيبان تبدو كتله معكوسة. وهو خطأ عرض لا خطأ بيانات، ما يجعله سهل الإغفال في الاختبار ومقلقاً حين يبلّغ عنه مستخدم.
والحل هو تغليفها بعنصر ذي اتجاه صريح:
<span dir="ltr">+966 50 123 4567</span>
في React Native اضبط writingDirection: "ltr" في نمط النص. وفي Flutter غلّفها بـDirectionality(textDirection: TextDirection.ltr, ...).
واستخدم الأرقام الغربية لهذه مهما كان اختيارك للواجهة. الآيبان بأرقام شرقية قابل للتمثيل تقنياً وغير قابل للاستخدام عملياً — لن يستطيع أحد مطابقته مع كشف حسابه البنكي.
أخطاء الاتجاه التي لا يتوقعها أحد
النص المختلط عربياً ولاتينياً ينتج علامات ترقيم في مواضع خاطئة بصرياً. وهذا ليس خطأ عرض — بل خوارزمية Unicode ثنائية الاتجاه تعمل صحيحاً على مدخل ملتبس.
أين تظهر:
أرقام في نهاية الجملة. الجملة العربية المنتهية برقم لاتيني تتبعه نقطة قد تُعرض النقطة في بداية السطر بصرياً. فالرقم محايد الاتجاه، والخوارزمية تحسمه وفق السياق المحيط.
الإنجليزية المُضمَّنة. أسماء المنتجات والروابط وعناوين البريد داخل الجمل العربية — علامات الترقيم المحيطة ترتبط بشكل غير متوقع.
المحتوى الذي ينشئه المستخدمون. المستخدمون يخلطون الأبجديات بحرية، وأي حقل يعرض نصوصهم سيواجه كل التركيبات.
والحل عزل صريح. في HTML:
<bdi>iPhone 15 Pro</bdi>
عنصر <bdi> يعزل محتواه عن سياق الاتجاه المحيط، وهو تماماً ما تريده لأي نص أجنبي مُضمَّن أو محتوى مستخدم. ولتحكم أدق، تعمل علامتا Unicode (RLM) و (LRM) في أي مكان، بما في ذلك تطبيقات الموبايل.
واختبر عمداً: ضع جملة عربية تحتوي اسم منتج إنجليزياً وسعراً في واجهتك وانظر أين تقع علامات الترقيم. هذا الاختبار وحده يكشف معظم أخطاء الاتجاه.
التواريخ والأوقات
للتواريخ دليلها الخاص، لكن نقطتين تخصّان هذا الدليل لأنهما قرارا تنسيق:
استخدم Intl.DateTimeFormat بدل التنسيق اليدوي، لتتبع نظام الأرقام وأسماء الشهور والترتيب إعدادات اللغة.
وقرّر هل يظهر الهجري وهل هو أساسي أم ثانوي. لمعظم المنتجات الاستهلاكية الخليجية هو عرض ثانوي إلى جانب الميلادي؛ وللمنتجات الحكومية وأنظمة الموارد البشرية أساسي غالباً. وخزّن ميلادياً في الحالتين — التواريخ الهجرية في التطبيقات يشرح السبب.
قائمة تحقق
- نظام أرقام واحد مختار ومضبوط في إعدادات اللغة
- لا أرقام مكتوبة داخل الكود في أي مكان
- كل التنسيق عبر
Intl.NumberFormat/NumberFormat - العملة مخزّنة كمبلغ ورمز، ومنسّقة عند العرض
- العملات ثلاثية المنازل (KWD, BHD, OMR) معالَجة صحيحاً
- أرقام الهواتف والآيبان والبطاقات مثبّتة LTR بأرقام غربية
- النص اللاتيني المُضمَّن معزول بـ
<bdi>أو علامات اتجاه - النصوص المختلطة عربي/إنجليزي مختبَرة لمواضع الترقيم
- التواريخ منسّقة عبر
Intl.DateTimeFormat - مراجعة بمتحدث عربي أصلي
اقرأ أيضاً
- الدليل الكامل لتعريب التطبيقات والمواقع — طبقات التعريب الست.
- التواريخ الهجرية في التطبيقات — التخزين والتحويل والتقويمات.
- دعم العربية وRTL في Flutter — التنفيذ في Flutter.
- دعم العربية وRTL في React Native — التنفيذ في React Native.
- بوابات الدفع في الخليج — حيث يلتقي تنسيق العملة بالمعاملات الحقيقية.
الأسئلة الشائعة
أستخدم ١٢٣ أم 123 في الواجهة العربية؟
كلاهما عربي صحيح. الأرقام الغربية (123) الخيار الأسلم للمنتجات التجارية الخليجية ولأي منتج يخدم المنطقة كاملة، لأنها مقروءة للجميع. والشرقية (١٢٣) تبدو أقرب للأصالة في مصر والشام والسياقات الرسمية والتحريرية. والخطأ الحقيقي هو الخلط بينهما في واجهة واحدة.
كيف أنسّق الأرقام العربية في JavaScript؟
استخدم Intl.NumberFormat مع نظام ترقيم صريح: new Intl.NumberFormat("ar-SA-u-nu-latn") للأرقام الغربية أو -u-nu-arab للشرقية. وتجنّب كتابة دالة تبديل أرقام — ستخطئ في الفواصل العشرية وفواصل الآلاف والأرقام السالبة، والعربية تستخدم محارف فواصل مختلفة مع الأرقام الشرقية.
لماذا يظهر رمز العملة في الجهة الخطأ من السعر؟
دمج النصوص في سياق ثنائي الاتجاه دائماً تقريباً. Intl.NumberFormat مع style: "currency" يضع الرمز في موضعه الصحيح ويتضمن علامات الاتجاه التي تبقيه هناك. أما دمج الرمز مع الرقم بنفسك فيُسقط تلك العلامات، وهذا ما يضع الرمز في الجهة الخطأ.
لماذا تظهر النقطة في بداية جملتي العربية؟
الجملة تنتهي على الأرجح برقم أو كلمة بأبجدية لاتينية. الأرقام محايدة الاتجاه، فتحسم الخوارزمية علامة الترقيم التالية وفق السياق المحيط وتضعها في البداية بصرياً. غلّف المحتوى المُضمَّن بـ<bdi> أو أضف علامة اتجاه من اليمين لليسار بعده.
كيف أعرض أرقام الهواتف في تطبيق عربي؟
ثبّت الاتجاه من اليسار لليمين بـdir="ltr" في HTML، أو writingDirection: "ltr" في React Native، أو ويدجت Directionality في Flutter — واستخدم الأرقام الغربية مهما كان اختيارك للواجهة. وينطبق الأمر نفسه على الآيبان وأرقام البطاقات وأرقام الإصدارات، حيث يحمل ترتيب المحارف معنى.
هل كل العملات الخليجية بمنزلتين عشريتين؟
لا، وهذه تفاجئ الناس. الدينار الكويتي والبحريني والعُماني تستخدم ثلاث منازل عشرية. والنظام المكتوب فيه toFixed(2) بشكل ثابت يعرضها خطأً وقد يُدخل أخطاء تقريب. وIntl.NumberFormat برمز العملة الصحيح يعالج ذلك تلقائياً.
هل أخزّن الأرقام بالصيغة العربية في قاعدة البيانات؟
لا. خزّن القيم العددية كأرقام ونسّق عند العرض. تخزين نصوص منسّقة — أرقاماً كانت أم عملات أم تواريخ — يجعل الترتيب والجمع والمقارنة غير موثوقة، ويقيّد بياناتك بخيار عرض واحد.
الخلاصة
اختر نظام أرقام واحداً وضعه في الإعدادات. الاتساق أهم من أيّهما تختار، وأي رقم مكتوب داخل الكود هو تناقض مستقبلي.
ودع Intl يتولى التنسيق. فهو يعرف محارف الفواصل والعملات ثلاثية المنازل وأعراف اللغة التي سيخطئ فيها أي محوّل مكتوب يدوياً.
واعزل كل ما يحمل ترتيب محارفه معنى. أرقام الهواتف والآيبان والنص اللاتيني المُضمَّن تحتاج اتجاهاً صريحاً، وإلا حسمتها خوارزمية الاتجاه بطرق سيبلّغ عنها مستخدموك كأخطاء.
تبني منتجاً عربياً؟ تواصل معنا لمحادثة تحديد نطاق — هذه التفاصيل هي الفرق بين تطبيق يعمل بالعربية وتطبيق يبدو عربياً. اطّلع على خدمات تطبيقات الموبايل وتطوير الويب.