WooCommerce Multilingual – run WooCommerce with WPML - Version 1.4

Version Description

  • Allow translating the 'Terms & Conditions' page.
  • Register shipping methods strings for translation.
  • Register several tax-related strings for translation.
  • Fix registration of payment gateway titles and descriptions.
  • Synchronize the default attribute of a variable product across its translations.
  • Allow saving WooCommerce/Settings while using a non-default language.
  • Fix problems when the shop page is at the home page.
  • Allow using Wordpress default permalink structure aswell.
  • Fix amount sent to payment gateway when using multiple currencies.
  • Fix for language switcher in shop pages (fixed in WPML)
  • Fix for subscriptions module price not showing (fixed in WPML)
  • Rewrite product variation sync: each variation is related to its translations, sync becomes easier
  • Remove several PHP warnings and notices.
  • Send order status update emails in the language the order was made.
Download this release

Release Info

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

Code changes from version 1.3 to 1.4

menu/management.php CHANGED
@@ -18,6 +18,10 @@
18
  <li><label for="multi_currency">Enable multi-currency: </label>
19
  <input type="checkbox" name="multi_currency" id="multi_currency" value="yes" <?php if(get_option('icl_enable_multi_currency') == 'yes'){ echo 'checked'; } ?> /></li>
20
 
 
 
 
 
21
  <input type='submit' name="general_options" value='<?php echo __('Save', 'wpml-wcml'); ?>' class='button-secondary' />
22
  <?php wp_nonce_field('general_options', 'general_options_nonce'); ?>
23
  </ul>
@@ -88,10 +92,10 @@
88
  </li>
89
 
90
  <li><label for="currency_code">Currency code: </label>
91
- <input type="text" name="currency_code" id="currency_code" maxlength="5" size="35" value="<?php if(isset($_GET['edit'])){ echo $currency_code; } ?>" /></li>
92
 
93
  <li><label for="exchange_rate">Exchange rate: </label>
94
- <input type="text" name="exchange_rate" id="exchange_rate" maxlength="10" size="35" value="<?php if(isset($_GET['edit'])){ echo $currency_exchange_rate; } ?>" /></li>
95
 
