الميزاتإضافةالتسعيرالموارد
تغيير اللغة
المواردكيفية ترجمة ملفات Drupal .po باستخدام الذكاء الاصطناعي

كيفية ترجمة ملفات Drupal .po باستخدام الذكاء الاصطناعي

SimplePoTranslate Team6 يونيو 2026
كيفية ترجمة ملفات Drupal .po باستخدام الذكاء الاصطناعي

يربط معظم الناس ملفات .po بـ WordPress، لكن تنسيق gettext يسبق WordPress بعقود ويدعم ترجمة الواجهة في جميع أنحاء عالم المصادر المفتوحة. Drupal هو أحد أكبر مستخدميه. إذا كنت تدير موقع Drupal متعدد اللغات، فإن كل تسمية قائمة، ووصف حقل، ورسالة خطأ، وسلسلة وحدة نمطية تمر عبر ملفات .po تمامًا كما هو الحال في WordPress، ولكن بلهجة عنصر نائب مختلفة وسير عمل استيراد مختلف. ومثل WordPress تمامًا، بمجرد أن يتجاوز موقعك عددًا قليلاً من السلاسل، يصبح ترجمة هذه الملفات يدويًا هي عنق الزجاجة.

يدور هذا الدليل حول كيفية ترجمة ملفات Drupal po باستخدام الذكاء الاصطناعي دون إفساد الأشياء التي تجعل Drupal هو Drupal. سنتناول نظام ترجمة Drupal، من أين تأتي السلاسل بالفعل، وبناء جملة العناصر النائبة الذي يختلف عن WordPress ويجب الحفاظ عليه تمامًا، ودورة التصدير والترجمة وإعادة الاستيراد الكاملة بما في ذلك أوامر drush التي تجعلها قابلة للتكرار.

كيف يعمل نظام ترجمة Drupal

يتعامل Drupal مع ترجمة الواجهة من خلال وحدة locale الأساسية (تُسمى أحيانًا "ترجمة الواجهة" في Drupal الحديث). بمجرد تمكينها، تدير جدول قاعدة بيانات لسلاسل المصدر وترجماتها لكل لغة، ويمكنها استيراد وتصدير تلك الترجمات كملفات .po قياسية بتنسيق gettext.

توجد واجهة الإدارة على /admin/config/regional/translate. من هناك يمكنك البحث عن السلاسل غير المترجمة، وتحريرها مباشرةً، والأهم من ذلك، استيراد ملف .po لتحميل الترجمات بكميات كبيرة أو تصدير الحالة الحالية إلى ملف .po للتحرير دون اتصال بالإنترنت. دورة التصدير/التحرير/الاستيراد هذه هي سير العمل الذي نقوم بتحسينه.

على عكس WordPress، حيث يقوم كل مكون إضافي ونسق بشحن ملفات .po و .mo الخاصة به في دليل languages/، يركز Drupal سلاسل الواجهة في قاعدة بياناته ويعامل .po كتنسيق للتبادل. تقوم بالتصدير، والعمل على الملف، ثم استيراده مرة أخرى. تتم معالجة خطوة .mo المجمعة التي يتطلبها WordPress داخليًا.

من أين تأتي السلاسل

تنشأ سلاسل Drupal من ثلاثة أماكن، ويجب أن تغطي الترجمة الكاملة جميعها:

  • النواة (Core) تشحن آلاف السلاسل القابلة للترجمة لواجهة المستخدم الإدارية والنماذج ورسائل النظام.
  • الوحدات النمطية المساهمة (Contrib modules) (مثل Views و Webform و Commerce والبقية) تسجل كل منها سلاسلها الخاصة من خلال دالة t().
  • السمات (Themes) تساهم بسلاسل القوالب، وتسميات المناطق، وأوصاف إعدادات السمات.

عند التصدير من /admin/config/regional/translate، يمكنك تحديد نطاق التصدير ليشمل السلاسل المترجمة أو غير المترجمة أو جميعها. لعملية ترجمة جديدة، يؤدي تصدير السلاسل غير المترجمة فقط إلى الحصول على ملف .po مركز يحتوي على العمل المتبقي بالضبط.

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

تجدر الإشارة أيضًا إلى أن Drupal يمكنه سحب الترجمات التي تساهم بها المجتمع تلقائيًا من localize.drupal.org للنواة والوحدات النمطية المساهمة الشائعة. تغطي تلك الترجمات السلاسل الشائعة، لكنها نادرًا ما تغطي وحداتك النمطية المخصصة، أو نسقك الخاص، أو الصياغة الخاصة بالمشروع التي يستخدمها موقعك فعليًا. الفجوة بين ترجمة المجتمع والموقع المترجم بالكامل هي بالضبط العمل الذي ينجزه الذكاء الاصطناعي بسرعة.

العناصر النائبة في Drupal ليست عناصر نائبة في WordPress

