WooCommerce Multilingual – run WooCommerce with WPML - Version 3.7.9

Version Description

  • Fixed an issue prevent the correct plugin activation in some cases
  • Fixed an issue potentially causing uncatched errors when using some specific payment gateways
Download this release

Release Info

Developer mihaimihai
Plugin Icon 128x128 WooCommerce Multilingual – run WooCommerce with WPML
Version 3.7.9
Comparing to
See all releases

Code changes from version 3.7.8 to 3.7.9

compatibility/class-wcml-composite-products.php CHANGED
@@ -9,10 +9,9 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
9
  add_filter( 'woocommerce_composite_component_default_option', array($this, 'woocommerce_composite_component_default_option'), 10, 3 );
10
  add_filter( 'wcml_cart_contents', array($this, 'wpml_composites_compat'), 11, 4 );
11
  add_filter( 'woocommerce_composite_component_options_query_args', array($this, 'wpml_composites_transients_cache_per_language'), 10, 3 );
 
12
 
13
  if( is_admin() ){
14
- add_action( 'save_post', array( $this, 'sync_composite_data_across_translations'), 10, 2 );
15
-
16
  add_filter( 'wcml_gui_additional_box', array( $this, 'custom_box_html'), 10, 3 );
17
  add_action('wcml_extra_titles',array($this,'product_editor_title'),10,1);
18
  add_action('wcml_update_extra_fields',array($this,'components_update'),10,2);
@@ -55,12 +54,16 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
55
  return $args;
56
  }
57
 
