WooCommerce Multilingual – run WooCommerce with WPML - Version 3.6.9

Version Description

  • Bug fix: Prices for variable products were not converted correctly when using multiple currencies after the WooCommerce 2.4 update
  • Bug fix: Variations translations were not created when using custom attributes with space characters in them
  • Bug fix: When the option to show only products with custom prices in the secondary currencies was on, no products were displayed
  • Changed the order in which the products are displayed on the WooCommerce Multilingual products editor: chronological DESC
Download this release

Release Info

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

Code changes from version 3.6.8 to 3.6.9

assets/css/management.css CHANGED
@@ -924,7 +924,7 @@ table.widefat.currency_lang_table{
924
 
925
  #wcml_currencies_order li {
926
  float: left;
927
- margin: 0 8px 0 0;
928
  padding: 2px 8px;
929
  border: 1px solid #DFDFDF;
930
  border-radius: 2px;
924
 
925
  #wcml_currencies_order li {
926
  float: left;
927
+ margin: 0 8px 8px 0;
928
  padding: 2px 8px;
929
  border: 1px solid #DFDFDF;
930
  border-radius: 2px;
compatibility/wc_checkout_addons.class.php CHANGED
@@ -1,20 +1,20 @@
1
- <?php
2
- /**
3
- * Description of wc_checkout_addons
4
- *
5
- * @author konrad
6
- */
7
- class WCML_Checkout_Addons {
8
- public function __construct() {
9
- add_filter( 'wc_checkout_add_ons_options', array( $this, 'wc_checkout_add_ons_options_wpml_multi_currency_support' ) );
10
- }
11
-
12
- public function wc_checkout_add_ons_options_wpml_multi_currency_support( $options ) {
13
-
14
- foreach ( $options as $i => $option ) {
15
- $options[ $i ]['cost'] = apply_filters( 'wcml_raw_price_amount', $options[ $i ]['cost'] );
16
- }
17
-
18
- return $options;
19
- }
20
- }
1
+ <?php
2
+ /**
3
+ * Description of wc_checkout_addons
4
+ *
5
+ * @author konrad
6
+ */
7
+ class WCML_Checkout_Addons {
8
+ public function __construct() {
9
+ add_filter( 'wc_checkout_add_ons_options', array( $this, 'wc_checkout_add_ons_options_wpml_multi_currency_support' ) );
10
+ }
11
+
12
+ public function wc_checkout_add_ons_options_wpml_multi_currency_support( $options ) {
13
+
14
+ foreach ( $options as $i => $option ) {
15
+ $options[ $i ]['cost'] = apply_filters( 'wcml_raw_price_amount', $options[ $i ]['cost'] );
16
+ }
17
+
18
+ return $options;
19
+ }
20
+ }
inc/multi-currency-support.class.php CHANGED
@@ -44,8 +44,11 @@ class WCML_Multi_Currency_Support{
44
  add_filter( 'woocommerce_cart_subtotal', array( $this, 'filter_woocommerce_cart_subtotal'), 100, 3 );
45
 
46
  add_action( 'update_option_woocommerce_currency', array( $this, 'set_default_currencies_languages' ), 10, 2 );
 
 
 
47
  }
48
-
49
  function _load_filters(){
50
  $load = false;
51
 
@@ -166,8 +169,8 @@ class WCML_Multi_Currency_Support{
166
  }
167
  }
168
 
169
- $this->currency_codes = array_keys($this->currencies);
170
-
171
  // default language currencies
172
  foreach($active_languages as $language){
173
  if(!isset($woocommerce_wpml->settings['default_currencies'][$language['code']])){
@@ -189,7 +192,17 @@ class WCML_Multi_Currency_Support{
189
  }
190
  }
191
  }
192
-
 
 
 
 
 
 
 
 
 
 
193
  if($save_to_db){
194
  $woocommerce_wpml->update_settings();
195
  }
@@ -367,7 +380,7 @@ class WCML_Multi_Currency_Support{
367
 
368
  exit;
369
  }
370
-
371
  function currencies_list(){
372
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
373
  if(!$nonce || !wp_verify_nonce($nonce, 'wcml_currencies_list')){
@@ -700,7 +713,7 @@ class WCML_Multi_Currency_Support{
700
 
701
  function product_price_filter($null, $object_id, $meta_key, $single){
702
  global $sitepress;
703
-
704
  static $no_filter = false;
705
 
706
  if(empty($no_filter) && in_array(get_post_type($object_id), array('product', 'product_variation'))){
44
  add_filter( 'woocommerce_cart_subtotal', array( $this, 'filter_woocommerce_cart_subtotal'), 100, 3 );
45
 
46
  add_action( 'update_option_woocommerce_currency', array( $this, 'set_default_currencies_languages' ), 10, 2 );
47
+
48
+
49
+
50
  }
51
+
52
  function _load_filters(){
53
  $load = false;
54
 
169
  }
170
  }
171
 
172
+ $this->currency_codes = array_keys($this->currencies);
173
+
174
  // default language currencies
175
  foreach($active_languages as $language){
176
  if(!isset($woocommerce_wpml->settings['default_currencies'][$language['code']])){
192
  }
193
  }
194
  }
195
+
196
+ // add missing currencies to currencies_order
197
+ if(isset($woocommerce_wpml->settings['currencies_order'])){
198
+ foreach ($this->currency_codes as $currency) {
199
+ if (!in_array($currency, $woocommerce_wpml->settings['currencies_order'])) {
200
+ $woocommerce_wpml->settings['currencies_order'][] = $currency;
201
+ $save_to_db = true;
202
+ }
203
+ }
204
+ }
205
+
206
  if($save_to_db){
207
  $woocommerce_wpml->update_settings();
208
  }
380
 
381
  exit;
382
  }
383
+
384
  function currencies_list(){
385
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
386
  if(!$nonce || !wp_verify_nonce($nonce, 'wcml_currencies_list')){
713
 
714
  function product_price_filter($null, $object_id, $meta_key, $single){
715
  global $sitepress;
716
+
717
  static $no_filter = false;
718
 
719
  if(empty($no_filter) && in_array(get_post_type($object_id), array('product', 'product_variation'))){
inc/multi-currency.class.php CHANGED
@@ -27,6 +27,8 @@ class WCML_WC_MultiCurrency{
27
  add_filter('wcml_raw_price_amount', array($this, 'raw_price_filter'), 10, 2);
28
 
29
  add_filter('wcml_formatted_price', array($this, 'formatted_price'), 10, 2);
 
 
30
 
31
  add_filter('wcml_shipping_price_amount', array($this, 'shipping_price_filter'));
32
  add_filter('wcml_shipping_free_min_amount', array($this, 'shipping_free_min_amount'));
@@ -97,11 +99,11 @@ class WCML_WC_MultiCurrency{
97
 
98
 
99
  //custom prices for different currencies for products/variations [BACKEND]
100
- add_action('woocommerce_product_options_pricing',array($this,'woocommerce_product_options_custom_pricing'));
101
- add_action('woocommerce_product_after_variable_attributes',array($this,'woocommerce_product_after_variable_attributes_custom_pricing'),10,3);
102
 
103
  }
104
-
105
  function raw_price_filter($price, $currency = false) {
106
 
107
  if( $currency === false ){
@@ -316,7 +318,17 @@ class WCML_WC_MultiCurrency{
316
 
317
  return $currency;
318
  }
319
-
 
 
 
 
 
 
 
 
 
 
320
  function get_exchange_rates(){
321
  global $woocommerce_wpml;
322
  if(empty($this->exchange_rates)){
27
  add_filter('wcml_raw_price_amount', array($this, 'raw_price_filter'), 10, 2);
28
 
29
  add_filter('wcml_formatted_price', array($this, 'formatted_price'), 10, 2);
30
+
31
+ add_filter( 'woocommerce_get_variation_prices_hash', array( $this, 'add_currency_to_variation_prices_hash' ) );
32
 
33
  add_filter('wcml_shipping_price_amount', array($this, 'shipping_price_filter'));
34
  add_filter('wcml_shipping_free_min_amount', array($this, 'shipping_free_min_amount'));
99
 
100
 
101
  //custom prices for different currencies for products/variations [BACKEND]
102
+ add_action( 'woocommerce_product_options_pricing', array( $this, 'woocommerce_product_options_custom_pricing' ) );
103
+ add_action( 'woocommerce_product_after_variable_attributes', array( $this, 'woocommerce_product_after_variable_attributes_custom_pricing'), 10, 3 );
104
 
105
  }
106
+
107
  function raw_price_filter($price, $currency = false) {
108
 
109
  if( $currency === false ){
318
 
319
  return $currency;
320
  }
321
+
322
+ function add_currency_to_variation_prices_hash($data){
323
+
324
+ $data['currency'] = $this->get_client_currency();
325
+ $data['exchange_rates_hash'] = md5( json_encode( $this->exchange_rates ) );
326
+
327
+ return $data;
328
+
329
+ }
330
+
331
+
332
  function get_exchange_rates(){
333
  global $woocommerce_wpml;
334
  if(empty($this->exchange_rates)){
inc/products.class.php CHANGED
@@ -155,7 +155,7 @@ class WCML_Products{
155
 
156
  $sql = "SELECT p.ID,p.post_parent FROM $wpdb->posts AS p
157
  LEFT JOIN {$wpdb->prefix}icl_translations AS icl ON icl.element_id = p.id
158
- WHERE p.post_type = 'product' AND p.post_status IN ('publish','future','draft','pending','private') AND icl.element_type= 'post_product' AND icl.source_language_code IS NULL";
159
 
160
  if($slang){
161
  $sql .= " AND icl.language_code = %s ";
@@ -1178,7 +1178,7 @@ class WCML_Products{
1178
  foreach($values_arrs as $key=>$value){
1179
  $value_sanitized = sanitize_title($value);
1180
 
1181
- if( ( $value_sanitized == strtolower(urldecode($meta_value)) || strtolower($value_sanitized == $meta_value) ) && isset($values_arrs_tr[$key])){
1182
  $meta_value = $values_arrs_tr[$key];
1183
  }
1184
  }
@@ -1803,15 +1803,19 @@ class WCML_Products{
1803
  if(isset($unserialized_orig_product_attributes[$attribute])){
1804
  $orig_attr_values = explode('|',$unserialized_orig_product_attributes[$attribute]['value']);
1805
  foreach($orig_attr_values as $key=>$orig_attr_value){
1806
- $orig_attr_value = str_replace(' ','-',trim($orig_attr_value));
1807
- $orig_attr_value = lcfirst($orig_attr_value);
1808
- if($orig_attr_value == $default_term_slug){
1809
  $tnsl_product_attributes = get_post_meta($transl_post_id, '_product_attributes', true);
1810
  $unserialized_tnsl_product_attributes = maybe_unserialize($tnsl_product_attributes);
1811
  if(isset($unserialized_tnsl_product_attributes[$attribute])){
1812
  $trnsl_attr_values = explode('|',$unserialized_tnsl_product_attributes[$attribute]['value']);
1813
- $trnsl_attr_value = str_replace(' ','-',trim($trnsl_attr_values[$key]));
1814
- $trnsl_attr_value = lcfirst($trnsl_attr_value);
 
 
 
 
 
1815
  $unserialized_default_attributes[$attribute] = $trnsl_attr_value;
1816
  }
1817
  }
@@ -3133,9 +3137,9 @@ class WCML_Products{
3133
  foreach ( $matched_products_query as $product ) {
3134
  if( !get_post_meta( $product->ID,'_price_'.$client_currency, true ) ) continue;
3135
  if ( $product->post_type == 'product' )
3136
- $matched_products[] = apply_filters( 'translate_object_id', $product->ID, 'post_'.get_post_type($product->ID), true );
3137
  if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
3138
- $matched_products[] = apply_filters( 'translate_object_id', $product->post_parent, 'post_'.get_post_type($product->post_parent), true );
3139
  }
3140
 
3141
  add_filter('get_post_metadata', array($woocommerce_wpml->multi_currency_support, 'product_price_filter'), 10, 4);
@@ -3203,7 +3207,7 @@ class WCML_Products{
3203
 
3204
  if( !$product_id ){
3205
  return;
3206
- }elseif( !$woocommerce_wpml->products->is_original_product( $_POST['product_id'] ) ){ ?>
3207
  <script type="text/javascript">
3208
  jQuery(document).ready(function() {
3209
  wcml_lock_variation_fields();
155
 
156
  $sql = "SELECT p.ID,p.post_parent FROM $wpdb->posts AS p
157
  LEFT JOIN {$wpdb->prefix}icl_translations AS icl ON icl.element_id = p.id
158
+ WHERE p.post_type = 'product' AND p.post_status IN ('publish','future','draft','pending','private') AND icl.element_type= 'post_product' AND icl.source_language_code IS NULL ORDER BY p.id DESC";
159
 
160
  if($slang){
161
  $sql .= " AND icl.language_code = %s ";
1178
  foreach($values_arrs as $key=>$value){
1179
  $value_sanitized = sanitize_title($value);
1180
 
1181
+ if( ( $value_sanitized == strtolower(urldecode($meta_value)) || strtolower($value_sanitized) == $meta_value || $value == $meta_value ) && isset($values_arrs_tr[$key])){
1182
  $meta_value = $values_arrs_tr[$key];
1183
  }
1184
  }
1803
  if(isset($unserialized_orig_product_attributes[$attribute])){
1804
  $orig_attr_values = explode('|',$unserialized_orig_product_attributes[$attribute]['value']);
1805
  foreach($orig_attr_values as $key=>$orig_attr_value){
1806
+ $orig_attr_value_sanitized = strtolower( sanitize_title ( $orig_attr_value ) );
1807
+ if( $orig_attr_value_sanitized == $default_term_slug || trim($orig_attr_value) == trim($default_term_slug) ){
 
1808
  $tnsl_product_attributes = get_post_meta($transl_post_id, '_product_attributes', true);
1809
  $unserialized_tnsl_product_attributes = maybe_unserialize($tnsl_product_attributes);
1810
  if(isset($unserialized_tnsl_product_attributes[$attribute])){
1811
  $trnsl_attr_values = explode('|',$unserialized_tnsl_product_attributes[$attribute]['value']);
1812
+
1813
+ if( $orig_attr_value_sanitized == $default_term_slug ){
1814
+ $trnsl_attr_value = strtolower( sanitize_title( trim( $trnsl_attr_values[$key] ) ) );
1815
+ }else{
1816
+ $trnsl_attr_value = trim($trnsl_attr_values[$key]);
1817
+ }
1818
+
1819
  $unserialized_default_attributes[$attribute] = $trnsl_attr_value;
1820
  }
1821
  }
3137
  foreach ( $matched_products_query as $product ) {
3138
  if( !get_post_meta( $product->ID,'_price_'.$client_currency, true ) ) continue;
3139
  if ( $product->post_type == 'product' )
3140
+ $matched_products[] = apply_filters( 'translate_object_id', $product->ID, 'product', true );
3141
  if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
3142
+ $matched_products[] = apply_filters( 'translate_object_id', $product->post_parent, get_post_type($product->post_parent), true );
3143
  }
3144
 
3145
  add_filter('get_post_metadata', array($woocommerce_wpml->multi_currency_support, 'product_price_filter'), 10, 4);
3207
 
3208
  if( !$product_id ){
3209
  return;
3210
+ }elseif( !$woocommerce_wpml->products->is_original_product( $product_id ) ){ ?>
3211
  <script type="text/javascript">
3212
  jQuery(document).ready(function() {
3213
  wcml_lock_variation_fields();
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.3
8
- Stable tag: 3.6.8
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
@@ -78,6 +78,12 @@ In order for the checkout and store pages to appear translated, you need to crea
78
 
79
  == Changelog ==
80
 
 
 
 
 
 
 
81
  = 3.6.8 =
82
  * Added a series of compatibility fixes for WooCommerce 2.4.x (custom attributes, endpoints)
83
  * Bug fix: Incorrect prices were calculated for Table Rate Shipping (bug originally fixed in version 3.6.5)
5
  License: GPLv2
6
  Requires at least: 3.0
7
  Tested up to: 4.3
8
+ Stable tag: 3.6.9
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
78
 
79
  == Changelog ==
80
 
81
+ = 3.6.9 =
82
+ * Bug fix: Prices for variable products were not converted correctly when using multiple currencies after the WooCommerce 2.4 update
83
+ * Bug fix: Variations translations were not created when using custom attributes with space characters in them
84
+ * Bug fix: When the option to show only products with custom prices in the secondary currencies was on, no products were displayed
85
+ * Changed the order in which the products are displayed on the WooCommerce Multilingual products editor: chronological DESC
86
+
87
  = 3.6.8 =
88
  * Added a series of compatibility fixes for WooCommerce 2.4.x (custom attributes, endpoints)
89
  * Bug fix: Incorrect prices were calculated for Table Rate Shipping (bug originally fixed in version 3.6.5)
wpml-woocommerce.php CHANGED
@@ -5,12 +5,12 @@
5
  Description: Allows running fully multilingual e-Commerce sites with WooCommerce and WPML. <a href="http://wpml.org/documentation/related-projects/woocommerce-multilingual/">Documentation</a>.
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
- Version: 3.6.8
9
  */
10
 
11
 
12
  if(defined('WCML_VERSION')) return;
13
- define('WCML_VERSION', '3.6.8');
14
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
15
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
16
  define('WCML_PLUGIN_URL', plugins_url() . '/' . WCML_PLUGIN_FOLDER);
5
  Description: Allows running fully multilingual e-Commerce sites with WooCommerce and WPML. <a href="http://wpml.org/documentation/related-projects/woocommerce-multilingual/">Documentation</a>.
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
+ Version: 3.6.9
9
  */
10
 
11
 
12
  if(defined('WCML_VERSION')) return;
13
+ define('WCML_VERSION', '3.6.9');
14
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
15
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
16
  define('WCML_PLUGIN_URL', plugins_url() . '/' . WCML_PLUGIN_FOLDER);