PluginProbe ʕ •ᴥ•ʔ
WPML Multilingual & Multicurrency for WooCommerce / 5.5.7
WPML Multilingual & Multicurrency for WooCommerce v5.5.7
5.5.7 5.3.8 5.3.9 5.4.3 5.4.4 5.4.5 5.5.1 5.5.1.1 5.5.2.2 5.5.2.3 5.5.3 5.5.3.1 5.5.4 5.5.5 5.5.6 trunk 0.9 1.0 1.1 1.2 1.3 1.4 1.5 2.0 2.2 2.3 2.3.1 2.3.2 3.0 3.0.1 3.1 3.2 3.2.1 3.2.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 3.4.1 3.4.2 3.4.3 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.6 3.6.1 3.6.10 3.6.11 3.6.2 3.6.3 3.6.4 3.6.5 3.6.5.1 3.6.6 3.6.7 3.6.8 3.6.9 3.7 3.7.1 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.15 3.7.16 3.7.2 3.7.3 3.7.4 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.9.0 3.9.1 3.9.1.1 3.9.2 3.9.3 3.9.4 3.9.5 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.10.4 4.11.2 4.11.3.2 4.11.5 4.11.6 4.12.1 4.12.4 4.12.5 4.12.6 4.2.0 4.2.0.1 4.2.1 4.2.1.1 4.2.10 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.7.1 4.2.8 4.2.8.1 4.2.9 4.3.0 4.3.1 4.3.2 4.3.2.1 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.4.0 4.4.1 4.4.2 4.4.2.1 4.5.0 4.6.0 4.6.1 4.6.2 4.6.2.1 4.6.3 4.6.5 4.6.6 4.6.7 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.9.0 4.9.1 5.0.1 5.0.2 5.1.1 5.1.2 5.1.3 5.2.0 5.2.1 5.3.2 5.3.3.1 5.3.4 5.3.5 5.3.6 5.3.7
woocommerce-multilingual / inc / class-wcml-wc-strings.php
woocommerce-multilingual / inc Last commit date
admin-menus 1 week ago currencies 1 week ago template-classes 1 week ago translation-editor 1 week ago class-wcml-ajax-setup.php 1 week ago class-wcml-attributes.php 1 week ago class-wcml-capabilities.php 1 week ago class-wcml-cart-removed-items-widget.php 1 year ago class-wcml-cart-switch-lang-functions.php 1 week ago class-wcml-cart-sync-warnings.php 1 week ago class-wcml-cart.php 1 week ago class-wcml-comments.php 1 week ago class-wcml-compatibility.php 1 week ago class-wcml-coupons.php 1 week ago class-wcml-dependencies.php 1 week ago class-wcml-emails.php 1 week ago class-wcml-endpoints.php 1 week ago class-wcml-install.php 1 week ago class-wcml-languages-upgrader.php 1 week ago class-wcml-locale.php 1 week ago class-wcml-orders.php 1 week ago class-wcml-products-screen-options.php 1 week ago class-wcml-products.php 1 week ago class-wcml-reports.php 1 week ago class-wcml-requests.php 1 week ago class-wcml-resources.php 1 week ago class-wcml-store-pages.php 1 week ago class-wcml-terms.php 1 week ago class-wcml-tp-support.php 1 week ago class-wcml-troubleshooting.php 1 week ago class-wcml-upgrade.php 1 week ago class-wcml-url-translation.php 1 week ago class-wcml-wc-gateways.php 1 week ago class-wcml-wc-shipping.php 1 week ago class-wcml-wc-strings.php 1 week ago class-wcml-widgets.php 1 week ago constants.php 1 week ago functions-pure.php 1 week ago functions.php 1 week ago installer-loader.php 1 week ago missing-php-functions.php 1 week ago wcml-core-functions.php 1 week ago wcml-switch-lang-request.php 1 week ago
class-wcml-wc-strings.php
458 lines
1 <?php
2
3 use WPML\FP\Fns;
4 use WPML\FP\Lst;
5 use WPML\FP\Str;
6
7 class WCML_WC_Strings {
8
9 const DOMAIN_WORDPRESS = 'WordPress';
10 const TAXONOMY_SINGULAR_NAME_PREFIX = 'taxonomy singular name: ';
11 const TAXONOMY_GENERAL_NAME_PREFIX = 'taxonomy general name: ';
12 const TAXONOMY_GENERAL_VALUE_PREFIX = 'Product ';
13
14 private $translations_from_mo_file = [];
15 private $mo_files = [];
16 private $current_language;
17
18 private $woocommerce_wpml;
19 private $sitepress;
20 private $wpdb;
21
22 public $settings = [];
23
24 public function __construct( woocommerce_wpml $woocommerce_wpml, \WPML\Core\ISitePress $sitepress, wpdb $wpdb ) {
25 $this->woocommerce_wpml = $woocommerce_wpml;
26 $this->sitepress = $sitepress;
27 $this->wpdb = $wpdb;
28 }
29
30 public function add_hooks() {
31
32 add_action( 'init', [ $this, 'add_on_init_hooks' ] );
33
34 foreach ( wc_get_attribute_taxonomies() as $tax ) {
35 add_filter(
36 'woocommerce_taxonomy_args_' . wc_attribute_taxonomy_name( $tax->attribute_name ),
37 function ( $args ) use ( $tax ) {
38 return $this->translate_attribute_labels( $args, $tax->attribute_label );
39 }
40 );
41 }
42 }
43
44 public function add_on_init_hooks() {
45 global $pagenow;
46
47 $this->current_language = $this->sitepress->get_current_language();
48 if ( 'all' === $this->current_language ) {
49 $this->current_language = $this->sitepress->get_default_language();
50 }
51
52 add_filter( 'woocommerce_attribute_label', Fns::withoutRecursion( Fns::identity(), [ $this, 'translated_attribute_label' ] ), 10, 3 );
53 add_filter( 'woocommerce_checkout_product_title', [ $this, 'translated_checkout_product_title' ], 10, 2 );
54 add_filter( 'woocommerce_cart_item_name', [ $this, 'translated_cart_item_name' ], -1, 2 );
55
56 if ( is_admin() ) {
57
58 if ( 'edit.php' !== $pagenow && ! wpml_is_ajax() ) {
59 add_filter(
60 'woocommerce_attribute_taxonomies',
61 [
62 $this,
63 'translate_attribute_taxonomies_labels',
64 ]
65 );
66 }
67 if ( 'options-permalink.php' === $pagenow ) {
68 add_filter( 'gettext_with_context', [ $this, 'category_base_in_strings_language' ], 99, 3 );
69 add_action( 'admin_footer', [ $this, 'show_custom_url_base_language_requirement' ] );
70 }
71 }
72
73 add_action(
74 'woocommerce_product_options_attributes',
75 [
76 $this,
77 'notice_after_woocommerce_product_options_attributes',
78 ]
79 );
80
81 add_filter( 'woocommerce_get_breadcrumb', [ $this, 'filter_woocommerce_breadcrumbs' ] );
82 }
83
84 public function translated_attribute_label( $label, $name, $product_obj = false ) {
85 global $product;
86
87 $product_id = false;
88 $lang = $this->sitepress->get_current_language();
89
90 if ( \WCML\Orders\Helper::isOrderEditAdminScreen() ) {
91 $lang = $this->sitepress->get_user_admin_language( get_current_user_id(), true );
92 }
93
94 if ( is_numeric( $product_obj ) ) {
95 $product_id = $product_obj;
96 } elseif ( $product_obj && is_object( $product_obj ) ) {
97 $product_id = $product_obj->get_id();
98 } elseif ( $product && is_object( $product ) ) {
99 $product_id = $product->get_id();
100 }
101
102 $product_id = apply_filters( 'wcml_translated_attribute_label_product_id', $product_id, $label, $name, $product_obj );
103
104 $name = $this->woocommerce_wpml->attributes->filter_attribute_name(
105 $name,
106 $product_id,
107 apply_filters( 'wcml_sanitize_name_for_translated_attribute_label', true, $name, $label )
108 );
109
110 if ( $product_id ) {
111
112 $custom_attr_translation = $this->woocommerce_wpml->attributes->get_attr_label_translations( $product_id, $lang );
113
114 if ( $custom_attr_translation ) {
115 if ( isset( $custom_attr_translation[ $name ] ) ) {
116 return $custom_attr_translation[ $name ];
117 }
118 }
119 }
120
121 $trnsl_label = apply_filters( 'wpml_translate_single_string', $label, self::DOMAIN_WORDPRESS, self::TAXONOMY_SINGULAR_NAME_PREFIX . $label, $lang );
122
123 if ( $label != $trnsl_label ) {
124 return $trnsl_label;
125 }
126
127 if ( is_admin() && ! wpml_is_ajax() ) {
128
129 $string_language = $this->get_string_language( self::TAXONOMY_SINGULAR_NAME_PREFIX . $label, self::DOMAIN_WORDPRESS );
130
131 if ( $this->sitepress->get_user_admin_language( get_current_user_id(), true ) != $string_language ) {
132 $string_id = icl_get_string_id( self::TAXONOMY_SINGULAR_NAME_PREFIX . $label, self::DOMAIN_WORDPRESS );
133 $strings = icl_get_string_translations_by_id( $string_id );
134 if ( $strings ) {
135 return $strings[ $this->sitepress->get_user_admin_language( get_current_user_id(), true ) ]['value'];
136 }
137 } else {
138 return $label;
139 }
140 }
141
142 $trnsl_labels = get_option( 'wcml_custom_attr_translations' );
143
144 if ( ! empty( $trnsl_labels[ $lang ][ $name ] ) ) {
145 return $trnsl_labels[ $lang ][ $name ];
146 }
147
148 return $label;
149 }
150
151 public function translated_cart_item_name( $title, array $values ) {
152
153 if ( $values ) {
154
155 $product_id = $values['variation_id'] ?: $values['product_id'];
156
157 $translated_product_id = apply_filters( 'wpml_object_id', $product_id, 'product', true );
158 $translated_product = wc_get_product( $translated_product_id );
159 $translated_title = $translated_product ? $translated_product->get_name() : '';
160
161 if ( strstr( $title, '</a>' ) ) {
162 $title = sprintf( '<a href="%s">%s</a>', $values['data']->get_permalink(), $translated_title );
163 } else {
164 $title = $translated_title . '&nbsp;';
165 }
166 }
167
168 return $title;
169 }
170
171 public function translated_checkout_product_title( $title, $product ) {
172
173 if ( $product ) {
174 $tr_product_id = apply_filters( 'wpml_object_id', $product->get_id(), 'product', true, $this->current_language );
175 $title = get_the_title( $tr_product_id );
176 }
177
178 return $title;
179 }
180
181 public function translate_default_slug( $translation, $text, $context, $domain ) {
182
183 if ( 'slug' === $context || 'default-slug' === $context ) {
184 $wc_slug = $this->woocommerce_wpml->url_translation->get_woocommerce_product_base();
185 $admin_language = is_admin() ? $this->sitepress->get_admin_language() : null;
186 $current_language = $this->sitepress->get_current_language();
187
188 $strings_language = $this->get_domain_language( 'woocommerce' );
189
190 if ( $text == $wc_slug && 'woocommerce' === $domain && $strings_language ) {
191 $this->sitepress->switch_lang( $strings_language );
192 $translation = _x( $text, 'URL slug', $domain );
193 $this->sitepress->switch_lang( $current_language );
194 if ( $admin_language ) {
195 $this->sitepress->set_admin_language( $admin_language );
196 }
197 } else {
198 $translation = $text;
199 }
200
201 if ( ! is_admin() ) {
202 $this->sitepress->switch_lang( $current_language );
203 }
204 }
205
206 return $translation;
207
208 }
209
210
211 public function show_custom_url_base_language_requirement() {
212 $category_base = ( $c = get_option( 'category_base' ) ) ? $c : 'category';
213 $category_notice = __( 'You are using the same value as for the regular category base. This is known to create conflicts resulting in urls not working properly.', 'woocommerce-multilingual' );
214 ?>
215 <script>
216 if (jQuery('input[name="woocommerce_product_category_slug"]').length && jQuery('input[name="woocommerce_product_category_slug"]').val() == '<?php echo esc_js( $category_base ); ?>') {
217 jQuery('input[name="woocommerce_product_category_slug"]').parent().append('<br><i class="icon-warning-sign"><?php echo esc_js( $category_notice ); ?></i>');
218 }
219 </script>
220 <?php
221
222 }
223
224 public function getUrlTranslation() {
225 return $this->woocommerce_wpml->url_translation;
226 }
227
228 public function category_base_in_strings_language( $text, $original_value, $context ) {
229 if ( $context === 'slug' && ( $original_value === 'product-category' || $original_value === 'product-tag' ) ) {
230 $text = $original_value;
231 }
232
233 return $text;
234 }
235
236 public function product_permalink_slug() {
237 $permalinks = get_option( 'woocommerce_permalinks' );
238 $slug = empty( $permalinks['product_base'] ) ? 'product' : trim( $permalinks['product_base'], '/' );
239
240 return $slug;
241 }
242
243 public function get_domain_language( $domain ) {
244
245 $lang_of_domain = new WPML_Language_Of_Domain( $this->sitepress );
246 $domain_lang = $lang_of_domain->get_language( $domain );
247
248 if ( $domain_lang ) {
249 $source_lang = $domain_lang;
250 } else {
251 $source_lang = 'en';
252 }
253
254 return $source_lang;
255 }
256
257 public function get_string_language( $value, $context, $name = false ) {
258
259 if ( $name !== false ) {
260
261 $string_language = apply_filters( 'wpml_get_string_language', null, $context, $name );
262
263 } else {
264
265 $string_id = icl_get_string_id( $value, $context );
266
267 if ( ! $string_id ) {
268 return 'en';
269 }
270
271 $string_object = new WPML_ST_String( $string_id, $this->wpdb );
272 $string_language = $string_object->get_language();
273
274 }
275
276 if ( ! $string_language ) {
277 return 'en';
278 }
279
280 return $string_language;
281
282 }
283
284 public function set_string_language( $value, $context, $name, $language ) {
285
286 $string_id = icl_get_string_id( $value, $context, $name );
287
288 $string_object = new WPML_ST_String( $string_id, $this->wpdb );
289 $string_object->set_language( $language );
290 }
291
292
293 public function filter_woocommerce_breadcrumbs( $breadcrumbs ) {
294
295 $current_language = $this->sitepress->get_current_language();
296 $default_language = $this->sitepress->get_default_language();
297
298 $woocommerce_shop_page = wc_get_page_id( 'shop' );
299
300 if ( $woocommerce_shop_page ) {
301
302 $is_shop_page_active = get_post_status( $woocommerce_shop_page );
303
304 if ( ( $current_language != $default_language || $default_language != 'en' ) && $is_shop_page_active === 'publish' ) {
305
306 $shop_page = get_post( $woocommerce_shop_page );
307
308 $trnsl_base = $this->woocommerce_wpml->url_translation->get_base_translation( 'product', $current_language );
309 if ( $trnsl_base['translated_base'] === '' ) {
310 $trnsl_base['translated_base'] = $trnsl_base['original_value'];
311 }
312
313 if ( is_woocommerce() && $shop_page->ID && strstr( $trnsl_base['translated_base'], urldecode( $shop_page->post_name ) ) && get_option( 'page_on_front' ) != $shop_page->ID ) {
314 $breadcrumbs_buff = [];
315 $i = 0;
316
317 foreach ( $breadcrumbs as $key => $breadcrumb ) {
318
319 if ( $key === 0 ) {
320
321 if ( isset( $breadcrumbs[1][1] ) && $breadcrumbs[1][1] != get_post_type_archive_link( 'product' ) ) {
322
323 if ( get_home_url() === $breadcrumbs[0][1] ) {
324 $breadcrumbs_buff[ $i ] = $breadcrumb;
325 $i ++;
326 }
327
328 $breadcrumbs_buff[ $i ] = [
329 $shop_page->post_title,
330 get_post_type_archive_link( 'product' ),
331 ];
332 $i ++;
333 }
334 }
335
336 if ( ! in_array( $breadcrumb, $breadcrumbs_buff ) ) {
337 $breadcrumbs_buff[ $i ] = $breadcrumb;
338 }
339 $i ++;
340 }
341
342 $breadcrumbs = $breadcrumbs_buff;
343
344 $breadcrumbs = array_values( $breadcrumbs );
345 }
346 }
347 }
348
349 return $breadcrumbs;
350 }
351
352 public function notice_after_woocommerce_product_options_attributes() {
353
354 if ( isset( $_GET['post'] ) && $this->sitepress->get_default_language() != $this->sitepress->get_current_language() ) {
355 $pointerFactory = new WCML\PointerUi\Factory();
356 $pointerFactory
357 ->create( [
358 'content' => sprintf(
359 /* translators: %1$s and %2$s are opening and closing HTML link tags */
360 esc_html__( 'To translate attributes, go to the %1$sTranslation Dashboard%2$s and send the associated product for translation.', 'woocommerce-multilingual' ),
361 '<a href="' . esc_url( \WCML\Utilities\AdminUrl::getWPMLTMDashboardProducts() ) . '">',
362 '</a>'
363 ),
364 'selectorId' => 'product_attributes',
365 'method' => 'append',
366 ] )
367 ->show();
368 }
369 }
370
371 public function translate_attribute_taxonomies_labels( $attribute_taxonomies ) {
372
373 foreach ( $attribute_taxonomies as $key => $attribute_taxonomy ) {
374 $string_language = $this->get_string_language( $attribute_taxonomy->attribute_label, self::DOMAIN_WORDPRESS, self::TAXONOMY_SINGULAR_NAME_PREFIX . $attribute_taxonomy->attribute_label );
375
376 if ( $this->sitepress->get_current_language() == $string_language ) {
377 continue;
378 }
379
380 $string_id = icl_get_string_id( $attribute_taxonomy->attribute_label, self::DOMAIN_WORDPRESS, self::TAXONOMY_SINGULAR_NAME_PREFIX . $attribute_taxonomy->attribute_label );
381 $strings = icl_get_string_translations_by_id( $string_id );
382
383 if ( $strings && isset( $strings[ $this->sitepress->get_current_language() ] ) ) {
384 $attribute_taxonomies[ $key ]->attribute_label = $strings[ $this->sitepress->get_current_language() ]['value'];
385 }
386 }
387
388 return $attribute_taxonomies;
389 }
390
391 public function get_translation_from_woocommerce_mo_file( $string, $language, $return_original = true ) {
392
393 $original_string = $string;
394
395 if ( ! isset( $this->translations_from_mo_file[ $original_string ][ $language ] ) ) {
396
397 if ( ! isset( $this->translations_from_mo_file[ $original_string ] ) ) {
398 $this->translations_from_mo_file[ $original_string ] = [];
399 }
400
401 if ( ! isset( $this->mo_files[ $language ] ) ) {
402 $mo = new MO();
403 $mo_file = WP_LANG_DIR . '/plugins/woocommerce-' . $this->sitepress->get_locale( $language ) . '.mo';
404 if ( ! file_exists( $mo_file ) ) {
405 return $return_original ? $this->get_original_string( $original_string ) : null;
406 }
407
408 $mo->import_from_file( $mo_file );
409 $this->mo_files[ $language ] = $mo->entries;
410 }
411
412 if ( in_array( $string, [ 'product', 'product-category', 'product-tag' ] ) ) {
413 $string = $this->get_msgid_for_mo( $string, 'slug' );
414 }
415
416 if ( isset( $this->mo_files[ $language ][ $string ] ) ) {
417 $this->translations_from_mo_file[ $original_string ][ $language ] = $this->mo_files[ $language ][ $string ]->translations[0];
418 } else {
419 $this->translations_from_mo_file[ $original_string ][ $language ] = $return_original ? $this->get_original_string( $original_string ) : null;
420 }
421 }
422
423 return $this->translations_from_mo_file[ $original_string ][ $language ];
424
425 }
426
427 public function translate_attribute_labels( $args, $attribute_label ) {
428 $singular_label = $this->get_translated_string_by_name_and_context( self::DOMAIN_WORDPRESS, self::TAXONOMY_SINGULAR_NAME_PREFIX . $attribute_label, null, $attribute_label );
429 if ( $singular_label ) {
430 $args['labels']['singular_name'] = $singular_label;
431 }
432
433 $label = self::TAXONOMY_GENERAL_VALUE_PREFIX . $attribute_label;
434 $label = $this->get_translated_string_by_name_and_context( self::DOMAIN_WORDPRESS, self::TAXONOMY_GENERAL_NAME_PREFIX . $label, null, $label );
435 if ( $label ) {
436 $args['labels']['name'] = $label;
437 }
438
439 return $args;
440 }
441
442 public function get_translated_string_by_name_and_context( $context, $name, $language = null, $value = false ) {
443 return apply_filters( 'wpml_translate_single_string', $value, $context, $name, $language );
444 }
445
446 public function get_msgid_for_mo( $string, $string_context ) {
447 return $string_context . self::mo_context_separator() . $string;
448 }
449
450 private static function mo_context_separator() {
451 return chr( 4 );
452 }
453
454 private function get_original_string( $string ) {
455 return Lst::last( Str::split( self::mo_context_separator(), $string ) );
456 }
457 }
458