لماذا يجب أن يتحدث موقع PHP الخاص بك بلغات مختلفة؟
\n\nتخيل: لقد أنشأت منتجًا مثاليًا — سريعًا، سهل الاستخدام، يحل المشكلات. لكن هناك مشكلة واحدة: واجهتك تتحدث العربية فقط. العملاء المحتملون من ألمانيا أو اليابان أو البرازيل سيغلقون علامة التبويب ببساطة، دون فهم أي زر. هذه ليست مجرد أرباح ضائعة — بل خسارة لأسواق بأكملها.
\n\nالتدويل (i18n — اختصارًا لـ "internationalization"، حيث 18 حرفًا بين i و n) والتعريب (l10n) ليسا مجرد "خانة اختيار" لشركة ناشئة، بل أداة استراتيجية. يخشى العديد من المطورين هذه الكلمة، معتقدين أنهم سيضطرون إلى إعادة كتابة كل الكود. في الواقع، التنظيم الذكي للترجمات في PHP هو عملية أنيقة تجعل الكود أنظف والأعمال أكثر عالمية.
\n\nفي هذه المقالة، سنستعرض ثلاث طرق عملية لتدويل تطبيقات PHP: من المصفوفات البسيطة إلى الإضافة القوية intl و gettext الكلاسيكية. ستتعلم ليس فقط كيفية ترجمة النص، بل أيضًا كيفية التعامل بشكل صحيح مع التواريخ والأرقام وصيغ الجمع — ففي اللغة العربية أو البولندية أو الروسية قواعد تصريف خاصة بها.
الطرق الرئيسية لـ i18n في PHP
\n\nقبل كتابة الكود، يجب اختيار البنية المناسبة. بشكل عام، تنقسم جميع الطرق إلى ثلاث فئات. يعتمد اختيار الطريقة على حجم المشروع ومتطلبات الأداء.
\n\n1. المصفوفات وملفات ini (طريقة DIY)
\n\nأبسط طريقة هي تخزين الترجمات في مصفوفات ترابطية أو ملفات .ini. مناسبة تمامًا للمشاريع الصغيرة أو النماذج الأولية (MVP).
// lang/ar.php\nreturn [\n 'welcome' => 'مرحبًا بك في الموقع!',\n 'logout' => 'تسجيل الخروج',\n 'cart_empty' => 'السلة فارغة'\n];\n\n// lang/en.php\nreturn [\n 'welcome' => 'Welcome to the website!',\n 'logout' => 'Logout',\n 'cart_empty' => 'Cart is empty'\n];\n\nاستخدامها بسيط: نقوم بتضمين الملف المناسب بناءً على جلسة المستخدم أو الكوكيز.
\n\nfunction __($key) {\n static $lang = null;\n if ($lang === null) {\n $locale = $_SESSION['lang'] ?? 'ar';\n $lang = include "lang/{$locale}.php";\n }\n return $lang[$key] ?? $key;\n}\n\necho __('welcome'); // مرحبًا بك في الموقع!\n\nالمزايا: البساطة، لا يتطلب إضافات، سهل التخزين المؤقت (يمكن حفظه حتى في Redis).
\nالعيوب: لا يدعم صيغ الجمع (ستحتاج لكتابة حل خاص)، غير مناسب للمشاريع الكبيرة (مئات الآلاف من المفاتيح في ملف واحد).
2. Gettext — الكلاسيكي
\n\nGettext هو المعيار الفعلي للتدويل في عالم Unix. في PHP، يمكن الوصول إليه عبر الإضافة gettext. إنها أداة قوية تُستخدم في WordPress و Drupal و Symfony.
أولاً، نقوم بإنشاء ملفات .po (مثلًا للغة العربية):
# ar_SA/LC_MESSAGES/messages.po\nmsgid "Hello, %s!"\nmsgstr "مرحبًا، %s!"\n\nmsgid "You have %d new message"\nmsgid_plural "You have %d new messages"\nmsgstr[0] "لديك %d رسالة جديدة"\nmsgstr[1] "لديك %d رسائل جديدة"\nmsgstr[2] "لديك %d رسالة جديدة"\n\nثم نقوم بترجمتها إلى ملف .mo (باستخدام أداة msgfmt). في كود PHP، يبدو الأمر كالتالي:
putenv('LC_ALL=ar_SA.UTF-8');\nsetlocale(LC_ALL, 'ar_SA.UTF-8');\nbindtextdomain('messages', './locale');\ntextdomain('messages');\n\necho gettext('Hello, %s!', 'أحمد'); // مرحبًا، أحمد!\n\n// صيغ الجمع — السحر:\necho ngettext('%d message', '%d messages', 3); // 3 رسائل\n\nبالمناسبة، لتسريع التطوير، استخدم Poedit — فهو يسلط الضوء على الأسطر غير المترجمة.
\n\n3. إضافة Intl (PHP 5.3+)
\n\nإذا كنت لا تحتاج فقط إلى ترجمة النص، بل أيضًا إلى تنسيق الأرقام والتواريخ والعملات بشكل صحيح وفقًا لمعايير البلد — استخدم Intl. إنها طبقة فوق مكتبة ICU (International Components for Unicode).
// تنسيق الأرقام