- الحالة
- تم الحل
- النوع
- لن يتم الحل
- مُبلّغ عنها لـ
- WPML Multilingual CMS 5.0
- وسوم الموضوع
- Compatibility
نظرة عامة على المشكلة
منذ WPML 5.0، أصبحت عمليات تبديل اللغة متداخلة. يفتح كل رمز لغة نطاقاً جديداً، وفقط null هو ما يغلقه.
غالباً ما تعود الإضافات المكتوبة للإصدار WPML 4.x إلى اللغة السابقة عن طريق تحديد اللغة التي حفظتها:
$current = apply_filters( 'wpml_current_language', null ); do_action( 'wpml_switch_language', 'de' ); // ... do_action( 'wpml_switch_language', $current ); // Meant as "and back".
كان WPML 4.x يتساهل مع هذا الأمر. فقد كان يحتفظ بخانة لغة واحدة، لذلك كانت اللغة الحالية تنتهي بشكل صحيح ويبقى التبديل غير المتوازن غير ملحوظ. لم تكن هذه طريقة صحيحة أبداً لإنهاء التبديل. لم يعد WPML 5.0 يستوعب ذلك: فالاستدعاء الأخير يفتح نطاقاً ثانياً بدلاً من إغلاق النطاق الأول، ويستمر WPML في الإبلاغ عن أن اللغة مُبدّلة.
لا يمكن لـ WPML اكتشاف ذلك، لأن الاستدعاء نفسه يُعد أيضاً تبديلاً صحيحاً إلى اللغة التي جاء منها الكود المحيط.
يتأخر ظهور العَرَض. فمباشرةً بعد الزوج، تكون اللغة الحالية صحيحة، لذا فإن الاختبار الذي يتحقق من ذلك فقط سوف ينجح. بعد ذلك، تقوم عملية الاستعادة الصحيحة التالية المحيطة بكودك بإغلاق النطاق المفتوح الخاص بك بدلاً من إغلاق نطاقها، ويعمل ذلك الكود باللغة الخاطئة. تظهر هذه المشكلة في رسائل البريد الإلكتروني، واستجابات REST، وشاشات لوحة التحكم.
يؤدي التبديل بدون استعادة، أو برمز لغة فارغ، إلى ترك النطاق مفتوحاً بالطريقة نفسها.
حل بديل مؤقت
أغلق كل نطاق باستخدام null، في كتلة finally:
do_action( 'wpml_switch_language', 'de' );
try {
// ...your work in German...
} finally {
do_action( 'wpml_switch_language', null ); // Closes the scope above.
}
دعم WPML 4.x و 5.0 في إصدار واحد
انسخ هذه الدوال المساعدة وأعد تسمية البادئة:
// Opens a scope. Returns the value for the close helper, or false if none opened.
function myplugin_wpml_open_language_switch( $language_code ) {
// '', false and 0 open a scope without changing the language. Only null closes one.
if ( ! $language_code ) {
return false;
}
$previous = apply_filters( 'wpml_current_language', '' );
do_action( 'wpml_switch_language', $language_code );
return $previous;
}
// Closes the scope the open helper opened. WPML 4.x has no stack: there null
// means "the language before the FIRST switch", so restore by name.
function myplugin_wpml_close_language_switch( $previous ) {
if ( ! $previous ) {
return;
}
$has_stack = defined( 'ICL_SITEPRESS_VERSION' )
&& version_compare( ICL_SITEPRESS_VERSION, '5.0', '>=' );
do_action( 'wpml_switch_language', $has_stack ? null : $previous );
}
يصبح كل موقع استدعاء بعد ذلك:
$previous = myplugin_wpml_open_language_switch( 'de' );
try {
// ... work ...
} finally {
myplugin_wpml_close_language_switch( $previous );
}
شغّل grep -rn "wpml_switch_language" . للعثور على كل موقع استدعاء. يحتاج كل منها إلى إغلاق مطابق. لا تقم أبداً بالاستعادة عن طريق تسمية اللغة، ولا تقم أبداً بالتبديل بناءً على رمز يمكن أن يكون فارغاً.
تتداخل خطّافات البريد الإلكتروني أيضاً: استدعِ wpml_restore_language_from_email مرة واحدة لكل wpml_switch_language_for_email.