كيفية إنشاء تطبيق متعدد اللغات: عرض توضيحي باستخدام PHP و Gettext

نشرت: 2022-03-11

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

الاختلافات الجوهرية بين معظم اللغات البشرية تجعل هذا شيئًا غير سهل. تتحد الاختلافات في القواعد النحوية والفروق الدقيقة في اللغة وتنسيقات التاريخ والمزيد لجعل التوطين تحديًا فريدًا وهائلًا.

تأمل في هذا المثال البسيط.

قواعد الجمع في اللغة الإنجليزية واضحة جدًا: يمكنك الحصول على صيغة المفرد للكلمة أو صيغة الجمع للكلمة.

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

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

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

كيفية إنشاء تطبيق متعدد اللغات: عرض توضيحي باستخدام PHP و Gettext

بمجرد أن يتم تدويل قاعدة الشفرة الخاصة بك ، تصبح الترجمة (l10n) مسألة ترجمة محتويات التطبيق الخاص بك إلى لغة / مكان محدد.

يجب إجراء الترجمة في كل مرة تحتاج فيها لغة أو منطقة جديدة إلى الدعم. أيضًا ، كلما تم تحديث جزء من الواجهة (يحتوي على نص) ، يصبح المحتوى الجديد متاحًا - والذي يحتاج بعد ذلك إلى أن يتم ترجمته (أي مترجم) إلى جميع اللغات المدعومة.

في هذه المقالة ، سوف نتعلم كيفية تدويل وتعريب البرامج المكتوبة بلغة PHP. سنتناول خيارات التنفيذ المختلفة والأدوات المختلفة المتاحة تحت تصرفنا لتسهيل العملية.

أدوات التدويل

أسهل طريقة لتدويل برامج PHP هي استخدام ملفات المصفوفات. ستتم تعبئة المصفوفات بسلاسل نصية مترجمة ، والتي يمكن البحث عنها بعد ذلك من داخل القوالب:

 <h1><?=$TRANS['title_about_page']?></h1>

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

واحدة من أكثر الأدوات الكلاسيكية (غالبًا ما يتم اعتبارها كمرجع لـ i18n و l10n) هي أداة Unix تسمى Gettext.

على الرغم من أنها تعود إلى عام 1995 ، إلا أنها لا تزال أداة شاملة لترجمة البرامج سهلة الاستخدام أيضًا. في حين أنه من السهل جدًا البدء به ، إلا أنه لا يزال يحتوي على أدوات دعم قوية.

Gettext هو ما سنستخدمه في هذا المنشور. سنقدم تطبيق GUI رائعًا يمكن استخدامه لتحديث ملفات مصدر l10n بسهولة ، وبالتالي تجنب الحاجة إلى التعامل مع سطر الأوامر.

مكتبات لتسهيل الأمور

مكتبات وأطر عمل ويب PHP الرئيسية التي تدعم Gettext

توجد مكتبات وأطر عمل ويب PHP رئيسية تدعم Gettext وتطبيقات أخرى لـ i18n. بعضها أسهل في التثبيت من البعض الآخر ، أو يتمتع بميزات إضافية أو يدعم تنسيقات ملفات i18n المختلفة. على الرغم من أننا نركز في هذا المستند على الأدوات المقدمة مع نواة PHP ، فإليك قائمة ببعض الأدوات الأخرى الجديرة بالذكر:

  • oscarotero / Gettext: دعم Gettext بواجهة كائنية التوجه ؛ يتضمن وظائف مساعدة محسّنة ومستخلصات قوية للعديد من تنسيقات الملفات (بعضها غير مدعوم أصلاً بواسطة الأمر gettext ). يمكن أيضًا التصدير إلى تنسيقات تتجاوز ملفات .mo / .po فقط ، والتي يمكن أن تكون مفيدة إذا كنت بحاجة إلى دمج ملفات الترجمة في أجزاء أخرى من النظام ، مثل واجهة JavaScript.

  • symfony / translation: يدعم الكثير من التنسيقات المختلفة ، لكنه يوصي باستخدام تنسيق XLIFF المطول. لا يتضمن وظائف مساعدة أو مستخرجًا مضمنًا ، ولكنه يدعم العناصر النائبة باستخدام strtr() داخليًا.

  • zend / i18n: يدعم ملفات المصفوفة و INI ، أو تنسيقات Gettext. تنفذ طبقة التخزين المؤقت لتجنب الحاجة إلى قراءة نظام الملفات في كل مرة. يتضمن أيضًا مساعدي العرض ، وعوامل تصفية الإدخال وأدوات التحقق من الصحة. ومع ذلك ، فإنه لا يحتوي على مستخرج الرسائل.