96
  <?php if(isset($_GET['edit'])){ ?>
97
  <input type="text" name="currency_id" id="currency_id" maxlength="5" size="10" value="<?php echo $currency_id; ?>" style="display: none;" /></li>
18
  <li><label for="multi_currency">Enable multi-currency: </label>
19
  <input type="checkbox" name="multi_currency" id="multi_currency" value="yes" <?php if(get_option('icl_enable_multi_currency') == 'yes'){ echo 'checked'; } ?> /></li>
20
 
21
+ <li><input type="radio" name="currency_converting_option[]" id="currency_converting_option" value="1" <?php if(get_option('currency_converting_option') == '1'){ echo 'checked'; } ?>> <label for="currency_converting_option"><?php echo __('Automatically calculate pricing in different currencies, based on the exchange rate', 'wpml-wcml'); ?></label></li>
22
+
23
+ <li><input type="radio" name="currency_converting_option[]" id="currency_converting_option_2" value="2" <?php if(get_option('currency_converting_option') == '2'){ echo 'checked'; } ?>> <label for="currency_converting_option_2"><?php echo __('I will manage the pricing in each currency myself', 'wpml-wcml'); ?></label></li>
24
+
25
  <input type='submit' name="general_options" value='<?php echo __('Save', 'wpml-wcml'); ?>' class='button-secondary' />
26
  <?php wp_nonce_field('general_options', 'general_options_nonce'); ?>
27
  </ul>
92
  </li>
93
 
94
  <li><label for="currency_code">Currency code: </label>
95
+ <input type="text" name="currency_code" id="currency_code" maxlength="3" size="3" value="<?php if(isset($_GET['edit'])){ echo $currency_code; } ?>" /> <i><?php _e('3 letter code, ie: GBP', 'wpml-wcml'); ?></i></li>
96
 
97
  <li><label for="exchange_rate">Exchange rate: </label>
98
+ <input type="text" name="exchange_rate" id="exchange_rate" maxlength="10" size="10" value="<?php if(isset($_GET['edit'])){ echo $currency_exchange_rate; } ?>" /></li>
99
 
100
  <?php if(isset($_GET['edit'])){ ?>
101
  <input type="text" name="currency_id" id="currency_id" maxlength="5" size="10" value="<?php echo $currency_id; ?>" style="display: none;" /></li>
readme.txt CHANGED
@@ -1,11 +1,11 @@
1
  === WooCommerce Multilingual - run WooCommerce with WPML ===
2
- Contributors: AmirHelzer, dominykasgel
3
- Donate link: http://wp-types.com
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.4.1
7
- Stable tag: 1.3
8
- Version: 1.3
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
@@ -60,6 +60,22 @@ In order for the checkout and store pages to appear translated, you need to crea
60
 
61
  == Changelog ==
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  = 1.3 =
64
  * Fixed all custom fields synchronization between translations
65
  * Fixed the stock issue for translations
@@ -97,6 +113,9 @@ In order for the checkout and store pages to appear translated, you need to crea
97
 
98
  == Upgrade Notice ==
99
 
 
 
 
100
  = 1.3 =
101
  Fixed compatibility between WooCommerce 1.5.8 and WPML 2.5.2
102
 
1
  === WooCommerce Multilingual - run WooCommerce with WPML ===
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
 
60
 
61
  == Changelog ==
62
 
63
+ = 1.4 =
64
+ * Allow translating the 'Terms & Conditions' page.
65
+ * Register shipping methods strings for translation.
66
+ * Register several tax-related strings for translation.
67
+ * Fix registration of payment gateway titles and descriptions.
68
+ * Synchronize the default attribute of a variable product across its translations.
69
+ * Allow saving WooCommerce/Settings while using a non-default language.
70
+ * Fix problems when the shop page is at the home page.
71
+ * Allow using Wordpress default permalink structure aswell.
72
+ * Fix amount sent to payment gateway when using multiple currencies.
73
+ * Fix for language switcher in shop pages (fixed in WPML)
74
+ * Fix for subscriptions module price not showing (fixed in WPML)
75
+ * Rewrite product variation sync: each variation is related to its translations, sync becomes easier
76
+ * Remove several PHP warnings and notices.
77
+ * Send order status update emails in the language the order was made.
78
+
79
  = 1.3 =
80
  * Fixed all custom fields synchronization between translations
81
  * Fixed the stock issue for translations
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
+
119
  = 1.3 =
120
  Fixed compatibility between WooCommerce 1.5.8 and WPML 2.5.2
121
 
woocommerce_wpml.class.php CHANGED
@@ -1,8 +1,21 @@
1
  <?php
2
  class woocommerce_wpml {
3
 
 
 
4
  function __construct(){
5
  add_action('plugins_loaded', array($this, 'init'), 2);
 
 
 
 
 
 
 
 
 
 
 
6
  }
7
 
8
  function init(){
@@ -20,7 +33,7 @@ class woocommerce_wpml {
20
  }
21
 
22
  if(get_option('icl_is_wcml_installed') !== 'yes'){
23
- add_action('init', array($this, 'wcml_install'));
24
  }
25
 
26
  add_action('admin_notices', array($this, 'check_for_incompatible_permalinks'));
@@ -34,11 +47,11 @@ class woocommerce_wpml {
34
  add_filter('woocommerce_get_change_password_page_id', array($this, 'get_change_password_page_id'));
35
  add_filter('woocommerce_get_thanks_page_id', array($this, 'get_thanks_page_id'));
36
  add_filter('woocommerce_get_shop_page_id', array($this, 'shop_page_id'));
 
37
  add_filter('woocommerce_get_pay_page_id', array($this, 'pay_page_id'));
38
- add_filter('woocommerce_get_checkout_payment_url', array($this, 'get_checkout_payment_url'));
39
- add_filter('woocommerce_get_cancel_order_url', array($this, 'get_cancel_order_url'));
40
- add_filter('woocommerce_get_return_url', array($this, 'get_return_url'));
41
- add_filter('woocommerce_get_remove_url', array($this, 'get_remove_url'));
42
  add_filter('woocommerce_in_cart_product_title', array($this, 'in_cart_product_title'), 13, 2);
43
  add_filter('woocommerce_in_cart_product_id', array($this, 'in_cart_product_id'), 11, 2);
44
  add_filter('woocommerce_params', array($this, 'ajax_params'));
@@ -46,20 +59,40 @@ class woocommerce_wpml {
46
  add_filter('woocommerce_attribute_label', array($this, 'translate_attributes'), 14, 2);
47
  add_filter('woocommerce_upsell_crosssell_search_products', array($this, 'woocommerce_upsell_crosssell_search_posts'));
48
  add_filter('icl_post_alternative_languages', array($this, 'post_alternative_languages'));
49
- add_filter('woocommerce_variation_term_name', array($this, 'variation_term_name'));
50
  add_filter('woocommerce_gateway_title', array($this, 'gateway_title'), 10);
51
- add_filter('woocommerce_gateway_raw_description', array($this, 'gateway_description'), 10, 3);
52
- add_filter('pre_get_posts', array($this, 'shop_page_query'), 10);
53
  add_filter('woocommerce_json_search_found_products', array($this, 'search_products'));
54
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  if(get_option('icl_enable_multi_currency') == 'yes'){
56
- add_filter('raw_woocommerce_price', array($this, 'woocommerce_price'));
 
 
 
 
57
  add_filter('woocommerce_currency_symbol', array($this, 'woocommerce_currency_symbol'), 2);
58
  }
59
 
60
  add_action('woocommerce_email_header', array($this, 'email_header'), 0);
61
  add_action('woocommerce_email_footer', array($this, 'email_footer'), 0);
62
  add_action('localize_woocommerce_on_ajax', array($this, 'localize_on_ajax'));
 
63
 
64
  add_action('woocommerce_reduce_order_stock', array($this, 'sync_product_stocks'));
65
 
@@ -68,24 +101,42 @@ class woocommerce_wpml {
68
  add_filter('woocommerce_price_filter_min_price', array($this, 'price_filter_min_price'));
69
  add_filter('woocommerce_price_filter_max_price', array($this, 'price_filter_max_price'));
70
 
71
- add_action('icl_make_duplicate', array($this, 'synchronize_variations'), 10, 4);
72
-
73
  add_action('admin_menu', array($this, 'menu'));
74
  add_action('init', array($this, 'load_css_and_js'));
75
 
76
  if(is_admin()){
77
  add_action('admin_init', array($this, 'make_new_attributes_translatable'));
 
 
 
 
 
 
 
 
 
78
  add_action('admin_init', array($this, 'translate_custom_attributes'));
79
  }
 
80
 
81
  if(isset($_POST['general_options']) && check_admin_referer('general_options', 'general_options_nonce')){
82
  $enable_multi_currency = (isset($_POST['multi_currency'])) ? trim($_POST['multi_currency']) : null;
 
 
 
 
 
 
 
83
 
84
  if($enable_multi_currency == 'yes'){
85
  add_option('icl_enable_multi_currency', 'yes');
86
  } else {
87
  delete_option('icl_enable_multi_currency');
88
  }
 
89
  }
90
 
91
  if(isset($_POST['add_currency']) && check_admin_referer('add_currency', 'add_currency_nonce')){
@@ -107,8 +158,7 @@ class woocommerce_wpml {
107
  wp_die(__('<strong>ERROR</strong>: please enter the correct exchange rate.'));
108
  }
109
 
110
- $result = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*)
111
- FROM ". $wpdb->prefix ."icl_currencies WHERE language_code = '$language_code'"));
112
 
113
  if($result && !$currency_id){
114
  add_action('admin_notices', array($this, 'currency_exists_error'));
@@ -154,19 +204,107 @@ class woocommerce_wpml {
154
  wp_safe_redirect(admin_url('admin.php?page=wpml-wcml'));
155
  }
156
 
157
- add_action('admin_footer', array($this, 'documentation_links'));
158
- add_action('admin_notices', array($this, 'admin_notice_after_install'));
159
 
160
- if(isset($_GET['wcml_action']) && $_GET['wcml_action'] = 'dismiss'){
161
- update_option('wpml_dismiss_doc_main', 'yes');
162
- }
163
 
164
  if (defined('DOING_AJAX') && DOING_AJAX){
165
  do_action('localize_woocommerce_on_ajax');
166
  }
167
 
168
- register_deactivation_hook(__FILE__, array($this, 'wcml_deactivate'));
169
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
  /**
172
  * Adds admin notice.
@@ -205,6 +343,7 @@ class woocommerce_wpml {
205
  global $wpdb;
206
 
207
  add_option('icl_is_wcml_installed', 'yes');
 
208
 
209
  $sql = "CREATE TABLE IF NOT EXISTS `". $wpdb->prefix ."icl_currencies` (
210
  `id` int(11) NOT NULL AUTO_INCREMENT,
@@ -233,12 +372,15 @@ class woocommerce_wpml {
233
  }
234
  // Check if translated shop pages have the same slug
235
  $shop_page_id = get_option('woocommerce_shop_page_id');
236
- $slug = get_page($shop_page_id)->post_name;
 
 
 
237
  $languages = icl_get_languages('skip_missing=0');
238
  $allsame = true;
239
  foreach ($languages as $language) {
240
  if ($language['language_code'] != $sitepress->get_default_language()) {
241
- $translated_slug = get_page(icl_object_id($shop_page_id, 'page', false, $language['language_code']))->post_name;
242
  if ($translated_slug != $slug) {
243
  $allsame = false;
244
  break;
@@ -285,6 +427,41 @@ class woocommerce_wpml {
285
  return $found_products;
286
  }
287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  /**
289
  * Filters WooCommerce checkout link.
290
  */
@@ -355,6 +532,13 @@ class woocommerce_wpml {
355
  return icl_object_id(get_option('woocommerce_shop_page_id'), 'page', false);
356
  }
357
 
 
 
 
 
 
 
 
358
  /**
359
  * Filters WooCommerce pay page id
360
  */
@@ -368,53 +552,6 @@ class woocommerce_wpml {
368
  }
369
  }
370
 
371
- /**
372
- * Filters WooCommerce payment link for unpaid - pending orders.
373
- *
374
- * @global type $sitepress
375
- * @param type $link
376
- * @return type
377
- */
378
- function get_checkout_payment_url($link){
379
- global $sitepress;
380
- return $sitepress->convert_url($link);
381
- }
382
-
383
- /**
384
- * Filters WooCommerce cancel order.
385
- *
386
- * @global type $sitepress
387
- * @param type $link
388
- * @return type
389
- */
390
- function get_cancel_order_url($link){
391
- global $sitepress;
392
- return $sitepress->convert_url($link);
393
- }
394
-
395
- /**
396
- * Filters WooCommerce return URL after payment.
397
- *
398
- * @global type $sitepress
399
- * @param type $link
400
- * @return type
401
- */
402
- function get_return_url($link){
403
- global $sitepress;
404
- return $sitepress->convert_url($link);
405
- }
406
-
407
- /**
408
- * Filters WooCommerce product remove link.
409
- *
410
- * @param type $link
411
- * @return type
412
- */
413
- function get_remove_url($link){
414
- // outputs raw
415
- return $link;
416
- }
417
-
418
  /**
419
  * After email translation switch language to default.
420
  *
@@ -423,7 +560,12 @@ class woocommerce_wpml {
423
  * @return type
424
  */
425
  function in_cart_product_title($title, $_product){
426
- $product_id = icl_object_id($_product['product_id'], 'product', false, ICL_LANGUAGE_CODE);
 
 
 
 
 
427
 
428
  if($product_id){
429
  $title = get_the_title($product_id);
@@ -495,7 +637,7 @@ class woocommerce_wpml {
495
  */
496
  function do_redirect($link){
497
  global $sitepress;
498
- return $sitepress->convert_url($link);
499
  }
500
 
501
  /**
@@ -546,7 +688,7 @@ class woocommerce_wpml {
546
  global $post;
547
 
548
  $post_type = get_post_type($post->ID);
549
- $checkout_page_id = wpml_checkout_page_id();
550
 
551
  if($post_type == 'product' || is_page($checkout_page_id)){
552
  $output = '';
@@ -573,24 +715,10 @@ class woocommerce_wpml {
573
  *
574
  * @return type
575
  */
576
- function gateway_title($title){
577
-
578
- if(function_exists('icl_t')){
579
- $translated_title = icl_t('woocommerce', $title .'_gateway_title', $title);
580
- }
581
-
582
- if(!$translated_title){
583
-
584
- if(function_exists('icl_register_string')){
585
- icl_register_string('woocommerce', $title .'_gateway_title', $title);
586
- }
587
-
588
- } else {
589
-
590
- return $translated_title;
591
-
592
  }
593
-
594
  return $title;
595
  }
596
 
@@ -599,48 +727,48 @@ class woocommerce_wpml {
599
  *
600
  * @return type
601
  */
602
- function gateway_description($description, $description_raw, $gateway_title){
603
-
604
- if(function_exists('icl_t')){
605
- $translated_description = icl_t('woocommerce', $gateway_title .'_gateway_description', $description_raw);
606
  }
607
-
608
- if(!$translated_description){
609
-
610
- if(function_exists('icl_register_string')){
611
- icl_register_string('woocommerce', $gateway_title .'_gateway_description', $description_raw);
612
- }
613
-
614
- } else {
615
-
616
- return $translated_description;
617
- }
618
-
619
  return $description;
620
  }
621
 
622
- /**
623
- * Filters WooCommerce query for translated shop page
624
- *
625
- */
626
- function shop_page_query($q) {
627
- if ( ! $q->is_main_query() )
628
- return;
629
-
630
- $shop_page_id = get_option('woocommerce_shop_page_id');
631
- $translated_shop_page_id = icl_object_id($shop_page_id, 'page', false);
632
- if (!empty($translated_shop_page_id) && $translated_shop_page_id == $q->get('page_id')) {
633
- $q->set( 'post_type', 'product' );
634
- $q->set( 'page_id', '' );
635
- if ( isset( $q->query['paged'] ) )
636
- $q->set( 'paged', $q->query['paged'] );
637
-
638
- // Fix conditional functions
639
- $q->is_singular = false;
640
- $q->is_archive = true;
641
- }
642
- return $q;
643
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
644
 
645
  /**
646
  * Filters the currency symbol.
@@ -648,27 +776,14 @@ class woocommerce_wpml {
648
  function woocommerce_currency_symbol($currency_symbol){
649
  global $sitepress, $wpdb;
650
 
651
- $sql = "SELECT (code) FROM ". $wpdb->prefix ."icl_currencies WHERE language_code = '". $sitepress->get_current_language() ."'";
652
- $db_currency = $wpdb->get_results($sql, OBJECT);
653
-
654
- if($db_currency){
655
- $currency = $db_currency[0]->code;
656
- $currencies = array('BRL', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'ZAR', 'CZK', 'THB', 'GBP');
657
-
658
- if(in_array($currency, $currencies)){
659
- switch ($currency) :
660
- case 'BRL' : $currency_symbol = 'R&#36;'; break;
661
- case 'USD' : $currency_symbol = '&#36;'; break;
662
- case 'EUR' : $currency_symbol = '&euro;'; break;
663
- case 'JPY' : $currency_symbol = '&yen;'; break;
664
- case 'TRY' : $currency_symbol = 'TL'; break;
665
- case 'NOK' : $currency_symbol = 'kr'; break;
666
- case 'ZAR' : $currency_symbol = 'R'; break;
667
- case 'CZK' : $currency_symbol = '&#75;&#269;'; break;
668
- case 'GBP' : $currency_symbol = '&pound;'; break;
669
- endswitch;
670
  } else {
671
- $currency_symbol = $currency;
672
  }
673
  }
674
 
@@ -730,56 +845,55 @@ class woocommerce_wpml {
730
  }
731
 
732
  /*
733
- Only when translated products are ordered, force adjusting stuck information for all translations
734
  When a product in the default language is ordered stocks are adjusted automatically
735
  */
736
- function sync_product_stocks($order){
737
  global $sitepress;
738
  $order_id = $order->id;
739
  $order_language = get_post_meta($order_id, 'wpml_language', true);
740
 
741
- if($sitepress->get_default_language() != $order_language){
742
- $items = $order->items;
743
- foreach($items as $item){
744
 
745
- if (isset($item['variation_id']) && $item['variation_id']>0){
746
- $_product = new WC_Product_Variation( $item['variation_id'] );
747
- }else{
748
- $_product = new WC_Product( $item['id'] );
749
- }
750
-
751
- // Out of stock attribute
752
- if ($_product->managing_stock() && !$_product->backorders_allowed() && $_product->get_total_stock()<=0){
753
- $outofstock = 'outofstock';
754
- }else{
755
- $outofstock = false;
756
- }
757
 
 
 
 
 
 
 
758
 
759
- if ( $_product && $_product->exists() && $_product->managing_stock() ) {
760
 
761
- $trid = $sitepress->get_element_trid($_product->id, 'post_product');
762
- $translations = $sitepress->get_element_translations($trid, 'post_product', true);
 
763
 
764
- $stock = get_post_meta($_product->id, '_stock', true);
765
- $total_sales = get_post_meta($_product->id, 'total_sales', true);
766
 
767
- foreach($translations as $translation){
768
- if($translation->element_id != $_product->id){
 
769
  update_post_meta($translation->element_id, '_stock', $stock);
770
  update_post_meta($translation->element_id, 'total_sales', $total_sales);
771
  if($outofstock){
772
  update_post_meta($translation->element_id, '_stock_status', 'outofstock');
773
  }
774
  }
 
775
  }
776
-
777
  }
778
 
779
  }
780
  }
781
 
782
- }
783
 
784
  /**
785
  * Adds language to order post type.
@@ -846,29 +960,33 @@ class woocommerce_wpml {
846
  return $max_price;
847
  }
848
 
849
- /**
850
- * If upsell and crosell products exists for the product, filter them for translations.
851
- * Sync attributes and variations during product duplication.
852
- * Sync: term relationship, post meta, post variations, post variations meta.
853
- *
854
- * @global type $wpdb
855
- * @global type $pagenow
856
- * @global type $post
857
- * @return type
858
- */
859
- function synchronize_variations($duplicated_post_id, $lang, $postarr, $post_id) {
860
- global $wpdb, $pagenow, $sitepress;
861
 
862
- $post_type = @get_post_type($post_id);
 
 
863
 
864
- $ajax_call = (!empty($_POST['icl_ajx_action']) && $_POST['icl_ajx_action'] == 'make_duplicates');
 
 
 
865
 
866
- // Filter upsell and crosell products for translations
867
- if(($pagenow == 'post.php' || $ajax_call ) && $post_type == 'product'){
 
 
 
 
868
 
 
 
 
 
 
 
 
869
  $original_product_upsell_ids = get_post_meta($duplicated_post_id, '_upsell_ids', TRUE);
870
- $original_product_crosssell_ids = get_post_meta($duplicated_post_id, '_crosssell_ids', TRUE);
871
-
872
  if(!empty($original_product_upsell_ids)){
873
  $unserialized_upsell_ids = maybe_unserialize($original_product_upsell_ids);
874
 
@@ -884,9 +1002,12 @@ class woocommerce_wpml {
884
  }
885
  }
886
 
887
- update_post_meta($post_id, '_upsell_ids', $unserialized_upsell_ids);
 
 
888
  }
889
 
 
890
  if(!empty($original_product_crosssell_ids)){
891
  $unserialized_crosssell_ids = maybe_unserialize($original_product_crosssell_ids);
892
 
@@ -902,11 +1023,35 @@ class woocommerce_wpml {
902
  }
903
  }
904
 
905
- update_post_meta($post_id, '_crosssell_ids', $unserialized_crosssell_ids);
 
 
906
  }
907
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
908
  }
909
-
910
  if( ($pagenow == 'post.php' || $ajax_call ) && $post_type == 'product' && !empty($duplicated_post_id)){
911
 
912
  $get_variation_term_name = $wpdb->get_results("SELECT * FROM $wpdb->terms WHERE name = 'variable'");
@@ -957,6 +1102,8 @@ class woocommerce_wpml {
957
  // Add new variation
958
  $guid = $post_data->guid;
959
  $replaced_guid = str_replace($duplicated_post_id, $post_id, $guid);
 
 
960
  $wpdb->insert( $wpdb->posts, array(
961
  'post_author' => $post_data->post_author,
962
  'post_date_gmt' => $post_data->post_date_gmt,
@@ -967,7 +1114,7 @@ class woocommerce_wpml {
967
  'comment_status' => $post_data->comment_status,
968
  'ping_status' => $post_data->ping_status,
969
  'post_password' => $post_data->post_password,
970
- 'post_name' => $post_data->post_name,
971
  'to_ping' => $post_data->to_ping,
972
  'pinged' => $post_data->pinged,
973
  'post_modified' => $post_data->post_modified,
@@ -980,7 +1127,10 @@ class woocommerce_wpml {
980
  'post_mime_type' => $post_data->post_mime_type,
981
  'comment_count' => $post_data->comment_count
982
  ));
983
- update_post_meta($wpdb->insert_id, '_wcml_duplicate_of_variation', $post_data->ID);
 
 
 
984
  }
985
  }
986
 
@@ -991,7 +1141,7 @@ class woocommerce_wpml {
991
  foreach ($get_current_post_variations as $post_data) {
992
  $variation_id = get_post_meta($post_data->ID, '_wcml_duplicate_of_variation', true);
993
  if (!in_array($variation_id, $duplicated_post_variation_ids)) {
994
- wp_delete_post($id, true);
995
  }
996
  }
997
 
@@ -1000,6 +1150,7 @@ class woocommerce_wpml {
1000
  $current_post_variation_ids[] = $post_data->ID;
1001
  }
1002
 
 
1003
  foreach($duplicated_post_variation_ids as $dp_key => $duplicated_post_variation_id){
1004
  $get_all_post_meta = $wpdb->get_results("SELECT * FROM $wpdb->postmeta WHERE post_id = '$duplicated_post_variation_id'");
1005
 
@@ -1010,6 +1161,7 @@ class woocommerce_wpml {
1010
  // adjust the global attribute slug in the custom field
1011
  if (substr($meta_key, 0, 10) == 'attribute_') {
1012
  $tax = substr($meta_key, 10);
 
1013
  $attid = get_term_by('slug', $meta_value, $tax)->term_id;
1014
  $attid = icl_object_id($attid, $tax, true, $lang);
1015
  $meta_value = get_term_by('id', $attid, $tax)->slug;
@@ -1019,6 +1171,16 @@ class woocommerce_wpml {
1019
  update_post_meta($current_post_variation_ids[$dp_key], $meta_key, $meta_value);
1020
  }
1021
  }
 
 
 
 
 
 
 
 
 
 
1022
  }
1023
  }
1024
  }
@@ -1100,6 +1262,28 @@ class woocommerce_wpml {
1100
  }
1101
  }
1102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1103
  /**
1104
  * Adds admin notice.
1105
  */
1
  <?php
2
  class woocommerce_wpml {
3
 
4
+ var $currencies;
5
+
6
  function __construct(){
7
  add_action('plugins_loaded', array($this, 'init'), 2);
8
+ $this->currencies = array(
9
+ 'BRL' => 'R&#36;',
10
+ 'USD' => '&#36;',
11
+ 'EUR' => '&euro;',
12
+ 'JPY' => '&yen;',
13
+ 'TRY' => 'TL',
14
+ 'NOK' => 'kr',
15
+ 'ZAR' => 'R',
16
+ 'CZK' => '&#75;&#269;',
17
+ 'GBP' => '&pound;'
18
+ );
19
  }
20
 
21
  function init(){
33
  }
34
 
35
  if(get_option('icl_is_wcml_installed') !== 'yes'){
36
+ $this->wcml_install();
37
  }
38
 
39
  add_action('admin_notices', array($this, 'check_for_incompatible_permalinks'));
47
  add_filter('woocommerce_get_change_password_page_id', array($this, 'get_change_password_page_id'));
48
  add_filter('woocommerce_get_thanks_page_id', array($this, 'get_thanks_page_id'));
49
  add_filter('woocommerce_get_shop_page_id', array($this, 'shop_page_id'));
50
+ add_filter('woocommerce_get_terms_page_id', array($this, 'terms_page_id'));
51
  add_filter('woocommerce_get_pay_page_id', array($this, 'pay_page_id'));
52
+ add_filter('woocommerce_get_checkout_payment_url', array($this, 'do_redirect'));
53
+ add_filter('woocommerce_get_cancel_order_url', array($this, 'do_redirect'));
54
+ add_filter('woocommerce_get_return_url', array($this, 'do_redirect'));
 
55
  add_filter('woocommerce_in_cart_product_title', array($this, 'in_cart_product_title'), 13, 2);
56
  add_filter('woocommerce_in_cart_product_id', array($this, 'in_cart_product_id'), 11, 2);
57
  add_filter('woocommerce_params', array($this, 'ajax_params'));
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'));
74
+ add_filter('option_woocommerce_cart_page_id', array($this, 'translate_pages_in_settings'));
75
+ add_filter('option_woocommerce_checkout_page_id', array($this, 'translate_pages_in_settings'));
76
+ add_filter('option_woocommerce_pay_page_id', array($this, 'translate_pages_in_settings'));
77
+ add_filter('option_woocommerce_thanks_page_id', array($this, 'translate_pages_in_settings'));
78
+ add_filter('option_woocommerce_myaccount_page_id', array($this, 'translate_pages_in_settings'));
79
+ add_filter('option_woocommerce_edit_address_page_id', array($this, 'translate_pages_in_settings'));
80
+ add_filter('option_woocommerce_view_order_page_id', array($this, 'translate_pages_in_settings'));
81
+ add_filter('option_woocommerce_change_password_page_id', array($this, 'translate_pages_in_settings'));
82
+
83
  if(get_option('icl_enable_multi_currency') == 'yes'){
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);
90
  }
91
 
92
  add_action('woocommerce_email_header', array($this, 'email_header'), 0);
93
  add_action('woocommerce_email_footer', array($this, 'email_footer'), 0);
94
  add_action('localize_woocommerce_on_ajax', array($this, 'localize_on_ajax'));
95
+ add_action('woocommerce_shipping_update_ajax', array($this, 'shipping_update'));
96
 
97
  add_action('woocommerce_reduce_order_stock', array($this, 'sync_product_stocks'));
98
 
101
  add_filter('woocommerce_price_filter_min_price', array($this, 'price_filter_min_price'));
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'));
108
 
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;
126
+ $currency_converting_option = $_POST['currency_converting_option'];
127
+
128
+ if($currency_converting_option[0] == '1'){
129
+ update_option('currency_converting_option', '1');
130
+ } else if($currency_converting_option[0] == '2'){
131
+ update_option('currency_converting_option', '2');
132
+ }
133
 
134
  if($enable_multi_currency == 'yes'){
135
  add_option('icl_enable_multi_currency', 'yes');
136
  } else {
137
  delete_option('icl_enable_multi_currency');
138
  }
139
+
140
  }
141
 
142
  if(isset($_POST['add_currency']) && check_admin_referer('add_currency', 'add_currency_nonce')){
158
  wp_die(__('<strong>ERROR</strong>: please enter the correct exchange rate.'));
159
  }
160
 
161
+ $result = $wpdb->get_var("SELECT COUNT(*) FROM ". $wpdb->prefix ."icl_currencies WHERE language_code = '$language_code'");
 
162
 
163
  if($result && !$currency_id){
164
  add_action('admin_notices', array($this, 'currency_exists_error'));
204
  wp_safe_redirect(admin_url('admin.php?page=wpml-wcml'));
205
  }
206
 
207
+ add_action('admin_footer', array($this, 'documentation_links'));
208
+ add_action('admin_notices', array($this, 'admin_notice_after_install'));
209
 
210
+ if(isset($_GET['wcml_action']) && $_GET['wcml_action'] = 'dismiss'){
211
+ update_option('wpml_dismiss_doc_main', 'yes');
212
+ }
213
 
214
  if (defined('DOING_AJAX') && DOING_AJAX){
215
  do_action('localize_woocommerce_on_ajax');
216
  }
217
 
218
+ register_deactivation_hook(__FILE__, array($this, 'wcml_deactivate'));
219
+
220
+ add_filter('woocommerce_available_shipping_methods', array($this, 'register_shipping_methods'));
221
+ add_filter('woocommerce_countries_tax_or_vat', array($this, 'register_tax_label'));
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){
228
+ if(function_exists('icl_register_string')){
229
+ icl_register_string('woocommerce', $method->label .'_shipping_method_title', $method->label);
230
+ }
231
+
232
+ if(function_exists('icl_t')){
233
+ $method->label = icl_t('woocommerce', $method->label .'_shipping_method_title', $method->label);
234
+ }
235
+ }
236
+
237
+ return $available_methods;
238
+
239
+ }
240
+
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
+
248
+ return $rates;
249
+ }
250
+
251
+ function register_tax_label($label){
252
+ global $sitepress;
253
+
254
+ if(function_exists('icl_translate')){
255
+ $label = icl_translate('woocommerce', 'VAT_tax_label', $label);
256
+ }
257
+
258
+ return $label;
259
+ }
260
+
261
+ function translate_pages_in_settings($id) {
262
+ return icl_object_id($id, 'page', true);
263
+ }
264
+
265
+ function translate_email_notifications() {
266
+ $email_actions = array(
267
+ 'woocommerce_order_status_pending_to_processing',
268
+ 'woocommerce_order_status_pending_to_completed',
269
+ 'woocommerce_order_status_pending_to_on-hold',
270
+ 'woocommerce_order_status_failed_to_processing',
271
+ 'woocommerce_order_status_failed_to_completed',
272
+ 'woocommerce_order_status_pending_to_processing',
273
+ 'woocommerce_order_status_pending_to_on-hold',
274
+ 'woocommerce_order_status_completed'
275
+ );
276
+ foreach ( $email_actions as $action ) {
277
+ add_action( $action, array( &$this, 'translate_email_notification'), 9 );
278
+ }
279
+ }
280
+
281
+ function translate_email_notification($order_id) {
282
+ global $sitepress;
283
+
284
+ $lang = get_post_meta($order_id, 'wpml_language', true);
285
+
286
+ if(!empty($lang)){
287
+ $sitepress->switch_lang($lang, true);
288
+ }
289
+
290
+ }
291
+
292
+ function translate_ls_shop_url($languages) {
293
+ global $sitepress;
294
+ $shop_id = get_option('woocommerce_shop_page_id');
295
+ $front_id = icl_object_id(get_option('page_on_front'), 'page');
296
+ if (is_post_type_archive('product')) {
297
+ foreach ($languages as &$language) {
298
+ if ($front_id == $shop_id) {
299
+ $url = $sitepress->language_url($language['language_code']);
300
+ } else {
301
+ $url = get_permalink(icl_object_id($shop_id, 'page', true, $language['language_code']));
302
+ }
303
+ $language['url'] = $url;
304
+ }
305
+ }
306
+ return $languages;
307
+ }
308
 
309
  /**
310
  * Adds admin notice.
343
  global $wpdb;
344
 
345
  add_option('icl_is_wcml_installed', 'yes');
346
+ add_option('currency_converting_option', '1');
347
 
348
  $sql = "CREATE TABLE IF NOT EXISTS `". $wpdb->prefix ."icl_currencies` (
349
  `id` int(11) NOT NULL AUTO_INCREMENT,
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;
427
  return $found_products;
428
  }
429
 
430
+ // Return the correct amount in a second language.
431
+ function paypal_amount($amount){
432
+ return $amount;
433
+ }
434
+
435
+ // Set multilingual currency.
436
+ function set_ml_currency($currency){
437
+ global $wpdb, $sitepress;
438
+
439
+ $db_currency = $wpdb->get_row("SELECT code FROM ". $wpdb->prefix ."icl_currencies WHERE language_code = '". $sitepress->get_current_language() ."'");
440
+
441
+ if(!empty($db_currency) && get_option('icl_enable_multi_currency') == 'yes'){
442
+
443
+ $currency = strtoupper(trim($db_currency->code));
444
+
445
+ }
446
+
447
+ return $currency;
448
+ }
449
+
450
+ // Fix for shipping update on the checkout page.
451
+ function shipping_update($amount){
452
+ global $sitepress, $post;
453
+
454
+ if($sitepress->get_current_language() !== $sitepress->get_default_language() && $post->ID == $this->checkout_page_id()){
455
+
456
+ $_SESSION['icl_checkout_shipping_amount'] = $amount;
457
+
458
+ $amount = $_SESSION['icl_checkout_shipping_amount'];
459
+
460
+ }
461
+
462
+ return $amount;
463
+ }
464
+
465
  /**
466
  * Filters WooCommerce checkout link.
467
  */
532
  return icl_object_id(get_option('woocommerce_shop_page_id'), 'page', false);
533
  }
534
 
535
+ /**
536
+ * Filters WooCommerce terms link.
537
+ */
538
+ function terms_page_id(){
539
+ return icl_object_id(get_option('woocommerce_terms_page_id'), 'page', false);
540
+ }
541
+
542
  /**
543
  * Filters WooCommerce pay page id
544
  */
552
  }
553
  }
554
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
555
  /**
556
  * After email translation switch language to default.
557
  *
560
  * @return type
561
  */
562
  function in_cart_product_title($title, $_product){
563
+ if (is_array($_product)) {
564
+ $product_id = $_product['product_id']; // backward compatibility
565
+ } else {
566
+ $product_id = $_product->id;
567
+ }
568
+ $product_id = icl_object_id($product_id, 'product', false, ICL_LANGUAGE_CODE);
569
 
570
  if($product_id){
571
  $title = get_the_title($product_id);
637
  */
638
  function do_redirect($link){
639
  global $sitepress;
640
+ return html_entity_decode($sitepress->convert_url($link));
641
  }
642
 
643
  /**
688
  global $post;
689
 
690
  $post_type = get_post_type($post->ID);
691
+ $checkout_page_id = $this->checkout_page_id();
692
 
693
  if($post_type == 'product' || is_page($checkout_page_id)){
694
  $output = '';
715
  *
716
  * @return type
717
  */
718
+ function gateway_title($title) {
719
+ if (function_exists('icl_translate')) {
720
+ $title = icl_translate('woocommerce', $title .'_gateway_title', $title);
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  }
 
722
  return $title;
723
  }
724
 
727
  *
728
  * @return type
729
  */
730
+ function gateway_description($description, $gateway_title) {
731
+ if (function_exists('icl_translate')) {
732
+ $description = icl_translate('woocommerce', $gateway_title .'_gateway_description', $description);
 
733
  }
 
 
 
 
 
 
 
 
 
 
 
 
734
  return $description;
735
  }
736
 
737
+ /**
738
+ * Filters WooCommerce query for translated shop page
739
+ *
740
+ */
741
+ function shop_page_query($q) {
742
+ if ( ! $q->is_main_query() )
743
+ return;
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'] ) )
752
+ $q->set( 'paged', $q->query['paged'] );
753
+
754
+ // Get the actual WP page to avoid errors
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;
762
+ $wp_post_types['product']->post_title = $shop_page->post_title;
763
+ $wp_post_types['product']->post_name = $shop_page->post_name;
764
+
765
+ // Fix conditional functions
766
+ $q->is_singular = false;
767
+ $q->is_post_type_archive = true;
768
+ $q->is_archive = true;
769
+ $q->queried_object = get_post_type_object('product');
770
+ }
771
+ }
772
 
773
  /**
774
  * Filters the currency symbol.
776
  function woocommerce_currency_symbol($currency_symbol){
777
  global $sitepress, $wpdb;
778
 
779
+ $db_currency = $wpdb->get_row("SELECT code FROM ". $wpdb->prefix ."icl_currencies WHERE language_code = '". $sitepress->get_current_language() ."'");
780
+
781
+ if($db_currency && get_option('icl_enable_multi_currency') == 'yes'){
782
+ $db_currency = $db_currency->code;
783
+ if(in_array($db_currency, array_keys($this->currencies))){
784
+ $currency_symbol = $this->currencies[$db_currency];
 
 
 
 
 
 
 
 
 
 
 
 
 
785
  } else {
786
+ $currency_symbol = $db_currency;
787
  }
788
  }
789
 
845
  }
846
 
847
  /*
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
 
898
  /**
899
  * Adds language to order post type.
960
  return $max_price;
961
  }
962
 
963
+ function sync_variations($post_id, $post){
964
+ global $wpdb, $pagenow, $sitepress;
 
 
 
 
 
 
 
 
 
 
965
 
966
+ $post_type = get_post_type($post_id);
967
+ $ajax_call = (!empty($_POST['icl_ajx_action']) && $_POST['icl_ajx_action'] == 'make_duplicates');
968
+ $duplicated_post_id = icl_object_id($post_id, 'product', false, $sitepress->get_default_language());
969
 
970
+ // exceptions
971
+ if (empty($duplicated_post_id) || isset($_POST['autosave'])) {
972
+ return;
973
+ }
974
 
975
+ // get language code
976
+ $language_details = $sitepress->get_element_language_details($post_id, 'post_product');
977
+ if (empty($language_details)) {
978
+ return;
979
+ }
980
+ $lang = $language_details->language_code;
981
 
982
+ if ($lang == $sitepress->get_default_language()) {
983
+ return;
984
+ }
985
+
986
+ // Filter upsell products, crosell products and default attributes for translations
987
+ if(($pagenow == 'post.php' || $pagenow == 'post-new.php' || $ajax_call ) && $post_type == 'product'){
988
+
989
  $original_product_upsell_ids = get_post_meta($duplicated_post_id, '_upsell_ids', TRUE);
 
 
990
  if(!empty($original_product_upsell_ids)){
991
  $unserialized_upsell_ids = maybe_unserialize($original_product_upsell_ids);
992
 
1002
  }
1003
  }
1004
 
1005
+ $data = array('meta_value' => maybe_serialize($unserialized_upsell_ids));
1006
+ $where = array('post_id' => $post_id, 'meta_key' => '_upsell_ids');
1007
+ $wpdb->update($wpdb->postmeta, $data, $where);
1008
  }
1009
 
1010
+ $original_product_crosssell_ids = get_post_meta($duplicated_post_id, '_crosssell_ids', TRUE);
1011
  if(!empty($original_product_crosssell_ids)){
1012
  $unserialized_crosssell_ids = maybe_unserialize($original_product_crosssell_ids);
1013
 
1023
  }
1024
  }
1025
 
1026
+ $data = array('meta_value' => maybe_serialize($unserialized_crosssell_ids));
1027
+ $where = array('post_id' => $post_id, 'meta_key' => '_crosssell_ids');
1028
+ $wpdb->update($wpdb->postmeta, $data, $where);
1029
  }
1030
 
1031
+ $original_default_attributes = get_post_meta($duplicated_post_id, '_default_attributes', TRUE);
1032
+ if(!empty($original_default_attributes)){
1033
+ $unserialized_default_attributes = maybe_unserialize($original_default_attributes);
1034
+ foreach($unserialized_default_attributes as $attribute => $default_term_slug){
1035
+ // get the correct language
1036
+ $default_term = get_term_by('slug', $default_term_slug, $attribute);
1037
+ $default_term_id = icl_object_id($default_term->term_id, $attribute, false, $lang);
1038
+
1039
+ if($default_term_id){
1040
+ $default_term = get_term_by('id', $default_term_id, $attribute);
1041
+ $unserialized_default_attributes[$attribute] = $default_term->slug;
1042
+ // if it isn't translated - unset it
1043
+ } else {
1044
+ unset($unserialized_default_attributes[$attribute]);
1045
+ }
1046
+ }
1047
+
1048
+ $data = array('meta_value' => maybe_serialize($unserialized_default_attributes));
1049
+ $where = array('post_id' => $post_id, 'meta_key' => '_default_attributes');
1050
+ $wpdb->update($wpdb->postmeta, $data, $where);
1051
+ }
1052
+
1053
  }
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'");
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,
1114
  'comment_status' => $post_data->comment_status,
1115
  'ping_status' => $post_data->ping_status,
1116
  'post_password' => $post_data->post_password,
1117
+ 'post_name' => $replaced_slug,
1118
  'to_ping' => $post_data->to_ping,
1119
  'pinged' => $post_data->pinged,
1120
  'post_modified' => $post_data->post_modified,
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
  }
1135
  }
1136
 
1141
  foreach ($get_current_post_variations as $post_data) {
1142
  $variation_id = get_post_meta($post_data->ID, '_wcml_duplicate_of_variation', true);
1143
  if (!in_array($variation_id, $duplicated_post_variation_ids)) {
1144
+ wp_delete_post($variation_id, true);
1145
  }
1146
  }
1147
 
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
 
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;
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
  }
1262
  }
1263
  }
1264
 
1265
+ /**
1266
+ * Preselects product-type in admin screen
1267
+ */
1268
+ function js_scripts_setup(){
1269
+ global $pagenow, $wpdb, $sitepress;
1270
+ if('post-new.php' == $pagenow){
1271
+ if(isset($_GET['post_type']) && $_GET['post_type'] == 'product' && isset($_GET['trid'])){
1272
+ $translations = $sitepress->get_element_translations($_GET['trid'], 'post_product_type');
1273
+ $source_lang = isset($_GET['source_lang'])?$_GET['source_lang']:$sitepress->get_default_language();
1274
+ $terms = get_the_terms($translations[$source_lang]->element_id, 'product_type');
1275
+ echo '<script type="text/javascript">';
1276
+ echo PHP_EOL . '// <![CDATA[' . PHP_EOL;
1277
+ echo 'addLoadEvent(function(){'. PHP_EOL;
1278
+ echo "jQuery('#product-type option').removeAttr('selected');" . PHP_EOL;
1279
+ echo "jQuery('#product-type option[value=\"" . $terms[0]->slug . "\"]').attr('selected', 'selected');" . PHP_EOL;
1280
+ echo '});'. PHP_EOL;
1281
+ echo PHP_EOL . '// ]]>' . PHP_EOL;
1282
+ echo '</script>';
1283
+ }
1284
+ }
1285
+ }
1286
+
1287
  /**
1288
  * Adds admin notice.
1289
  */
wpml-config.xml CHANGED
@@ -28,7 +28,6 @@
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">_default_attributes</custom-field>
32
  <custom-field action="copy">_downloadable</custom-field>
33
  <custom-field action="copy">_download_limit</custom-field>
34
  <custom-field action="copy">_featured</custom-field>
@@ -61,12 +60,20 @@
61
  <custom-field action="copy">_woocommerce_exclude_image</custom-field>
62
  <custom-field action="copy">_wp_attached_file</custom-field>
63
  <custom-field action="copy">_product_attributes</custom-field>
 
64
  <custom-field action="copy">_upsell_ids</custom-field>
65
  <custom-field action="copy">_crosssell_ids</custom-field>
 
 
 
 
 
 
 
66
  </custom-fields>
67
  <custom-types>
68
  <custom-type translate="1">product</custom-type>
69
- <custom-type translate="0">product_variation</custom-type>
70
  <custom-type translate="0">shop_order</custom-type>
71
  </custom-types>
72
  <taxonomies>
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>
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>
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.3
9
  */
10
 
11
  if(defined('WCML_VERSION')) return;
12
- define('WCML_VERSION', '1.3');
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.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);