- สถานะ
- แก้ไขแล้ว
- ประเภท
- จะไม่แก้ไข
- รายงานสำหรับ
- 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 ในเวอร์ชันที่เผยแพร่เดียว
คัดลอก helper เหล่านี้เข้าไปและเปลี่ยนชื่อคำนำหน้า:
// 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 ทุก ๆ รายการ