WooCommerce Multilingual – run WooCommerce with WPML - Version 2.3.2

Version Description

  • Sync also default options for custom attributes.
  • Global resync (done only once) of the orderings of product attribute values and categories across all languages.
  • Fixed a bug and a corner case in variation synchronization.
Download this release

Release Info

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

Code changes from version 2.3.1 to 2.3.2

Files changed (3) hide show
  1. readme.txt +8 -3
  2. woocommerce_wpml.class.php +84 -27
  3. wpml-woocommerce.php +2 -2
readme.txt CHANGED
@@ -4,8 +4,8 @@ Donate link: http://wpml.org/documentation/related-projects/woocommerce-multilin
4
  Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multilingual, e-shop, shop
5
  License: GPLv2
6
  Requires at least: 3.0
7
- Tested up to: 3.5
8
- Stable tag: 2.3.1
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
@@ -13,7 +13,7 @@ Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
13
 
14
  This 'glue' plugin makes it possible to run fully multilingual e-commerce sites using [WooCommerce](http://wordpress.org/extend/plugins/woocommerce/) and [WPML](http://wpml.org). It makes products and store pages translatable, lets visitors switch languages and order products in their language.
15
 
16
- >> This version of WooCommerce Multilingual has been updated to work with WooCommerce 2.x. We are keeping backward compatibility with WooCommerce 1.x.
17
 
18
  = Features =
19
 
@@ -68,6 +68,11 @@ In order for the checkout and store pages to appear translated, you need to crea
68
 
69
  == Changelog ==
70
 
 
 
 
 
 
71
  = 2.3.1 =
72
  * Fixed incompatibility with PHP 5.2
73
 
4
  Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multilingual, e-shop, shop
5
  License: GPLv2
6
  Requires at least: 3.0
7
+ Tested up to: 3.6.1
8
+ Stable tag: 2.3.2
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
13
 
14
  This 'glue' plugin makes it possible to run fully multilingual e-commerce sites using [WooCommerce](http://wordpress.org/extend/plugins/woocommerce/) and [WPML](http://wpml.org). It makes products and store pages translatable, lets visitors switch languages and order products in their language.
15
 
16
+ > There is a new version of WooCommerce Multilingual, which is far easier to use and a lot more stable. Since it is in release candidate state, it's only available via WPML.org. See the [WooCommerce Multilingual 3.0 announcement blog post](http://wpml.org/2013/10/woocommerce-multilingual-3-0-release-candidate/) for users guide and download instructions.
17
 
18
  = Features =
19
 
68
 
69
  == Changelog ==
70
 
71
+ = 2.3.2 =
72
+ * Sync also default options for custom attributes.
73
+ * Global resync (done only once) of the orderings of product attribute values and categories across all languages.
74
+ * Fixed a bug and a corner case in variation synchronization.
75
+
76
  = 2.3.1 =
77
  * Fixed incompatibility with PHP 5.2
78
 
woocommerce_wpml.class.php CHANGED
@@ -21,7 +21,6 @@ class woocommerce_wpml {
21
 
22
  function init(){
23
  global $sitepress;
24
-
25
  $allok = true;
26
  $this->missing = array();
27
  if(!defined('ICL_SITEPRESS_VERSION') || ICL_PLUGIN_INACTIVE){
@@ -58,6 +57,11 @@ class woocommerce_wpml {
58
  $this->wcml_install();
59
  }
60
 
 
 
 
 
 
61
  add_action('admin_notices', array($this, 'check_for_incompatible_permalinks'));
62
 
63
  add_filter('woocommerce_get_checkout_url', array($this, 'get_checkout_page_url'));
@@ -251,7 +255,7 @@ class woocommerce_wpml {
251
  add_action('updated_post_meta', array($this,'update_post_meta'), 100, 4);
252
  add_action('added_post_meta', array($this,'update_post_meta'), 100, 4);
253
  add_action('updated_woocommerce_term_meta',array($this,'sync_term_order'), 100,4);
254
- }
255
 
256
  function set_price_config() {
257
  global $sitepress, $iclTranslationManagement;
@@ -422,7 +426,6 @@ class woocommerce_wpml {
422
  //added for WC 2.0.x
423
  $function = create_function('$val', 'return $val . "_notification";');
424
  $email_actions = array_merge($email_actions, array_map($function, $email_actions));
425
-
426
  foreach ( $email_actions as $action ) {
427
  add_action( $action, array($this, 'translate_email_notification'), 9 );
428
  }
@@ -430,7 +433,6 @@ class woocommerce_wpml {
430
 
431
  function translate_email_notification($order_id) {
432
  global $sitepress;
433
-
434
  $lang = get_post_meta($order_id, 'wpml_language', true);
435
 
436
  if(!empty($lang)){
@@ -439,8 +441,6 @@ class woocommerce_wpml {
439
 
440
  }
441
 
442
-
443
-
444
  /**
445
  * Adds admin notice.
446
  */
@@ -1088,6 +1088,9 @@ class woocommerce_wpml {
1088
  if($pagenow != 'post.php' && $pagenow != 'post-new.php' && !$ajax_call){
1089
  return;
1090
  }
 
 
 
1091
 
1092
  // get language code
1093
  $language_details = $sitepress->get_element_language_details($post_id, 'post_product');
@@ -1095,6 +1098,10 @@ class woocommerce_wpml {
1095
  return;
1096
  }
1097
 
 
 
 
 
1098
  // pick posts to sync
1099
  $posts = array();
1100
  $translations = $sitepress->get_element_translations($language_details->trid, 'post_product');
@@ -1106,8 +1113,8 @@ class woocommerce_wpml {
1106
  }
1107
  }
1108
 
 
1109
  // TODO: move outside the loop all db queries on duplicated_post_id
1110
- // don't want to do it so close to release, just in case
1111
  foreach ($posts as $post_id => $translation) {
1112
  $lang = $translation->language_code;
1113
 
@@ -1159,15 +1166,17 @@ class woocommerce_wpml {
1159
  $unserialized_default_attributes = maybe_unserialize($original_default_attributes);
1160
  foreach($unserialized_default_attributes as $attribute => $default_term_slug){
1161
  // get the correct language
1162
- $default_term = get_term_by('slug', $default_term_slug, $attribute);
1163
- $default_term_id = icl_object_id($default_term->term_id, $attribute, false, $lang);
1164
-
1165
- if($default_term_id){
1166
- $default_term = get_term_by('id', $default_term_id, $attribute);
1167
- $unserialized_default_attributes[$attribute] = $default_term->slug;
1168
- // if it isn't translated - unset it
1169
- } else {
1170
- unset($unserialized_default_attributes[$attribute]);
 
 
1171
  }
1172
  }
1173
 
@@ -1177,20 +1186,23 @@ class woocommerce_wpml {
1177
  }
1178
 
1179
  //sync product categories
 
 
 
 
1180
  $terms = get_the_terms($duplicated_post_id, 'product_cat');
1181
- foreach ($terms as $term) {
1182
- $trid = $sitepress->get_element_trid($term->term_id, 'tax_product_cat');
1183
  if ($trid) {
1184
  $translations = $sitepress->get_element_translations($trid,'tax_product_cat');
 
1185
  if (isset($translations[$lang])) {
1186
- $updates[$tax][] = intval($translations[$lang]->term_id);
1187
  }
1188
  }
1189
  }
1190
 
1191
  //synchronize term data, postmeta (Woocommerce "global" product attributes and custom attributes)
1192
- $taxs = array();
1193
- $updates = array();
1194
 
1195
  $taxonomies = get_post_meta($duplicated_post_id, '_product_attributes', true);
1196
  //error_log('Trans tax '.var_export($taxonomies,true));
@@ -1200,8 +1212,8 @@ class woocommerce_wpml {
1200
  $taxs[] = $tax;
1201
  $updates[$tax] = array();
1202
  $terms = get_the_terms($duplicated_post_id, $tax);
1203
- foreach ($terms as $term) {
1204
- $trid = $sitepress->get_element_trid($term->term_id, 'tax_' . $tax);
1205
  if ($trid) {
1206
  $translations = $sitepress->get_element_translations($trid,'tax_' . $tax);
1207
  if (isset($translations[$lang])) {
@@ -1339,7 +1351,7 @@ class woocommerce_wpml {
1339
  if ($trid) {
1340
  $translations = $sitepress->get_element_translations($trid,'tax_' . $tax);
1341
  if (isset($translations[$lang])) {
1342
- $meta_value = get_term_by('id', $translations[$lang]->term_id, $tax)->slug;
1343
  }
1344
  }
1345
  }
@@ -1355,7 +1367,6 @@ class woocommerce_wpml {
1355
  }
1356
  }
1357
 
1358
-
1359
  /**
1360
  * Sync term order for product attributes, categories and tags
1361
  */
@@ -1383,10 +1394,54 @@ class woocommerce_wpml {
1383
  }
1384
  }
1385
 
1386
- function sync_variation_order($variation_id) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1387
 
 
 
1388
  }
1389
-
1390
  function sanitize_cpa_values($values) {
1391
  // Text based, separate by pipe
1392
  $values = explode('|', esc_html(stripslashes($values)));
@@ -1587,6 +1642,8 @@ class woocommerce_wpml {
1587
  $cart->calculate_totals();
1588
  }
1589
 
 
 
1590
  /**
1591
  * WooCommerce Multilingual deactivation hook.
1592
  */
21
 
22
  function init(){
23
  global $sitepress;
 
24
  $allok = true;
25
  $this->missing = array();
26
  if(!defined('ICL_SITEPRESS_VERSION') || ICL_PLUGIN_INACTIVE){
57
  $this->wcml_install();
58
  }
59
 
60
+ if (get_option('icl_is_wcml_term_order_synched') !== 'yes') {
61
+ //global term ordering resync when moving to >= 3.3.x
62
+ add_action('init',array($this,'sync_term_order_globally'));
63
+ }
64
+
65
  add_action('admin_notices', array($this, 'check_for_incompatible_permalinks'));
66
 
67
  add_filter('woocommerce_get_checkout_url', array($this, 'get_checkout_page_url'));
255
  add_action('updated_post_meta', array($this,'update_post_meta'), 100, 4);
256
  add_action('added_post_meta', array($this,'update_post_meta'), 100, 4);
257
  add_action('updated_woocommerce_term_meta',array($this,'sync_term_order'), 100,4);
258
+ }
259
 
260
  function set_price_config() {
261
  global $sitepress, $iclTranslationManagement;
426
  //added for WC 2.0.x
427
  $function = create_function('$val', 'return $val . "_notification";');
428
  $email_actions = array_merge($email_actions, array_map($function, $email_actions));
 
429
  foreach ( $email_actions as $action ) {
430
  add_action( $action, array($this, 'translate_email_notification'), 9 );
431
  }
433
 
434
  function translate_email_notification($order_id) {
435
  global $sitepress;
 
436
  $lang = get_post_meta($order_id, 'wpml_language', true);
437
 
438
  if(!empty($lang)){
441
 
442
  }
443
 
 
 
444
  /**
445
  * Adds admin notice.
446
  */
1088
  if($pagenow != 'post.php' && $pagenow != 'post-new.php' && !$ajax_call){
1089
  return;
1090
  }
1091
+ if (isset($_GET['action']) && $_GET['action'] == 'trash') {
1092
+ return;
1093
+ }
1094
 
1095
  // get language code
1096
  $language_details = $sitepress->get_element_language_details($post_id, 'post_product');
1098
  return;
1099
  }
1100
 
1101
+ // If we reach this point, we go ahead with sync.
1102
+ // Remove filter to avoid double sync
1103
+ remove_action('save_post', array($this, 'sync_variations'), 11, 2);
1104
+
1105
  // pick posts to sync
1106
  $posts = array();
1107
  $translations = $sitepress->get_element_translations($language_details->trid, 'post_product');
1113
  }
1114
  }
1115
 
1116
+
1117
  // TODO: move outside the loop all db queries on duplicated_post_id
 
1118
  foreach ($posts as $post_id => $translation) {
1119
  $lang = $translation->language_code;
1120
 
1166
  $unserialized_default_attributes = maybe_unserialize($original_default_attributes);
1167
  foreach($unserialized_default_attributes as $attribute => $default_term_slug){
1168
  // get the correct language
1169
+ if (substr($attribute, 0, 3) == 'pa_') {
1170
+ $default_term = get_term_by('slug', $default_term_slug, $attribute);
1171
+ $default_term_id = icl_object_id($default_term->term_id, $attribute, false, $lang);
1172
+
1173
+ if($default_term_id){
1174
+ $default_term = get_term_by('id', $default_term_id, $attribute);
1175
+ $unserialized_default_attributes[$attribute] = $default_term->slug;
1176
+ } else {
1177
+ // if it isn't translated - unset it
1178
+ unset($unserialized_default_attributes[$attribute]);
1179
+ }
1180
  }
1181
  }
1182
 
1186
  }
1187
 
1188
  //sync product categories
1189
+ $taxs = array();
1190
+ $updates = array();
1191
+
1192
+ $taxs[] = 'product_cat';
1193
  $terms = get_the_terms($duplicated_post_id, 'product_cat');
1194
+ if ($terms) foreach ($terms as $term) {
1195
+ $trid = $sitepress->get_element_trid($term->term_taxonomy_id, 'tax_product_cat');
1196
  if ($trid) {
1197
  $translations = $sitepress->get_element_translations($trid,'tax_product_cat');
1198
+ //error_log("translations ".var_export($translations,true));
1199
  if (isset($translations[$lang])) {
1200
+ $updates['product_cat'][] = intval($translations[$lang]->term_id);
1201
  }
1202
  }
1203
  }
1204
 
1205
  //synchronize term data, postmeta (Woocommerce "global" product attributes and custom attributes)
 
 
1206
 
1207
  $taxonomies = get_post_meta($duplicated_post_id, '_product_attributes', true);
1208
  //error_log('Trans tax '.var_export($taxonomies,true));
1212
  $taxs[] = $tax;
1213
  $updates[$tax] = array();
1214
  $terms = get_the_terms($duplicated_post_id, $tax);
1215
+ if ($terms) foreach ($terms as $term) {
1216
+ $trid = $sitepress->get_element_trid($term->term_taxonomy_id, 'tax_' . $tax);
1217
  if ($trid) {
1218
  $translations = $sitepress->get_element_translations($trid,'tax_' . $tax);
1219
  if (isset($translations[$lang])) {
1351
  if ($trid) {
1352
  $translations = $sitepress->get_element_translations($trid,'tax_' . $tax);
1353
  if (isset($translations[$lang])) {
1354
+ $meta_value = $wpdb->get_var($wpdb->prepare("SELECT slug FROM $wpdb->terms WHERE term_id = %s", $translations[$lang]->term_id));
1355
  }
1356
  }
1357
  }
1367
  }
1368
  }
1369
 
 
1370
  /**
1371
  * Sync term order for product attributes, categories and tags
1372
  */
1394
  }
1395
  }
1396
 
1397
+ function sync_term_order_globally() {
1398
+ //syncs the term order of any taxonomy in $wpdb->prefix.'woocommerce_attribute_taxonomies'
1399
+ //use it when term orderings have become unsynched, e.g. before WCML 3.3.
1400
+ global $sitepress, $wpdb, $woocommerce;
1401
+ $cur_lang = $sitepress->get_current_language();
1402
+ $lang = $sitepress->get_default_language();
1403
+ $sitepress->switch_lang($lang);
1404
+
1405
+ $taxes = $woocommerce->get_attribute_taxonomies(); //="SELECT * FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies"
1406
+
1407
+ if ($taxes) foreach ($taxes as $woo_tax) {
1408
+ $tax = 'pa_'.$woo_tax->attribute_name;
1409
+ $meta_key = 'order_'.$tax;
1410
+ //if ($tax != 'pa_frame') continue;
1411
+ $terms = get_terms($tax);
1412
+ if ($terms)foreach ($terms as $term) {
1413
+ $term_order = get_woocommerce_term_meta($term->term_id,$meta_key);
1414
+ $trid = $sitepress->get_element_trid($term->term_taxonomy_id,'tax_'.$tax);
1415
+ error_log("trid $trid tt_id {$term->term_taxonomy_id}");
1416
+ $translations = $sitepress->get_element_translations($trid,'tax_' . $tax);
1417
+ if ($translations) foreach ($translations as $trans) {
1418
+ if ($trans->language_code != $lang) {
1419
+ error_log("Updating {$trans->term_id} {$trans->language_code} to $term_order" );
1420
+ update_woocommerce_term_meta( $trans->term_id, $meta_key, $term_order);
1421
+ }
1422
+ }
1423
+ }
1424
+ }
1425
+
1426
+ //sync product categories ordering
1427
+ $terms = get_terms('product_cat');
1428
+ if ($terms) foreach($terms as $term) {
1429
+ $term_order = get_woocommerce_term_meta($term->term_id,'order');
1430
+ $trid = $sitepress->get_element_trid($term->term_taxonomy_id,'tax_product_cat');
1431
+ //error_log("product_cat: trid $trid tt_id {$term->term_taxonomy_id}");
1432
+ $translations = $sitepress->get_element_translations($trid,'tax_product_cat');
1433
+ if ($translations) foreach ($translations as $trans) {
1434
+ if ($trans->language_code != $lang) {
1435
+ error_log("Updating {$trans->term_id} {$trans->language_code} to $term_order" );
1436
+ update_woocommerce_term_meta( $trans->term_id, 'order', $term_order);
1437
+ }
1438
+ }
1439
+ }
1440
 
1441
+ $sitepress->switch_lang($cur_lang);
1442
+ add_option('icl_is_wcml_term_order_synched', 'yes');
1443
  }
1444
+
1445
  function sanitize_cpa_values($values) {
1446
  // Text based, separate by pipe
1447
  $values = explode('|', esc_html(stripslashes($values)));
1642
  $cart->calculate_totals();
1643
  }
1644
 
1645
+
1646
+
1647
  /**
1648
  * WooCommerce Multilingual deactivation hook.
1649
  */
wpml-woocommerce.php CHANGED
@@ -5,11 +5,11 @@
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: ICanLocalize
7
  Author URI: http://wpml.org/
8
- Version: 2.3.1
9
  */
10
 
11
  if(defined('WCML_VERSION')) return;
12
- define('WCML_VERSION', '2.3.1');
13
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
14
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
15
  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: ICanLocalize
7
  Author URI: http://wpml.org/
8
+ Version: 2.3.2
9
  */
10
 
11
  if(defined('WCML_VERSION')) return;
12
+ define('WCML_VERSION', '2.3.2');
13
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
14
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
15
  define('WCML_PLUGIN_URL', plugins_url() . '/' . WCML_PLUGIN_FOLDER);