التدويل (i18n)
التدويل (Internationalization أو i18n) هو العمل الهندسي الذي يجعل المنتج قادراً على قبول أي لغة ومنطقة دون تغيير الكود: فالنصوص تُحفظ في ملفات موارد، والتواريخ والمبالغ تأتي من تنسيق واعٍ بالإعداد المحلي، والتخطيط لا يفترض اتجاهاً، وكل طبقة تخزّن يونيكود. ثم يأتي التوطين (Localization أو l10n) ليكيّف المنتج مع إعداد محلي (Locale) واحد، مثل العربية في السعودية (ar-SA) أو الهندية في الهند (hi-IN).
حالة ملموسة: كود صفحة الدفع يبني الإجمالي بالشكل "Total: SAR " + amount. تبدو الإنجليزية صحيحة. أما في العربية والهندية فتبقى كلمة «Total» إنجليزية، ويبقى ترتيب التسمية والرمز والمبلغ وصيغة الرقم كما كتبها المطوّر بدلاً من أن تتبع نمط العملة في الإعداد المحلي نفسه. ولا يستطيع أي مترجم إصلاح ذلك، لأن النص لم يصل أصلاً إلى ملفات الترجمة. هذا عيب تدويل، وهذا الدرس يتناول اكتشاف هذه الفئة مبكراً.
لماذا يهم
معظم عيوب التدويل غير مرئية في لغة المصدر، فالفريق الذي يختبر بالإنجليزية وحدها يشحنها إلى كل الأسواق الأخرى دفعة واحدة. وإصلاحها متأخراً أغلى من إصلاح عيوب الترجمة: فالنص المكتوب في الكود أو نمط التاريخ الثابت يعني تغييراً في الكود وبناءً جديداً وإعادة اختبار في كل إعداد محلي، بينما الترجمة الخاطئة سطر واحد في ملف موارد.
وبالنسبة إلى المختبِر، تحدد معرفة التدويل إلى أين يذهب التقرير. فالتسمية الإنجليزية العادية في الواجهة العربية ليست خطأ ترجمة يُحال إلى المترجم، بل عيب في الكود، ولا يوجد لها مفتاح نص أصلاً.
عملان مختلفان: مرة في الكود، ثم لكل إعداد محلي
قدّم دليل اختبار التوطين المصطلحات، أما ما يهم تصميم الاختبار فهو مكان العمل. التدويل يُنجز مرة واحدة، في الكود، على يد المطورين: إنه خاصية في المنتج. والتوطين يُنجز لكل إعداد محلي على حدة، في المحتوى، على يد المترجمين والخبراء المحليين: نصوص مترجمة وصيغ محلية ونصوص قانونية ووسائل دفع. وبعض الفرق تسمّي الاثنين معاً العولمة (g11n).
ولأن العمل يحدث في أماكن مختلفة، فالعيوب كذلك. عيب التدويل يظهر عادةً في كل إعداد محلي عدا لغة المصدر، ويستطيع أي مختبِر لديه البيانات المناسبة إعادة إنتاجه. وعيب التوطين يظهر في إعداد محلي واحد ويحتاج غالباً إلى متحدث أصلي للحكم عليه. وقد تحمل الشاشة الواحدة النوعين: سعر مبني من قالب نصي (تدويل) ومصطلح عربي خاطئ مقابل كلمة «cart» (توطين).
- سؤال التدويل: هل يقبل المنتج أي إعداد محلي؟ اختبره قبل وجود الترجمة، بإعداد زائف وبيانات يونيكود واتجاه من اليمين إلى اليسار وصيغ غير افتراضية.
- سؤال التوطين: هل هذا الإعداد المحلي صحيح؟ اختبره بعد وجود الترجمة، بالنصوص الحقيقية والصيغ الحقيقية ومتحدث أصلي.
- إعداد محلي لا لغة فقط:
arيختار النص العربي؛ وar-SAيضيف المنطقة التي تحدد الصيغ والعملة والتقويم الافتراضي. ووسوم اللغات تتبع RFC 5646.
التدويل (i18n)
اجعل المنتج قادراً على قبول أي إعداد محلي
- أين يُنجز ومن ينجزه:
- مرة واحدة، في الكود، على يد المطورين
- أين يقع العيب:
- قالب، أو كود تنسيق، أو قاعدة تخطيط، أو مسار تخزين
- من يراه:
- عادةً كل إعداد محلي عدا لغة المصدر
- في شاشة الدفع:
"Total: SAR " + amount: تبقى «Total» إنجليزية ولا يتبع المبلغ صيغة الإعداد المحلي- متى يُكتشف:
- قبل الترجمة: الإعداد الزائف، وبيانات يونيكود، والإعداد الزائف من اليمين إلى اليسار
- يذهب التقرير إلى:
- المطورين، مع الطبقة ومفتاح النص إن وُجد
التوطين (l10n)
كيّف المنتج مع إعداد محلي واحد
- أين يُنجز ومن ينجزه:
- لكل إعداد محلي، في المحتوى، على يد المترجمين والخبراء المحليين
- أين يقع العيب:
- ملف موارد إعداد محلي واحد أو محتواه
- من يراه:
- مستخدمو ذلك الإعداد المحلي وحدهم
- في شاشة الدفع:
- مصطلح عربي خاطئ مقابل كلمة «cart» في ملف الموارد العربي
- متى يُكتشف:
- بعد الترجمة: البناء الموطّن، والصيغ الحقيقية، ومتحدث أصلي
- يذهب التقرير إلى:
- المترجم أو مسؤول التوطين، مع المفتاح ولقطة شاشة
النصوص المستخرجة وبيانات الإعداد المحلي
استخراج النص (Externalising) يعني نقله من الكود إلى ملف موارد تحت مفتاح: يطلب الكود checkout.total ويعيد وقت التشغيل نص الإعداد المحلي الحالي. وكل جملة رسالة واحدة بمعاملات مسماة، لا شظايا تُلصق ببعضها، لأن ترتيب الكلمات والمطابقة يختلفان بين اللغات. أما الأعداد فتستخدم فئات الجمع: قواعد CLDR من يونيكود تعطي الإنجليزية فئتين والهندية فئتين والعربية ست فئات، فتحمل الرسالة صيغة لكل فئة ويختارها المنسِّق؛ وفي صيغة ICU MessageFormat أدناه يحلّ العدد محلّ #.
وبيانات الإعداد المحلي (Locale data) هي كل ما يعرفه وقت التشغيل عن إعداد محلي مما ليس ترجمة: أنماط التاريخ والأرقام، وأشكال الأرقام، ورموز العملات ومواضعها، والتقويم، وأول أيام الأسبوع، وقواعد الجمع، وترتيب الفرز. ومصدرها في معظم المنصات CLDR، وتصل إلى الكود عبر واجهات واعية بالإعداد المحلي مثل كائنات Intl في ECMAScript (المعيار ECMA-402). والكود المدوَّل لا يكتب نمطاً مثل DD/MM/YYYY أبداً؛ بل يمرّر وسم الإعداد المحلي للمستخدم إلى الواجهة ويعرض ما تعيده. وتتغير بيانات CLDR مع إصداراتها الجديدة، لذا يأخذ الاختبار الصيغة المتوقعة من منسِّق المنصة نفسها لا من قيمة نُسخت مرة واحدة من موقع ما.
- المفاتيح الناقصة: قارن كل ملف إعداد محلي بملف المصدر؛ فالمفتاح الموجود في
en.jsonوالغائب عنar.jsonيعود إلى الإنجليزية أو يُظهر المفتاح الخام. - المعاملات: يجب أن تبقى
{name}و{amount}كما هي بعد الترجمة؛ فالمعامل المترجَم يظهر بأقواسه المعقوصة كما هو أو يعطّل المنسِّق، والمعامل المحذوف يُسقط القيمة بصمت.
en.json
"checkout.total": "Total: {amount}"
"checkout.nights": "{count, plural, one {# night} other {# nights}}"
"checkout.greeting": "Welcome back, {name}"
ar.json (المفاتيح نفسها؛ وتحمل العربية فئات الجمع الست كلها)
"checkout.total": "الإجمالي: {amount}"
"checkout.nights": "{count, plural, zero {لا ليالي} one {ليلة واحدة} two {ليلتان}
few {# ليالٍ} many {# ليلة} other {# ليلة}}"
"checkout.greeting": "أهلاً بعودتك يا {name}"
ما يفحصه المختبِر
لكل نص ظاهر مفتاح -> لا شيء مكتوب في القالب
{amount} يصل منسّقاً مسبقاً -> من واجهة الإعداد المحلي لا من الرسالة
{count} يصيب كل فئة جمع -> 0 و1 و2 و3 و11 و100 للعربيةمثال تطبيقي: شاشة دفع بإعداد محلي زائف
التوطين الزائف (Pseudo-localization) يولّد إعداداً محلياً وهمياً من النصوص المصدرية: تُضاف إلى الحروف علامات (Accents)، وتطول كل رسالة وتُحاط بأقواس، ويمكن اختيارياً قلب الاتجاه الأساسي ليصبح من اليمين إلى اليسار. يظل الفريق قادراً على قراءة الشاشة، وأي نص في الواجهة لم يتحوّل لم يُستخرج أصلاً. ولا حاجة إلى مترجم، فيمكن تشغيله في التكامل المستمر مع كل بناء. ويوفّر Android مثلاً الإعدادين الزائفين en-XA (حروف بعلامات ونص أطول) وar-XB (من اليمين إلى اليسار).
فيما يلي شاشة دفع في تطبيق فندقي بالإنجليزية وبالإعداد الزائف، مع ما يخبر به كل سطر المختبِر. ابحث عن إنجليزية عادية، وعن عدة أزواج أقواس حيث يُفترض جملة واحدة، وعن قوس ختامي مفقود، وعن علامات استفهام في مكان الحروف ذات العلامات.
- التمديد: يطول كل نص بمعامل يختاره الفريق، لأن كثيراً من الترجمات أطول من الإنجليزية والعناوين القصيرة تطول أكثر. والتخطيط الذي يصمد أمامه يصمد عادةً أمام النصوص العربية والهندية الحقيقية.
- الإعداد الزائف من اليمين إلى اليسار: يقلب الاتجاه الأساسي دون ترجمة عربية، فتظهر الأيقونات غير المعكوسة وأسهم الرجوع في غير مكانها والنص المحاذى للجهة الخطأ قبل أسابيع من وجود الملف العربي.
English Pseudo-locale ما يراه المختبِر
------------------------ ----------------------------- --------------------------------
Checkout [Çĥéçķöüţ ····] سليم: مستخرج
Book now Book now مكتوب في القالب
You have 2 guests [Ýöü ĥàṽé] 2 [ĝüéšţš] ثلاث قطع: دمج
Total: SAR 1,250.00 Total: SAR 1,250.00 مكتوب في الكود: لا مفتاح له
Room type [?ööm ?ý?é ····] علامات استفهام: مسار ليس UTF-8
Cancel booking [Çàñçéļ ḃööķí مقتطع: زر بعرض ثابت
Welcome back, Ahmed [Ŵéļçömé ḃàçķ, Ahmed ····] سليم: بقي {name} كما هوعيوب التدويل الشائعة وأين تقع
تقع معظم عيوب التدويل في فئات قليلة. لكل فئة عرَض، ومكان في الكود، وطريقة قليلة الكلفة لكشفها؛ ومعرفة الفئة تتيح لك الإبلاغ عن السبب لا عن العرَض فقط.
- نصوص مكتوبة في الكود في رسائل التحقق من المدخلات وأخطاء الواجهة البرمجية والبريد والتسميات ونصوص الصور. للكشف عنها: الإعداد الزائف ثم العربية، مع قراءة كل رسالة بما فيها الرسائل التي لا تظهر إلا عند خطأ.
- الدمج والجمع بشرط
if:"You have " + n + " items"وcount === 1 ? "night" : "nights". العرَض: شظايا بين أقواس، و«2 ليلة» بدلاً من «ليلتان». للكشف عنه: الأعداد 0 و1 و2 و3 و11 و100. - الصيغ الثابتة: قوالب
DD/MM/YYYY، ورموز عملة موضوعة يدوياً، وفاصلة عشرية مكتوبة في الكود. العرَض: الصيغة نفسها في كل إعداد محلي. للكشف عنها:ar-SAوhi-INمع المقارنة بمنسِّق المنصة نفسها. - اتجاه فيزيائي في التخطيط:
margin-leftوtext-align: leftبدلاً من الخصائص المنطقية التي تتبع اتجاه النص (margin-inline-startوtext-align: start) والسمةdir. العرَض: صفحة عربية يبقى تخطيطها إنجليزياً. للكشف عنه: الإعداد الزائف من اليمين إلى اليسار. - مسارات غير يونيكود: عمود أو واجهة برمجية أو تصدير بترميز قديم بدلاً من يونيكود، أو حد طول يُحسب بالبايتات. العرَض: علامات استفهام، أو نص مشوّه (Mojibake)، أو حقل من 100 حرف يرفض 60 حرفاً عربياً (120 بايت في UTF-8). للكشف عنها: مجموعات بيانات يونيكود في كل حقل، ثم افحص القيمة المخزنة.
- الإعداد المحلي يضيع في الطريق: الواجهة عربية لكن البريد أو إيصال PDF أو الرسالة القصيرة بالإنجليزية. للكشف عنه: أكمل مساراً بالعربية وافتح كل مخرج ليس شاشة.
جرّبها: مولّد مجموعات بيانات Unicode جرّبها: عدّاد طول السلاسل النصية جرّبها: مولّد بيانات الاختبار العربية جرّبها: مولّد بيانات الاختبار الهندية
أخطاء شائعة
- انتظار الترجمة قبل اختبار أي شيء؛ فعيوب التدويل تظهر في الإعداد الزائف قبل ذلك بأسابيع.
- الإبلاغ عن تسمية إنجليزية مكتوبة في الكود بوصفها طلب ترجمة؛ فالمترجم لا يستطيع إصلاح نص لا مفتاح له.
- اختبار الصفحات فقط: البريد وملفات PDF والرسائل القصيرة وأخطاء الواجهة البرمجية والتصديرات هي حيث يضيع الإعداد المحلي عادةً.
- اعتبار نجاح الإنجليزية دليلاً؛ فمعظم عيوب التدويل لا تظهر في لغة المصدر أبداً.
- استخدام بيانات اختبار لاتينية فقط في النماذج، فلا يُختبر المسار غير اليونيكودي أبداً.
- معاملة الإعداد الزائف بديلاً عن البناء العربي والبناء الهندي الحقيقيين وعن المراجعة اللغوية.
من منظور ضمان الجودة
عملياً يبدأ اختبار التدويل في مراجعة المتطلبات بثلاثة أسئلة: ما الإعدادات المحلية التي يجب شحنها؟ ومن أين يأتي الإعداد المحلي (إعداد المستخدم، أو ترويسة Accept-Language، أو الجهاز، أو الرابط)؟ وما الذي لا يُترجم عمداً (أسماء العلامات التجارية والرموز والنصوص القانونية)؟ وفي مراجعة الكود، أو مع المطور، اسأل هل النصوص مستخرجة، وهل يمر التنسيق عبر واجهة الإعداد المحلي، وهل يستخدم التخطيط الخصائص المنطقية.
وفي التنفيذ، شغّل بناء الإعداد الزائف أولاً، ثم البناء العربي والبناء الهندي ببيانات اختبار يونيكود، ثم كل مخرج ليس شاشة. وسجّل في التقرير وسم الإعداد المحلي، ومفتاح النص إن وُجد، والشاشة أو المخرج، ولقطة شاشة، والطبقة التي أخطأت فيها القيمة: القالب أو ملف الموارد أو الواجهة البرمجية أو قاعدة البيانات أو خدمة البريد. فالعيب الموصوف بعبارة «مكتوب في قالب الدفع، ويتكرر في كل إعداد محلي» يُصلح في مكان واحد؛ أما تقرير «الترجمة العربية مفقودة» فقد يذهب إلى مترجم لا يستطيع فعل شيء.
تمرين عملي
صنّف نتائج تشغيل بالإعداد الزائف
شُغّل تطبيق حجز فندقي بالإعداد الزائف (en-XA) ثم بالعربية (ar-SA). قرر لكل نتيجة من النتائج الثماني أدناه هل هي عيب تدويل (i18n) أم عيب توطين (l10n)، واذكر أين يقع العيب (الكود، أو ملف الموارد، أو المحتوى المحلي)، ومن يجب أن يتلقى التقرير.
ثم اكتب عنوان خطأ من سطر واحد للنتيجة 3 يسمّي السبب لا العرَض فقط.
1 يظهر زر «Book now» إنجليزياً عادياً في الإعداد الزائف، بينما تعرض بقية الأزرار
نصاً على نمط [Ḃööķ ñöẃ ····].
2 يُقرأ سطر الضيوف [Ýöü ĥàṽé] 2 [ĝüéšţš]: ثلاث قطع بين أقواس.
3 في العربية يظهر سطر الإجمالي «Total: SAR 1,250.00» بالإنجليزية وبأرقام غربية،
بينما تستخدم بقية المبالغ في الصفحة الأرقام العربية-الهندية والرمز ر.س.
4 نوع الغرفة «Deluxe» يظهر «ديلوكس» في صفحة البحث و«فاخرة» في الفاتورة.
5 حقل تاريخ الوصول يقبل MM/DD/YYYY فقط في كل إعداد محلي.
6 بعد حجز بالعربية يصل بريد التأكيد بالإنجليزية، مع أن قالب البريد العربي مكتمل.
7 يظهر عدد الليالي 2 بالشكل «2 ليلة» في العربية بدلاً من «ليلتان»، والإنجليزية سليمة.
وفي الملف العربي المدخلان نفساهما الموجودان في الإنجليزية لهذا النص: واحد للعدد 1
وآخر لأي عدد آخر، والكود لا يقرأ غيرهما.
8 تسمح سياسة الإلغاء العربية بالإلغاء المجاني حتى 24 ساعة قبل الوصول، بينما يقول
النص الإنجليزي المصدر 48 ساعة.- اسأل هل تظهر النتيجة في كل إعداد محلي أم في العربية فقط.
- اسأل هل يستطيع مترجم يملك ملف الموارد إصلاحها.
- سمِّ الطبقة: القالب، أو كود التنسيق، أو ملف الموارد، أو خدمة البريد، أو المحتوى المحلي.
- اكتب عنوان النتيجة 3 على هيئة عرَض ومكان وسبب.
إظهار الإجابة النموذجية
تدويل، في الكود، إلى المطورين: 1 نص مكتوب في القالب؛ 2 جملة مدموجة؛ 3 تسمية مكتوبة في الكود ومبلغ مبني بقالب نصي بدلاً من واجهة الإعداد المحلي؛ 5 نمط تاريخ ثابت بدلاً من حقل تاريخ واعٍ بالإعداد المحلي؛ 6 إعداد محلي لم يُمرَّر إلى خدمة البريد؛ 7 جمع مختار بشرط ثنائي مثل count === 1، بينما تحتاج العربية إلى ست فئات. وكل منها يُصلح مرة واحدة في الكود لكل الإعدادات المحلية.
توطين، في المحتوى العربي، إلى المترجم أو مسؤول التوطين مع مفاتيح النصوص ولقطات الشاشة: 4 مصطلح غير متسق بين شاشتين، في ملف الموارد العربي؛ 8 ترجمة خاطئة تغيّر معنى سياسة الإلغاء، في نص السياسة الموطّن.
النتيجة 7 تظهر في العربية وحدها، فتشير الخطوة الأولى إلى التوطين، لكن الخطوة الثانية تحسم الأمر: لا يستطيع أي مترجم كتابة «ليلتان» في ملف لا يقدّم إلا صيغة للعدد 1 وأخرى لكل ما سواه. والإصلاح رسالة جمع بفئات CLDR، في الكود.
عنوان النتيجة 3: «إجمالي الدفع في ar-SA يعرض Total: SAR 1,250.00 بالإنجليزية وبأرقام غربية: التسمية مكتوبة في الكود والمبلغ منسّق بقالب نصي بدلاً من واجهة الإعداد المحلي».
أسئلة شائعة
هل التدويل مهمة المطورين أم المختبِرين؟
بناؤه عمل هندسي، وفحصه عمل اختباري. يكتشف المختبِرون عيوب التدويل في أبكر وقت بمراجعة المتطلبات بحثاً عن قرارات الإعداد المحلي، وتشغيل الإعداد الزائف مع كل بناء، وتمرير بيانات يونيكود عبر كل طبقة، ويبلّغون عن كل عيب بسببه ليُصلح في الكود مرة واحدة لا أن يُرقَّع لكل إعداد محلي.
هل يغني التوطين الزائف عن الاختبار بالعربية والهندية الحقيقيتين؟
لا. فهو يكشف العيوب التي لا تعتمد على ترجمة حقيقية: النصوص المكتوبة في الكود، والدمج، والاقتطاع، ومشكلات الترميز والاتجاه. أما المصطلحات والقواعد والملاءمة الثقافية وصيغ الإعداد المحلي الحقيقية فما زالت تحتاج إلى البناء الموطّن لكل لغة وبيانات اختبار موطّنة ومراجعة المتحدث الأصلي التي يتناولها درس اختبار الترجمة واللغة.
ما الفرق بين اللغة والإعداد المحلي؟
الوسم الفرعي للغة (Language subtag) مثل ar يختار الترجمة التي تُعرض. والإعداد المحلي يضيف منطقة، كما في ar-SA أو ar-EG (وكلاهما وسم لغة وفق RFC 5646)، وهذه المنطقة تحدد الصيغ والعملة والتقويم وغيرها من الافتراضات. ومستخدمان باللغة نفسها ومنطقتين مختلفتين قد يريان تواريخ ومبالغ مختلفة من الكود نفسه.
هل أحتاج إلى إتقان العربية أو الهندية لاكتشاف عيوب التدويل؟
لا. تظهر عيوب التدويل في صورة إنجليزية عادية، أو شظايا بين أقواس، أو أرقام خاطئة، أو اتجاه تخطيط مكسور، أو محارف ضائعة، ويستطيع أي مختبِر رؤيتها بالتوطين الزائف وبيانات اختبار مولّدة. أما الحكم على جودة الترجمة فيحتاج فعلاً إلى متحدث أصلي.
المراجع
- Internationalization (i18n) Activityمقالات W3C ودروسها وفحوصها في التدويل لبناء محتوى ويب متعدد اللغات واختباره.
- RFC 5646: Tags for Identifying Languagesوسوم اللغات BCP 47 (ar وar-SA وhi-IN وen-GB) — المعرّفات المستخدمة في سمة lang وترويسة Accept-Language وإعدادات اللغة.
- Unicode CLDR Projectمستودع بيانات اللغات والمناطق المشترك: بيانات صيغ التاريخ والوقت والأرقام والعملات وقواعد الجمع التي تعتمدها معظم المنصات.
- ECMAScript Internationalization API Specification (ECMA-402)مواصفة واجهة Intl في JavaScript — التنسيق الواعي باللغة والمنطقة للتواريخ والأرقام والعملات والقوائم وقواعد الجمع في المتصفح.
تدرّب بأدوات متقن
ولّد السجلات نفسها بلغات متعددة (الإنجليزية والعربية والهندية وغيرها) لاختبار التدويل (i18n) واختلاط RTL/LTR.
ولّد سلاسل نصية اختبارية بترميز Unicode عبر الخطوط (العربية والديفاناغارية وCJK والسيريلية) والرموز التعبيرية وعلامات الدمج وصيغ التطبيع.
قِس طول السلسلة النصية بالأحرف ونقاط الترميز (code points) وبايتات UTF-8 ووحدات UTF-16.
مقارنة مستندي JSON دلالياً وإبراز القيم المضافة والمحذوفة والمتغيرة.
ولّد أسماء وعناوين وجملاً وأرقاماً عربية (بالأرقام العربية-الهندية) وحالات حدّية للكتابة من اليمين إلى اليسار لاختبار التوطين.
ولّد أسماء وعناوين وجملاً وأرقاماً هندية (بالخط الديفاناغاري) لاختبار التوطين.
للتعمّق أكثر
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.