58
- function sync_composite_data_across_translations( $product_id, $post = null ){
 
 
 
 
 
 
59
  global $sitepress, $woocommerce_wpml;
60
 
61
- if( is_null( $post ) ){
62
- $post = get_post( $product_id );
63
- }
64
 
65
  // skip auto-drafts // skip autosave
66
  if ( $post->post_status == 'auto-draft' || isset( $_POST[ 'autosave' ] ) ) {
@@ -69,16 +72,18 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
69
 
70
  if( $post->post_type == 'product' ) {
71
 
72
- if( $this->get_product_type( $product_id ) == 'composite' ) {
 
 
73
 
74
- if ( $woocommerce_wpml->products->is_original_product( $product_id ) ) {
75
 
76
- $original_product_id = $product_id;
77
 
78
  } else {
79
 
80
- $original_product_language = $woocommerce_wpml->products->get_original_product_language( $product_id );
81
- $original_product_id = apply_filters( 'translate_object_id', $product_id, 'product', true, $original_product_language );
82
 
83
  }
84
 
@@ -87,8 +92,6 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
87
  $product_trid = $sitepress->get_element_trid( $original_product_id, 'post_product' );
88
  $product_translations = $sitepress->get_element_translations( $product_trid, 'post_product' );
89
 
90
- $composite_data = $product->get_composite_data();
91
-
92
  foreach ( $product_translations as $product_translation ) {
93
 
94
  if ( empty($product_translation->original) ) {
@@ -131,6 +134,8 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
131
 
132
  }
133
 
 
 
134
  }
135
 
136
  }
9
  add_filter( 'woocommerce_composite_component_default_option', array($this, 'woocommerce_composite_component_default_option'), 10, 3 );
10
  add_filter( 'wcml_cart_contents', array($this, 'wpml_composites_compat'), 11, 4 );
11
  add_filter( 'woocommerce_composite_component_options_query_args', array($this, 'wpml_composites_transients_cache_per_language'), 10, 3 );
12
+ add_action( 'updated_post_meta', array( $this, 'sync_composite_data_across_translations'), 10, 4 );
13
 
14
  if( is_admin() ){
 
 
15
  add_filter( 'wcml_gui_additional_box', array( $this, 'custom_box_html'), 10, 3 );
16
  add_action('wcml_extra_titles',array($this,'product_editor_title'),10,1);
17
  add_action('wcml_update_extra_fields',array($this,'components_update'),10,2);
54
  return $args;
55
  }
56
 
57
+ function sync_composite_data_across_translations( $meta_id, $post_id, $meta_key, $composite_data ){
58
+
59
+
60
+ if( $meta_key != '_bto_data' )
61
+ return false;
62
+
63
+
64
  global $sitepress, $woocommerce_wpml;
65
 
66
+ $post = get_post( $post_id );
 
 
67
 
68
  // skip auto-drafts // skip autosave
69
  if ( $post->post_status == 'auto-draft' || isset( $_POST[ 'autosave' ] ) ) {
72
 
73
  if( $post->post_type == 'product' ) {
74
 
75
+ if( $this->get_product_type( $post_id ) == 'composite' ) {
76
+
77
+ remove_action( 'updated_post_meta', array( $this, 'sync_composite_data_across_translations'), 10, 4 );
78
 
79
+ if ( $woocommerce_wpml->products->is_original_product( $post_id ) ) {
80
 
81
+ $original_product_id = $post_id;
82
 
83
  } else {
84
 
85
+ $original_product_language = $woocommerce_wpml->products->get_original_product_language( $post_id );
86
+ $original_product_id = apply_filters( 'translate_object_id', $post_id, 'product', true, $original_product_language );
87
 
88
  }
89
 
92
  $product_trid = $sitepress->get_element_trid( $original_product_id, 'post_product' );
93
  $product_translations = $sitepress->get_element_translations( $product_trid, 'post_product' );
94
 
 
 
95
  foreach ( $product_translations as $product_translation ) {
96
 
97
  if ( empty($product_translation->original) ) {
134
 
135
  }
136
 
137
+ add_action( 'updated_post_meta', array( $this, 'sync_composite_data_across_translations'), 10, 4 );
138
+
139
  }
140
 
141
  }
compatibility/class-wcml-wc-subscriptions.php CHANGED
@@ -7,7 +7,9 @@ class WCML_WC_Subscriptions{
7
  add_action('init', array($this, 'init'),9);
8
  add_filter('wcml_variation_term_taxonomy_ids',array($this,'wcml_variation_term_taxonomy_ids'));
9
  add_filter('woocommerce_subscription_lengths', array($this, 'woocommerce_subscription_lengths'), 10, 2);
10
-
 
 
11
  }
12
 
13
  function init(){
@@ -51,5 +53,13 @@ class WCML_WC_Subscriptions{
51
 
52
  return isset($new_subscription_ranges) ? $new_subscription_ranges : $subscription_ranges;
53
  }
54
-
 
 
 
 
 
 
 
 
55
  }
7
  add_action('init', array($this, 'init'),9);
8
  add_filter('wcml_variation_term_taxonomy_ids',array($this,'wcml_variation_term_taxonomy_ids'));
9
  add_filter('woocommerce_subscription_lengths', array($this, 'woocommerce_subscription_lengths'), 10, 2);
10
+
11
+ // reenable coupons for subscriptions when multicurrency is on
12
+ add_action('woocommerce_subscription_cart_after_grouping', array($this, 'woocommerce_subscription_cart_after_grouping'));
13
  }
14
 
15
  function init(){
53
 
54
  return isset($new_subscription_ranges) ? $new_subscription_ranges : $subscription_ranges;
55
  }
56
+
57
+ public function woocommerce_subscription_cart_after_grouping() {
58
+ global $woocommerce_wpml;
59
+
60
+ if( $woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ){
61
+ remove_action('woocommerce_before_calculate_totals', 'WC_Subscriptions_Coupon::remove_coupons', 10);
62
+ }
63
+
64
+ }
65
  }
inc/class-wcml-languages-upgrader.php CHANGED
@@ -26,7 +26,7 @@ class WCML_Languages_Upgrader{
26
 
27
  $locale = $sitepress->get_locale( $lang_code );
28
 
29
- if( $locale != 'en_US' ){
30
 
31
  $wc_version = $wc_version ? $wc_version : WC_VERSION;
32
 
@@ -231,9 +231,10 @@ class WCML_Languages_Upgrader{
231
  * @return bool
232
  */
233
  function check_if_language_pack_exists( $locale ) {
 
234
  $response = wp_safe_remote_get( $this->get_language_pack_uri( $locale ), array( 'timeout' => 60 ) );
235
 
236
- if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
237
  return true;
238
  } else {
239
  return false;
26
 
27
  $locale = $sitepress->get_locale( $lang_code );
28
 
29
+ if( $locale != 'en_US' && $this->has_available_update( $locale ) ){
30
 
31
  $wc_version = $wc_version ? $wc_version : WC_VERSION;
32
 
231
  * @return bool
232
  */
233
  function check_if_language_pack_exists( $locale ) {
234
+
235
  $response = wp_safe_remote_get( $this->get_language_pack_uri( $locale ), array( 'timeout' => 60 ) );
236
 
237
+ if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 && $response['body'] != '404 File not found' ) {
238
  return true;
239
  } else {
240
  return false;
inc/products.class.php CHANGED
@@ -2959,7 +2959,10 @@ class WCML_Products{
2959
 
2960
  $sitepress->set_element_language_details( $new_orig_id, 'post_' . $post->post_type, false, $orig_lang );
2961
  $new_trid = $sitepress->get_element_trid( $new_orig_id, 'post_' . $post->post_type );
2962
- update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
 
 
 
2963
 
2964
  $sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $sitepress->get_current_language() );
2965
  }
@@ -2979,13 +2982,16 @@ class WCML_Products{
2979
 
2980
  $new_id_obj = get_post( $new_id );
2981
  $new_slug = wp_unique_post_slug( sanitize_title( $new_id_obj->post_title ), $new_id, $post_to_duplicate->post_status, $post_to_duplicate->post_type, $new_id_obj->post_parent );
2982
- $wpdb->update( $wpdb->posts, array( 'post_name' => $new_slug ), array( 'ID' => $new_id ) );
2983
 
2984
  do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
2985
 
2986
  $sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $translation->language_code );
2987
 
2988
- update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
 
 
 
2989
  }
2990
  }
2991
  }
2959
 
2960
  $sitepress->set_element_language_details( $new_orig_id, 'post_' . $post->post_type, false, $orig_lang );
2961
  $new_trid = $sitepress->get_element_trid( $new_orig_id, 'post_' . $post->post_type );
2962
+ if( get_post_meta( $orig_id, '_icl_lang_duplicate_of' ) ){
2963
+ update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
2964
+ }
2965
+
2966
 
2967
  $sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $sitepress->get_current_language() );
2968
  }
2982
 
2983
  $new_id_obj = get_post( $new_id );
2984
  $new_slug = wp_unique_post_slug( sanitize_title( $new_id_obj->post_title ), $new_id, $post_to_duplicate->post_status, $post_to_duplicate->post_type, $new_id_obj->post_parent );
2985
+ $wpdb->update( $wpdb->posts, array( 'post_name' => $new_slug, 'post_status' => $post_to_duplicate->post_status ), array( 'ID' => $new_id ) );
2986
 
2987
  do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
2988
 
2989
  $sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $translation->language_code );
2990
 
2991
+ if( get_post_meta( $translation->element_id, '_icl_lang_duplicate_of' ) ){
2992
+ update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
2993
+ }
2994
+
2995
  }
2996
  }
2997
  }
