WPML
สถานะ
แก้ไขแล้ว
ประเภท
จะไม่แก้ไข
รายงานสำหรับ
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 ทุก ๆ รายการ

ปัญหาที่ทราบแล้วทั้งหมด →