WooCommerce Multilingual – run WooCommerce with WPML - Version 1.5

Version Description

  • Fixed manually setting prices in translated products.
  • Take advantage of WPML's new slug translation feature.
  • Added the possibility of translating custom attributes.
  • Improvements to product variation synchronization.
  • Fixed product stock sync for variable products .
  • Fix and improve checks made to incompatible permalink configurations.
  • Fix tax label translation when there is more than one of them.
  • Send order notifications in the language the order was made.
  • Removed several warnings and updated deprecated code.
  • Cleanup language configuration file and add missing strings.
Download this release

Release Info

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

Code changes from version 1.4 to 1.5

menu/management.php CHANGED
@@ -36,7 +36,7 @@
36
  <table class="widefat">
37
  <thead>
38
  <tr>
39
- <th><?php echo __('Add currency', 'wpml-wcml') ?></th>
40
  </tr>
41
  </thead>
42
  <tbody>
36
  <table class="widefat">
37
  <thead>
38
  <tr>
39
+ <th><?php if (!isset($_GET['edit'])): ?>Add currency<?php else: ?>Edit currency<?php endif; ?></th>
40
  </tr>
41
  </thead>
42
  <tbody>
readme.txt CHANGED
@@ -2,35 +2,43 @@
2
  Contributors: AmirHelzer, dominykasgel, dgwatkins
3
  Donate link: http://wpml.org/documentation/related-projects/woocommerce-multilingual/
4
  Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multilingual, e-shop, shop
 
5
  Requires at least: 3.0
6
  Tested up to: 3.5
7
- Stable tag: 1.4
8
- Version: 1.4
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
12
  == Description ==
13
 
14
- This 'glue' plugin makes it possible to run fully multilingual e-commerce sites using WooCommerce and WPML. It makes products and store pages translatable, lets visitors switch languages and order products in their language.
 
 
15
 
16
  = Features =
17
 
18
- * Lets you translate products, attributes and categories
 
19
  * Keeps the same language through the checkout process
20
  * Sends emails to clients and admins in their selected language
21
  * Allows inventory tracking without breaking products into languages
22
  * Enables running a single WooCommerce store with multiple currencies
23
 
24
- = Documentation =
 
 
 
 
25
 