تتضمن الأطر الأخرى أيضًا وحدات i18n ، ولكنها غير متوفرة خارج قواعد الرموز الخاصة بها:

  • Laravel: يدعم ملفات المصفوفة الأساسية ؛ لا يحتوي على مستخرج تلقائي ولكنه يتضمن مساعد @lang لملفات القوالب.

  • Yii: يدعم ترجمة المصفوفة ، Gettext ، والترجمة المستندة إلى قاعدة البيانات ، ويتضمن مستخرج الرسائل. مدعوم بامتداد Intl ، المتاح منذ PHP 5.3 ، ويعتمد على مشروع ICU. يتيح ذلك لـ Yii تشغيل بدائل قوية ، مثل تهجئة الأرقام وتواريخ التنسيق والأوقات والفترات الزمنية والعملة والأرقام الترتيبية.

إذا قررت الذهاب إلى إحدى المكتبات التي لا توفر برامج الاستخراج ، فقد ترغب في استخدام تنسيقات Gettext ، بحيث يمكنك استخدام سلسلة أدوات Gettext الأصلية (بما في ذلك Poedit) كما هو موضح في باقي الفصل.

تثبيت Gettext

قد تحتاج إلى تثبيت Gettext ومكتبة PHP ذات الصلة باستخدام مدير الحزم ، مثل apt-get أو yum. بعد تثبيته ، قم بتمكينه عن طريق إضافة extension=gettext.so (Linux / Unix) أو extension=php_gettext.dll (Windows) إلى ملف php.ini الخاص بك.

سنستخدم هنا أيضًا Poedit لإنشاء ملفات الترجمة. من المحتمل أن تجده في مدير الحزم في نظامك ؛ إنه متاح لأنظمة Unix و Mac و Windows ويمكن تنزيله مجانًا على موقعه على الويب أيضًا.

أنواع ملفات Gettext

هناك ثلاثة أنواع من الملفات التي عادة ما تتعامل معها أثناء العمل مع Gettext.

والملفات الرئيسية هي ملفات PO (كائن محمول) و MO (كائن آلي) ، الأول عبارة عن قائمة "كائنات مترجمة" قابلة للقراءة والثاني هو الملف الثنائي المقابل (يتم تفسيره بواسطة Gettext عند القيام بالتوطين). يوجد أيضًا ملف POT (PO Template) ، والذي يحتوي ببساطة على جميع المفاتيح الموجودة من ملفات المصدر الخاصة بك ، ويمكن استخدامه كدليل لإنشاء وتحديث جميع ملفات PO.

ملفات القوالب ليست إلزامية ؛ اعتمادًا على الأداة التي تستخدمها لتنفيذ l10n ، ستكون على ما يرام مع ملفات PO / MO فقط. سيكون لديك زوج واحد من ملفات PO / MO لكل لغة ومنطقة ، ولكن سيكون لديك ملف POT واحد فقط لكل مجال.

مجالات منفصلة

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

في هذه الحالات ، ستحتاج إلى تقسيمها إلى "مجالات" مختلفة ، والتي تُسمى أساسًا مجموعات من ملفات POT / PO / MO ، حيث يكون اسم الملف هو مجال الترجمة المذكور.

عادة ما تستخدم المشاريع الصغيرة والمتوسطة الحجم مجالًا واحدًا فقط من أجل التبسيط ؛ اسمها تعسفي ، لكننا سنستخدم "main" في عينات التعليمات البرمجية الخاصة بنا.

في مشاريع Symfony ، على سبيل المثال ، تُستخدم المجالات لفصل الترجمة عن رسائل التحقق من الصحة.

رمز المنطقة