إليك أهم شيء يجب فهمه قبل إرسال أي ملف Drupal .po إلى مترجم ذكاء اصطناعي: لا يستخدم Drupal العناصر النائبة من نمط printf مثل %s و %1$s التي تهيمن على WordPress. تستخدم دالة t() في Drupal ثلاث بادئات مختلفة للعناصر النائبة، لكل منها سلوك هروب مختلف:

  • @variable — يتم هروب القيمة لـ HTML، وهو الافتراضي الآمن للنصوص التي يزودها المستخدم.
  • %variable — يتم هروب القيمة وتغليفها في علامة <em> لتأكيد النص.
  • :placeholder — يستخدم لسمات URL، ويمر عبر تنقية URL.

تبدو سلسلة مصدر Drupal النموذجية هكذا في ملف .po المصدر:

#: core/modules/node/node.module
msgid "@count comments"
msgid_plural "@count comments"
msgstr[0] ""
msgstr[1] ""

#: core/modules/user/user.module
msgid "Welcome @name, you last logged in on %date."
msgstr ""

إذا قام المترجم بتغيير @count إلى @cuenta، استبدل @name بالكلمة المترجمة لكلمة "name"، أو أدخل مسافة تحول @count إلى @ count، فإن العنصر النائب لم يعد يطابق ما تمرره دالة t(). يقوم Drupal عندئذ بطباعة الرمز الحرفي @count إلى الصفحة بدلاً من الرقم الفعلي. تبدو الترجمة منتهية ولكن الموقع معطل بشكل واضح.

هذا هو نفس نوع الخطأ الذي يصيب سلاسل WordPress %s، ونغطي المبدأ العام بعمق في كيفية ترجمة ملفات PO دون إفساد متغيرات التعليمات البرمجية. الخصوصية في Drupal هي ببساطة وجود ثلاثة أنماط للعناصر النائبة بدلاً من واحد، ويجب أن تتعرف أداة الترجمة عليها جميعًا.

لماذا تفشل أدوات الترجمة العامة هنا

الصق سلسلة node.module تلك في مربع ترجمة آلية للمستخدم وستجد غالبًا أن @count مشوهة، أو أن %date المقيدة بـ <em> قد تم تعريبها إلى رمز مختلف، أو أن صيغ الجمع قد تم دمجها في صيغة واحدة. لم يتم بناء أي من هذه الأدوات مع مراعاة دلالات gettext. إنها تترجم النصوص؛ ولا تفهم أن @count هو عقد مع رمز التطبيق.

يعامل خط أنابيب الترجمة المتوافق مع gettext والذي يتميز بـ Syntax Locking (قفل بناء الجملة) الرموز @variable و %variable و :placeholder على أنها رموز غير قابلة للتغيير. يتم قفلها قبل الترجمة وإعادتها بعد ذلك، بحيث تُترجم الجملة المحيطة بينما تمر العناصر النائبة دون تغيير. يغطي نفس القفل %s و %1$s في WordPress، و {{name}} في i18next، و HTML المضمن، وهذا هو السبب في أن أداة واحدة يمكنها خدمة مشروع Drupal أو Symfony أو Laravel بسهولة مثل مشروع WordPress. يتم الحفاظ على صيغ الجمع في Drupal عبر msgid_plural كصيغ جمع بدلاً من تسطيحها، وهذا مهم لأن لغات Drupal يمكن أن تحتوي على ما يتراوح بين متغير واحد إلى ستة متغيرات جمع.

هناك أيضًا وضع فشل أكثر دقة يستحق الإشارة إليه. غالبًا ما تتضمن سلاسل Drupal ترميزًا وروابط مدمجة داخل النص القابل للترجمة، مثل Read the <a href=":url">documentation</a> حيث :url هو عنصر نائب ويجب أن تظل علامات <a> قائمة. المترجم الذي لا يفهم البنية قد يترجم سمة href، أو يسقط العلامة الختامية، أو يعرب اسم العنصر النائب. الذكاء الاصطناعي الواعي بالسياق (Context-Aware AI) الذي يقرأ السلسلة بأكملها كوحدة واحدة، جنبًا إلى جنب مع قفل الرموز، يحافظ على الترميز وعقد :url سليمين بينما يترجم فقط نص "documentation" القابل للقراءة البشرية بينهما.

حلقة التصدير، الترجمة، إعادة الاستيراد

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

الخطوة 1: تصدير ملف PO

يمكنك التصدير من واجهة المستخدم على /admin/config/regional/translate باختيار لغة ونطاق تصدير، أو القيام بذلك من سطر الأوامر. توفر وحدة locale وظيفة التصدير عبر خدمات الترجمة في Drupal، ومعظم الفرق تقوم ببرمجتها. يبدو استدعاء drush النموذجي لتشغيل استيراد الترجمة (العكس، الذي نستخدمه في الخطوة الثالثة) كما يلي:

# Re-import a translated PO file for Spanish, overwriting customized strings
drush locale:import es /var/www/translations/es-untranslated.po \
  --type=customized --override=all

# Rebuild caches so the new strings render immediately
drush cache:rebuild

