أظهرت النسخة الإنجليزية من محلل Cache-Control الذي صدر حديثًا نصًا يابانيًا؛ حيث كانت حالته تظهر "新鮮" بدلاً من "Fresh". ويعود سبب هذا الخطأ إلى منطق برمجي مشترك (shared logic) كان يعيد نصوصًا يابانية مكتوبة بشكل ثابت (hard-coded)، بينما كانت الصفحة توفر تسميات باللغة الإنجليزية فقط.

يقوم المطور ببناء سلسلة من أدوات المتصفح خفيفة الوزن، لكل منها صفحة بالإنجليزية وصفحة باليابانية تعيدان استخدام نفس وظائف التحليل (parsing functions) والمنطق الأساسي. يجب أن يختلف النص المرئي فقط. وعند إطلاق محلل Cache-Control، عرضت الواجهة الإنجليزية التسميات الصحيحة، لكن القيم التي تم عرضها جاءت من طبقة المنطق (logic layer)، والتي كانت لا تزال تحتوي على نصوص يابانية حرفية. لم تظهر أي أخطاء في وحدة التحكم (console)؛ وبدت الصفحة طبيعية، ومع ذلك كانت المعلومات المقدمة للمستخدمين المتحدثين بالإنجليزية خاطئة.

لماذا يمكن للمنطق المشترك أن يخذل الترجمة

نبع الخطأ من خيار في التصميم: الوظيفة الأساسية التي تقرر ما يجب عرضه كانت تعيد نصوصًا حرفية باللغة اليابانية. ولم تحصل طبقة الصفحة، المسؤولة عن النص الإنجليزي المحيط، على فرصة لاستبدال تلك القيم. ولأن المنطق وواجهة المستخدم (UI) كانا منفصلين تمامًا، ظل المشكلة غير مرئية أثناء الاختبار؛ فكل شيء كان "يعمل" من الناحية التقنية، رغم أن اللغة الموجهة للمستخدم كانت غير صحيحة.

الجانب السلبي هو أن اللغة المستخدمة داخل الوحدة المشتركة تصبح هي اللغة الافتراضية لكل واجهة أمامية (front-end) تستهلكها. وإذا كانت هناك حاجة إلى لغة مختلفة، فإن هذه اللغة الافتراضية تتحول إلى خطأ برمجي خفي.

الحل: المفاتيح، الحزم، وشبكة الأمان

أعاد المؤلف كتابة البنية البرمجية لفصل المهام:

  • حزم الرسائل (Message packs) تحتوي الآن على جميع النصوص القابلة للقراءة البشرية لكل لغة.
  • المنطق المشترك (Shared logic) يعيد مفاتيح رمزية فقط، ولا يعيد نصوصًا خامًا أبدًا.
  • الصفحات (Pages) تبحث عن الكلمة المناسبة من الحزمة ذات الصلة بناءً على المفتاح.

عندما يجب أن تتضمن الرسالة رقمًا، يستخدم الكود الجديد وظيفة صغيرة بدلاً من سلسلة القوالب (template string). يتيح ذلك لكل لغة تحديد مكان الرقم، مما يستوعب الاختلافات في ترتيب الكلمات.

تمت إضافة خطوة بسيطة للتحليل الساكن (static-analysis) أيضًا: تقوم عملية البناء (build process) بفحص الملفات المشتركة بحثًا عن أي أحرف يابانية. وإذا ظهرت أي منها، يتم تنبيه المطور فورًا، مما يمنع تسلل النصوص الأجنبية المكتوبة بشكل ثابت مرة أخرى.

ما تعلمه المؤلف من هذه التجربة

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

توصيات لأي شخص يقوم بصيانة أدوات متعددة اللغات

  • أعد المفاتيح (keys) بدلاً من النصوص (strings) من الوظائف الأساسية. اترك طبقة واجهة المستخدم تتولى عملية التوطين (localization).
  • أو مرر النصوص المطلوبة إلى الوظيفة كمعاملات (parameters). هذا يجعل المنطق مستقلاً عن اللغة.
  • راجع الوحدات المشتركة بحثًا عن نصوص مكتوبة بلغة أصلية بشكل ثابت. يمكن للبحث السريع عن أحرف غير ASCII أن يكشف المشكلات الخفية.
  • أضف فحصًا أثناء وقت البناء (build-time) بحثًا عن الأحرف الأجنبية في الكود المشترك. الاكتشاف المبكر أفضل من الارتباك بعد الإصدار.

ما يجب مراقبته لاحقًا

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