اللغة هي ببساطة رمز يعرف إصدارًا واحدًا من اللغة. يتم تعريفه وفقًا لمواصفات ISO 639-1 و ISO 3166-1 alpha-2: حرفان صغيران للغة ، متبوعين اختياريًا بشرطة سفلية وحرفين كبيرين يحددان رمز البلد أو المنطقة.

للغات النادرة ، يتم استخدام ثلاثة أحرف.

بالنسبة لبعض المتحدثين ، قد يبدو الجزء الخاص بالبلد زائدًا عن الحاجة. في الواقع ، بعض اللغات لها لهجات في بلدان مختلفة ، مثل الألمانية النمساوية (de_AT) أو البرازيلية البرتغالية (pt_BR). يستخدم الجزء الثاني للتمييز بين تلك اللهجات - عندما لا تكون موجودة ، يتم أخذها على أنها نسخة "عامة" أو "هجينة" من اللغة.

بنية الدليل

لاستخدام Gettext ، سنحتاج إلى الالتزام ببنية محددة من المجلدات.

أولاً ، ستحتاج إلى تحديد جذر تعسفي لملفاتك l10n في مستودع المصدر الخاص بك. بداخله ، سيكون لديك مجلد لكل موقع مطلوب ، ومجلد "LC_MESSAGES" ثابت يحتوي على جميع أزواج PO / MO.

مجلد LC_MESSAGES

صيغ الجمع

كما قلنا في المقدمة ، قد تحتوي اللغات المختلفة على قواعد تعدد مختلفة. ومع ذلك ، فإن Gettext يوفر علينا هذه المشكلة.

عند إنشاء ملف .po جديد ، سيتعين عليك الإعلان عن قواعد الجمع لتلك اللغة ، وسيكون للمقاطع المترجمة الحساسة للجمع شكل مختلف لكل من هذه القواعد.

عند استدعاء Gettext في الكود ، سيتعين عليك تحديد رقم مرتبط بالجملة (على سبيل المثال بالنسبة للعبارة "لديك n من الرسائل" ، ستحتاج إلى تحديد قيمة n) ، وستعمل على الشكل الصحيح لاستخدامها - حتى باستخدام استبدال السلسلة إذا لزم الأمر.

تتكون قواعد الجمع من عدد القواعد اللازمة مع اختبار منطقي لكل قاعدة (يمكن حذف اختبار لقاعدة واحدة على الأكثر). علي سبيل المثال:

  • اليابانية: nplurals=1; plural=0; nplurals=1; plural=0; - قاعدة واحدة: لا توجد صيغ جمع

  • الإنجليزية: nplurals=2; plural=(n != 1); nplurals=2; plural=(n != 1); - قاعدتان: استخدم صيغة الجمع فقط عندما لا تكون n 1 ، وإلا استخدم صيغة المفرد.

  • البرتغالية البرازيلية: nplurals=2; plural=(n > 1); nplurals=2; plural=(n > 1); - قاعدتان ، استخدم صيغة الجمع فقط عندما تكون n أكبر من 1 ، وإلا استخدم صيغة المفرد.

للحصول على شرح أعمق ، هناك برنامج تعليمي إعلامي متاح عبر الإنترنت من LingoHub.

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

تنفيذ العينة

بعد كل هذه النظرية ، دعنا نتخذ القليل من العملية. في ما يلي مقتطف من ملف .po (لا تقلق كثيرًا بشأن البنية ، ولكن بدلاً من ذلك ، فقط تعرف على المحتوى العام):

 msgid "" msgstr "" "Language: pt_BR\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgid "We're now translating some strings" msgstr "Nos estamos traduzindo algumas strings agora" msgid "Hello %1$s! Your last visit was on %2$s" msgstr "Ola %1$s! Sua ultima visita foi em %2$s" msgid "Only one unread message" msgid_plural "%d unread messages" msgstr[0] "So uma mensagem nao lida" msgstr[1] "%d mensagens nao lidas"

يعمل القسم الأول كرأس ، حيث يكون كل من msgid و msgstr فارغين.

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

القسم الأخير هو عينة من صيغ الجمع ، ويعرض صيغة المفرد والجمع كـ msgid باللغة الإنجليزية والترجمات المقابلة لها كـ msgstr 0 و 1 (بعد الرقم المعطى بواسطة قاعدة الجمع).