26
- Please go to [WooCommerce Multilingual Doc](http://wpml.org/documentation/related-projects/woocommerce-multilingual/) page. You'll find instructions for translating the shop pages, the products and plugin strings.
 
 
27
 
28
  = Downloads =
29
 
30
- You will need:
31
 
32
- * [WooCommerce](http://wordpress.org/extend/plugins/woocommerce/) version 1.6.5 and up. Please note that the official WooCommerce release might not be 100% compatible. Always check the [development version on wpml.org](http://wpml.org/documentation/related-projects/woocommerce-multilingual/).
33
- * [WPML](http://wpml.org) version 2.6.0 and up - the multilingual WordPress plugin
34
 
35
  == Installation ==
36
 
@@ -60,6 +68,18 @@ In order for the checkout and store pages to appear translated, you need to crea
60
 
61
  == Changelog ==
62
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  = 1.4 =
64
  * Allow translating the 'Terms & Conditions' page.
65
  * Register shipping methods strings for translation.
@@ -113,6 +133,9 @@ In order for the checkout and store pages to appear translated, you need to crea
113
 
114
  == Upgrade Notice ==
115
 
 
 
 
116
  = 1.4 =
117
  This version runs with WooCommerce 1.6.5.x and 1.7.x. Recommeded WPML version is 2.6.2 and above.
118
 
2
  Contributors: AmirHelzer, dominykasgel, dgwatkins
3
  Donate link: http://wpml.org/documentation/related-projects/woocommerce-multilingual/
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: 1.5
 
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
12
  == Description ==
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
+ >> WooCommerce Multilingual is currently compatible with WooCommerce 1.x only. We are working on a new version for WooCommerce 2.x. We will write about updates in [WPML blog](http://wpml.org/blog/).
17
 
18
  = Features =
19
 
20
+ * Lets you translate products, variations, attributes and categories
21
+ * Easily synchronizes between products and variations between different languages
22
  * Keeps the same language through the checkout process
23
  * Sends emails to clients and admins in their selected language
24
  * Allows inventory tracking without breaking products into languages
25
  * Enables running a single WooCommerce store with multiple currencies
26
 
27
+ = Usage Instructions =
28
+
29
+ You will need to translate all the standard WooCommerce pages. Then, translate products and product categories and you're on your way.
30
+
31
+ Strings that are not part of any product, will be translatable via WPML's String Translation.
32
 
33
+ For complete information on setting up a multilingual shop, please go to [WooCommerce Multilingual Manual](http://wpml.org/documentation/related-projects/woocommerce-multilingual/) page.
34
+
35
+ When you need help, go to [WPML technical support forum](http://wpml.org/forums/forum/english-support/).
36
 
37
  = Downloads =
38
 
39
+ This version of WooCommerce Multilingual works with WooCommerce 1.x. The latest version is [WooCommerce 1.6.6](http://downloads.wordpress.org/plugin/woocommerce.1.6.6.zip). You can see other versions in the [WooCommerce Developers](http://wordpress.org/extend/plugins/woocommerce/developers/) page.
40
 
41
+ You will also need [WPML](http://wpml.org), together with the String Translation module, which is part of the [Multilingual CMS](http://wpml.org/purchase/) package.
 
42
 
43
  == Installation ==
44
 
68
 
69
  == Changelog ==
70
 
71
+ = 1.5 =
72
+ * Fixed manually setting prices in translated products.
73
+ * Take advantage of WPML's new slug translation feature.
74
+ * Added the possibility of translating custom attributes.
75
+ * Improvements to product variation synchronization.
76
+ * Fixed product stock sync for variable products .
77
+ * Fix and improve checks made to incompatible permalink configurations.
78
+ * Fix tax label translation when there is more than one of them.
79
+ * Send order notifications in the language the order was made.
80
+ * Removed several warnings and updated deprecated code.
81
+ * Cleanup language configuration file and add missing strings.
82
+
83
  = 1.4 =
84
  * Allow translating the 'Terms & Conditions' page.
85
  * Register shipping methods strings for translation.
133
 
134
  == Upgrade Notice ==
135
 
136
+ = 1.5 =
137
+ Variation translation works a lot better now. This version runs best with WooCommerce 1.6.6.
138
+
139
  = 1.4 =
140
  This version runs with WooCommerce 1.6.5.x and 1.7.x. Recommeded WPML version is 2.6.2 and above.
141
 
woocommerce_wpml.class.php CHANGED
@@ -19,6 +19,8 @@ class woocommerce_wpml {
19
  }
20
 
21
  function init(){
 
 
22
  if(!defined('ICL_SITEPRESS_VERSION') || ICL_PLUGIN_INACTIVE){
23
  if(!function_exists('is_multisite') || !is_multisite()) {
24
  add_action('admin_notices', array($this, 'no_wpml_warning'));
@@ -57,17 +59,21 @@ class woocommerce_wpml {
57
  add_filter('woocommerce_params', array($this, 'ajax_params'));
58
  add_filter('woocommerce_redirect', array($this, 'do_redirect'));
59
  add_filter('woocommerce_attribute_label', array($this, 'translate_attributes'), 14, 2);
 
 
60
  add_filter('woocommerce_upsell_crosssell_search_products', array($this, 'woocommerce_upsell_crosssell_search_posts'));
61
  add_filter('icl_post_alternative_languages', array($this, 'post_alternative_languages'));
62
  add_filter('woocommerce_gateway_title', array($this, 'gateway_title'), 10);
63
  add_filter('woocommerce_gateway_description', array($this, 'gateway_description'), 10, 2);
64
- add_filter('pre_get_posts', array($this, 'shop_page_query'), 9);
65
  add_filter('woocommerce_json_search_found_products', array($this, 'search_products'));
66
  add_filter('woocommerce_currency', array($this, 'set_ml_currency'));
67
  //add_filter('woocommerce_paypal_amount', array($this, 'paypal_amount'));
68
  add_action('admin_print_scripts', array($this,'js_scripts_setup'), 11);
69
  add_action('init', array($this, 'translate_email_notifications'));
70
 
 
 
 
71
  // Translate shop page settings
72
  add_filter('option_woocommerce_shop_page_id', array($this, 'translate_pages_in_settings'));
73
  add_filter('option_woocommerce_terms_page_id', array($this, 'translate_pages_in_settings'));
@@ -84,6 +90,9 @@ class woocommerce_wpml {
84
  if(get_option('currency_converting_option') == '1'){
85
  add_filter('raw_woocommerce_price', array($this, 'woocommerce_price'));
86
  add_filter('woocommerce_order_amount_total', array($this, 'woocommerce_price'));
 
 
 
87
  }
88
 
89
  add_filter('woocommerce_currency_symbol', array($this, 'woocommerce_currency_symbol'), 2);
@@ -102,6 +111,8 @@ class woocommerce_wpml {
102
  add_filter('woocommerce_price_filter_max_price', array($this, 'price_filter_max_price'));
103
 
104
  add_action('save_post', array($this, 'sync_variations'), 11, 2); // After WPML
 
 
105
 
106
  add_action('admin_menu', array($this, 'menu'));
107
  add_action('init', array($this, 'load_css_and_js'));
@@ -109,17 +120,13 @@ class woocommerce_wpml {
109
  if(is_admin()){
110
  add_action('admin_init', array($this, 'make_new_attributes_translatable'));
111
  } else {
112
- add_filter('icl_ls_languages', array($this, 'translate_ls_shop_url'));
113
- }
114
-
115
- /*
116
- // Hooks for translating product attribute values, not really needed as they can be translated
117
- // with WPML as terms. Commenting it in case its requested.
118
- add_filter('woocommerce_variation_term_name', array($this, 'variation_term_name'));
119
- if(is_admin()){
120
- add_action('admin_init', array($this, 'translate_custom_attributes'));
121
  }
122
- */
 
 
 
123
 
124
  if(isset($_POST['general_options']) && check_admin_referer('general_options', 'general_options_nonce')){
125
  $enable_multi_currency = (isset($_POST['multi_currency'])) ? trim($_POST['multi_currency']) : null;
@@ -139,6 +146,9 @@ class woocommerce_wpml {
139
 
140
  }
141
 
 
 
 
142
  if(isset($_POST['add_currency']) && check_admin_referer('add_currency', 'add_currency_nonce')){
143
  global $wpdb, $pagenow;
144
 
@@ -222,6 +232,73 @@ class woocommerce_wpml {
222
  add_action('option_woocommerce_tax_rates', array($this, 'tax_rates'));
223
  }
224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  function register_shipping_methods($available_methods){
226
 
227
  foreach($available_methods as $method){
@@ -241,7 +318,7 @@ class woocommerce_wpml {
241
  function tax_rates($rates){
242
  if (!empty($rates)) {
243
  foreach ($rates as &$rate) {
244
- $rate['label'] = icl_translate('woocommerce', 'incl_VAT_tax_label', $rate['label']);
245
  }
246
  }
247
 
@@ -364,36 +441,59 @@ class woocommerce_wpml {
364
  * one of these must be true for product urls to work
365
  * if none of these are true, display a warning message
366
  */
367
- function check_for_incompatible_permalinks() {
368
- global $sitepress;
369
- // Check if the shop prefix is disabled, if so we are ok
370
- if (get_option('woocommerce_prepend_shop_page_to_products') != "yes") {
371
- return;
372
- }
373
- // Check if translated shop pages have the same slug
374
- $shop_page_id = get_option('woocommerce_shop_page_id');
375
- if (empty($shop_page_id)) {
376
- return;
377
- }
378
- $slug = @get_page($shop_page_id)->post_name;
379
- $languages = icl_get_languages('skip_missing=0');
380
- $allsame = true;
381
- foreach ($languages as $language) {
382
- if ($language['language_code'] != $sitepress->get_default_language()) {
383
- $translated_slug = @get_page(icl_object_id($shop_page_id, 'page', false, $language['language_code']))->post_name;
384
- if ($translated_slug != $slug) {
385
- $allsame = false;
386
- break;
387
- }
388
- }
389
- }
390
- if (!$allsame) {
391
- ?>
392
- <div class="message error"><p><?php printf(__('If you want different slugs for shop pages, you need to disable the shop prefix for products in <a href="%s">WooCommerce Settings</a>', 'plugin woocommerce'),
393
- 'admin.php?page=woocommerce_settings&tab=pages'); ?></p></div>
394
- <?php
395
- }
396
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
 
398
  /**
399
  * Switch the language on AJAX action, because in some ways the correct language is missing.
@@ -617,7 +717,7 @@ class woocommerce_wpml {
617
  } else if($translated_checkout_page_id == $post->ID || $checkout_page_id == $post->ID){
618
  $value['is_checkout'] = 1;
619
 
620
- $value['locale'] = '';
621
 
622
  $_SESSION['wpml_globalcart_language'] = $sitepress->get_current_language();
623
 
@@ -697,18 +797,30 @@ class woocommerce_wpml {
697
  return $output;
698
  }
699
 
700
- /**
701
- * Translates custom attribute/variation title.
702
- *
703
- * @return type
704
- */
705
- function variation_term_name($term_name){
706
- if(function_exists('icl_t')){
707
- $term_name = icl_t('woocommerce', $term_name .'_attribute_name', $term_name);
708
- }
709
 
710
- return $term_name;
711
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
712
 
713
  /**
714
  * Translates the payment gateway title text.
@@ -744,8 +856,9 @@ class woocommerce_wpml {
744
 
745
  $front_page_id = get_option('page_on_front');
746
  $shop_page_id = get_option('woocommerce_shop_page_id');
 
747
 
748
- if ($q->get('page_id') !== $front_page_id && $shop_page_id == $q->get('page_id')) {
749
  $q->set( 'post_type', 'product' );
750
  $q->set( 'page_id', '' );
751
  if ( isset( $q->query['paged'] ) )
@@ -755,7 +868,6 @@ class woocommerce_wpml {
755
  // This is hacky but works. Awaiting http://core.trac.wordpress.org/ticket/21096
756
  global $wp_post_types;
757
 
758
- $shop_page = get_post( woocommerce_get_page_id('shop') );
759
  $q->is_page = true;
760
 
761
  $wp_post_types['product']->ID = $shop_page->ID;
@@ -796,7 +908,7 @@ class woocommerce_wpml {
796
  function woocommerce_price($price){
797
  global $sitepress, $wpdb;
798
 
799
- $sql = "SELECT (value) FROM ". $wpdb->prefix ."icl_currencies WHERE language_code = '". $sitepress->get_current_language() ."'";
800
  $currency = $wpdb->get_results($sql, OBJECT);
801
 
802
  if($currency){
@@ -819,7 +931,10 @@ class woocommerce_wpml {
819
  function email_header() {
820
  global $sitepress, $order_id;
821
 
822
- $lang = get_post_meta($order_id, 'wpml_language', TRUE);
 
 
 
823
 
824
  if(empty($lang)){
825
  if(isset($_SESSION['wpml_globalcart_language'])){
@@ -848,50 +963,40 @@ class woocommerce_wpml {
848
  Only when translated products are ordered, force adjusting stock information for all translations
849
  When a product in the default language is ordered stocks are adjusted automatically
850
  */
851
- function sync_product_stocks($order){
852
- global $sitepress;
853
- $order_id = $order->id;
854
- $order_language = get_post_meta($order_id, 'wpml_language', true);
855
-
856
- $items = $order->items;
857
- foreach($items as $item){
858
-
859
- if (isset($item['variation_id']) && $item['variation_id']>0){
860
- $_product = new WC_Product_Variation( $item['variation_id'] );
861
- }else{
862
- $_product = new WC_Product( $item['id'] );
863
- }
864
-
865
- // Out of stock attribute
866
- if ($_product->managing_stock() && !$_product->backorders_allowed() && $_product->get_total_stock()<=0){
867
- $outofstock = 'outofstock';
868
- }else{
869
- $outofstock = false;
870
- }
871
-
872
-
873
- if ( $_product && $_product->exists() && $_product->managing_stock() ) {
874
- $trid = $sitepress->get_element_trid($_product->id, 'post_product');
875
- $translations = $sitepress->get_element_translations($trid, 'post_product', true);
876
 
877
- $stock = get_post_meta($_product->id, '_stock', true);
878
- $total_sales = get_post_meta($_product->id, 'total_sales', true);
879
 
880
- foreach($translations as $translation){
881
- if($translation->element_id != $_product->id){
882
- if($sitepress->get_default_language() != $order_language){
883
- update_post_meta($translation->element_id, '_stock', $stock);
884
- update_post_meta($translation->element_id, 'total_sales', $total_sales);
885
- if($outofstock){
886
- update_post_meta($translation->element_id, '_stock_status', 'outofstock');
887
- }
888
- }
889
- delete_transient('wc_product_total_stock_' . $translation->element_id);
890
- }
891
- }
892
 
893
- }
894
- }
 
 
 
 
 
 
895
 
896
  }
897
 
@@ -959,6 +1064,10 @@ function sync_product_stocks($order){
959
 
960
  return $max_price;
961
  }
 
 
 
 
962
 
963
  function sync_variations($post_id, $post){
964
  global $wpdb, $pagenow, $sitepress;
@@ -1054,10 +1163,12 @@ function sync_product_stocks($order){
1054
 
1055
  if( ($pagenow == 'post.php' || $ajax_call ) && $post_type == 'product' && !empty($duplicated_post_id)){
1056
 
1057
- $get_variation_term_name = $wpdb->get_results("SELECT * FROM $wpdb->terms WHERE name = 'variable'");
1058
- $get_variation_term_id = $get_variation_term_name[0]->term_id;
 
 
1059
 
1060
- $is_post_has_variations = $wpdb->get_results("SELECT * FROM $wpdb->term_relationships WHERE object_id = '$duplicated_post_id' AND term_taxonomy_id = '$get_variation_term_id'");
1061
  if(!empty($is_post_has_variations)) $is_post_has_variations = TRUE;
1062
 
1063
  // synchronize term data, postmeta and post variations
@@ -1066,6 +1177,7 @@ function sync_product_stocks($order){
1066
  $get_all_post_variations = $wpdb->get_results("SELECT * FROM $wpdb->posts
1067
  WHERE post_status = 'publish' AND post_type = 'product_variation' AND post_parent = '$duplicated_post_id'");
1068
 
 
1069
  foreach($get_all_post_variations as $k => $post_data){
1070
  $duplicated_post_variation_ids[] = $post_data->ID;
1071
  }
@@ -1076,7 +1188,8 @@ function sync_product_stocks($order){
1076
 
1077
  if (!empty($variation_id)) {
1078
  // Update variation
1079
- $wpdb->update( $wpdb->posts, array(
 
1080
  'post_author' => $post_data->post_author,
1081
  'post_date_gmt' => $post_data->post_date_gmt,
1082
  'post_content' => $post_data->post_content,
@@ -1097,14 +1210,14 @@ function sync_product_stocks($order){
1097
  'post_type' => $post_data->post_type,
1098
  'post_mime_type' => $post_data->post_mime_type,
1099
  'comment_count' => $post_data->comment_count
1100
- ), array('ID' => $variation_id));
1101
  } else {
1102
  // Add new variation
1103
  $guid = $post_data->guid;
1104
  $replaced_guid = str_replace($duplicated_post_id, $post_id, $guid);
1105
  $slug = $post_data->post_name;
1106
  $replaced_slug = str_replace($duplicated_post_id, $post_id, $slug);
1107
- $wpdb->insert( $wpdb->posts, array(
1108
  'post_author' => $post_data->post_author,
1109
  'post_date_gmt' => $post_data->post_date_gmt,
1110
  'post_content' => $post_data->post_content,
@@ -1127,8 +1240,8 @@ function sync_product_stocks($order){
1127
  'post_mime_type' => $post_data->post_mime_type,
1128
  'comment_count' => $post_data->comment_count
1129
  ));
1130
- $variation_id = $wpdb->insert_id;
1131
  update_post_meta($variation_id, '_wcml_duplicate_of_variation', $post_data->ID);
 
1132
  $trid = $sitepress->get_element_trid($post_data->ID, 'post_product_variation');
1133
  $sitepress->set_element_language_details($variation_id, 'post_product_variation', $trid, $lang, $sitepress->get_default_language());
1134
  }
@@ -1144,43 +1257,67 @@ function sync_product_stocks($order){
1144
  wp_delete_post($variation_id, true);
1145
  }
1146
  }
 
 
 
 
 
 
 
 
 
 
1147
 
1148
- // synchronize post variations post meta
1149
- foreach($get_current_post_variations as $k => $post_data){
1150
- $current_post_variation_ids[] = $post_data->ID;
1151
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1152
 
1153
- $taxs = array();
1154
- foreach($duplicated_post_variation_ids as $dp_key => $duplicated_post_variation_id){
1155
- $get_all_post_meta = $wpdb->get_results("SELECT * FROM $wpdb->postmeta WHERE post_id = '$duplicated_post_variation_id'");
1156
-
1157
- foreach($get_all_post_meta as $k => $post_meta){
1158
- $meta_key = $post_meta->meta_key;
1159
- $meta_value = $post_meta->meta_value;
1160
-
1161
- // adjust the global attribute slug in the custom field
1162
- if (substr($meta_key, 0, 10) == 'attribute_') {
1163
- $tax = substr($meta_key, 10);
1164
- $taxs[] = $tax;
1165
- $attid = get_term_by('slug', $meta_value, $tax)->term_id;
1166
- $attid = icl_object_id($attid, $tax, true, $lang);
1167
- $meta_value = get_term_by('id', $attid, $tax)->slug;
1168
- }
1169
-
1170
- // update current post variations meta
1171
- update_post_meta($current_post_variation_ids[$dp_key], $meta_key, $meta_value);
1172
- }
1173
- }
1174
  // Sync terms
 
1175
  $taxs = array_unique($taxs);
1176
  foreach ($taxs as $tax) {
1177
  $terms = wp_get_object_terms($duplicated_post_id, $tax);
1178
  $update = array();
1179
  foreach ($terms as $term) {
1180
- $update[] = intval(icl_object_id($term->term_id, $tax, true, $lang));
 
 
 
 
 
 
1181
  }
1182
- $a = wp_set_object_terms($post_id, $update, $tax);
1183
  }
 
1184
  }
1185
  }
1186
  }
@@ -1221,9 +1358,10 @@ function sync_product_stocks($order){
1221
  * Makes all new attributes translatable.
1222
  */
1223
  function make_new_attributes_translatable(){
 
1224
  if(isset($_GET['page']) && $_GET['page'] == 'woocommerce_attributes'){
1225
 
1226
- $wpml_settings = get_option('icl_sitepress_settings');
1227
 
1228
  $get_all_taxonomies = get_taxonomies();
1229
 
@@ -1236,29 +1374,7 @@ function sync_product_stocks($order){
1236
  }
1237
  }
1238
 
1239
- update_option('icl_sitepress_settings', $wpml_settings);
1240
- }
1241
- }
1242
-
1243
- /**
1244
- * Registers custom attribute/variation title for translation.
1245
- *
1246
- * @global type $wpdb
1247
- * @return type
1248
- */
1249
- function translate_custom_attributes(){
1250
- global $wpdb;
1251
-
1252
- $all_variations = $wpdb->get_results("SELECT ID FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'product_variation'");
1253
-
1254
- $attribute_meta_keys = $wpdb->get_results("SELECT DISTINCT(meta_value) FROM $wpdb->postmeta WHERE meta_key LIKE 'attribute_%'");
1255
-
1256
- foreach($attribute_meta_keys as $k => $meta){
1257
- $variation_name = $meta->meta_value;
1258
-
1259
- if(function_exists('icl_register_string')){
1260
- icl_register_string('woocommerce', $variation_name .'_attribute_name', $variation_name);
1261
- }
1262
  }
1263
  }
1264
 
19
  }
20
 
21
  function init(){
22
+ global $sitepress;
23
+
24
  if(!defined('ICL_SITEPRESS_VERSION') || ICL_PLUGIN_INACTIVE){
25
  if(!function_exists('is_multisite') || !is_multisite()) {
26
  add_action('admin_notices', array($this, 'no_wpml_warning'));
59
  add_filter('woocommerce_params', array($this, 'ajax_params'));
60
  add_filter('woocommerce_redirect', array($this, 'do_redirect'));
61
  add_filter('woocommerce_attribute_label', array($this, 'translate_attributes'), 14, 2);
62
+ add_filter('get_term', array($this, 'clean_term'), 14, 2);
63
+ add_filter('wp_get_object_terms', array($sitepress, 'get_terms_filter'));
64
  add_filter('woocommerce_upsell_crosssell_search_products', array($this, 'woocommerce_upsell_crosssell_search_posts'));
65
  add_filter('icl_post_alternative_languages', array($this, 'post_alternative_languages'));
66
  add_filter('woocommerce_gateway_title', array($this, 'gateway_title'), 10);
67
  add_filter('woocommerce_gateway_description', array($this, 'gateway_description'), 10, 2);
 
68
  add_filter('woocommerce_json_search_found_products', array($this, 'search_products'));
69
  add_filter('woocommerce_currency', array($this, 'set_ml_currency'));
70
  //add_filter('woocommerce_paypal_amount', array($this, 'paypal_amount'));
71
  add_action('admin_print_scripts', array($this,'js_scripts_setup'), 11);
72
  add_action('init', array($this, 'translate_email_notifications'));
73
 
74
+ add_filter('gettext_with_context', array($this, 'default_slug_translation'), 0, 4);
75
+ add_filter('option_woocommerce_permalinks', array($this, 'custom_slug_translation'));
76
+
77
  // Translate shop page settings
78
  add_filter('option_woocommerce_shop_page_id', array($this, 'translate_pages_in_settings'));
79
  add_filter('option_woocommerce_terms_page_id', array($this, 'translate_pages_in_settings'));
90
  if(get_option('currency_converting_option') == '1'){
91
  add_filter('raw_woocommerce_price', array($this, 'woocommerce_price'));
92
  add_filter('woocommerce_order_amount_total', array($this, 'woocommerce_price'));
93
+ add_filter('woocommerce_order_amount_item_total', array($this, 'woocommerce_price'));
94
+ add_filter('woocommerce_order_amount_shipping', array($this, 'woocommerce_price'));
95
+ add_filter('woocommerce_order_amount_total_tax', array($this, 'woocommerce_price'));
96
  }
97
 
98
  add_filter('woocommerce_currency_symbol', array($this, 'woocommerce_currency_symbol'), 2);
111
  add_filter('woocommerce_price_filter_max_price', array($this, 'price_filter_max_price'));
112
 
113
  add_action('save_post', array($this, 'sync_variations'), 11, 2); // After WPML
114
+ add_filter('icl_make_duplicate', array($this, 'sync_variations_for_duplicates'), 11, 4);
115
+
116
 
117
  add_action('admin_menu', array($this, 'menu'));
118
  add_action('init', array($this, 'load_css_and_js'));
120
  if(is_admin()){
121
  add_action('admin_init', array($this, 'make_new_attributes_translatable'));
122
  } else {
123
+ add_filter('pre_get_posts', array($this, 'shop_page_query'), 9);
124
+ add_filter('icl_ls_languages', array($this, 'translate_ls_shop_url'));
 
 
 
 
 
 
 
125
  }
126
+
127
+ // Hooks for translating product attribute values
128
+ add_filter('woocommerce_variation_option_name', array($this, 'variation_term_name'));
129
+ add_filter('woocommerce_attribute', array($this, 'attribute_terms'));
130
 
131
  if(isset($_POST['general_options']) && check_admin_referer('general_options', 'general_options_nonce')){
132
  $enable_multi_currency = (isset($_POST['multi_currency'])) ? trim($_POST['multi_currency']) : null;
146
 
147
  }
148
 
149
+ // set prices to copy/translate depending on settings
150
+ add_action('init', array($this, 'set_price_config'), 16); // After TM parses wpml-config.xml
151
+
152
  if(isset($_POST['add_currency']) && check_admin_referer('add_currency', 'add_currency_nonce')){
153
  global $wpdb, $pagenow;
154
 
232
  add_action('option_woocommerce_tax_rates', array($this, 'tax_rates'));
233
  }
234
 
235
+ function set_price_config() {
236
+ global $sitepress, $iclTranslationManagement;
237
+
238
+ $wpml_settings = $sitepress->get_settings();
239
+ if (!isset($wpml_settings['translation-management'])) {
240
+ return;
241
+ }
242
+
243
+ $multi = get_option('icl_enable_multi_currency', false);
244
+ $option = get_option('currency_converting_option', 1);
245
+ if ($multi && $option == 2) {
246
+ $mode = 2; // translate
247
+ } else {
248
+ $mode = 1; // copy
249
+ }
250
+ $keys = array(
251
+ '_regular_price',
252
+ '_sale_price',
253
+ '_price',
254
+ '_min_variation_regular_price',
255
+ '_min_variation_sale_price',
256
+ '_min_variation_price',
257
+ '_max_variation_regular_price',
258
+ '_max_variation_sale_price',
259
+ '_max_variation_price'
260
+ );
261
+ $save = false;
262
+ foreach ($keys as $key) {
263
+ $iclTranslationManagement->settings['custom_fields_readonly_config'][] = $key;
264
+ if (!isset($sitepress_settings['translation-management']['custom_fields_translation'][$key]) ||
265
+ $wpml_settings['translation-management']['custom_fields_translation'][$key] != $mode) {
266
+ $wpml_settings['translation-management']['custom_fields_translation'][$key] = $mode;
267
+ $save = true;
268
+ }
269
+ }
270
+ if ($save) {
271
+ $sitepress->save_settings($wpml_settings);
272
+ }
273
+ }
274
+
275
+ // Catch the default slugs for translation
276
+ function default_slug_translation($translation, $text, $context, $domain) {
277
+ if ($context == 'slug') {
278
+ // taxonomy slug translation is not ready yet, return no translation
279
+ if ($text == 'product-category' || $text == 'product-tag') {
280
+ return $text;
281
+ }
282
+ // re-request translation through URL slug context to trigger slug translation
283
+ return _x($text, 'URL slug', $domain);
284
+ }
285
+ return $translation;
286
+ }
287
+
288
+ function clean_term($terms) {
289
+ global $sitepress;
290
+ $terms->name = $sitepress->the_category_name_filter($terms->name);
291
+ return $terms;
292
+ }
293
+
294
+ // Catch custom slugs for translation
295
+ function custom_slug_translation($permalinks) {
296
+ if (!empty($permalinks['product_base'])) {
297
+ $permalinks['product_base'] = _x($permalinks['product_base'], 'URL slug', 'woocommerce');
298
+ }
299
+ return $permalinks;
300
+ }
301
+
302
  function register_shipping_methods($available_methods){
303
 
304
  foreach($available_methods as $method){
318
  function tax_rates($rates){
319
  if (!empty($rates)) {
320
  foreach ($rates as &$rate) {
321
+ $rate['label'] = icl_translate('woocommerce', 'tax_label_' . esc_url_raw($rate['label']), $rate['label']);
322
  }
323
  }
324
 
441
  * one of these must be true for product urls to work
442
  * if none of these are true, display a warning message
443
  */
444
+ function check_for_incompatible_permalinks() {
445
+ global $sitepress, $sitepress_settings;
446
+
447
+ // Check if the shop prefix is disabled, if so we are ok
448
+ if (get_option('woocommerce_prepend_shop_page_to_products', 'yes') != "yes") {
449
+ return;
450
+ }
451
+
452
+ // Check if slug translation is enabled
453
+ $compatible = true;
454
+ if (!empty($sitepress_settings['posts_slug_translation']['on'])
455
+ && !empty($sitepress_settings['posts_slug_translation']['types'])
456
+ && $sitepress_settings['posts_slug_translation']['types']['product']) {
457
+ $compatible = false;
458
+ }
459
+
460
+ // Check if translated shop pages have the same slug
461
+ $allsame = true;
462
+ $shop_page_id = get_option('woocommerce_shop_page_id', false);
463
+ if (!empty($shop_page_id)) {
464
+ $slug = @get_page($shop_page_id)->post_name;
465
+ $languages = icl_get_languages('skip_missing=0');
466
+ if (sizeof($languages) < 2) {
467
+ return;
468
+ }
469
+ foreach ($languages as $language) {
470
+ if ($language['language_code'] != $sitepress->get_default_language()) {
471
+ $translated_shop_page_id = icl_object_id($shop_page_id, 'page', false, $language['language_code']);
472
+ if (!empty($translated_shop_page_id)) {
473
+ $translated_slug = get_page($translated_shop_page_id)->post_name;
474
+ if (!empty($translated_slug) && $translated_slug != $slug) {
475
+ $allsame = false;
476
+ break;
477
+ }
478
+ }
479
+ }
480
+ }
481
+ }
482
+
483
+ // display messages
484
+ if (!$allsame) {
485
+ ?>
486
+ <div class="message error"><p><?php printf(__('If you want different slugs for shop pages (%s/%s), you need to disable the shop prefix for products in <a href="%s">WooCommerce Settings</a>', 'plugin woocommerce'),
487
+ $slug, $translated_slug, 'admin.php?page=woocommerce_settings&tab=pages'); ?></p></div>
488
+ <?php
489
+ }
490
+ if (!$compatible) {
491
+ ?>
492
+ <div class="message error"><p><?php printf(__('If you want to translate product slugs, you need to disable the shop prefix for products in <a href="%s">WooCommerce Settings</a>', 'plugin woocommerce'),
493
+ 'admin.php?page=woocommerce_settings&tab=pages'); ?></p></div>
494
+ <?php
495
+ }
496
+ }
497
 
498
  /**
499
  * Switch the language on AJAX action, because in some ways the correct language is missing.
717
  } else if($translated_checkout_page_id == $post->ID || $checkout_page_id == $post->ID){
718
  $value['is_checkout'] = 1;
719
 
720
+ //$value['locale'] = '';
721
 
722
  $_SESSION['wpml_globalcart_language'] = $sitepress->get_current_language();
723
 
797
  return $output;
798
  }
799
 
800
+ /**
801
+ * Translates custom attribute/variation title.
802
+ *
803
+ * @return type
804
+ */
805
+ function variation_term_name($term){
806
+ return icl_t('woocommerce', $term .'_attribute_name', $term);
807
+ }
 
808
 
809
+ function attribute_terms($terms){
810
+ // remove autop
811
+ $terms = str_replace('<p>', '', $terms);
812
+ $terms = str_replace('</p>', '', $terms);
813
+
814
+ // iterate terms translating
815
+ $terms = explode(",", $terms);
816
+ $out = array();
817
+ foreach ($terms as $term) {
818
+ $term = trim($term);
819
+ $out[] = icl_t('woocommerce', $term .'_attribute_name', $term);
820
+ }
821
+
822
+ return wpautop(wptexturize(implode(", ", $out)));
823
+ }
824
 
825
  /**
826
  * Translates the payment gateway title text.
856
 
857
  $front_page_id = get_option('page_on_front');
858
  $shop_page_id = get_option('woocommerce_shop_page_id');
859
+ $shop_page = get_post( woocommerce_get_page_id('shop') );
860
 
861
+ if (!empty($shop_page) && $q->get('page_id') !== $front_page_id && $shop_page_id == $q->get('page_id')) {
862
  $q->set( 'post_type', 'product' );
863
  $q->set( 'page_id', '' );
864
  if ( isset( $q->query['paged'] ) )
868
  // This is hacky but works. Awaiting http://core.trac.wordpress.org/ticket/21096
869
  global $wp_post_types;
870
 
 
871
  $q->is_page = true;
872
 
873
  $wp_post_types['product']->ID = $shop_page->ID;
908
  function woocommerce_price($price){
909
  global $sitepress, $wpdb;
910
 
911
+ $sql = "SELECT value FROM ". $wpdb->prefix ."icl_currencies WHERE language_code = '". $sitepress->get_current_language() ."'";
912
  $currency = $wpdb->get_results($sql, OBJECT);
913
 
914
  if($currency){
931
  function email_header() {
932
  global $sitepress, $order_id;
933
 
934
+ $lang = null;
935
+ if (!current_user_can( 'manage_woocommerce' )) {
936
+ $lang = get_post_meta($order_id, 'wpml_language', TRUE);
937
+ }
938
 
939
  if(empty($lang)){
940
  if(isset($_SESSION['wpml_globalcart_language'])){
963
  Only when translated products are ordered, force adjusting stock information for all translations
964
  When a product in the default language is ordered stocks are adjusted automatically
965
  */
966
+ function sync_product_stocks($order){
967
+ global $sitepress;
968
+ $order_id = $order->id;
969
+
970
+ foreach ( $order->get_items() as $item ) {
971
+
972
+ if (isset($item['variation_id']) && $item['variation_id']>0){
973
+ $ld = $sitepress->get_element_language_details($item['variation_id'], 'post_product_variation');
974
+ $product_id = icl_object_id( $item['variation_id'], 'product_variation', true, $sitepress->get_default_language());
975
+ $_product = new WC_Product_Variation( $product_id );
976
+ }else{
977
+ $ld = $sitepress->get_element_language_details($item['id'], 'post_product');
978
+ $product_id = icl_object_id( $item['id'], 'product', true, $sitepress->get_default_language());
979
+ $_product = new WC_Product( $product_id );
980
+ }
 
 
 
 
 
 
 
 
 
 
981
 
982
+ // Process for non-default languages
983
+ if ($ld->language_code != $sitepress->get_default_language()) {
984
 
985
+ // Out of stock attribute
986
+ if ($_product->managing_stock() && !$_product->backorders_allowed() && $_product->get_total_stock()<=0){
987
+ $outofstock = 'outofstock';
988
+ }else{
989
+ $outofstock = false;
990
+ }
 
 
 
 
 
 
991
 
992
+ if ( $_product && $_product->exists() && $_product->managing_stock() ) {
993
+ $stock = $_product->reduce_stock($item['qty']);
994
+ $total_sales = get_post_meta($_product->id, 'total_sales', true);
995
+ $total_sales += $item['qty'];
996
+ update_post_meta($product_id, 'total_sales', $total_sales);
997
+ }
998
+ }
999
+ }
1000
 
1001
  }
1002
 
1064
 
1065
  return $max_price;
1066
  }
1067
+
1068
+ function sync_variations_for_duplicates($master_post_id, $lang, $postarr, $id) {
1069
+ $this->sync_variations($id, $postarr);
1070
+ }
1071
 
1072
  function sync_variations($post_id, $post){
1073
  global $wpdb, $pagenow, $sitepress;
1163
 
1164
  if( ($pagenow == 'post.php' || $ajax_call ) && $post_type == 'product' && !empty($duplicated_post_id)){
1165
 
1166
+ $get_variation_term_id = $wpdb->get_var("SELECT term_id FROM $wpdb->terms WHERE name = 'variable'");
1167
+ $get_variation_term_taxonomy_id = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM $wpdb->term_relationships tr
1168
+ LEFT JOIN $wpdb->term_taxonomy tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
1169
+ WHERE object_id = '$duplicated_post_id' AND taxonomy = 'product_type'");
1170
 
1171
+ $is_post_has_variations = $wpdb->get_results("SELECT * FROM $wpdb->term_relationships WHERE object_id = '$duplicated_post_id' AND term_taxonomy_id = '$get_variation_term_taxonomy_id'");
1172
  if(!empty($is_post_has_variations)) $is_post_has_variations = TRUE;
1173
 
1174
  // synchronize term data, postmeta and post variations
1177
  $get_all_post_variations = $wpdb->get_results("SELECT * FROM $wpdb->posts
1178
  WHERE post_status = 'publish' AND post_type = 'product_variation' AND post_parent = '$duplicated_post_id'");
1179
 
1180
+ $duplicated_post_variation_ids = array();
1181
  foreach($get_all_post_variations as $k => $post_data){
1182
  $duplicated_post_variation_ids[] = $post_data->ID;
1183
  }
1188
 
1189
  if (!empty($variation_id)) {
1190
  // Update variation
1191
+ wp_update_post(array(
1192
+ 'ID' => $variation_id,
1193
  'post_author' => $post_data->post_author,
1194
  'post_date_gmt' => $post_data->post_date_gmt,
1195
  'post_content' => $post_data->post_content,
1210
  'post_type' => $post_data->post_type,
1211
  'post_mime_type' => $post_data->post_mime_type,
1212
  'comment_count' => $post_data->comment_count
1213
+ ));
1214
  } else {
1215
  // Add new variation
1216
  $guid = $post_data->guid;
1217
  $replaced_guid = str_replace($duplicated_post_id, $post_id, $guid);
1218
  $slug = $post_data->post_name;
1219
  $replaced_slug = str_replace($duplicated_post_id, $post_id, $slug);
1220
+ $variation_id = wp_insert_post(array(
1221
  'post_author' => $post_data->post_author,
1222
  'post_date_gmt' => $post_data->post_date_gmt,
1223
  'post_content' => $post_data->post_content,
1240
  'post_mime_type' => $post_data->post_mime_type,
1241
  'comment_count' => $post_data->comment_count
1242
  ));
 
1243
  update_post_meta($variation_id, '_wcml_duplicate_of_variation', $post_data->ID);
1244
+ update_post_meta($variation_id, '_icl_duplicate_of', $post_data->ID);
1245
  $trid = $sitepress->get_element_trid($post_data->ID, 'post_product_variation');
1246
  $sitepress->set_element_language_details($variation_id, 'post_product_variation', $trid, $lang, $sitepress->get_default_language());
1247
  }
1257
  wp_delete_post($variation_id, true);
1258
  }
1259
  }
1260
+
1261
+ // custom fields to copy
1262
+ global $iclTranslationManagement;
1263
+ $cf = $iclTranslationManagement->settings['custom_fields_translation'];
1264
+
1265
+ // synchronize post variations post meta
1266
+ $current_post_variation_ids = array();
1267
+ foreach($get_current_post_variations as $k => $post_data){
1268
+ $current_post_variation_ids[] = $post_data->ID;
1269
+ }
1270
 
1271
+ $taxs = array();
1272
+ foreach($duplicated_post_variation_ids as $dp_key => $duplicated_post_variation_id){
1273
+ $get_all_post_meta = $wpdb->get_results("SELECT * FROM $wpdb->postmeta WHERE post_id = '$duplicated_post_variation_id'");
1274
+
1275
+ foreach($get_all_post_meta as $k => $post_meta){
1276
+ $meta_key = $post_meta->meta_key;
1277
+ $meta_value = $post_meta->meta_value;
1278
+
1279
+ // adjust the global attribute slug in the custom field
1280
+ $attid = null;
1281
+ if (substr($meta_key, 0, 10) == 'attribute_') {
1282
+ $tax = substr($meta_key, 10);
1283
+ if (taxonomy_exists($tax)) {
1284
+ $taxs[] = $tax;
1285
+ $attid = get_term_by('slug', $meta_value, $tax)->term_id;
1286
+ $attid = icl_object_id($attid, $tax, false, $lang);
1287
+ if (!$attid) {
1288
+ // if term not translated, skip
1289
+ continue;
1290
+ }
1291
+ $meta_value = get_term_by('id', $attid, $tax)->slug;
1292
+ } else {
1293
+ icl_register_string('woocommerce', $meta_value .'_attribute_name', $meta_value);
1294
+ }
1295
+ }
1296
+ // update current post variations meta
1297
+ if (!empty($attid) || in_array($meta_key, $cf) && $cf[$meta_key] == 1) {
1298
+ update_post_meta($current_post_variation_ids[$dp_key], $meta_key, $meta_value);
1299
+ }
1300
+ }
1301
+ }
1302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1303
  // Sync terms
1304
+ $nontranslated = array();
1305
  $taxs = array_unique($taxs);
1306
  foreach ($taxs as $tax) {
1307
  $terms = wp_get_object_terms($duplicated_post_id, $tax);
1308
  $update = array();
1309
  foreach ($terms as $term) {
1310
+ $term_id = intval(icl_object_id($term->term_id, $tax, false, $lang));
1311
+ if ($term_id > 0) {
1312
+ $update[] = $term_id;
1313
+ } else {
1314
+ // dont sync non-translated terms
1315
+ $nontranslated[] = $term;
1316
+ }
1317
  }
1318
+ wp_set_object_terms($post_id, $update, $tax);
1319
  }
1320
+
1321
  }
1322
  }
1323
  }
1358
  * Makes all new attributes translatable.
1359
  */
1360
  function make_new_attributes_translatable(){
1361
+ global $sitepress;
1362
  if(isset($_GET['page']) && $_GET['page'] == 'woocommerce_attributes'){
1363
 
1364
+ $wpml_settings = $sitepress->get_settings();
1365
 
1366
  $get_all_taxonomies = get_taxonomies();
1367
 
1374
  }
1375
  }
1376
 
1377
+ $sitepress->save_settings($wpml_settings);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1378
  }
1379
  }
1380
 
wpml-config.xml CHANGED
@@ -1,86 +1,54 @@
1
  <wpml-config>
2
- <custom-fields>
3
- <custom-field action="copy">backorders</custom-field>
4
- <custom-field action="copy">description</custom-field>
5
- <custom-field action="copy">downloadable</custom-field>
6
- <custom-field action="copy">featured</custom-field>
7
- <custom-field action="copy">height</custom-field>
8
- <custom-field action="copy">keywords</custom-field>
9
- <custom-field action="copy">length</custom-field>
10
- <custom-field action="copy">price</custom-field>
11
- <custom-field action="copy">regular_price</custom-field>
12
- <custom-field action="copy">sale_price</custom-field>
13
- <custom-field action="copy">sale_price_dates_from</custom-field>
14
- <custom-field action="copy">sale_price_dates_to</custom-field>
15
- <custom-field action="copy">seo_description</custom-field>
16
- <custom-field action="copy">seo_follow</custom-field>
17
- <custom-field action="copy">seo_keywords</custom-field>
18
- <custom-field action="copy">sku</custom-field>
19
- <custom-field action="copy">stock</custom-field>
20
- <custom-field action="copy">stock_status</custom-field>
21
- <custom-field action="copy">manage_stock</custom-field>
22
- <custom-field action="copy">tax_class</custom-field>
23
- <custom-field action="copy">tax_status</custom-field>
24
- <custom-field action="copy">title</custom-field>
25
- <custom-field action="copy">virtual</custom-field>
26
- <custom-field action="copy">visibility</custom-field>
27
- <custom-field action="copy">weight</custom-field>
28
- <custom-field action="copy">width</custom-field>
29
- <custom-field action="copy">total_sales</custom-field>
30
  <custom-field action="copy">_backorders</custom-field>
31
- <custom-field action="copy">_downloadable</custom-field>
 
32
  <custom-field action="copy">_download_limit</custom-field>
 
33
  <custom-field action="copy">_featured</custom-field>
34
  <custom-field action="copy">_file_path</custom-field>
35
- <custom-field action="copy">_height</custom-field>
36
- <custom-field action="copy">_length</custom-field>
37
  <custom-field action="copy">_manage_stock</custom-field>
38
- <custom-field action="copy">_max_variation_price</custom-field>
39
- <custom-field action="copy">_max_variation_regular_price</custom-field>
40
- <custom-field action="copy">_max_variation_sale_price</custom-field>
41
- <custom-field action="copy">_min_variation_price</custom-field>
42
- <custom-field action="copy">_min_variation_regular_price</custom-field>
43
- <custom-field action="copy">_min_variation_sale_price</custom-field>
44
- <custom-field action="copy">_price</custom-field>
45
  <custom-field action="copy">_purchase_note</custom-field>
46
- <custom-field action="copy">_regular_price</custom-field>
47
- <custom-field action="copy">_sale_price</custom-field>
48
  <custom-field action="copy">_sale_price_dates_from</custom-field>
49
  <custom-field action="copy">_sale_price_dates_to</custom-field>
50
  <custom-field action="copy">_sku</custom-field>
51
  <custom-field action="copy">_stock</custom-field>
52
  <custom-field action="copy">_stock_status</custom-field>
 
 
 
 
 
 
 
53
  <custom-field action="copy">_tax_class</custom-field>
54
  <custom-field action="copy">_tax_status</custom-field>
55
- <custom-field action="copy">_thumbnail_id</custom-field>
56
  <custom-field action="copy">_virtual</custom-field>
57
  <custom-field action="copy">_visibility</custom-field>
58
  <custom-field action="copy">_weight</custom-field>
59
  <custom-field action="copy">_width</custom-field>
 
 
60
  <custom-field action="copy">_woocommerce_exclude_image</custom-field>
61
  <custom-field action="copy">_wp_attached_file</custom-field>
62
- <custom-field action="copy">_product_attributes</custom-field>
63
- <custom-field action="copy">_default_attributes</custom-field>
64
- <custom-field action="copy">_upsell_ids</custom-field>
65
- <custom-field action="copy">_crosssell_ids</custom-field>
66
- <custom-field action="copy">_subscription_price</custom-field>
67
- <custom-field action="copy">_subscription_trial_length</custom-field>
68
- <custom-field action="copy">_subscription_sign_up_fee</custom-field>
69
- <custom-field action="copy">_subscription_period</custom-field>
70
- <custom-field action="copy">_subscription_period_interval</custom-field>
71
- <custom-field action="copy">_subscription_length</custom-field>
72
- <custom-field action="copy">_subscription_trial_period</custom-field>
73
- </custom-fields>
74
- <custom-types>
75
- <custom-type translate="1">product</custom-type>
76
  <custom-type translate="1">product_variation</custom-type>
77
  <custom-type translate="0">shop_order</custom-type>
78
- </custom-types>
79
- <taxonomies>
80
- <taxonomy translate="1">product_cat</taxonomy>
81
- <taxonomy translate="0">product_type</taxonomy>
82
  <taxonomy translate="0">shop_order_status</taxonomy>
83
  <taxonomy translate="1">product_tag</taxonomy>
84
- <taxonomy translate="1">product_shipping_class</taxonomy>
85
- </taxonomies>
 
 
 
 
86
  </wpml-config>
1
  <wpml-config>
2
+ <custom-fields>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  <custom-field action="copy">_backorders</custom-field>
4
+ <custom-field action="copy">_crosssell_ids</custom-field>
5
+ <custom-field action="copy">_default_attributes</custom-field>
6
  <custom-field action="copy">_download_limit</custom-field>
7
+ <custom-field action="copy">_downloadable</custom-field>
8
  <custom-field action="copy">_featured</custom-field>
9
  <custom-field action="copy">_file_path</custom-field>
 
 
10
  <custom-field action="copy">_manage_stock</custom-field>
11
+ <custom-field action="copy">_product_attributes</custom-field>
 
 
 
 
 
 
12
  <custom-field action="copy">_purchase_note</custom-field>
 
 
13
  <custom-field action="copy">_sale_price_dates_from</custom-field>
14
  <custom-field action="copy">_sale_price_dates_to</custom-field>
15
  <custom-field action="copy">_sku</custom-field>
16
  <custom-field action="copy">_stock</custom-field>
17
  <custom-field action="copy">_stock_status</custom-field>
18
+ <custom-field action="copy">_subscription_length</custom-field>
19
+ <custom-field action="copy">_subscription_period</custom-field>
20
+ <custom-field action="copy">_subscription_period_interval</custom-field>
21
+ <custom-field action="copy">_subscription_price</custom-field>
22
+ <custom-field action="copy">_subscription_sign_up_fee</custom-field>
23
+ <custom-field action="copy">_subscription_trial_length</custom-field>
24
+ <custom-field action="copy">_subscription_trial_period</custom-field>
25
  <custom-field action="copy">_tax_class</custom-field>
26
  <custom-field action="copy">_tax_status</custom-field>
27
+ <custom-field action="copy">_upsell_ids</custom-field>
28
  <custom-field action="copy">_virtual</custom-field>
29
  <custom-field action="copy">_visibility</custom-field>
30
  <custom-field action="copy">_weight</custom-field>
31
  <custom-field action="copy">_width</custom-field>
32
+ <custom-field action="copy">_height</custom-field>
33
+ <custom-field action="copy">_length</custom-field>
34
  <custom-field action="copy">_woocommerce_exclude_image</custom-field>
35
  <custom-field action="copy">_wp_attached_file</custom-field>
36
+ <custom-field action="copy">total_sales</custom-field>
37
+ </custom-fields>
38
+ <custom-types>
39
+ <custom-type translate="1">product</custom-type>
 
 
 
 
 
 
 
 
 
 
40
  <custom-type translate="1">product_variation</custom-type>
41
  <custom-type translate="0">shop_order</custom-type>
42
+ </custom-types>
43
+ <taxonomies>
44
+ <taxonomy translate="1">product_cat</taxonomy>
45
+ <taxonomy translate="0">product_type</taxonomy>
46
  <taxonomy translate="0">shop_order_status</taxonomy>
47
  <taxonomy translate="1">product_tag</taxonomy>
48
+ <taxonomy translate="0">product_shipping_class</taxonomy>
49
+ </taxonomies>
50
+ <admin-texts>
51
+ <key name="woocommerce_shop_page_title" />
52
+ <key name="woocommerce_email_footer_text" />
53
+ </admin-texts>
54
  </wpml-config>
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: 1.4
9
  */
10
 
11
  if(defined('WCML_VERSION')) return;
12
- define('WCML_VERSION', '1.4');
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: 1.5
9
  */
10
 
11
  if(defined('WCML_VERSION')) return;
12
+ define('WCML_VERSION', '1.5');
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);