inc/wc-strings.class.php CHANGED
@@ -7,19 +7,28 @@ class WCML_WC_Strings{
7
 
8
  function __construct(){
9
 
10
- add_action('init', array($this, 'init'));
11
- add_action('init', array($this, 'pre_init'));
12
- add_filter('query_vars', array($this, 'translate_query_var_for_product'));
13
- add_filter('wp_redirect', array($this, 'encode_shop_slug'),10,2);
14
  add_action( 'registered_taxonomy', array ( $this, 'translate_attributes_label_in_wp_taxonomies' ), 100, 3 );
15
  add_filter( 'woocommerce_payment_gateways', array( $this, 'payment_gateways_filters' ), 100 );
 
16
 
17
  }
18
 
19
  function payment_gateways_filters( $payment_gateways ){
20
 
21
  foreach ( $payment_gateways as $gateway ) {
22
- $gateway_id = strtolower( str_replace( 'WC_Gateway_', '', $gateway ) );
 
 
 
 
 
 
 
 
23
 
24
  add_filter( 'woocommerce_settings_api_sanitized_fields_'.$gateway_id, array( $this, 'register_gateway_strings' ) );
25
  add_filter( 'option_woocommerce_'.$gateway_id.'_settings', array( $this, 'translate_gateway_strings' ), 9, 2 );
@@ -28,6 +37,25 @@ class WCML_WC_Strings{
28
  return $payment_gateways;
29
  }
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  function pre_init(){
32
  // Slug translation
33
  if( !WPML_SUPPORT_STRINGS_IN_DIFF_LANG ){
@@ -39,7 +67,7 @@ class WCML_WC_Strings{
39
  function init(){
40
  global $pagenow;
41
 
42
- add_filter('woocommerce_package_rates', array($this, 'register_shipping_methods'));
43
  add_action('woocommerce_tax_rate_added', array($this, 'register_tax_rate_label_string'), 10, 2 );
44
  add_filter('woocommerce_rate_label',array($this,'translate_woocommerce_rate_label'));
45
 
@@ -250,15 +278,56 @@ class WCML_WC_Strings{
250
 
251
  }
252
 
253
- function register_shipping_methods($available_methods){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  foreach($available_methods as $key => $method){
255
- do_action('wpml_register_single_string', 'woocommerce', $key .'_shipping_method_title', $method->label );
256
- $method->label = apply_filters( 'wpml_translate_single_string', $method->label, 'woocommerce', $key .'_shipping_method_title');
257
  }
258
 
259
  return $available_methods;
260
  }
261
 
 
 
 
 
 
 
 
 
262
  function translate_woocommerce_rate_label( $label ){
263
 
264
  $label = apply_filters( 'wpml_translate_single_string', $label, 'woocommerce taxes', $label );
@@ -287,7 +356,10 @@ class WCML_WC_Strings{
287
 
288
  if( isset( $gateway_id ) ){
289
  do_action('wpml_register_single_string', 'woocommerce', $gateway_id .'_gateway_title', $fields['title'] );
290
- do_action('wpml_register_single_string', 'woocommerce', $gateway_id .'_gateway_description', $fields['description'] );
 
 
 
291
 
292
  if( isset( $fields['instructions'] ) ){
293
  do_action('wpml_register_single_string', 'woocommerce', $gateway_id .'_gateway_instructions', $fields['instructions'] );
7
 
8
  function __construct(){
9
 
10
+ add_action( 'init', array( $this, 'init' ) );
11
+ add_action( 'init', array( $this, 'pre_init' ) );
12
+ add_filter( 'query_vars', array( $this, 'translate_query_var_for_product' ) );
13
+ add_filter( 'wp_redirect', array( $this, 'encode_shop_slug' ), 10, 2 );
14
  add_action( 'registered_taxonomy', array ( $this, 'translate_attributes_label_in_wp_taxonomies' ), 100, 3 );
15
  add_filter( 'woocommerce_payment_gateways', array( $this, 'payment_gateways_filters' ), 100 );
16
+ add_filter( 'woocommerce_shipping_methods', array( $this, 'shipping_methods_filters' ), 100 );
17
 
18
  }
19
 
20
  function payment_gateways_filters( $payment_gateways ){
21
 
22
  foreach ( $payment_gateways as $gateway ) {
23
+
24
+ if( is_string( $gateway ) ){
25
+ $gateway_id = strtolower( str_replace( 'WC_Gateway_', '', $gateway ) ) ;
26
+ }elseif( isset( $gateway->id ) ){
27
+ $gateway_id = $gateway->id;
28
+ }else{
29
+ continue;
30
+ }
31
+
32
 
33
  add_filter( 'woocommerce_settings_api_sanitized_fields_'.$gateway_id, array( $this, 'register_gateway_strings' ) );
34
  add_filter( 'option_woocommerce_'.$gateway_id.'_settings', array( $this, 'translate_gateway_strings' ), 9, 2 );
37
  return $payment_gateways;
38
  }
39
 
40
+ function shipping_methods_filters( $shipping_methods ){
41
+
42
+ foreach ( $shipping_methods as $shipping_method ) {
43
+
44
+ if( is_string( $shipping_method ) ){
45
+ $shipping_method_id = strtolower( str_replace( 'WC_Shipping_', '', $shipping_method ) );
46
+ }elseif( isset( $shipping_method->id ) ){
47
+ $shipping_method_id = $shipping_method->id;
48
+ }else{
49
+ continue;
50
+ }
51
+
52
+ add_filter( 'woocommerce_settings_api_sanitized_fields_'.$shipping_method_id, array( $this, 'register_shipping_strings' ) );
53
+ add_filter( 'option_woocommerce_'.$shipping_method_id.'_settings', array( $this, 'translate_shipping_strings' ), 9, 2 );
54
+ }
55
+
56
+ return $shipping_methods;
57
+ }
58
+
59
  function pre_init(){
60
  // Slug translation
61
  if( !WPML_SUPPORT_STRINGS_IN_DIFF_LANG ){
67
  function init(){
68
  global $pagenow;
69
 
70
+ add_filter('woocommerce_package_rates', array($this, 'translate_shipping_methods_in_package'));
71
  add_action('woocommerce_tax_rate_added', array($this, 'register_tax_rate_label_string'), 10, 2 );
72
  add_filter('woocommerce_rate_label',array($this,'translate_woocommerce_rate_label'));
73
 
278
 
279
  }
280
 
281
+ function register_shipping_strings( $fields ){
282
+ $shipping = WC_Shipping::instance();
283
+
284
+ foreach( $shipping->get_shipping_methods() as $shipping_method ){
285
+ if( isset( $_POST['woocommerce_'.$shipping_method->id.'_enabled'] ) ){
286
+ $shipping_method_id = $shipping_method->id;
287
+ break;
288
+ }
289
+ }
290
+
291
+ if( isset( $shipping_method_id ) ){
292
+ do_action( 'wpml_register_single_string', 'woocommerce', $shipping_method_id .'_shipping_method_title', $fields['title'] );
293
+ }
294
+
295
+ return $fields;
296
+ }
297
+
298
+ function translate_shipping_strings( $value, $option = false ){
299
+
300
+ if( $option && isset( $value['enabled']) && $value['enabled'] == 'no' ){
301
+ return $value;
302
+ }
303
+
304
+ $shipping_id = str_replace( 'woocommerce_', '', $option );
305
+ $shipping_id = str_replace( '_settings', '', $shipping_id );
306
+
307
+ if( isset( $value['title'] ) ){
308
+ $value['title'] = $this->translate_shipping_method_title( $value['title'], $shipping_id );
309
+ }
310
+
311
+ return $value;
312
+ }
313
+
314
+ function translate_shipping_methods_in_package( $available_methods ){
315
+
316
  foreach($available_methods as $key => $method){
317
+ $method->label = $this->translate_shipping_method_title( $method->label, $key );
 
318
  }
319
 
320
  return $available_methods;
321
  }
322
 
323
+ function translate_shipping_method_title( $title, $shipping_id ) {
324
+ global $sitepress;
325
+
326
+ $title = apply_filters( 'wpml_translate_single_string', $title, 'woocommerce', $shipping_id .'_shipping_method_title', $sitepress->get_current_language() );
327
+
328
+ return $title;
329
+ }
330
+
331
  function translate_woocommerce_rate_label( $label ){
332
 
333
  $label = apply_filters( 'wpml_translate_single_string', $label, 'woocommerce taxes', $label );
356
 
357
  if( isset( $gateway_id ) ){
358
  do_action('wpml_register_single_string', 'woocommerce', $gateway_id .'_gateway_title', $fields['title'] );
359
+
360
+ if( isset( $fields['description'] ) ) {
361
+ do_action('wpml_register_single_string', 'woocommerce', $gateway_id . '_gateway_description', $fields['description']);
362
+ }
363
 
364
  if( isset( $fields['instructions'] ) ){
365
  do_action('wpml_register_single_string', 'woocommerce', $gateway_id .'_gateway_instructions', $fields['instructions'] );
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multili
5
  License: GPLv2
6
  Requires at least: 3.0
7
  Tested up to: 4.4.1
8
- Stable tag: 3.7.8
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
@@ -78,6 +78,10 @@ In order for the checkout and store pages to appear translated, you need to crea
78
 
79
  == Changelog ==
80
 
 
 
 
 
81
  = 3.7.8 =
82
  * Updated the logic for downloading WooCommerce translations from translate.wordpress.org
83
  * Compatibility with WooCommerce Bookings 1.9 (and fixed othe small compatibility issues with older versions)
5
  License: GPLv2
6
  Requires at least: 3.0
7
  Tested up to: 4.4.1
8
+ Stable tag: 3.7.9
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
78
 
79
  == Changelog ==
80
 
81
+ = 3.7.9 =
82
+ * Fixed an issue prevent the correct plugin activation in some cases
83
+ * Fixed an issue potentially causing uncatched errors when using some specific payment gateways
84
+
85
  = 3.7.8 =
86
  * Updated the logic for downloading WooCommerce translations from translate.wordpress.org
87
  * Compatibility with WooCommerce Bookings 1.9 (and fixed othe small compatibility issues with older versions)
wpml-woocommerce.php CHANGED
@@ -6,12 +6,12 @@
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
  Text Domain: woocommerce-multilingual
9
- Version: 3.7.8
10
  */
11
 
12
 
13
  if(defined('WCML_VERSION')) return;
14
- define('WCML_VERSION', '3.7.8');
15
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
16
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
17
  define('WCML_LOCALE_PATH',WCML_PLUGIN_PATH.'/locale');
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
  Text Domain: woocommerce-multilingual
9
+ Version: 3.7.9
10
  */
11
 
12
 
13
  if(defined('WCML_VERSION')) return;
14
+ define('WCML_VERSION', '3.7.9');
15
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
16
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
17
  define('WCML_LOCALE_PATH',WCML_PLUGIN_PATH.'/locale');