هناك ، يتم استخدام استبدال السلسلة أيضًا ، بحيث يمكن رؤية الرقم مباشرة في الجملة ، باستخدام %d . تحتوي صيغ الجمع دائمًا على نوعين من msgid (المفرد والجمع) ، لذلك يُنصح بعدم استخدام لغة معقدة كمصدر للترجمة.

مفاتيح الترجمة

كما لاحظت ، نحن نستخدم الجملة الإنجليزية الفعلية كمعرف المصدر. هذا msgid هو نفسه المستخدم في جميع ملفات .po ، مما يعني أن اللغات الأخرى سيكون لها نفس التنسيق ونفس حقول msgid لكن سطور msgstr المترجمة.

عند الحديث عن مفاتيح الترجمة ، هناك نهجان "فلسفيان" معياريان هنا:

1. msgid باعتبارها جملة حقيقية

المزايا الرئيسية لهذا النهج هي:

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

  • من الأسهل بكثير على المترجم فهم ما يجري وإجراء ترجمة مناسبة بناءً على msgid .

  • يمنحك l10n "مجانيًا" للغة واحدة - اللغة المصدر.

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

2. msgid كمفتاح منظم فريد

سيصف هذا دور الجملة في التطبيق بطريقة منظمة ، بما في ذلك القالب أو الجزء الذي توجد فيه السلسلة بدلاً من محتواها.

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

ستكون هناك حاجة إلى ملف لغة المصدر كأساس للترجمات الأخرى. على سبيل المثال ، سيكون لدى المطور بشكل مثالي ملف “en.po” ، والذي سيقرأه المترجمون لفهم ما يكتبون في “fr.po”.

قد تعرض الترجمات المفقودة مفاتيح لا معنى لها على الشاشة ("top_menu.welcome" بدلاً من "Hello there، User!" في الصفحة الفرنسية غير المترجمة المذكورة).

هذا جيد لأنه سيجبر الترجمة على الاكتمال قبل النشر - لكن سيئًا لأن مشكلات الترجمة ستكون فظيعة حقًا في الواجهة. على الرغم من ذلك ، تتضمن بعض المكتبات خيارًا لتحديد لغة معينة على أنها "احتياطي" ، ولها سلوك مشابه للنهج الآخر.

يفضل دليل Gettext النهج الأول لأنه ، بشكل عام ، يكون أسهل للمترجمين والمستخدمين في حالة حدوث مشكلة. هذا هو النهج الذي سنستخدمه هنا أيضًا.

وتجدر الإشارة ، مع ذلك ، إلى أن وثائق Symfony تفضل الترجمة القائمة على الكلمات الرئيسية ، للسماح بإجراء تغييرات مستقلة لجميع الترجمات دون التأثير على القوالب أيضًا.

الاستخدام اليومي

في تطبيق شائع ، يمكنك استخدام بعض وظائف Gettext أثناء كتابة نص ثابت في صفحاتك.

ستظهر هذه الجمل بعد ذلك في ملفات .po ، ويتم ترجمتها وترجمتها إلى ملفات .mo ، ثم استخدامها بواسطة Gettext عند عرض الواجهة الفعلية. بالنظر إلى ذلك ، دعنا نربط ما ناقشناه حتى الآن في مثال خطوة بخطوة:

1. نموذج ملف ، بما في ذلك بعض استدعاءات gettext المختلفة

 <?php include 'i18n_setup.php' ?> <div> <h1><?=sprintf(gettext('Welcome, %s!'), $name)?></h1> <!-- code indented this way only for legibility → <?php if ($unread): ?> <h2> <?=sprintf( ngettext('Only one unread message', '%d unread messages', $unread), $unread )?> </h2> <?php endif ?> </div> <h1><?=gettext('Introduction')?></h1> <p><?=gettext('We\'re now translating some strings')?></p>
  • يترجم gettext() ببساطة msgid إلى msgstr المقابل للغة معينة. هناك أيضًا وظيفة الاختزال _() التي تعمل بنفس الطريقة

  • ngettext() يفعل الشيء نفسه لكن مع قواعد الجمع

  • هناك أيضًا dgettext() و dngettext() ، مما يسمح لك بتجاوز المجال لمكالمة واحدة (المزيد عن تكوين المجال في المثال التالي)

