Tìm hiểu cách sử dụng mã PHP tùy chỉnh và bộ lọc WPML để đăng ký thủ công các widget Elementor tùy chỉnh cho việc dịch thuật.
Có hai loại widget Elementor tùy chỉnh:
- Các widget đơn giản: Đây là các widget không có các trường lặp lại. Bạn có thể đăng ký các widget đơn giản bằng plugin Multilingual Tools của WPML để tránh phải viết thêm mã bằng PHP.
- Các widget phức tạp: Các widget có cấu trúc phức tạp hơn. Chúng có thể bao gồm một hoặc nhiều trường lặp lại.
Để làm cho widget phức tạp của bạn có thể dịch được với WPML, bạn có thể sử dụng một trong hai cách sau:
- Được khuyên dùng: Sử dụng wpml-config.xml, tệp cấu hình của WPML. Quá trình này được nêu chi tiết trong hướng dẫn của chúng tôi về cách đăng ký các widget của trình tạo trang để dịch.
- Thủ công: Sử dụng mã PHP tùy chỉnh. Nếu bạn muốn sử dụng phương pháp này, bạn có thể làm theo các hướng dẫn trên trang này.
Thêm hỗ trợ dịch thuật WPML bằng PHP
Để minh họa cho quá trình thủ công, chúng tôi đã lấy một trong các widget của Elementor và mở rộng nó để bao gồm hỗ trợ WPML. Bạn có thể tìm thấy widget này trên trang GitHub này.
1. Thêm bộ lọc WPML vào widget của bạn
Đối với mỗi plugin widget tùy chỉnh, bạn nên thêm bộ lọc wpml_elementor_widgets_to_translate trong quá trình thực thi hành động init của chúng. WPML sử dụng bộ lọc này để thu thập thêm thông tin về các văn bản của widget cần dịch.
Bộ lọc WPML cho các widget Elementor
add_filter( 'wpml_elementor_widgets_to_translate', [ $this, 'wpml_widgets_to_translate_filter' ] );
Bộ lọc này truyền mảng liệt kê tất cả các loại widget cần được dịch. Mảng này bao gồm các phần mặc định của Elementor và thông tin về những gì cần dịch.
Bạn nên thêm bất kỳ loại widget mới nào vào cấu trúc này, như trong ví dụ sau.
Thêm các widget Elementor
public function wpml_widgets_to_translate_filter( $widgets ) {
$widgets[ $this->get_name() ] = [
'conditions' => [ 'widgetType' => $this->get_name() ],
'fields' => [
[
'field' => 'title',
'type' => __( 'Hello World Title', 'hello-world' ),
'editor_type' => 'LINE'
],
],
];
return $widgets;
}2. Tạo một lớp tùy chỉnh sẽ xử lý các bản dịch
Sau khi đã có bộ lọc, hãy tạo một lớp tùy chỉnh để quản lý các bản dịch cho widget của bạn. Chỉ định tên lớp trong trường integration-class.
Chỉ định một lớp tùy chỉnh có các widget phức tạp hơn
public function wpml_widgets_to_translate_filter( $widgets ) {
$widgets[ $this->get_name() ] = [
'conditions' => [ 'widgetType' => $this->get_name() ],
'fields' => [],
'integration-class' => 'My_Custom_Widget_WPML_Support’,
],
];
return $widgets;
}Trong mảng fields, bạn có thể chỉ định các phần tử sau:
- field – id của trường. Nó giống với id được sử dụng khi thêm một điều khiển thông qua hàm Control_stack::add_control.
- type – Loại trường. Đây là văn bản được hiển thị trong Trình biên tập dịch thuật WPML để giúp người dịch biết trường nào sẽ được dịch.
- editor_type – Đây là loại trường văn bản được sử dụng trong trình biên tập dịch thuật WPML. Các giá trị hợp lệ là LINE, AREA và VISUAL.
3. Triển khai giao diện IWPML_Page_Builders_Module
Lớp tích hợp cần triển khai các hàm get và update. Hàm get trả về danh sách các chuỗi cần dịch và hàm update cập nhật dữ liệu Elementor khi nhận được bản dịch.
Ví dụ về một lớp tùy chỉnh có các widget phức tạp hơn
/**
* Class IWPML_Page_Builders_Module
*/
interface IWPML_Page_Builders_Module {
/**
* @param string|int $node_id
* @param mixed $element
* @param WPML_PB_String[] $strings
*
* @return WPML_PB_String[]
*/
public function get( $node_id, $element, $strings );
/**
* @param string|int $node_id
* @param mixed $element
* @param WPML_PB_String $string
*
* @return array
*/
public function update( $node_id, $element, WPML_PB_String $string );
}4. Xử lý nhiều lần xuất hiện của cùng một trường trong một khối bằng cách sử dụng field_id
Nếu bạn có nhiều lần xuất hiện của cùng một trường bên trong một khối, hãy sử dụng field_id để mô tả một trường bên trong một khối Elementor. Điều này cho phép bạn phân biệt các lần xuất hiện của cùng một trường trong một nút.
Nhiều lần xuất hiện của cùng một trường
public function wpml_widgets_to_translate_filter( $widgets ) {
$widgets[ $this->get_name() ] = [
'conditions' => [ 'widgetType' => $this->get_name() ],
'fields' => [
'title_1' => [
'field' => 'title',
'field_id' => 'title_1',
'type' => __( 'Hello World Title', 'hello-world' ),
'editor_type' => 'LINE'
],
'title_2' => [
'field' => 'title',
'field_id' => 'title_2',
'type' => __( 'Hello World Title', 'hello-world' ),
'editor_type' => 'LINE'
],
],
];
return $widgets;
}5. Xử lý các widget có danh sách các phần tử khác bằng cách sử dụng lớp WPML_Elementor_Module_With_Items
Một số widget Elementor, chẳng hạn như widget Slides, chứa danh sách các phần tử (ví dụ: nhiều slide có tiêu đề và nút). Nếu widget tùy chỉnh của bạn có các danh sách tương tự, bạn có thể mở rộng lớp WPML_Elementor_Module_With_Items để xử lý việc dịch cho từng mục một cách riêng lẻ.
Ví dụ về một lớp tùy chỉnh có danh sách các phần tử khác
/**
* Class WPML_Elementor_Slides
*/
class WPML_Elementor_Slides extends WPML_Elementor_Module_With_Items {
/**
* @return string
*/
public function get_items_field() {
return 'slides';
}
/**
* @return array
*/
public function get_fields() {
return array( 'heading', 'description', 'button_text' );
}
/**
* @param string $field
*
* @return string
*/
protected function get_title( $field ) {
switch( $field ) {
case 'heading':
return esc_html__( 'Slides: heading', 'wpml-string-translation' );
case 'description':
return esc_html__( 'Slides: description', 'wpml-string-translation' );
case 'button_text':
return esc_html__( 'Slides: button text', 'wpml-string-translation' );
default:
return '';
}
}
/**
* @param string $field
*
* @return string
*/
protected function get_editor_type( $field ) {
switch( $field ) {
case 'heading':
case 'button_text':
return 'LINE';
case 'description':
return 'VISUAL';
default:
return '';
}
}
}Bạn có thể tìm thấy thêm các ví dụ trong thư mục sau của plugin lõi WPML:
- ..\wp-content\plugins\sitepress-multilingual-cms\addons\wpml-page-builders\classes\Integrations\Elementor\modules\
Đảm bảo tải các lớp trên hook init . Kể từ WPML 4.5, việc tải các lớp trước hook hành động init sẽ dẫn đến lỗi nghiêm trọng.