بالنسبة لجانب التصدير، تنتج استمارة التصدير الإدارية ملف .po؛ تقوم العديد من الفرق بتغليف خدمة تصدير اللغة المحلية في أمر Drush مخصص صغير لأتمتة كاملة. في كلتا الحالتين، ينتهي بك الأمر بملف .po قياسي بتنسيق gettext يحتوي على إدخالات msgid غير المترجمة الخاصة بك.

الخطوة 2: ترجمة الملف

هذه هي المرحلة التي يحل فيها الذكاء الاصطناعي محل ساعات من التحرير اليدوي. ارفع ملف .po المصدر إلى مترجم سحابي، اختر لغتك المستهدفة، ودعه يقوم بالمعالجة. نظرًا لأن ملفات Drupal .po لموقع كبير تتجاوز عادةً 10 ميجابايت بمجرد دمج النواة والمساهمات والسمات، فإن التجميع الذكي (Smart Batching) مهم هنا: يتم تقسيم الملف إلى أجزاء، وترجمته، وإعادة تجميعه دون الحاجة إلى تقسيمه يدويًا أو تجاوز حدود الحجم. المخرج هو ملف .po كامل مع ملء كل msgstr وكل عنصر نائب @count و %date و :url في مكانه الأصلي تمامًا.

الخطوة 3: إعادة الاستيراد إلى Drupal

استورد الملف المترجم مرة أخرى عبر /admin/config/regional/translate أو عبر أمر drush locale:import الموضح أعلاه، ثم أعد بناء ذاكرة التخزين المؤقت. يدمج Drupal الترجمات في جداول اللغات المحلية الخاصة به، وتظهر السلاسل عبر الموقع على الفور. أعد تشغيل الحلقة كلما أضفت وحدة نمطية أو حدثت النواة، حيث يجلب كل منهما سلاسل جديدة غير مترجمة.

تفصيل واحد مهم للاستيراد: علامة --override تتحكم فيما إذا كانت الترجمات الواردة تحل محل الترجمات الموجودة. استخدم --override=all عندما تريد أن يكون الملف المترجم بالذكاء الاصطناعي هو المصدر الموثوق، أو إعدادًا أكثر تحفظًا إذا قمت بتعديل بعض السلاسل يدويًا في واجهة مستخدم Drupal ولا تريد أن يتم تجاوزها. بالنسبة لمعظم خطوط الأنابيب المؤتمتة، فإن التعامل مع ملف .po كمصدر للحقيقة وتجاوز كل شيء يجعل النظام قابلاً للتنبؤ به: الملف في التحكم بالإصدار هو ما يعرضه الموقع، لا أكثر ولا أقل.

بالنسبة للمواقع متعددة اللغات التي تحتوي على عدة لغات مستهدفة، تعمل الحلقة مرة واحدة لكل لغة. صدّر المجموعة غير المترجمة، ترجمها إلى الألمانية، استوردها؛ صدّر مرة أخرى، ترجم إلى الإسبانية، استوردها؛ وهكذا. نظرًا لأن كل لغة هي ملف .po مستقل، يمكنك تشغيلها بالتوازي، ويقوم المترجم السحابي الذي يعالجها في نفس الوقت بتحويل ما كان يستغرق أسبوعًا من وقت المتعاقد إلى فترة بعد الظهر.

ملف PO في Drupal هو أحد التنسيقات المتعددة

تجدر الإشارة إلى أن gettext .po ليس الطريقة الوحيدة التي يتعامل بها Drupal مع الترجمة. يمكن أيضًا تبادل الكيانات التكوينية والمحتوى بتنسيق XLIFF، وهو المعيار الذي تعتمد عليه وحدة Translation Management Tool (TMGMT) لسير عمل موردي الترجمة المحترفين. إذا كان تعريب Drupal الخاص بك يتم عبر XLIFF بدلاً من ملفات .po للواجهة، فإن مبادئ الحفاظ على العناصر النائبة متطابقة ولكن هيكل الملف يختلف، ونغطي هذا المسار في ترجمة ملفات XLIFF لـ Drupal و Symfony و Angular.

بالنسبة لطبقة ترجمة الواجهة، ومع ذلك، يظل .po هو الأداة الرئيسية. تحول حلقة التصدير والترجمة بالذكاء الاصطناعي وإعادة الاستيراد مهمة يدوية تستغرق عدة أيام إلى بضع دقائق من المعالجة، وطالما أن الأداة التي تستخدمها تفهم حقًا العناصر النائبة لـ gettext، فإن عقود @variable الخاصة بك تظل سليمة ويظل موقع Drupal الخاص بك يعمل دون عوائق في كل لغة تقوم بشحنها.

هل أنت مستعد لترجمة ملفات Drupal .po الخاصة بك دون إفساد أي @variable؟ جرب SimplePoTranslate مجانًا — لا يتطلب بطاقة ائتمان. تتعامل الطبقة المجانية مع ملفات .po و .pot القياسية بتنسيق gettext مع قفل كامل لبناء الجملة (Syntax Locking)، لذلك تمر عناصر Drupal النائبة الخاصة بك تمامًا كما يتوقعها الكود.