2. نموذج ملف الإعداد (i18n_setup.php كما هو مستخدم أعلاه) ، واختيار اللغة الصحيحة وتكوين Gettext

يتضمن استخدام Gettext جزءًا من التعليمات البرمجية المعيارية ، ولكنه يتعلق في الغالب بتكوين دليل locales واختيار المعلمات المناسبة (لغة ومجال).

 <?php /** * Verifies if the given $locale is supported in the project * @param string $locale * @return bool */ function valid($locale) { return in_array($locale, ['en_US', 'en', 'pt_BR', 'pt', 'es_ES', 'es'); } //setting the source/default locale, for informational purposes $lang = 'en_US'; if (isset($_GET['lang']) && valid($_GET['lang'])) { // the locale can be changed through the query-string $lang = $_GET['lang']; //you should sanitize this! setcookie('lang', $lang); //it's stored in a cookie so it can be reused } elseif (isset($_COOKIE['lang']) && valid($_COOKIE['lang'])) { // if the cookie is present instead, let's just keep it $lang = $_COOKIE['lang']; //you should sanitize this! } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { // default: look for the languages the browser says the user accepts $langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); array_walk($langs, function (&$lang) { $lang = strtr(strtok($lang, ';'), ['-' => '_']); }); foreach ($langs as $browser_lang) { if (valid($browser_lang)) { $lang = $browser_lang; break; } } } // here we define the global system locale given the found language putenv("LANG=$lang"); // this might be useful for date functions (LC_TIME) or money formatting (LC_MONETARY), for instance setlocale(LC_ALL, $lang); // this will make Gettext look for ../locales/<lang>/LC_MESSAGES/main.mo bindtextdomain('main', '../locales'); // indicates in what encoding the file should be read bind_textdomain_codeset('main', 'UTF-8'); // if your application has additional domains, as cited before, you should bind them here as well bindtextdomain('forum', '../locales'); bind_textdomain_codeset('forum', 'UTF-8'); // here we indicate the default domain the gettext() calls will respond to textdomain('main'); // this would look for the string in forum.mo instead of main.mo // echo dgettext('forum', 'Welcome back!'); ?>

3. إعداد الترجمة للتشغيل الأول

واحدة من المزايا الرائعة التي يتمتع بها Gettext مقارنة بحزم إطار العمل المخصص i18n هو تنسيق الملفات الشامل والقوي.

ربما كنت تفكر "يا رجل ، من الصعب جدًا فهمه وتحريره يدويًا ، سيكون من الأسهل استخدام مصفوفة بسيطة!" لا تخطئ ، فهناك تطبيقات مثل Poedit هنا للمساعدة - كثيرًا. يمكنك الحصول على البرنامج من موقعه على الانترنت ، فهو مجاني ومتاح لجميع المنصات. إنها أداة سهلة التعود عليها ، وهي أداة قوية جدًا في نفس الوقت - باستخدام جميع الميزات المتوفرة في Gettext. سنعمل هنا مع أحدث إصدار ، Poedit 1.8.

عرض داخل Poedit.

في الجولة الأولى ، يجب تحديد "ملف> جديد ..." من القائمة. سيُطلب منك اللغة ؛ حدد / تصفية اللغة التي تريد الترجمة إليها ، أو استخدم التنسيق الذي ذكرناه من قبل ، مثل en_US أو pt_BR .

اختيار اللغة.

الآن ، احفظ الملف - باستخدام بنية الدليل التي ذكرناها أيضًا. ثم يجب النقر فوق "استخراج من المصادر" ، وهنا ستقوم بتكوين إعدادات متنوعة لمهام الاستخراج والترجمة. ستتمكن من العثور عليها لاحقًا من خلال "الكتالوج> الخصائص":

  • مسارات المصدر: قم بتضمين جميع المجلدات من المشروع حيث يُطلق على gettext() (والأشقاء) - وهذا عادة ما يكون مجلد (مجلدات) القوالب / العروض الخاصة بك. هذا هو الإعداد الإلزامي الوحيد.

  • خصائص الترجمة:

    • اسم المشروع وإصداره ، عنوان البريد الإلكتروني للفريق والفريق: معلومات مفيدة موجودة في رأس ملف .po.
    • صيغ الجمع: هذه هي القواعد التي ذكرناها من قبل. يمكنك تركه مع الخيار الافتراضي في معظم الأوقات ، حيث يتضمن Poedit بالفعل قاعدة بيانات مفيدة لقواعد الجمع للعديد من اللغات.
    • مجموعات الأحرف: يفضل UTF-8.
    • مجموعة أحرف الكود المصدري: مجموعة الأحرف المستخدمة بواسطة قاعدة الرموز الخاصة بك - من المحتمل أن تكون UTF-8 أيضًا ، أليس كذلك؟
  • الكلمات الأساسية المصدر: يعرف البرنامج الأساسي كيف تبدو gettext() الوظائف المماثلة في العديد من لغات البرمجة ، ولكن يمكنك أيضًا إنشاء وظائف الترجمة الخاصة بك. سيكون هنا ستضيف تلك الطرق الأخرى. سيتم مناقشة هذا لاحقًا في قسم "النصائح".

بعد تعيين هذه الخصائص ، سيقوم Poedit بإجراء مسح ضوئي لملفات المصدر الخاصة بك للعثور على جميع مكالمات الترجمة. بعد كل عملية مسح ، سيعرض Poedit ملخصًا لما تم العثور عليه وما تم إزالته من الملفات المصدر. ستكون الإدخالات الجديدة فارغة في جدول الترجمة ، مما يسمح لك بإدخال الإصدارات المترجمة من تلك السلاسل. احفظه وسيتم (إعادة) تجميع ملف .mo في نفس المجلد و ، المعزوفة! ، مشروعك دولي!

مشروع تدويل.

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

4. ترجمة الجمل

كما لاحظت ، هناك نوعان رئيسيان من الجمل المترجمة: البسيطة وتلك التي تحتوي على صيغ الجمع.

تحتوي الصناديق البسيطة على صندوقين فقط: المصدر والسلسلة المترجمة. لا يمكن تعديل سلسلة المصدر ، لأن Gettext / Poedit لا يتضمنان القدرة على تعديل ملفات المصدر الخاصة بك ؛ بدلاً من ذلك ، ستحتاج إلى تغيير المصدر نفسه وإعادة فحص الملفات. ( نصيحة: إذا نقرت بزر الماوس الأيمن فوق سطر ترجمة ، فسيعرض تلميحًا بالملفات المصدر والأسطر حيث يتم استخدام هذه السلسلة.)

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

تكوين النماذج النهائية.

مثال على سلسلة بصيغة الجمع في Poedit ، تظهر علامة تبويب ترجمة لكل منها.

عندما تقوم بتغيير ملفات التعليمات البرمجية المصدر وتحتاج إلى تحديث الترجمات ، فقط اضغط على Refresh وسيقوم Poedit بإعادة فحص الشفرة ، وإزالة الإدخالات غير الموجودة ، ودمج تلك التي تغيرت وإضافة أخرى جديدة.

قد يحاول Poedit أيضًا تخمين بعض الترجمات ، بناءً على ترجمات أخرى قمت بها. ستتلقى هذه التخمينات والإدخالات التي تم تغييرها علامة "غير واضحة" ، تشير إلى أنها بحاجة إلى مراجعة ، معروضة باللون الأصفر في القائمة.

من المفيد أيضًا أن يكون لديك فريق ترجمة ويحاول شخص ما كتابة شيء غير متأكد منه: ما عليك سوى وضع علامة عليه Fuzzy وسيقوم شخص آخر بمراجعته لاحقًا.

أخيرًا ، يُنصح بترك "عرض> الإدخالات غير المترجمة أولاً" علامة ، حيث سيساعدك ذلك على تجنب نسيان أي إدخالات. من تلك القائمة ، يمكنك أيضًا فتح أجزاء من واجهة المستخدم تتيح لك ترك المعلومات السياقية للمترجمين إذا لزم الأمر.

نصائح وخدع

قد ينتهي الأمر بخوادم الويب بالتخزين المؤقت لملفات .mo.

إذا كنت تقوم بتشغيل PHP كوحدة نمطية على Apache (mod_php) ، فقد تواجه مشكلات في تخزين ملف .mo مؤقتًا. يحدث ذلك في المرة الأولى التي يقرأ فيها ، وبعد ذلك ، لتحديثه ، قد تحتاج إلى إعادة تشغيل الخادم.

في Nginx و PHP5 ، عادة ما يستغرق الأمر بضع صفحات فقط لتحديث ذاكرة التخزين المؤقت للترجمة ، ونادرًا ما تكون مطلوبة في PHP7.

توفر المكتبات وظائف مساعدة للحفاظ على رمز الترجمة قصيرًا.

كما يفضل العديد من الأشخاص ، من الأسهل استخدام _() بدلاً من gettext() . تستخدم العديد من مكتبات i18n المخصصة من أطر العمل شيئًا مشابهًا لـ t() أيضًا ، لجعل الشفرة المترجمة أقصر. ومع ذلك ، فهذه هي الوظيفة الوحيدة التي تتميز باختصار.

قد ترغب في إضافة بعض المشاريع الأخرى في مشروعك ، مثل __() أو _n() لـ ngettext() ، أو ربما _r() الفاخرة التي ستنضم إلى مكالمات gettext() و sprintf() . المكتبات الأخرى ، مثل oscarotero's Gettext توفر أيضًا وظائف مساعدة مثل هذه.

في هذه الحالات ، ستحتاج إلى إرشاد الأداة المساعدة Gettext حول كيفية استخراج السلاسل من تلك الوظائف الجديدة. لا تخافوا ، إنه سهل للغاية. إنه مجرد حقل في ملف .po أو شاشة إعدادات في Poedit (في المحرر ، يوجد هذا الخيار داخل "الكتالوج> الخصائص> الكلمات الرئيسية للمصادر").

تذكر: Gettext يعرف بالفعل الوظائف الافتراضية للعديد من اللغات ، لذلك لا تقلق إذا كانت هذه القائمة تبدو فارغة. يجب أن تُدرج في تلك القائمة مواصفات الوظائف الجديدة ، باتباع هذا التنسيق المحدد:

  • إذا أنشأت شيئًا مثل t() ، فهذا يعيد ببساطة ترجمة سلسلة ، يمكنك تحديدها كـ t . سيعرف Gettext أن وسيطة الوظيفة الوحيدة هي السلسلة المراد ترجمتها ؛

  • إذا كانت الوظيفة تحتوي على أكثر من وسيطة ، فيمكنك تحديد أي سلسلة هي السلسلة الأولى ، وإذا لزم الأمر ، صيغة الجمع أيضًا. على سبيل المثال ، إذا كان توقيع وظيفتنا هو __('one user', '%d users', $number) ، فإن المواصفات ستكون __:1,2 1 ، 2 ، مما يعني أن النموذج الأول هو الوسيطة الأولى ، والشكل الثاني هو الحجة الثانية. إذا كان الرقم الخاص بك هو الوسيطة الأولى بدلاً من ذلك ، فستكون المواصفات __:2,3 ، مما يشير إلى أن النموذج الأول هو الوسيطة الثانية ، وهكذا.

بعد تضمين هذه القواعد الجديدة في ملف .po ، سيؤدي الفحص الجديد إلى إدخال السلاسل الجديدة بنفس السهولة التي كانت عليها من قبل.

اجعل تطبيق PHP متعدد اللغات باستخدام Gettext

Gettext هي أداة قوية للغاية لتدويل مشروع PHP الخاص بك. بالإضافة إلى مرونته التي تسمح بدعم عدد كبير من اللغات البشرية ، فإن دعمه لأكثر من 20 لغة برمجة يسمح لك بسهولة نقل معرفتك باستخدامها مع PHP إلى لغات أخرى مثل Python أو Java أو C #.

علاوة على ذلك ، يمكن أن يساعد Poedit في تسهيل المسار بين الكود والسلاسل المترجمة ، مما يجعل العملية أكثر وضوحًا وأسهل في المتابعة. يمكنه أيضًا تبسيط جهود الترجمة المشتركة من خلال تكامل Crowdin.

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

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

الموضوعات ذات الصلة: مقدمة إلى PHP 7: ما الجديد وما مضى