WooCommerce Multilingual – run WooCommerce with WPML - Version 3.6.5

Version Description

  • Enabled the WooCommerce Bookings compatibility support
  • Bug fix: Fixed a bug that caused a wrong price to be displayed when adding a product in the cart from two different languages
  • Bug fix: After a product translation was edited in the standard product editor, the WooCommerce custom attribute translations were lost
  • Bug fix: The product variations failed to sync when the term_id was different than the term_taxonomy_id for the terms used to create the variations
  • Bug fix: Some product translations were showing non existing discounted prices
  • Fixed a couple of compatibility issues with WooCommerce Product Bundles (e.g. with using the Flatsome theme)
  • Fixed a small usability issue related to Sensei
  • Bug fix: Stock quantity not synchronized when items were used in orders created in the backend
  • Bug fix: Payment gateways strings were not registered for string translation
  • Bug fix: Global Attributes were not translated in the WooCommerce Mail
  • Bug fix: In some cases the WooCommerce endpoints were not translated correctly
  • Bug fix: An extra 'a' tag was added to products in the mini-cart
  • Bug fix: A 404 error was returned on the translated product category archive page
  • Bug fix: Some shipping methods were displayed incorrectly on the cart page when using Table Rate Shipping
  • Bug fix: In some cases prices showing the Paypal order summary included decimals even if the prices were supposed to be rounded to integers
  • Bug fix: When adding different variations of a product, a single variation was added more times
  • Bug fix: Urls in the secondary languages were not working properly when using the deafault translations (from teh mo files) instead of translating tehm with string translation
  • Bug fix: In some cases some email notification strings were not registered
  • Fixed a compatibility problem with Dynamic Pricing: in a specific context, based on a price rule, the end price was multiplied by a factor with each page reload
Download this release

Release Info

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

Code changes from version 3.6.4 to 3.6.5

compatibility/wc_bookings.class.php CHANGED
@@ -18,6 +18,7 @@ class WCML_Bookings{
18
  add_action( 'admin_footer', array( $this, 'load_assets' ) );
19
 
20
  add_action( 'save_post', array( $this, 'save_custom_costs' ), 11, 2 );
 
21
  add_action( 'wcml_before_sync_product', array( $this, 'sync_booking_data' ), 10, 2 );
22
 
23
  add_filter( 'update_post_metadata', array( $this, 'update_wc_booking_costs' ), 10, 5 );
@@ -47,6 +48,8 @@ class WCML_Bookings{
47
  add_filter( 'wcml_product_content_exception', array( $this, 'remove_custom_fields_to_translate' ), 10, 3 );
48
  add_filter( 'wcml_product_content_label', array( $this, 'product_content_resource_label' ), 10, 2 );
49
  add_action( 'wcml_update_extra_fields', array( $this, 'wcml_products_tab_sync_resources_and_persons'), 10, 3 );
 
 
50
  }
51
 
52
  function wcml_price_field_after_booking_base_cost( $post_id ){
@@ -315,7 +318,29 @@ class WCML_Bookings{
315
  }
316
  }
317
 
 
 
 
 
 
318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
 
320
  }
321
 
@@ -1365,4 +1390,127 @@ class WCML_Bookings{
1365
 
1366
  }
1367
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1368
  }
18
  add_action( 'admin_footer', array( $this, 'load_assets' ) );
19
 
20
  add_action( 'save_post', array( $this, 'save_custom_costs' ), 11, 2 );
21
+ add_action( 'wcml_before_sync_product_data', array( $this, 'sync_bookings' ), 10, 3 );
22
  add_action( 'wcml_before_sync_product', array( $this, 'sync_booking_data' ), 10, 2 );
23
 
24
  add_filter( 'update_post_metadata', array( $this, 'update_wc_booking_costs' ), 10, 5 );
48
  add_filter( 'wcml_product_content_exception', array( $this, 'remove_custom_fields_to_translate' ), 10, 3 );
49
  add_filter( 'wcml_product_content_label', array( $this, 'product_content_resource_label' ), 10, 2 );
50
  add_action( 'wcml_update_extra_fields', array( $this, 'wcml_products_tab_sync_resources_and_persons'), 10, 3 );
51
+
52
+ add_action( 'woocommerce_new_booking', array( $this, 'duplicate_booking_for_translations') );
53
  }
54
 
55
  function wcml_price_field_after_booking_base_cost( $post_id ){
318
  }
319
  }
320
 
321
+ }
322
+
323
+ // sync existing product bookings for translations
324
+ function sync_bookings( $original_product_id, $product_id, $lang ){
325
+ global $wpdb;
326
 
327
+ $all_bookings_for_product = WC_Bookings_Controller::get_bookings_for_product( $original_product_id , array( 'in-cart', 'unpaid', 'confirmed', 'paid' ) );
328
+
329
+ foreach($all_bookings_for_product as $booking ){
330
+ $check_if_exists = $wpdb->get_row( $wpdb->prepare( "SELECT pm3.* FROM {$wpdb->postmeta} AS pm1
331
+ LEFT JOIN {$wpdb->postmeta} AS pm2 ON pm1.post_id = pm2.post_id
332
+ LEFT JOIN {$wpdb->postmeta} AS pm3 ON pm1.post_id = pm3.post_id
333
+ WHERE pm1.meta_key = '_booking_duplicate_of' AND pm1.meta_value = %s AND pm2.meta_key = '_language_code' AND pm2.meta_value = %s AND pm3.meta_key = '_booking_product_id'"
334
+ , $booking->id, $lang ) );
335
+
336
+ if( is_null( $check_if_exists ) ){
337
+ $this->duplicate_booking_for_translations( $booking->id, $lang );
338
+ }elseif( $check_if_exists->meta_value === '' ){
339
+ update_post_meta( $check_if_exists->post_id, '_booking_product_id', $this->get_translated_booking_product_id( $booking->id, $lang ) );
340
+ update_post_meta( $check_if_exists->post_id, '_booking_resource_id', $this->get_translated_booking_resource_id( $booking->id, $lang ) );
341
+ update_post_meta( $check_if_exists->post_id, '_booking_persons', $this->get_translated_booking_persons_ids( $booking->id, $lang ) );
342
+ }
343
+ }
344
 
345
  }
346
 
1390
 
1391
  }
1392
 
1393
+ function duplicate_booking_for_translations( $booking_id, $lang = false ){
1394
+ global $sitepress;
1395
+
1396
+ $booking_object = get_post( $booking_id );
1397
+
1398
+ $booking_data = array(
1399
+ 'post_type' => 'wc_booking',
1400
+ 'post_title' => $booking_object->post_title,
1401
+ 'post_status' => $booking_object->post_status,
1402
+ 'ping_status' => 'closed',
1403
+ 'post_parent' => $booking_object->post_parent,
1404
+ );
1405
+
1406
+ $active_languages = $sitepress->get_active_languages();
1407
+
1408
+ foreach( $active_languages as $language ){
1409
+
1410
+ $booking_product_id = get_post_meta( $booking_id, '_booking_product_id', true );
1411
+
1412
+ if( !$lang ){
1413
+ $booking_language = $sitepress->get_element_language_details( $booking_product_id, 'post_product' );
1414
+ if ( $booking_language->language_code == $language['code'] ) {
1415
+ continue;
1416
+ }
1417
+ }elseif( $lang != $language['code'] ){
1418
+ continue;
1419
+ }
1420
+
1421
+ $booking_persons = maybe_unserialize( get_post_meta( $booking_id, '_booking_persons', true ) );
1422
+ $trnsl_booking_persons = array();
1423
+
1424
+ foreach( $booking_persons as $person_id => $person_count ){
1425
+
1426
+ $trnsl_person_id = apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $language['code'] );
1427
+
1428
+ if( is_null( $trnsl_person_id ) ){
1429
+ $trnsl_booking_persons[] = $person_count;
1430
+ }else{
1431
+ $trnsl_booking_persons[ $trnsl_person_id ] = $person_count;
1432
+ }
1433
+
1434
+ }
1435
+
1436
+ $trnsl_booking_id = wp_insert_post( $booking_data );
1437
+
1438
+ $meta_args = array(
1439
+ '_booking_order_item_id' => get_post_meta( $booking_id, '_booking_order_item_id', true ),
1440
+ '_booking_product_id' => $this->get_translated_booking_product_id( $booking_id, $language['code'] ),
1441
+ '_booking_resource_id' => $this->get_translated_booking_resource_id( $booking_id, $language['code'] ),
1442
+ '_booking_persons' => $this->get_translated_booking_persons_ids( $booking_id, $language['code'] ),
1443
+ '_booking_cost' => get_post_meta( $booking_id, '_booking_cost', true ),
1444
+ '_booking_start' => get_post_meta( $booking_id, '_booking_start', true ),
1445
+ '_booking_end' => get_post_meta( $booking_id, '_booking_end', true ),
1446
+ '_booking_all_day' => intval( get_post_meta( $booking_id, '_booking_all_day', true ) ),
1447
+ '_booking_parent_id' => get_post_meta( $booking_id, '_booking_parent_id', true ),
1448
+ '_booking_customer_id' => get_post_meta( $booking_id, '_booking_customer_id', true ),
1449
+ '_booking_duplicate_of' => $booking_id,
1450
+ '_language_code' => $language['code'],
1451
+ );
1452
+
1453
+ foreach ( $meta_args as $key => $value ) {
1454
+ update_post_meta( $trnsl_booking_id, $key, $value );
1455
+ }
1456
+
1457
+ WC_Cache_Helper::get_transient_version( 'bookings', true );
1458
+
1459
+ }
1460
+
1461
+
1462
+ }
1463
+
1464
+ function get_translated_booking_product_id( $booking_id, $language ){
1465
+
1466
+ $booking_product_id = get_post_meta( $booking_id, '_booking_product_id', true );
1467
+
1468
+ if( $booking_product_id ){
1469
+ $trnsl_booking_product_id = apply_filters( 'translate_object_id', $booking_product_id, 'product', false, $language );
1470
+ if( is_null( $trnsl_booking_product_id ) ){
1471
+ $trnsl_booking_product_id = '';
1472
+ }
1473
+ }
1474
+
1475
+ return $trnsl_booking_product_id;
1476
+
1477
+ }
1478
+
1479
+ function get_translated_booking_resource_id( $booking_id, $language ){
1480
+
1481
+ $booking_resource_id = get_post_meta( $booking_id, '_booking_resource_id', true );
1482
+ $trnsl_booking_resource_id = '';
1483
+
1484
+ if( $booking_resource_id ){
1485
+ $trnsl_booking_resource_id = apply_filters( 'translate_object_id', $booking_resource_id, 'bookable_resource', false, $language );
1486
+
1487
+ if( is_null( $trnsl_booking_resource_id ) ){
1488
+ $trnsl_booking_resource_id = '';
1489
+ }
1490
+ }
1491
+
1492
+ return $trnsl_booking_resource_id;
1493
+ }
1494
+
1495
+ function get_translated_booking_persons_ids( $booking_id, $language ){
1496
+
1497
+ $booking_persons = maybe_unserialize( get_post_meta( $booking_id, '_booking_persons', true ) );
1498
+ $trnsl_booking_persons = array();
1499
+
1500
+ foreach( $booking_persons as $person_id => $person_count ){
1501
+
1502
+ $trnsl_person_id = apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $language );
1503
+
1504
+ if( is_null( $trnsl_person_id ) ){
1505
+ $trnsl_booking_persons[] = $person_count;
1506
+ }else{
1507
+ $trnsl_booking_persons[ $trnsl_person_id ] = $person_count;
1508
+ }
1509
+
1510
+ }
1511
+
1512
+ return $trnsl_booking_persons;
1513
+
1514
+ }
1515
+
1516
  }
compatibility/wc_dynamic_pricing.class.php CHANGED
@@ -8,6 +8,8 @@ class WCML_Dynamic_Pricing{
8
  add_filter('woocommerce_dynamic_pricing_is_applied_to', array($this, 'woocommerce_dynamic_pricing_is_applied_to'),10,5);
9
  add_filter('woocommerce_dynamic_pricing_get_rule_amount',array($this,'woocommerce_dynamic_pricing_get_rule_amount'),10,4);
10
  add_filter('dynamic_pricing_product_rules',array($this,'dynamic_pricing_product_rules'));
 
 
11
  }
12
  }
13
 
@@ -19,12 +21,12 @@ class WCML_Dynamic_Pricing{
19
  foreach($available_rulesets as $rule_key=>$available_ruleset){
20
  $rules = $available_ruleset['rules'];
21
 
22
- if($rules){
23
- foreach($rules as $r_key=>$rule){
24
- if($rule['type'] == 'fixed_product'){
25
- $rules[$r_key]['amount'] = apply_filters('wcml_raw_price_amount', $rule['amount']);
26
- }
27
- }
28
  $modules[$mod_key]->available_rulesets[$rule_key]['rules'] = $rules;
29
 
30
  }
@@ -32,7 +34,7 @@ class WCML_Dynamic_Pricing{
32
 
33
  }
34
  }
35
-
36
  return $modules;
37
  }
38
 
@@ -72,4 +74,8 @@ class WCML_Dynamic_Pricing{
72
  return $rules;
73
  }
74
 
 
 
 
 
75
  }
8
  add_filter('woocommerce_dynamic_pricing_is_applied_to', array($this, 'woocommerce_dynamic_pricing_is_applied_to'),10,5);
9
  add_filter('woocommerce_dynamic_pricing_get_rule_amount',array($this,'woocommerce_dynamic_pricing_get_rule_amount'),10,4);
10
  add_filter('dynamic_pricing_product_rules',array($this,'dynamic_pricing_product_rules'));
11
+ add_filter('translate_cart_subtotal_exception',array($this,'translate_cart_subtotal_exception'),10,2);
12
+
13
  }
14
  }
15
 
21
  foreach($available_rulesets as $rule_key=>$available_ruleset){
22
  $rules = $available_ruleset['rules'];
23
 
24
+ if($rules){
25
+ foreach($rules as $r_key=>$rule){
26
+ if($rule['type'] == 'fixed_product'){
27
+ $rules[$r_key]['amount'] = apply_filters('wcml_raw_price_amount', $rule['amount']);
28
+ }
29
+ }
30
  $modules[$mod_key]->available_rulesets[$rule_key]['rules'] = $rules;
31
 
32
  }
34
 
35
  }
36
  }
37
+
38
  return $modules;
39
  }
40
 
74
  return $rules;
75
  }
76
 
77
+ function translate_cart_subtotal_exception( $value, $cart ){
78
+ return true;
79
+ }
80
+
81
  }
compatibility/wc_extra_product_options.class.php CHANGED
@@ -57,7 +57,7 @@ class WCML_Extra_Product_Options{
57
  if( $action == 'register'){
58
  do_action('wpml_register_single_string', 'wc_extra_product_options', $id.'_option_'.$value_key.'_'.$key, $value );
59
  }else{
60
- $options[ 'tmfbuilder' ][ $key ][ $value_key ] = icl_t('wc_extra_product_options', $id.'_option_'.$value_key.'_'.$key, $value);
61
  }
62
  }
63
 
57
  if( $action == 'register'){
58
  do_action('wpml_register_single_string', 'wc_extra_product_options', $id.'_option_'.$value_key.'_'.$key, $value );
59
  }else{
60
+ $options[ 'tmfbuilder' ][ $key ][ $value_key ] = apply_filters( 'wpml_translate_single_string', $value, 'wc_extra_product_options', $id.'_option_'.$value_key.'_'.$key);
61
  }
62
  }
63
 
compatibility/wc_product_addons.class.php CHANGED
@@ -41,10 +41,10 @@ class WCML_Product_Addons{
41
  $object_id = $sitepress->get_original_element_id( $object_id , 'post_'.$addon_type );
42
 
43
  foreach($addons as $add_id => $addon){
44
- $addons[$add_id]['name'] = icl_t('wc_product_addons_strings', $object_id.'_addon_'.$addon['type'].'_'.$addon['position'].'_name', $addon['name']);
45
- $addons[$add_id]['description'] = icl_t('wc_product_addons_strings', $object_id.'_addon_'.$addon['type'].'_'.$addon['position'].'_description', $addon['description']);
46
  foreach($addon['options'] as $key=>$option){
47
- $addons[$add_id]['options'][$key]['label'] = icl_t('wc_product_addons_strings', $object_id.'_addon_'.$addon['type'].'_'.$addon['position'].'_option_label_'.$key, $option['label']);
48
 
49
  //price filter
50
  $addons[$add_id]['options'][$key]['price'] = apply_filters('wcml_raw_price_amount', $option['price']);
41
  $object_id = $sitepress->get_original_element_id( $object_id , 'post_'.$addon_type );
42
 
43
  foreach($addons as $add_id => $addon){
44
+ $addons[$add_id]['name'] = apply_filters( 'wpml_translate_single_string', $addon['name'], 'wc_product_addons_strings', $object_id.'_addon_'.$addon['type'].'_'.$addon['position'].'_name' );
45
+ $addons[$add_id]['description'] = apply_filters( 'wpml_translate_single_string', $addon['description'], 'wc_product_addons_strings', $object_id.'_addon_'.$addon['type'].'_'.$addon['position'].'_description');
46
  foreach($addon['options'] as $key=>$option){
47
+ $addons[$add_id]['options'][$key]['label'] = apply_filters( 'wpml_translate_single_string', $option['label'], 'wc_product_addons_strings', $object_id.'_addon_'.$addon['type'].'_'.$addon['position'].'_option_label_'.$key);
48
 
49
  //price filter
50
  $addons[$add_id]['options'][$key]['price'] = apply_filters('wcml_raw_price_amount', $option['price']);
compatibility/wc_product_bundles.class.php CHANGED
@@ -10,6 +10,7 @@ class WCML_Product_Bundles{
10
  add_filter('wcml_cart_contents', array($this, 'cart_bundle_update_lang_switch'), 10, 4);
11
  add_filter('wcml_update_cart_contents_lang_switch', array($this, 'cart_contents_bundle_update_lang_switch'), 10, 4);
12
  add_filter('wcml_filter_cart_item_data', array($this, 'filter_cart_item_data') );
 
13
  add_filter('wcml_exception_duplicate_products_in_cart', array($this, 'check_on_bundle_product_in_cart'), 10, 2 );
14
  }
15
 
@@ -289,13 +290,23 @@ class WCML_Product_Bundles{
289
  return $cart_contents;
290
  }
291
 
 
 
 
 
 
 
 
 
292
  function check_on_bundle_product_in_cart( $flag, $cart_item ){
293
- if( isset( $cart_item['bundled_by'] ) ){
 
294
  return true;
295
  }
296
 
297
  return false;
298
- }
 
299
 
300
 
301
  }
10
  add_filter('wcml_cart_contents', array($this, 'cart_bundle_update_lang_switch'), 10, 4);
11
  add_filter('wcml_update_cart_contents_lang_switch', array($this, 'cart_contents_bundle_update_lang_switch'), 10, 4);
12
  add_filter('wcml_filter_cart_item_data', array($this, 'filter_cart_item_data') );
13
+ add_filter('wcml_check_on_duplicated_products_in_cart', array($this, 'removeduplicated_bundle_product_in_cart'), 10, 3 );
14
  add_filter('wcml_exception_duplicate_products_in_cart', array($this, 'check_on_bundle_product_in_cart'), 10, 2 );
15
  }
16
 
290
  return $cart_contents;
291
  }
292
 
293
+ function removeduplicated_bundle_product_in_cart( $cart_contents, $key, $cart_item ){
294
+ if( isset( $cart_item['bundled_by'] ) && !isset($cart_contents[$cart_item['bundled_by']])){
295
+ unset($cart_contents[$key]);
296
+ }
297
+
298
+ return $cart_contents;
299
+ }
300
+
301
  function check_on_bundle_product_in_cart( $flag, $cart_item ){
302
+
303
+ if( isset( $cart_item['bundled_by'] ) ) {
304
  return true;
305
  }
306
 
307
  return false;
308
+
309
+ }
310
 
311
 
312
  }
compatibility/wc_sensei.class.php CHANGED
@@ -13,6 +13,15 @@ class WCML_sensei{
13
  add_action( 'delete_comment', array( $this, 'delete_user_activity' ) );
14
 
15
  add_action( 'pre_get_comments', array( $this, 'pre_get_comments') );
 
 
 
 
 
 
 
 
 
16
  }
17
 
18
  function save_post_actions( $post_id, $post ){
@@ -73,7 +82,7 @@ class WCML_sensei{
73
  $lesson_id = get_post_meta( $original_post_id, '_quiz_lesson', true );
74
 
75
  if( $lesson_id ){
76
- $tr_lesson_id = apply_filters( 'translate_object_id', $lesson_id, 'post_lesson', false, $language );
77
 
78
  if( !is_null( $tr_lesson_id ) ){
79
  update_post_meta( $post_id, '_quiz_lesson', $tr_lesson_id );
@@ -87,7 +96,7 @@ class WCML_sensei{
87
  $course_id = get_post_meta( $original_post_id, '_lesson_course', true );
88
 
89
  if( $course_id ){
90
- $tr_course_id = apply_filters( 'translate_object_id', $course_id, 'post_course', false, $language );
91
 
92
  if( !is_null( $tr_course_id ) ){
93
  update_post_meta( $post_id, '_lesson_course', $tr_course_id );
@@ -100,7 +109,7 @@ class WCML_sensei{
100
  $lesson_id = get_post_meta( $original_post_id, '_lesson_prerequisite', true );
101
 
102
  if( $lesson_id ){
103
- $tr_lesson_id = apply_filters( 'translate_object_id', $lesson_id, 'post_lesson', false, $language );
104
 
105
  if( !is_null( $tr_lesson_id ) ){
106
  update_post_meta( $post_id, '_lesson_prerequisite', $tr_lesson_id );
@@ -110,11 +119,12 @@ class WCML_sensei{
110
  }
111
 
112
  }else{
 
113
  //sync course woocommerce_product
114
  $product_id = get_post_meta( $original_post_id, '_course_woocommerce_product', true );
115
 
116
  if( $product_id ){
117
- $tr_product_id = apply_filters( 'translate_object_id', $product_id, 'post_product', false, $language );
118
 
119
  if( !is_null( $tr_product_id ) ){
120
  update_post_meta( $post_id, '_course_woocommerce_product', $tr_product_id );
@@ -127,7 +137,7 @@ class WCML_sensei{
127
  $course_id = get_post_meta( $original_post_id, '_course_prerequisite', true );
128
 
129
  if( $course_id ){
130
- $tr_course_id = apply_filters( 'translate_object_id', $course_id, 'post_course', false, $language );
131
 
132
  if( !is_null( $tr_course_id ) ){
133
  update_post_meta( $post_id, '_course_prerequisite', $tr_course_id );
@@ -140,9 +150,13 @@ class WCML_sensei{
140
 
141
  }
142
 
143
- function log_activity_after ( $args, $data, $comment_id ){
144
  global $sitepress;
145
 
 
 
 
 
146
  $comment_post_id = $data['comment_post_ID'];
147
  $trid = $sitepress->get_element_trid( $comment_post_id, 'post_'.get_post_type( $comment_post_id ) );
148
  $translations = $sitepress->get_element_translations( $trid, 'post_'.get_post_type( $comment_post_id ) );
@@ -172,7 +186,7 @@ class WCML_sensei{
172
 
173
  $order_language = get_post_meta( $order->id, 'wpml_language', true );
174
 
175
- $tr_product_id = apply_filters( 'translate_object_id', $product_id, 'post_'.get_post_type( $product_id ), false, $order_language );
176
 
177
  if( !is_null( $tr_product_id ) ){
178
  return $tr_product_id;
13
  add_action( 'delete_comment', array( $this, 'delete_user_activity' ) );
14
 
15
  add_action( 'pre_get_comments', array( $this, 'pre_get_comments') );
16
+
17
+ if( is_admin() &&
18
+ (
19
+ ( isset($_GET['post_type']) && $_GET['post_type'] == 'sensei_message' ) ||
20
+ ( isset($_GET['page']) && $_GET['page'] == 'sensei_grading' )
21
+ ) ){
22
+ remove_action( 'wp_before_admin_bar_render', array($sitepress, 'admin_language_switcher') );
23
+ }
24
+
25
  }
26
 
27
  function save_post_actions( $post_id, $post ){
82
  $lesson_id = get_post_meta( $original_post_id, '_quiz_lesson', true );
83
 
84
  if( $lesson_id ){
85
+ $tr_lesson_id = apply_filters( 'translate_object_id', $lesson_id, 'lesson', false, $language );
86
 
87
  if( !is_null( $tr_lesson_id ) ){
88
  update_post_meta( $post_id, '_quiz_lesson', $tr_lesson_id );
96
  $course_id = get_post_meta( $original_post_id, '_lesson_course', true );
97
 
98
  if( $course_id ){
99
+ $tr_course_id = apply_filters( 'translate_object_id', $course_id, 'course', false, $language );
100
 
101
  if( !is_null( $tr_course_id ) ){
102
  update_post_meta( $post_id, '_lesson_course', $tr_course_id );
109
  $lesson_id = get_post_meta( $original_post_id, '_lesson_prerequisite', true );
110
 
111
  if( $lesson_id ){
112
+ $tr_lesson_id = apply_filters( 'translate_object_id', $lesson_id, 'lesson', false, $language );
113
 
114
  if( !is_null( $tr_lesson_id ) ){
115
  update_post_meta( $post_id, '_lesson_prerequisite', $tr_lesson_id );
119
  }
120
 
121
  }else{
122
+
123
  //sync course woocommerce_product
124
  $product_id = get_post_meta( $original_post_id, '_course_woocommerce_product', true );
125
 
126
  if( $product_id ){
127
+ $tr_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), false, $language );
128
 
129
  if( !is_null( $tr_product_id ) ){
130
  update_post_meta( $post_id, '_course_woocommerce_product', $tr_product_id );
137
  $course_id = get_post_meta( $original_post_id, '_course_prerequisite', true );
138
 
139
  if( $course_id ){
140
+ $tr_course_id = apply_filters( 'translate_object_id', $course_id, 'course', false, $language );
141
 
142
  if( !is_null( $tr_course_id ) ){
143
  update_post_meta( $post_id, '_course_prerequisite', $tr_course_id );
150
 
151
  }
152
 
153
+ function log_activity_after ( $args, $data, $comment_id = false ){
154
  global $sitepress;
155
 
156
+ if( !$comment_id ){
157
+ return false;
158
+ }
159
+
160
  $comment_post_id = $data['comment_post_ID'];
161
  $trid = $sitepress->get_element_trid( $comment_post_id, 'post_'.get_post_type( $comment_post_id ) );
162
  $translations = $sitepress->get_element_translations( $trid, 'post_'.get_post_type( $comment_post_id ) );
186
 
187
  $order_language = get_post_meta( $order->id, 'wpml_language', true );
188
 
189
+ $tr_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), false, $order_language );
190
 
191
  if( !is_null( $tr_product_id ) ){
192
  return $tr_product_id;
inc/compatibility.class.php CHANGED
@@ -83,7 +83,7 @@ class WCML_Compatibility {
83
  }
84
 
85
  // WooCommerce Bookings
86
- if(defined( 'WC_BOOKINGS_VERSION' ) && version_compare(WC_BOOKINGS_VERSION, '2.0', '>') ){
87
  require_once WCML_PLUGIN_PATH . '/compatibility/wc_bookings.class.php';
88
  $this->bookings = new WCML_Bookings();
89
  }
@@ -99,6 +99,19 @@ class WCML_Compatibility {
99
  $this->wc_bulk_stock_management = new WCML_Bulk_Stock_Management();
100
  }
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  }
103
 
104
  }
83
  }
84
 
85
  // WooCommerce Bookings
86
+ if(defined( 'WC_BOOKINGS_VERSION' ) && version_compare(WC_BOOKINGS_VERSION, '1.7.8', '>=') ){
87
  require_once WCML_PLUGIN_PATH . '/compatibility/wc_bookings.class.php';
88
  $this->bookings = new WCML_Bookings();
89
  }
99
  $this->wc_bulk_stock_management = new WCML_Bulk_Stock_Management();
100
  }
101
 
102
+ // WooCommerce Advanced Ajax Layered Navigation
103
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
104
+ if ( is_plugin_active( 'woocommerce-ajax-layered-nav/ajax_layered_nav-widget.php' ) ) {
105
+ require_once WCML_PLUGIN_PATH . '/compatibility/wc_ajax_layered_nav_widget.class.php';
106
+ $this->wc_ajax_layered_nav_widget = new WCML_Ajax_Layered_Nav_Widget();
107
+ }
108
+
109
+ // woocommerce composite products
110
+ if ( isset( $GLOBALS[ 'woocommerce_composite_products' ] ) ) {
111
+ require_once WCML_PLUGIN_PATH . '/compatibility/wc_composite_products.class.php';
112
+ $this->wc_composite_products = new WCML_Composite_Products();
113
+ }
114
+
115
  }
116
 
117
  }
inc/emails.class.php CHANGED
@@ -137,16 +137,16 @@ class WCML_Emails{
137
  if(class_exists('WC_Email_Customer_Completed_Order') || $no_checking){
138
  $heading = $this->wcml_get_email_string_info( '[woocommerce_customer_completed_order_settings]heading' );
139
  if($heading)
140
- $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->heading = icl_t($heading[0]->context,'[woocommerce_customer_completed_order_settings]heading',$heading[0]->value);
141
  $subject = $this->wcml_get_email_string_info( '[woocommerce_customer_completed_order_settings]subject' );
142
  if($subject)
143
- $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->subject = icl_t($subject[0]->context,'[woocommerce_customer_completed_order_settings]subject',$subject[0]->value);
144
  $heading_downloadable = $this->wcml_get_email_string_info( '[woocommerce_customer_completed_order_settings]heading_downloadable' );
145
  if($heading_downloadable)
146
- $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->heading_downloadable = icl_t($heading_downloadable[0]->context,'[woocommerce_customer_completed_order_settings]heading_downloadable',$heading_downloadable[0]->value);
147
  $subject_downloadable = $this->wcml_get_email_string_info( '[woocommerce_customer_completed_order_settings]subject_downloadable' );
148
  if($subject_downloadable)
149
- $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->subject_downloadable = icl_t($subject_downloadable[0]->context,'[woocommerce_customer_completed_order_settings]subject_downloadable',$subject_downloadable[0]->value);
150
 
151
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->enabled;
152
  $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->enabled = false;
@@ -160,10 +160,10 @@ class WCML_Emails{
160
  if(class_exists('WC_Email_Customer_Processing_Order')){
161
  $heading = $this->wcml_get_email_string_info( '[woocommerce_customer_processing_order_settings]heading' );
162
  if($heading)
163
- $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->heading = icl_t($heading[0]->context,'[woocommerce_customer_processing_order_settings]heading',$heading[0]->value);
164
  $subject = $this->wcml_get_email_string_info( '[woocommerce_customer_processing_order_settings]subject' );
165
  if($subject)
166
- $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->subject = icl_t($subject[0]->context,'[woocommerce_customer_processing_order_settings]subject',$subject[0]->value);
167
 
168
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled;
169
  $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled = false;
@@ -178,11 +178,11 @@ class WCML_Emails{
178
  if(class_exists('WC_Email_Customer_Note')){
179
  $heading = $this->wcml_get_email_string_info( '[woocommerce_customer_note_settings]heading' );
180
  if($heading)
181
- $woocommerce->mailer()->emails['WC_Email_Customer_Note']->heading = icl_t($heading[0]->context,'[woocommerce_customer_note_settings]heading',$heading[0]->value);
182
 
183
  $subject = $this->wcml_get_email_string_info( '[woocommerce_customer_note_settings]subject' );
184
  if($subject)
185
- $woocommerce->mailer()->emails['WC_Email_Customer_Note']->subject = icl_t($subject[0]->context,'[woocommerce_customer_note_settings]subject',$subject[0]->value);
186
 
187
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Note']->enabled;
188
  $woocommerce->mailer()->emails['WC_Email_Customer_Note']->enabled = false;
@@ -206,10 +206,10 @@ class WCML_Emails{
206
  $this->change_email_language($user_lang);
207
  $heading = $this->wcml_get_email_string_info( '[woocommerce_new_order_settings]heading' );
208
  if($heading)
209
- $woocommerce->mailer()->emails['WC_Email_New_Order']->heading = icl_t($heading[0]->context,'[woocommerce_new_order_settings]heading',$heading[0]->value);
210
  $subject = $this->wcml_get_email_string_info( '[woocommerce_new_order_settings]subject' );
211
  if($subject)
212
- $woocommerce->mailer()->emails['WC_Email_New_Order']->subject = icl_t($subject[0]->context,'[woocommerce_new_order_settings]subject',$subject[0]->value);
213
 
214
  $woocommerce->mailer()->emails['WC_Email_New_Order']->recipient = $recipient;
215
 
137
  if(class_exists('WC_Email_Customer_Completed_Order') || $no_checking){
138
  $heading = $this->wcml_get_email_string_info( '[woocommerce_customer_completed_order_settings]heading' );
139
  if($heading)
140
+ $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->heading = apply_filters( 'wpml_translate_single_string', $heading[0]->value, $heading[0]->context,'[woocommerce_customer_completed_order_settings]heading' );
141
  $subject = $this->wcml_get_email_string_info( '[woocommerce_customer_completed_order_settings]subject' );
142
  if($subject)
143
+ $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->subject = apply_filters( 'wpml_translate_single_string', $subject[0]->value, $subject[0]->context,'[woocommerce_customer_completed_order_settings]subject');
144
  $heading_downloadable = $this->wcml_get_email_string_info( '[woocommerce_customer_completed_order_settings]heading_downloadable' );
145
  if($heading_downloadable)
146
+ $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->heading_downloadable = apply_filters( 'wpml_translate_single_string', $heading_downloadable[0]->value, $heading_downloadable[0]->context,'[woocommerce_customer_completed_order_settings]heading_downloadable');
147
  $subject_downloadable = $this->wcml_get_email_string_info( '[woocommerce_customer_completed_order_settings]subject_downloadable' );
148
  if($subject_downloadable)
149
+ $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->subject_downloadable = apply_filters( 'wpml_translate_single_string', $subject_downloadable[0]->value, $subject_downloadable[0]->context,'[woocommerce_customer_completed_order_settings]subject_downloadable' );
150
 
151
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->enabled;
152
  $woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->enabled = false;
160
  if(class_exists('WC_Email_Customer_Processing_Order')){
161
  $heading = $this->wcml_get_email_string_info( '[woocommerce_customer_processing_order_settings]heading' );
162
  if($heading)
163
+ $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->heading = apply_filters( 'wpml_translate_single_string', $heading[0]->value, $heading[0]->context,'[woocommerce_customer_processing_order_settings]heading' );
164
  $subject = $this->wcml_get_email_string_info( '[woocommerce_customer_processing_order_settings]subject' );
165
  if($subject)
166
+ $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->subject = apply_filters( 'wpml_translate_single_string', $subject[0]->value, $subject[0]->context,'[woocommerce_customer_processing_order_settings]subject' );
167
 
168
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled;
169
  $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled = false;
178
  if(class_exists('WC_Email_Customer_Note')){
179
  $heading = $this->wcml_get_email_string_info( '[woocommerce_customer_note_settings]heading' );
180
  if($heading)
181
+ $woocommerce->mailer()->emails['WC_Email_Customer_Note']->heading = apply_filters( 'wpml_translate_single_string', $heading[0]->value, $heading[0]->context,'[woocommerce_customer_note_settings]heading');
182
 
183
  $subject = $this->wcml_get_email_string_info( '[woocommerce_customer_note_settings]subject' );
184
  if($subject)
185
+ $woocommerce->mailer()->emails['WC_Email_Customer_Note']->subject = apply_filters( 'wpml_translate_single_string', $subject[0]->value, $subject[0]->context,'[woocommerce_customer_note_settings]subject' );
186
 
187
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Note']->enabled;
188
  $woocommerce->mailer()->emails['WC_Email_Customer_Note']->enabled = false;
206
  $this->change_email_language($user_lang);
207
  $heading = $this->wcml_get_email_string_info( '[woocommerce_new_order_settings]heading' );
208
  if($heading)
209
+ $woocommerce->mailer()->emails['WC_Email_New_Order']->heading = apply_filters( 'wpml_translate_single_string', $heading[0]->value, $heading[0]->context,'[woocommerce_new_order_settings]heading' );
210
  $subject = $this->wcml_get_email_string_info( '[woocommerce_new_order_settings]subject' );
211
  if($subject)
212
+ $woocommerce->mailer()->emails['WC_Email_New_Order']->subject = apply_filters( 'wpml_translate_single_string', $subject[0]->value, $subject[0]->context,'[woocommerce_new_order_settings]subject' );
213
 
214
  $woocommerce->mailer()->emails['WC_Email_New_Order']->recipient = $recipient;
215
 
inc/endpoints.class.php CHANGED
@@ -8,14 +8,23 @@ class WCML_Endpoints{
8
 
9
  //endpoints hooks
10
  $this->register_endpoints_translations();
 
11
  add_action( 'icl_ajx_custom_call', array( $this, 'rewrite_rule_endpoints' ), 11, 2 );
12
  add_action( 'woocommerce_update_options', array( $this, 'update_endpoints_rules' ) );
13
  add_filter( 'pre_update_option_rewrite_rules', array( $this, 'update_rewrite_rules' ), 100, 2 );
14
 
15
  add_filter( 'page_link', array( $this, 'endpoint_permalink_filter' ), 10, 2 ); //after WPML
16
 
 
 
 
 
 
 
 
17
  }
18
 
 
19
  function register_endpoints_translations(){
20
  if( !class_exists( 'woocommerce' ) || !defined( 'ICL_SITEPRESS_VERSION' ) || ICL_PLUGIN_INACTIVE || version_compare( WOOCOMMERCE_VERSION, '2.2', '<' ) ) return false;
21
 
@@ -24,16 +33,16 @@ class WCML_Endpoints{
24
  if ( !empty( $wc_vars ) ){
25
  $query_vars = array(
26
  // Checkout actions
27
- 'order-pay' => $this->get_endpoint_translation( $wc_vars['order-pay'] ),
28
- 'order-received' => $this->get_endpoint_translation( $wc_vars['order-received'] ),
29
 
30
  // My account actions
31
- 'view-order' => $this->get_endpoint_translation( $wc_vars['view-order'] ),
32
- 'edit-account' => $this->get_endpoint_translation( $wc_vars['edit-account'] ),
33
- 'edit-address' => $this->get_endpoint_translation( $wc_vars['edit-address'] ),
34
- 'lost-password' => $this->get_endpoint_translation( $wc_vars['lost-password'] ),
35
- 'customer-logout' => $this->get_endpoint_translation( $wc_vars['customer-logout'] ),
36
- 'add-payment-method' => $this->get_endpoint_translation( $wc_vars['add-payment-method'] ),
37
  );
38
 
39
  WC()->query->query_vars = $query_vars;
@@ -42,19 +51,19 @@ class WCML_Endpoints{
42
 
43
  }
44
 
45
- function get_endpoint_translation( $endpoint ){
46
  global $wpdb;
47
 
48
- $string = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'Endpoint slug: ' . $endpoint, $endpoint ) );
49
 
50
  if( !$string && function_exists( 'icl_register_string' ) ){
51
- do_action('wpml_register_single_string', 'WordPress', 'Endpoint slug: ' . $endpoint, $endpoint );
52
  }else{
53
  $this->endpoints_strings[] = $string;
54
  }
55
 
56
  if( function_exists('icl_t') ){
57
- return icl_t( 'WordPress', 'Endpoint slug: '. $endpoint, $endpoint );
58
  }else{
59
  return $endpoint;
60
  }
@@ -63,7 +72,14 @@ class WCML_Endpoints{
63
  function rewrite_rule_endpoints( $call, $data ){
64
  if( $call == 'icl_st_save_translation' && in_array( $data['icl_st_string_id'], $this->endpoints_strings ) ){
65
  $this->add_endpoints();
 
 
 
 
 
 
66
  flush_rewrite_rules();
 
67
  }
68
  }
69
 
@@ -85,7 +101,9 @@ class WCML_Endpoints{
85
  global $wpdb;
86
  //add endpoints and flush rules
87
  foreach( $this->endpoints_strings as $string_id ){
88
- $strings = $wpdb->get_results( $wpdb->prepare( "SELECT value FROM {$wpdb->prefix}icl_string_translations WHERE string_id = %s AND status = 1", $string_id ) );
 
 
89
  foreach( $strings as $string ){
90
  add_rewrite_endpoint( $string->value, EP_ROOT | EP_PAGES );
91
  }
@@ -112,7 +130,8 @@ class WCML_Endpoints{
112
  }else{
113
  $endpoint = get_option( 'woocommerce_myaccount_'.str_replace( '-','_',$key).'_endpoint' );
114
  }
115
- $p = $this->get_endpoint_url($this->get_endpoint_translation( $endpoint ),$wp->query_vars[ $key ],$p);
 
116
  }
117
  }
118
  }
@@ -121,7 +140,22 @@ class WCML_Endpoints{
121
  return $p;
122
  }
123
 
124
- function get_endpoint_url($endpoint, $value = '', $permalink = ''){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  if ( get_option( 'permalink_structure' ) ) {
126
  if ( strstr( $permalink, '?' ) ) {
127
  $query_string = '?' . parse_url( $permalink, PHP_URL_QUERY );
@@ -136,5 +170,76 @@ class WCML_Endpoints{
136
  return $url;
137
  }
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
  }
8
 
9
  //endpoints hooks
10
  $this->register_endpoints_translations();
11
+ $this->maybe_flush_rules();
12
  add_action( 'icl_ajx_custom_call', array( $this, 'rewrite_rule_endpoints' ), 11, 2 );
13
  add_action( 'woocommerce_update_options', array( $this, 'update_endpoints_rules' ) );
14
  add_filter( 'pre_update_option_rewrite_rules', array( $this, 'update_rewrite_rules' ), 100, 2 );
15
 
16
  add_filter( 'page_link', array( $this, 'endpoint_permalink_filter' ), 10, 2 ); //after WPML
17
 
18
+ if(!is_admin()){
19
+ add_filter('pre_get_posts', array($this, 'check_if_endpoint_exists'));
20
+ }
21
+
22
+ add_filter( 'woocommerce_get_endpoint_url', array( $this, 'filter_get_endpoint_url' ), 10, 4 );
23
+
24
+
25
  }
26
 
27
+
28
  function register_endpoints_translations(){
29
  if( !class_exists( 'woocommerce' ) || !defined( 'ICL_SITEPRESS_VERSION' ) || ICL_PLUGIN_INACTIVE || version_compare( WOOCOMMERCE_VERSION, '2.2', '<' ) ) return false;
30
 
33
  if ( !empty( $wc_vars ) ){
34
  $query_vars = array(
35
  // Checkout actions
36
+ 'order-pay' => $this->get_endpoint_translation( 'order-pay', $wc_vars['order-pay'] ),
37
+ 'order-received' => $this->get_endpoint_translation( 'order-received', $wc_vars['order-received'] ),
38
 
39
  // My account actions
40
+ 'view-order' => $this->get_endpoint_translation( 'view-order', $wc_vars['view-order'] ),
41
+ 'edit-account' => $this->get_endpoint_translation( 'edit-account', $wc_vars['edit-account'] ),
42
+ 'edit-address' => $this->get_endpoint_translation( 'edit-address', $wc_vars['edit-address'] ),
43
+ 'lost-password' => $this->get_endpoint_translation( 'lost-password', $wc_vars['lost-password'] ),
44
+ 'customer-logout' => $this->get_endpoint_translation( 'customer-logout', $wc_vars['customer-logout'] ),
45
+ 'add-payment-method' => $this->get_endpoint_translation( 'add-payment-method', $wc_vars['add-payment-method'] ),
46
  );
47
 
48
  WC()->query->query_vars = $query_vars;
51
 
52
  }
53
 
54
+ function get_endpoint_translation( $key, $endpoint, $language = null ){
55
  global $wpdb;
56
 
57
+ $string = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'Endpoint slug: ' . $key, $endpoint ) );
58
 
59
  if( !$string && function_exists( 'icl_register_string' ) ){
60
+ do_action('wpml_register_single_string', 'WordPress', 'Endpoint slug: ' . $key, $endpoint );
61
  }else{
62
  $this->endpoints_strings[] = $string;
63
  }
64
 
65
  if( function_exists('icl_t') ){
66
+ return apply_filters( 'wpml_translate_single_string', $endpoint, 'WordPress', 'Endpoint slug: '. $key, $language );
67
  }else{
68
  return $endpoint;
69
  }
72
  function rewrite_rule_endpoints( $call, $data ){
73
  if( $call == 'icl_st_save_translation' && in_array( $data['icl_st_string_id'], $this->endpoints_strings ) ){
74
  $this->add_endpoints();
75
+ add_option( 'flush_rules_for_endpoints_translations', true );
76
+ }
77
+ }
78
+
79
+ function maybe_flush_rules(){
80
+ if( get_option( 'flush_rules_for_endpoints_translations' ) ){
81
  flush_rewrite_rules();
82
+ delete_option( 'flush_rules_for_endpoints_translations' );
83
  }
84
  }
85
 
101
  global $wpdb;
102
  //add endpoints and flush rules
103
  foreach( $this->endpoints_strings as $string_id ){
104
+
105
+ $strings = $wpdb->get_results( $wpdb->prepare( "SELECT value FROM {$wpdb->prefix}icl_string_translations WHERE string_id = %s AND status = %s", $string_id , ICL_STRING_TRANSLATION_COMPLETE) );
106
+
107
  foreach( $strings as $string ){
108
  add_rewrite_endpoint( $string->value, EP_ROOT | EP_PAGES );
109
  }
130
  }else{
131
  $endpoint = get_option( 'woocommerce_myaccount_'.str_replace( '-','_',$key).'_endpoint' );
132
  }
133
+
134
+ $p = $this->get_endpoint_url( $this->get_endpoint_translation( $key, $endpoint, $current_lang ), $wp->query_vars[ $key ], $p, $page_lang );
135
  }
136
  }
137
  }
140
  return $p;
141
  }
142
 
143
+ function get_endpoint_url($endpoint, $value = '', $permalink = '', $page_lang = false ){
144
+ global $sitepress;
145
+
146
+ if( $page_lang ){
147
+ $edit_address_shipping = $this->get_translated_edit_address_slug( 'shipping', $page_lang );
148
+ $edit_address_billing = $this->get_translated_edit_address_slug( 'billing', $page_lang );
149
+
150
+ if( $edit_address_shipping == urldecode( $value ) ){
151
+ $value = $this->get_translated_edit_address_slug( 'shipping', $sitepress->get_current_language() );
152
+ }elseif( $edit_address_billing == urldecode( $value ) ){
153
+ $value = $this->get_translated_edit_address_slug( 'billing', $sitepress->get_current_language() );
154
+ }
155
+
156
+ }
157
+
158
+
159
  if ( get_option( 'permalink_structure' ) ) {
160
  if ( strstr( $permalink, '?' ) ) {
161
  $query_string = '?' . parse_url( $permalink, PHP_URL_QUERY );
170
  return $url;
171
  }
172
 
173
+ /*
174
+ * We need check special case - when you manually put in URL default not translated endpoint it not generated 404 error
175
+ */
176
+ function check_if_endpoint_exists($q){
177
+ global $wp_query;
178
+
179
+ $my_account_id = wc_get_page_id('myaccount');
180
+
181
+ $current_id = $q->query_vars['page_id'];
182
+ if(!$current_id){
183
+ $current_id = $q->queried_object_id;
184
+ }
185
+
186
+ if( !$q->is_404 && $current_id == $my_account_id ){
187
+
188
+ $uri_vars = array_filter( explode( '/', $_SERVER['REQUEST_URI']) );
189
+ $endpoints = WC()->query->get_query_vars();
190
+ $endpoint_in_url = urldecode( end( $uri_vars ) );
191
+
192
+ $endpoints['shipping'] = urldecode( $this->get_translated_edit_address_slug( 'shipping' ) );
193
+ $endpoints['billing'] = urldecode( $this->get_translated_edit_address_slug( 'billing' ) );
194
+
195
+ if( urldecode( $q->query['pagename'] ) != $endpoint_in_url && !in_array( $endpoint_in_url,$endpoints ) && is_numeric( $endpoint_in_url ) && !in_array( urldecode( prev( $uri_vars ) ) ,$endpoints ) ){
196
+ $wp_query->set_404();
197
+ status_header(404);
198
+ include( get_query_template( '404' ) );
199
+ die();
200
+ }
201
+
202
+ }
203
+
204
+ }
205
+
206
+ function get_translated_edit_address_slug( $slug, $language = false ){
207
+ global $woocommerce_wpml;
208
+
209
+ $strings_language = $woocommerce_wpml->strings->get_wc_context_language();
210
+
211
+ if( $strings_language == $language ){
212
+ return $slug;
213
+ }
214
+
215
+ $translated_slug = apply_filters( 'wpml_translate_single_string', $slug, 'woocommerce', 'edit-address-slug: '.$slug, $language );
216
+
217
+ if( $translated_slug == $slug ){
218
+
219
+ if( $language ){
220
+ $translated_slug = $woocommerce_wpml->terms->get_translation_from_woocommerce_mo_file( 'edit-address-slug'. chr(4) .$slug, $language );
221
+ }else{
222
+ $translated_slug = _x( $slug, 'edit-address-slug', 'woocommerce' );
223
+ }
224
+
225
+ }
226
+
227
+ return $translated_slug;
228
+ }
229
+
230
+ function filter_get_endpoint_url( $url, $endpoint, $value, $permalink ){
231
+
232
+ // return translated edit account slugs
233
+ if( isset( WC()->query->query_vars[ 'edit-address' ] ) && isset( WC()->query->query_vars[ 'edit-address' ] ) == $endpoint && in_array( $value, array('shipping','billing'))){
234
+ remove_filter('woocommerce_get_endpoint_url', array( $this, 'filter_get_endpoint_url'),10,4);
235
+ $url = wc_get_endpoint_url( 'edit-address', $this->get_translated_edit_address_slug( $value ) );
236
+ add_filter('woocommerce_get_endpoint_url', array( $this, 'filter_get_endpoint_url'),10,4);
237
+
238
+
239
+ }
240
+
241
+ return $url;
242
+ }
243
+
244
 
245
  }
inc/missing-php-functions.php CHANGED
@@ -62,5 +62,11 @@ function wcml_check_wpml_functions(){
62
  }
63
  }
64
 
 
 
 
 
 
 
65
  }
66
  ?>
62
  }
63
  }
64
 
65
+ if( !has_filter( 'wpml_translate_single_string' ) ){
66
+ if( function_exists( 'icl_t' ) ){
67
+ add_filter( 'wpml_translate_single_string', 'icl_t', 10, 6 );
68
+ }
69
+ }
70
+
71
  }
72
  ?>
inc/multi-currency-support.class.php CHANGED
@@ -1031,7 +1031,7 @@ class WCML_Multi_Currency_Support{
1031
  }
1032
 
1033
  }
1034
-
1035
  return $methods;
1036
  }
1037
 
@@ -1057,7 +1057,7 @@ class WCML_Multi_Currency_Support{
1057
 
1058
  return $settings;
1059
  }
1060
-
1061
  function adjust_min_amount_required($options){
1062
 
1063
  if(!empty($options['min_amount'])){
@@ -1150,6 +1150,15 @@ class WCML_Multi_Currency_Support{
1150
 
1151
  return apply_filters('wcml_client_currency', $this->client_currency);
1152
  }
 
 
 
 
 
 
 
 
 
1153
 
1154
  function set_client_currency($currency){
1155
 
@@ -1232,14 +1241,6 @@ class WCML_Multi_Currency_Support{
1232
  return $args;
1233
  }
1234
 
1235
- function get_exchange_rates(){
1236
-
1237
- $exchange_rates = apply_filters('wcml_exchange_rates', $this->exchange_rates);
1238
-
1239
- return $exchange_rates;
1240
-
1241
- }
1242
-
1243
  function legacy_update_custom_rates(){
1244
 
1245
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
1031
  }
1032
 
1033
  }
1034
+
1035
  return $methods;
1036
  }
1037
 
1057
 
1058
  return $settings;
1059
  }
1060
+
1061
  function adjust_min_amount_required($options){
1062
 
1063
  if(!empty($options['min_amount'])){
1150
 
1151
  return apply_filters('wcml_client_currency', $this->client_currency);
1152
  }
1153
+
1154
+ function get_currency_details_by_code( $code ){
1155
+
1156
+ if( isset( $this->currencies[ $code ] ) ){
1157
+ return $this->currencies[ $code ] ;
1158
+ }
1159
+
1160
+ return false;
1161
+ }
1162
 
1163
  function set_client_currency($currency){
1164
 
1241
  return $args;
1242
  }
1243
 
 
 
 
 
 
 
 
 
1244
  function legacy_update_custom_rates(){
1245
 
1246
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
inc/multi-currency.class.php CHANGED
@@ -29,8 +29,6 @@ class WCML_WC_MultiCurrency{
29
  add_filter('wcml_shipping_price_amount', array($this, 'shipping_price_filter'));
30
  add_filter('wcml_shipping_free_min_amount', array($this, 'shipping_free_min_amount'));
31
  add_action('woocommerce_product_meta_start', array($this, 'currency_switcher'));
32
-
33
- add_filter('wcml_exchange_rates', array($this, 'get_exchange_rates'));
34
 
35
  add_filter('wcml_get_client_currency', array($this, 'get_client_currency'));
36
 
@@ -190,7 +188,7 @@ class WCML_WC_MultiCurrency{
190
  function shipping_price_filter($price) {
191
 
192
  $price = $this->convert_price_amount($price, $this->get_client_currency());
193
-
194
  return $price;
195
 
196
  }
@@ -203,8 +201,9 @@ class WCML_WC_MultiCurrency{
203
 
204
  }
205
 
206
- function convert_price_amount($amount, $currency = false, $decimals_num = 0, $decimal_sep = '.', $thousand_sep = ',' ){
207
-
 
208
  if(empty($currency)){
209
  $currency = $this->get_client_currency();
210
  }
@@ -233,17 +232,30 @@ class WCML_WC_MultiCurrency{
233
  $amount = 0;
234
  }
235
 
236
- if( $decimals_num ){
237
- $amount = number_format( (float)$amount, $decimals_num, $decimal_sep, $thousand_sep );
 
 
 
 
 
 
238
  }
239
 
 
 
 
 
 
 
240
  return $amount;
241
 
242
  }
243
 
244
  // convert back to default currency
245
- function unconvert_price_amount($amount, $currency = false, $decimals_num = 0, $decimal_sep = '.', $thousand_sep = ','){
246
-
 
247
  if(empty($currency)){
248
  $currency = $this->get_client_currency();
249
  }
@@ -276,10 +288,22 @@ class WCML_WC_MultiCurrency{
276
 
277
  }
278
 
279
- if( $decimals_num ){
280
- $amount = number_format( (float)$amount, $decimals_num, $decimal_sep, $thousand_sep );
 
 
 
 
 
 
281
  }
282
 
 
 
 
 
 
 
283
  return $amount;
284
 
285
  }
@@ -309,8 +333,8 @@ class WCML_WC_MultiCurrency{
309
  }
310
  }
311
  }
312
-
313
- return $this->exchange_rates;
314
  }
315
 
316
  function currency_switcher(){
29
  add_filter('wcml_shipping_price_amount', array($this, 'shipping_price_filter'));
30
  add_filter('wcml_shipping_free_min_amount', array($this, 'shipping_free_min_amount'));
31
  add_action('woocommerce_product_meta_start', array($this, 'currency_switcher'));
 
 
32
 
33
  add_filter('wcml_get_client_currency', array($this, 'get_client_currency'));
34
 
188
  function shipping_price_filter($price) {
189
 
190
  $price = $this->convert_price_amount($price, $this->get_client_currency());
191
+
192
  return $price;
193
 
194
  }
201
 
202
  }
203
 
204
+ function convert_price_amount($amount, $currency = false, $decimals_num = false, $decimal_sep = false, $thousand_sep = false ){
205
+ global $woocommerce_wpml;
206
+
207
  if(empty($currency)){
208
  $currency = $this->get_client_currency();
209
  }
232
  $amount = 0;
233
  }
234
 
235
+ $currency_details = $woocommerce_wpml->multi_currency_support->get_currency_details_by_code( $currency );
236
+
237
+ if( is_bool( $decimals_num ) ){
238
+ $decimals_num = $currency_details['num_decimals'];
239
+ }
240
+
241
+ if( !$decimal_sep ){
242
+ $decimal_sep = $currency_details['decimal_sep'];
243
  }
244
 
245
+ if( !$thousand_sep ){
246
+ $thousand_sep = $currency_details['thousand_sep'];
247
+ }
248
+
249
+ $amount = number_format( (float)$amount, $decimals_num, $decimal_sep, $thousand_sep );
250
+
251
  return $amount;
252
 
253
  }
254
 
255
  // convert back to default currency
256
+ function unconvert_price_amount($amount, $currency = false, $decimals_num = false, $decimal_sep = false, $thousand_sep = false){
257
+ global $woocommerce_wpml;
258
+
259
  if(empty($currency)){
260
  $currency = $this->get_client_currency();
261
  }
288
 
289
  }
290
 
291
+ $currency_details = $woocommerce_wpml->multi_currency_support->get_currency_details_by_code( $currency );
292
+
293
+ if( is_bool( $decimals_num ) ){
294
+ $decimals_num = $currency_details['num_decimals'];
295
+ }
296
+
297
+ if( !$decimal_sep ){
298
+ $decimal_sep = $currency_details['decimal_sep'];
299
  }
300
 
301
+ if( !$thousand_sep ){
302
+ $thousand_sep = $currency_details['thousand_sep'];
303
+ }
304
+
305
+ $amount = number_format( (float)$amount, $decimals_num, $decimal_sep, $thousand_sep );
306
+
307
  return $amount;
308
 
309
  }
333
  }
334
  }
335
  }
336
+
337
+ return apply_filters('wcml_exchange_rates', $this->exchange_rates);
338
  }
339
 
340
  function currency_switcher(){
inc/products.class.php CHANGED
@@ -56,7 +56,6 @@ class WCML_Products{
56
  add_filter( 'loop_shop_post_in', array( $this, 'filter_products_with_custom_prices' ), 100 );
57
  add_filter( 'woocommerce_related_products_args', array( $this, 'filter_related_products_args' ) );
58
  }
59
- add_filter( 'woocommerce_restore_order_stock_quantity', array( $this, 'woocommerce_restore_order_stock_quantity' ), 10, 2 );
60
 
61
  add_action( 'woocommerce_email', array( $this, 'woocommerce_email_refresh_text_domain' ) );
62
  add_action( 'wp_ajax_woocommerce_update_shipping_method', array( $this, 'wcml_refresh_text_domain' ), 9 );
@@ -67,7 +66,8 @@ class WCML_Products{
67
 
68
  add_filter( 'icl_post_alternative_languages', array( $this, 'hide_post_translation_links' ) );
69
 
70
- add_action( 'woocommerce_reduce_order_stock', array( $this, 'sync_product_stocks' ) );
 
71
 
72
  add_filter( 'wcml_custom_box_html', array( $this, 'downloadable_files_box' ), 10, 3 );
73
 
@@ -538,37 +538,11 @@ class WCML_Products{
538
 
539
  }
540
 
541
- do_action('wcml_update_extra_fields',$tr_product_id,$data,$language);
542
 
543
- //get "_product_attributes" from original product
544
- $orig_product_attrs = $this->get_product_atributes($original_product_id);
545
- $trnsl_labels = get_post_meta( $tr_product_id, 'attr_label_translations', true );
546
- foreach ($orig_product_attrs as $key => $orig_product_attr) {
547
- $sanitized_key = sanitize_title( $orig_product_attr['name'] );
548
-
549
- if( $sanitized_key != $key ) {
550
- $orig_product_attrs_buff = $orig_product_attrs[$key];
551
- unset($orig_product_attrs[$key]);
552
- $orig_product_attrs[$sanitized_key] = $orig_product_attrs_buff;
553
- $key_to_save = $sanitized_key;
554
- }else{
555
- $key_to_save = $key;
556
- }
557
 
558
- if (isset($data[$key . '_' . $language]) && !empty($data[$key . '_' . $language]) && !is_array($data[$key . '_' . $language])) {
559
- //get translation values from $data
560
-
561
- $trnsl_labels[$language][$key_to_save] = stripslashes( $data[$key . '_name_' . $language] );
562
- $orig_product_attrs[$key_to_save]['value'] = $data[$key . '_' . $language];
563
- } else {
564
- $orig_product_attrs[$key_to_save]['value'] = '';
565
- }
566
-
567
- }
568
- update_post_meta( $tr_product_id, 'attr_label_translations', $trnsl_labels );
569
-
570
- //update "_product_attributes"
571
- update_post_meta($tr_product_id, '_product_attributes', $orig_product_attrs);
572
 
573
  $this->sync_default_product_attr($original_product_id, $tr_product_id, $language);
574
 
@@ -646,35 +620,73 @@ class WCML_Products{
646
  die();
647
  }
648
 
649
- function sync_product_data($original_product_id,$tr_product_id,$lang){
650
 
651
- $this->duplicate_product_post_meta($original_product_id,$tr_product_id);
 
 
 
652
 
653
- //duplicate product attrs
654
- $orig_product_attrs = $this->get_product_atributes($original_product_id);
655
- update_post_meta($tr_product_id,'_product_attributes',$orig_product_attrs);
656
 
657
- $this->sync_default_product_attr($original_product_id, $tr_product_id, $lang);
 
 
 
 
 
 
 
658
 
659
- $wpml_media_options = maybe_unserialize(get_option('_wpml_media'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
660
  //sync media
661
- if($wpml_media_options['new_content_settings']['duplicate_featured']){
662
  //sync feature image
663
- $this->sync_thumbnail_id($original_product_id, $tr_product_id,$lang);
664
  }
665
 
666
- if($wpml_media_options['new_content_settings']['duplicate_media']){
667
  //sync product gallery
668
- $this->sync_product_gallery($original_product_id);
669
  }
670
 
671
  //sync taxonomies
672
- $this->sync_product_taxonomies($original_product_id,$tr_product_id,$lang);
673
 
674
  //duplicate variations
675
- $this->sync_product_variations($original_product_id,$tr_product_id,$lang);
676
 
677
- $this->sync_linked_products($original_product_id,$tr_product_id,$lang);
678
  }
679
 
680
 
@@ -1139,8 +1151,11 @@ class WCML_Products{
1139
  if (taxonomy_exists($tax)) {
1140
 
1141
  $attid = $this->wcml_get_term_id_by_slug( $tax, $meta_value );
 
1142
  if($attid){
1143
- $trid = $sitepress->get_element_trid($attid, 'tax_' . $tax);
 
 
1144
  if ($trid) {
1145
  $translations = $sitepress->get_element_translations($trid,'tax_' . $tax);
1146
  if (isset($translations[$lang])) {
@@ -1161,7 +1176,7 @@ class WCML_Products{
1161
  $values_arrs_tr = array_map('trim',explode('|',$tr_product_attr[$tax]['value']));
1162
  foreach($values_arrs as $key=>$value){
1163
  $value_sanitized = sanitize_title($value);
1164
- if($value_sanitized == urldecode($meta_value) && isset($values_arrs_tr[$key])){
1165
  $meta_value = $values_arrs_tr[$key];
1166
  }
1167
  }
@@ -1424,15 +1439,15 @@ class WCML_Products{
1424
  return $output;
1425
  }
1426
 
1427
- function sync_product_stocks($order) {
1428
- return $this->sync_product_stocks20($order);
1429
  }
1430
 
1431
- /*
1432
- Only when translated products are ordered, force adjusting stock information for all translations
1433
- When a product in the default language is ordered stocks are adjusted automatically
1434
- */
1435
- function sync_product_stocks20($order){
1436
  global $sitepress;
1437
  $order_id = $order->id;
1438
 
@@ -1459,9 +1474,16 @@ class WCML_Products{
1459
  $_product = wc_get_product($translation->element_id);
1460
 
1461
  if ( $_product && $_product->exists() && $_product->managing_stock() ) {
1462
- $stock = $_product->reduce_stock($item['qty']);
1463
  $total_sales = get_post_meta($_product->id, 'total_sales', true);
1464
- $total_sales += $item['qty'];
 
 
 
 
 
 
 
1465
  update_post_meta($translation->element_id, 'total_sales', $total_sales);
1466
  }
1467
  }
@@ -1482,56 +1504,56 @@ class WCML_Products{
1482
  /**
1483
  * This function takes care of synchronizing original product
1484
  */
1485
- function sync_post_action($post_id, $post){
1486
  global $pagenow, $sitepress, $sitepress_settings,$woocommerce_wpml;
1487
- $original_language = $this->get_original_product_language($post_id);
1488
  $current_language = $sitepress->get_current_language();
1489
- $duplicated_post_id = apply_filters( 'translate_object_id',$post_id, 'product', false, $original_language);
1490
- $wpml_media_options = maybe_unserialize(get_option('_wpml_media'));
1491
 
1492
- if($wpml_media_options['new_content_settings']['duplicate_media']){
1493
  //sync product gallery
1494
- $this->sync_product_gallery($duplicated_post_id);
1495
  }
1496
 
1497
  // check its a product
1498
- $post_type = get_post_type($post_id);
1499
 
1500
  //set trid for variations
1501
- if ($post_type == 'product_variation') {
1502
- $var_lang = $sitepress->get_language_for_element( wp_get_post_parent_id($post_id), 'post_product' );
1503
  if( $this->is_original_product( wp_get_post_parent_id( $post_id ) ) ){
1504
- $sitepress->set_element_language_details($post_id, 'post_product_variation', false, $var_lang);
1505
  }
1506
  }
1507
 
1508
- if ($post_type != 'product') {
1509
  return;
1510
  }
1511
 
1512
  // exceptions
1513
- $ajax_call = (!empty($_POST['icl_ajx_action']) && $_POST['icl_ajx_action'] == 'make_duplicates');
1514
- if (empty($duplicated_post_id) || isset($_POST['autosave'])) {
1515
  return;
1516
  }
1517
 
1518
- if($pagenow != 'post.php' && $pagenow != 'post-new.php' && $pagenow != 'admin.php' && !$ajax_call){
1519
  return;
1520
  }
1521
- if (isset($_GET['action']) && $_GET['action'] == 'trash') {
1522
  return;
1523
  }
1524
 
1525
  // If we reach this point, we go ahead with sync.
1526
  // Remove filter to avoid double sync
1527
- remove_action('save_post', array($this, 'sync_post_action'), 11, 2);
1528
 
1529
  do_action( 'wcml_before_sync_product', $duplicated_post_id, $post_id );
1530
 
1531
  //trnsl_interface option
1532
  if (!$woocommerce_wpml->settings['trnsl_interface'] && $original_language != $current_language ) {
1533
 
1534
- if( !isset( $_POST['wp-preview'] ) || empty( $_POST['wp-preview'] ) ){
1535
  $this->sync_status_and_parent( $duplicated_post_id, $post_id, $current_language );
1536
  $this->sync_product_data( $duplicated_post_id, $post_id, $current_language );
1537
  }
@@ -1540,92 +1562,84 @@ class WCML_Products{
1540
  }
1541
 
1542
  // get language code
1543
- $language_details = $sitepress->get_element_language_details($post_id, 'post_product');
1544
- if ($pagenow == 'admin.php' && empty($language_details)) {
1545
  //translation editor support: sidestep icl_translations_cache
1546
  global $wpdb;
1547
  $language_details = $wpdb->get_row( $wpdb->prepare( "SELECT element_id, trid, language_code, source_language_code FROM {$wpdb->prefix}icl_translations WHERE element_id = %d AND element_type = 'post_product'", $post_id ) );
1548
  }
1549
- if (empty($language_details)) {
1550
  return;
1551
  }
1552
 
1553
  //save custom prices
1554
  $nonce = filter_input( INPUT_POST, '_wcml_custom_prices_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
1555
 
1556
- if( isset( $_POST['_wcml_custom_prices'] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_prices' )){
1557
 
1558
- if( isset( $_POST['_wcml_custom_prices'][$post_id] ) ) {
1559
- $wcml_custom_prices_option = $_POST['_wcml_custom_prices'][$post_id];
1560
  }else{
1561
- $wcml_custom_prices_option = $_POST['_wcml_custom_prices'][0];
1562
  }
1563
 
1564
- update_post_meta($post_id,'_wcml_custom_prices_status',$wcml_custom_prices_option);
1565
 
1566
  if( $wcml_custom_prices_option == 1){
1567
 
1568
  $currencies = $woocommerce_wpml->multi_currency_support->get_currencies();
1569
 
1570
  foreach( $currencies as $code => $currency ){
1571
- $sale_price = $_POST['_custom_sale_price'][$code];
1572
- $regular_price = $_POST['_custom_regular_price'][$code];
1573
 
1574
- $date_from = strtotime($_POST['_custom_sale_price_dates_from'][$code]);
1575
- $date_to = strtotime($_POST['_custom_sale_price_dates_to'][$code]);
1576
- $schedule = $_POST['_wcml_schedule'][$code];
1577
 
1578
- $pr_price = $this->update_custom_prices($post_id,$regular_price,$sale_price,$schedule,$date_from,$date_to,$code);
1579
  }
1580
  }
1581
  }
1582
 
1583
  // pick posts to sync
1584
  $posts = array();
1585
- $translations = $sitepress->get_element_translations($language_details->trid, 'post_product');
1586
- foreach ($translations as $translation) {
1587
- if ($translation->original) {
1588
  $duplicated_post_id = $translation->element_id;
1589
  } else {
1590
- $posts[$translation->element_id] = $translation;
1591
  }
1592
  }
1593
 
1594
 
1595
- foreach ($posts as $post_id => $translation) {
1596
  $lang = $translation->language_code;
1597
 
 
1598
  // Filter upsell products, crosell products and default attributes for translations
1599
- $this->duplicate_product_post_meta($duplicated_post_id,$post_id);
1600
 
1601
- if($wpml_media_options['new_content_settings']['duplicate_featured']){
1602
  //sync feature image
1603
- $this->sync_thumbnail_id($duplicated_post_id,$post_id, $lang);
1604
  }
1605
 
1606
  $this->sync_status_and_parent( $duplicated_post_id, $post_id, $lang );
1607
 
1608
- $this->sync_product_taxonomies($duplicated_post_id,$post_id,$lang);
1609
 
1610
- $this->sync_default_product_attr($duplicated_post_id,$post_id,$lang);
1611
 
1612
- //get "_product_attributes" from original product
1613
- $orig_product_attrs = $this->get_product_atributes($duplicated_post_id);
1614
- $trnsl_product_attrs = $this->get_product_atributes($post_id);
1615
- foreach ($orig_product_attrs as $key => $orig_product_attr) {
1616
- if(!$orig_product_attr['is_taxonomy']){
1617
- $orig_product_attrs[$key]['value'] = $trnsl_product_attrs[$key]['value'];
1618
- }
1619
- }
1620
-
1621
- update_post_meta($post_id, '_product_attributes', $orig_product_attrs);
1622
 
1623
  // synchronize post variations
1624
- $this->sync_product_variations($duplicated_post_id,$post_id,$lang);
1625
- $this->sync_linked_products($duplicated_post_id,$post_id,$lang);
1626
  }
1627
 
1628
- $this->sync_product_variations_custom_prices($duplicated_post_id);
1629
  }
1630
 
1631
  //sync product parent & post_status
@@ -2397,6 +2411,11 @@ class WCML_Products{
2397
  }
2398
 
2399
  function translate_cart_subtotal($cart) {
 
 
 
 
 
2400
  $cart->calculate_totals();
2401
  }
2402
 
@@ -2575,6 +2594,8 @@ class WCML_Products{
2575
 
2576
  foreach( $cart_contents as $key => $cart_content ){
2577
 
 
 
2578
  if( apply_filters( 'wcml_exception_duplicate_products_in_cart', false, $cart_content ) ){
2579
  continue;
2580
  }
@@ -2583,6 +2604,9 @@ class WCML_Products{
2583
  $search_key = $cart_content[ 'product_id' ];
2584
  }else{
2585
  $search_key = $cart_content[ 'product_id' ].'_'.$cart_content['variation_id'];
 
 
 
2586
  }
2587
 
2588
  if( array_key_exists( $search_key, $exists_products ) ){
@@ -2842,27 +2866,6 @@ class WCML_Products{
2842
 
2843
  }
2844
 
2845
- function woocommerce_restore_order_stock_quantity($stock_change,$item_id){
2846
- global $sitepress;
2847
-
2848
- $order_id = absint( filter_input( INPUT_POST, 'order_id', FILTER_SANITIZE_NUMBER_INT ) );
2849
- $order = new WC_Order( $order_id );
2850
- $order_items = $order->get_items();
2851
- $_product = $order->get_product_from_item( $order_items[$item_id] );
2852
- $language_details = $sitepress->get_element_language_details($_product->post->ID, 'post_'.$_product->post->post_type);
2853
- $translations = $sitepress->get_element_translations($language_details->trid, 'post_'.$_product->post->post_type);
2854
-
2855
- foreach ($translations as $translation) {
2856
- if($translation->element_id != $_product->post->ID){
2857
- $prod = get_product($translation->element_id);
2858
- $prod->increase_stock( $stock_change );
2859
- }
2860
- }
2861
-
2862
- return $stock_change;
2863
- }
2864
-
2865
-
2866
  function woocommerce_product_quick_edit_save($product){
2867
  global $sitepress;
2868
  $is_original = $this->is_original_product($product->id);
56
  add_filter( 'loop_shop_post_in', array( $this, 'filter_products_with_custom_prices' ), 100 );
57
  add_filter( 'woocommerce_related_products_args', array( $this, 'filter_related_products_args' ) );
58
  }
 
59
 
60
  add_action( 'woocommerce_email', array( $this, 'woocommerce_email_refresh_text_domain' ) );
61
  add_action( 'wp_ajax_woocommerce_update_shipping_method', array( $this, 'wcml_refresh_text_domain' ), 9 );
66
 
67
  add_filter( 'icl_post_alternative_languages', array( $this, 'hide_post_translation_links' ) );
68
 
69
+ add_action( 'woocommerce_reduce_order_stock', array( $this, 'sync_product_stocks_reduce' ) );
70
+ add_action( 'woocommerce_restore_order_stock', array( $this, 'sync_product_stocks_restore' ) );
71
 
72
  add_filter( 'wcml_custom_box_html', array( $this, 'downloadable_files_box' ), 10, 3 );
73
 
538
 
539
  }
540
 
541
+ do_action( 'wcml_update_extra_fields', $tr_product_id, $data, $language );
542
 
543
+ do_action( 'wcml_before_sync_product_data', $original_product_id, $tr_product_id, $language );
 
 
 
 
 
 
 
 
 
 
 
 
 
544
 
545
+ $this->sync_product_attr( $original_product_id, $tr_product_id, $language, $data );
 
 
 
 
 
 
 
 
 
 
 
 
 
546
 
547
  $this->sync_default_product_attr($original_product_id, $tr_product_id, $language);
548
 
620
  die();
621
  }
622
 
623
+ function sync_product_attr( $original_product_id, $tr_product_id, $language = false, $data = false ){
624
 
625
+ //get "_product_attributes" from original product
626
+ $orig_product_attrs = $this->get_product_atributes( $original_product_id );
627
+ $trnsl_product_attrs = $this->get_product_atributes( $tr_product_id );
628
+ $trnsl_labels = get_post_meta( $tr_product_id, 'attr_label_translations', true );
629
 
630
+ foreach ( $orig_product_attrs as $key => $orig_product_attr ) {
631
+ $sanitized_key = sanitize_title( $orig_product_attr['name'] );
 
632
 
633
+ if( $sanitized_key != $key ) {
634
+ $orig_product_attrs_buff = $orig_product_attrs[ $key ];
635
+ unset( $orig_product_attrs[ $key ] );
636
+ $orig_product_attrs[$sanitized_key] = $orig_product_attrs_buff;
637
+ $key_to_save = $sanitized_key;
638
+ }else{
639
+ $key_to_save = $key;
640
+ }
641
 
642
+ if ( $data ){
643
+ if ( isset( $data[ $key . '_' . $language ] ) && !empty( $data[ $key . '_' . $language ] ) && !is_array( $data[ $key . '_' . $language ] ) ) {
644
+ //get translation values from $data
645
+ $trnsl_labels[ $language ][ $key_to_save ] = stripslashes( $data[ $key . '_name_' . $language ] );
646
+ $orig_product_attrs[ $key_to_save ][ 'value' ] = $data[ $key . '_' . $language ];
647
+ } else {
648
+ $orig_product_attrs[ $key_to_save ][ 'value' ] = '';
649
+ }
650
+ }elseif( !$orig_product_attr[ 'is_taxonomy' ] ){
651
+ $orig_product_attrs[ $key_to_save ][ 'value' ] = $trnsl_product_attrs[ $key ][ 'value' ];
652
+ }
653
+
654
+ }
655
+
656
+ update_post_meta( $tr_product_id, 'attr_label_translations', $trnsl_labels );
657
+
658
+ //update "_product_attributes"
659
+ update_post_meta( $tr_product_id, '_product_attributes', $orig_product_attrs );
660
+
661
+ }
662
+
663
+ function sync_product_data( $original_product_id, $tr_product_id, $lang ){
664
+
665
+ $this->duplicate_product_post_meta( $original_product_id, $tr_product_id );
666
+
667
+ $this->sync_product_attr( $original_product_id, $tr_product_id );
668
+
669
+ $this->sync_default_product_attr( $original_product_id, $tr_product_id, $lang );
670
+
671
+ $wpml_media_options = maybe_unserialize( get_option( '_wpml_media' ) );
672
  //sync media
673
+ if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_featured' ] ){
674
  //sync feature image
675
+ $this->sync_thumbnail_id( $original_product_id, $tr_product_id, $lang );
676
  }
677
 
678
+ if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_media' ]){
679
  //sync product gallery
680
+ $this->sync_product_gallery( $original_product_id );
681
  }
682
 
683
  //sync taxonomies
684
+ $this->sync_product_taxonomies( $original_product_id, $tr_product_id, $lang );
685
 
686
  //duplicate variations
687
+ $this->sync_product_variations( $original_product_id, $tr_product_id, $lang );
688
 
689
+ $this->sync_linked_products( $original_product_id, $tr_product_id, $lang );
690
  }
691
 
692
 
1151
  if (taxonomy_exists($tax)) {
1152
 
1153
  $attid = $this->wcml_get_term_id_by_slug( $tax, $meta_value );
1154
+
1155
  if($attid){
1156
+
1157
+ $term_obj = $this->wcml_get_term_by_id( $attid, $tax );
1158
+ $trid = $sitepress->get_element_trid( $term_obj->term_taxonomy_id, 'tax_' . $tax );
1159
  if ($trid) {
1160
  $translations = $sitepress->get_element_translations($trid,'tax_' . $tax);
1161
  if (isset($translations[$lang])) {
1176
  $values_arrs_tr = array_map('trim',explode('|',$tr_product_attr[$tax]['value']));
1177
  foreach($values_arrs as $key=>$value){
1178
  $value_sanitized = sanitize_title($value);
1179
+ if( ( $value_sanitized == urldecode($meta_value) || $value_sanitized == $meta_value ) && isset($values_arrs_tr[$key])){
1180
  $meta_value = $values_arrs_tr[$key];
1181
  }
1182
  }
1439
  return $output;
1440
  }
1441
 
1442
+ function sync_product_stocks_reduce( $order ){
1443
+ return $this->sync_product_stocks( $order, 'reduce' );
1444
  }
1445
 
1446
+ function sync_product_stocks_restore( $order ){
1447
+ return $this->sync_product_stocks( $order, 'restore' );
1448
+ }
1449
+
1450
+ function sync_product_stocks( $order, $action ){
1451
  global $sitepress;
1452
  $order_id = $order->id;
1453
 
1474
  $_product = wc_get_product($translation->element_id);
1475
 
1476
  if ( $_product && $_product->exists() && $_product->managing_stock() ) {
1477
+
1478
  $total_sales = get_post_meta($_product->id, 'total_sales', true);
1479
+
1480
+ if( $action == 'reduce'){
1481
+ $stock = $_product->reduce_stock($item['qty']);
1482
+ $total_sales += $item['qty'];
1483
+ }else{
1484
+ $stock = $_product->increase_stock( $item['qty'] );
1485
+ $total_sales -= $item['qty'];
1486
+ }
1487
  update_post_meta($translation->element_id, 'total_sales', $total_sales);
1488
  }
1489
  }
1504
  /**
1505
  * This function takes care of synchronizing original product
1506
  */
1507
+ function sync_post_action( $post_id, $post ){
1508
  global $pagenow, $sitepress, $sitepress_settings,$woocommerce_wpml;
1509
+ $original_language = $this->get_original_product_language( $post_id );
1510
  $current_language = $sitepress->get_current_language();
1511
+ $duplicated_post_id = apply_filters( 'translate_object_id', $post_id, 'product', false, $original_language );
1512
+ $wpml_media_options = maybe_unserialize( get_option( '_wpml_media' ) );
1513
 
1514
+ if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_media' ] ){
1515
  //sync product gallery
1516
+ $this->sync_product_gallery( $duplicated_post_id );
1517
  }
1518
 
1519
  // check its a product
1520
+ $post_type = get_post_type( $post_id );
1521
 
1522
  //set trid for variations
1523
+ if ( $post_type == 'product_variation' ) {
1524
+ $var_lang = $sitepress->get_language_for_element( wp_get_post_parent_id( $post_id ), 'post_product' );
1525
  if( $this->is_original_product( wp_get_post_parent_id( $post_id ) ) ){
1526
+ $sitepress->set_element_language_details( $post_id, 'post_product_variation', false, $var_lang );
1527
  }
1528
  }
1529
 
1530
+ if ( $post_type != 'product' ) {
1531
  return;
1532
  }
1533
 
1534
  // exceptions
1535
+ $ajax_call = ( !empty( $_POST[ 'icl_ajx_action' ] ) && $_POST[ 'icl_ajx_action' ] == 'make_duplicates' );
1536
+ if ( empty( $duplicated_post_id ) || isset( $_POST[ 'autosave' ] ) ) {
1537
  return;
1538
  }
1539
 
1540
+ if( $pagenow != 'post.php' && $pagenow != 'post-new.php' && $pagenow != 'admin.php' && !$ajax_call ){
1541
  return;
1542
  }
1543
+ if ( isset( $_GET[ 'action' ] ) && $_GET[ 'action' ] == 'trash') {
1544
  return;
1545
  }
1546
 
1547
  // If we reach this point, we go ahead with sync.
1548
  // Remove filter to avoid double sync
1549
+ remove_action( 'save_post', array( $this, 'sync_post_action' ), 11, 2 );
1550
 
1551
  do_action( 'wcml_before_sync_product', $duplicated_post_id, $post_id );
1552
 
1553
  //trnsl_interface option
1554
  if (!$woocommerce_wpml->settings['trnsl_interface'] && $original_language != $current_language ) {
1555
 
1556
+ if( !isset( $_POST[ 'wp-preview' ] ) || empty( $_POST[ 'wp-preview' ] ) ){
1557
  $this->sync_status_and_parent( $duplicated_post_id, $post_id, $current_language );
1558
  $this->sync_product_data( $duplicated_post_id, $post_id, $current_language );
1559
  }
1562
  }
1563
 
1564
  // get language code
1565
+ $language_details = $sitepress->get_element_language_details( $post_id, 'post_product' );
1566
+ if ( $pagenow == 'admin.php' && empty( $language_details ) ) {
1567
  //translation editor support: sidestep icl_translations_cache
1568
  global $wpdb;
1569
  $language_details = $wpdb->get_row( $wpdb->prepare( "SELECT element_id, trid, language_code, source_language_code FROM {$wpdb->prefix}icl_translations WHERE element_id = %d AND element_type = 'post_product'", $post_id ) );
1570
  }
1571
+ if ( empty( $language_details ) ) {
1572
  return;
1573
  }
1574
 
1575
  //save custom prices
1576
  $nonce = filter_input( INPUT_POST, '_wcml_custom_prices_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
1577
 
1578
+ if( isset( $_POST[ '_wcml_custom_prices' ] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_prices' )){
1579
 
1580
+ if( isset( $_POST[ '_wcml_custom_prices' ][ $post_id ] ) ) {
1581
+ $wcml_custom_prices_option = $_POST[ '_wcml_custom_prices' ][ $post_id ];
1582
  }else{
1583
+ $wcml_custom_prices_option = $_POST[ '_wcml_custom_prices' ][ 0 ];
1584
  }
1585
 
1586
+ update_post_meta( $post_id, '_wcml_custom_prices_status', $wcml_custom_prices_option );
1587
 
1588
  if( $wcml_custom_prices_option == 1){
1589
 
1590
  $currencies = $woocommerce_wpml->multi_currency_support->get_currencies();
1591
 
1592
  foreach( $currencies as $code => $currency ){
1593
+ $sale_price = $_POST[ '_custom_sale_price' ][ $code ];
1594
+ $regular_price = $_POST[ '_custom_regular_price' ][ $code ];
1595
 
1596
+ $date_from = strtotime( $_POST[ '_custom_sale_price_dates_from' ][ $code ] );
1597
+ $date_to = strtotime( $_POST[ '_custom_sale_price_dates_to' ][ $code ] );
1598
+ $schedule = $_POST[ '_wcml_schedule' ][ $code ];
1599
 
1600
+ $pr_price = $this->update_custom_prices( $post_id, $regular_price, $sale_price, $schedule, $date_from, $date_to, $code );
1601
  }
1602
  }
1603
  }
1604
 
1605
  // pick posts to sync
1606
  $posts = array();
1607
+ $translations = $sitepress->get_element_translations( $language_details->trid, 'post_product' );
1608
+ foreach ( $translations as $translation ) {
1609
+ if ( $translation->original ) {
1610
  $duplicated_post_id = $translation->element_id;
1611
  } else {
1612
+ $posts[ $translation->element_id ] = $translation;
1613
  }
1614
  }
1615
 
1616
 
1617
+ foreach( $posts as $post_id => $translation ) {
1618
  $lang = $translation->language_code;
1619
 
1620
+ do_action( 'wcml_before_sync_product_data', $duplicated_post_id, $post_id, $lang );
1621
  // Filter upsell products, crosell products and default attributes for translations
1622
+ $this->duplicate_product_post_meta( $duplicated_post_id, $post_id );
1623
 
1624
+ if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_featured' ] ){
1625
  //sync feature image
1626
+ $this->sync_thumbnail_id( $duplicated_post_id, $post_id, $lang );
1627
  }
1628
 
1629
  $this->sync_status_and_parent( $duplicated_post_id, $post_id, $lang );
1630
 
1631
+ $this->sync_product_taxonomies( $duplicated_post_id, $post_id, $lang );
1632
 
1633
+ $this->sync_default_product_attr( $duplicated_post_id, $post_id, $lang );
1634
 
1635
+ $this->sync_product_attr( $duplicated_post_id, $post_id );
 
 
 
 
 
 
 
 
 
1636
 
1637
  // synchronize post variations
1638
+ $this->sync_product_variations( $duplicated_post_id, $post_id, $lang );
1639
+ $this->sync_linked_products( $duplicated_post_id, $post_id, $lang );
1640
  }
1641
 
1642
+ $this->sync_product_variations_custom_prices( $duplicated_post_id );
1643
  }
1644
 
1645
  //sync product parent & post_status
2411
  }
2412
 
2413
  function translate_cart_subtotal($cart) {
2414
+
2415
+ if ( apply_filters( 'translate_cart_subtotal_exception', false, $cart ) ){
2416
+ return;
2417
+ }
2418
+
2419
  $cart->calculate_totals();
2420
  }
2421
 
2594
 
2595
  foreach( $cart_contents as $key => $cart_content ){
2596
 
2597
+ $cart_contents = apply_filters( 'wcml_check_on_duplicated_products_in_cart', $cart_contents, $key, $cart_content );
2598
+
2599
  if( apply_filters( 'wcml_exception_duplicate_products_in_cart', false, $cart_content ) ){
2600
  continue;
2601
  }
2604
  $search_key = $cart_content[ 'product_id' ];
2605
  }else{
2606
  $search_key = $cart_content[ 'product_id' ].'_'.$cart_content['variation_id'];
2607
+ foreach( $cart_content['variation'] as $var_key => $value ){
2608
+ $search_key .= '_'.$var_key.'-'.$value;
2609
+ }
2610
  }
2611
 
2612
  if( array_key_exists( $search_key, $exists_products ) ){
2866
 
2867
  }
2868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2869
  function woocommerce_product_quick_edit_save($product){
2870
  global $sitepress;
2871
  $is_original = $this->is_original_product($product->id);
inc/store-pages.class.php CHANGED
@@ -44,9 +44,38 @@ class WCML_Store_Pages{
44
  }
45
 
46
  function switch_pages_language( $pages ){
47
- global $sitepress,$wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
- $sitepress->switch_lang($sitepress->get_default_language());
 
 
 
 
 
50
 
51
  return $pages;
52
  }
@@ -351,8 +380,8 @@ class WCML_Store_Pages{
351
 
352
  foreach ($check_pages as $page) {
353
  $page_id = get_option($page);
354
-
355
- if(!$page_id || !get_post($page_id)){
356
  return 'non_exist';
357
  }
358
  }
44
  }
45
 
46
  function switch_pages_language( $pages ){
47
+ global $sitepress,$woocommerce_wpml;
48
+
49
+ $default_language = $sitepress->get_default_language();
50
+
51
+ if( $sitepress->get_current_language() != $default_language ){
52
+ foreach( $pages as $key => $page ){
53
+
54
+ switch( $key ){
55
+ case 'shop':
56
+ $page['name'] = 'shop';
57
+ $page['title'] = 'Shop';
58
+ break;
59
+ case 'cart':
60
+ $page['name'] = 'cart';
61
+ $page['title'] = 'Cart';
62
+ break;
63
+ case 'checkout':
64
+ $page['name'] = 'checkout';
65
+ $page['title'] = 'Checkout';
66
+ break;
67
+ case 'myaccount':
68
+ $page['name'] = 'my-account';
69
+ $page['title'] = 'My account';
70
+ break;
71
+ }
72
 
73
+ if( $sitepress->get_default_language() != 'en' ){
74
+ $page['name'] = $woocommerce_wpml->terms->get_translation_from_woocommerce_mo_file( 'Page slug'.$page['name'], $default_language );
75
+ $page['title'] = $woocommerce_wpml->terms->get_translation_from_woocommerce_mo_file( 'Page title'.$page['title'], $default_language );
76
+ }
77
+ }
78
+ }
79
 
80
  return $pages;
81
  }
380
 
381
  foreach ($check_pages as $page) {
382
  $page_id = get_option($page);
383
+ $page_obj = get_post($page_id);
384
+ if(!$page_id || !$page_obj || $page_obj->post_status != 'publish' ){
385
  return 'non_exist';
386
  }
387
  }
inc/terms.class.php CHANGED
@@ -141,40 +141,18 @@ class WCML_Terms{
141
  $taxonomies = array('product_cat', 'product_tag');
142
 
143
  foreach($taxonomies as $taxonomy ){
144
-
145
- $taxonomy_obj = get_taxonomy($taxonomy);
146
- $slug = isset($taxonomy_obj->rewrite['slug']) ? trim($taxonomy_obj->rewrite['slug'] ,'/') : false;
147
-
148
- if($slug && $sitepress->get_current_language() != $strings_language){
149
 
150
- $slug_translation = $wpdb->get_var($wpdb->prepare("
151
- SELECT t.value
152
- FROM {$wpdb->prefix}icl_string_translations t
153
- JOIN {$wpdb->prefix}icl_strings s ON t.string_id = s.id
154
- WHERE t.language = %s AND t.status = %s AND s.name = %s AND s.value = %s
155
- ", $sitepress->get_current_language(), ICL_STRING_TRANSLATION_COMPLETE, 'URL ' . $taxonomy . ' slug: ' . $slug, $slug));
156
-
157
- if(!$slug_translation){
158
- // handle exception - default woocommerce category and tag bases used
159
- // get translation from WooCommerce mo files?
160
- unload_textdomain('woocommerce');
161
- $woocommerce->load_plugin_textdomain();
162
- $slug_translation = _x($slug, 'slug', 'woocommerce');
163
- $slug = $taxonomy == 'product_tag' ? 'product-tag' : 'product-category'; // strings language
164
- }
165
-
166
- if($slug_translation){
167
- $buff_value = array();
168
- foreach((array)$value as $k=>$v){
169
- if($slug != $slug_translation && preg_match('#^[^/]*/?' . $slug . '/#', $k)){
170
- $k = preg_replace('#^([^/]*)(/?)' . $slug . '/#', '$1$2' . $slug_translation . '/' , $k);
171
- }
172
- $buff_value[$k] = $v;
173
  }
174
- $value = $buff_value;
175
- unset($buff_value);
176
  }
177
-
 
178
  }
179
 
180
  }
@@ -188,7 +166,7 @@ class WCML_Terms{
188
 
189
  foreach($wc_taxonomies_wc_format as $taxonomy ){
190
  $taxonomy_obj = get_taxonomy($taxonomy);
191
-
192
  if(isset($taxonomy_obj->rewrite['slug'])){
193
  $exp = explode('/', trim($taxonomy_obj->rewrite['slug'],'/'));
194
  $slug = join('/', array_slice($exp, 0, count($exp) - 1));
@@ -266,75 +244,116 @@ class WCML_Terms{
266
  return $value;
267
  }
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  function _switch_wc_locale(){
270
  global $sitepress;
271
  $locale = !empty($this->_tmp_locale_val) ? $this->_tmp_locale_val : $sitepress->get_locale($sitepress->get_current_language());
272
  return $locale;
273
  }
274
-
275
  function translate_category_base($termlink, $term, $taxonomy){
276
- global $sitepress_settings, $sitepress, $wp_rewrite, $wpdb, $woocommerce,$woocommerce_wpml;
277
  static $no_recursion_flag;
278
-
279
  // handles product categories, product tags and attributes
280
-
281
  $wc_taxonomies = wc_get_attribute_taxonomies();
282
  foreach($wc_taxonomies as $k => $v){
283
- $wc_taxonomies_wc_format[] = 'pa_' . $v->attribute_name;
284
  }
285
-
286
- if(($taxonomy == 'product_cat' || $taxonomy == 'product_tag' || !empty($wc_taxonomies_wc_format) && in_array($taxonomy, $wc_taxonomies_wc_format)) && !$no_recursion_flag){
287
-
288
  $cache_key = 'termlink#' . $taxonomy .'#' . $term->term_id;
289
- if($link = wp_cache_get($cache_key, 'terms')){
290
  $termlink = $link;
291
-
292
- }else{
293
-
294
  $no_recursion_flag = false;
295
-
296
- $strings_language = $woocommerce_wpml->strings->get_wc_context_language();
297
- $term_language = $sitepress->get_element_language_details($term->term_taxonomy_id, 'tax_' . $taxonomy);
298
-
299
- if(!empty($term_language)){
300
-
301
- $permalinks = get_option( 'woocommerce_permalinks' );
302
- $base = $taxonomy == 'product_tag' ? trim($permalinks['tag_base'],'/') : ($taxonomy == 'product_cat' ? trim($permalinks['category_base'],'/') : trim($permalinks['attribute_base'],'/'));
303
-
304
-
305
- $string_identifier = $taxonomy == 'product_tag' || $taxonomy == 'product_cat' ? $taxonomy : 'attribute';
306
-
307
- if($base === ''){
308
- $base = $taxonomy == 'product_tag' ? 'product-tag' : 'product-category'; // strings language
309
- do_action('wpml_register_single_string', 'URL ' . $taxonomy . ' slugs - ' . $base, 'Url ' . $string_identifier . ' slug: ' . $base, $base, array('language' => 'en'));
310
- }
311
-
312
- //
313
- if($term_language->language_code != $strings_language){
314
 
315
- $prepared = array();
316
 
317
- $sql = "SELECT t.value
318
- FROM {$wpdb->prefix}icl_strings s
319
- JOIN {$wpdb->prefix}icl_string_translations t ON t.string_id = s.id
320
- WHERE s.value=%s AND t.status = %s ";
321
- $prepared[] = esc_sql($base);
322
- $prepared[] = ICL_STRING_TRANSLATION_COMPLETE;
323
 
324
- if ( !WPML_SUPPORT_STRINGS_IN_DIFF_LANG ) {
325
- $sql .= " AND s.language = %s ";
326
- $prepared[] = $strings_language;
327
- }
328
 
329
- $sql .= " AND s.name LIKE %s AND t.language = %s";
330
- $prepared[] = 'Url '.$string_identifier.' slug:%';
331
- $prepared[] = $term_language->language_code;
332
 
333
- $base_translated = $wpdb->get_var( $wpdb->prepare( $sql,$prepared ) );
334
-
335
- }else{
336
- $base_translated = $base;
337
- }
338
 
339
  if(!empty($base_translated) && $base_translated != $base && isset( $wp_rewrite->extra_permastructs[$taxonomy] ) ){
340
 
@@ -342,18 +361,18 @@ class WCML_Terms{
342
  $wp_rewrite->extra_permastructs[$taxonomy]['struct'] = str_replace($base, $base_translated, $wp_rewrite->extra_permastructs[$taxonomy]['struct']);
343
  $no_recursion_flag = true;
344
  $termlink = get_term_link($term, $taxonomy);
345
-
346
  $wp_rewrite->extra_permastructs[$taxonomy]['struct'] = $buff;
347
-
348
- }
349
-
350
  }
351
-
352
- $no_recursion_flag = false;
353
-
354
  wp_cache_add($cache_key, $termlink, 'terms', 0);
355
- }
356
-
357
  }
358
 
359
  return $termlink;
@@ -1064,12 +1083,9 @@ class WCML_Terms{
1064
  }
1065
 
1066
  function shipping_terms($terms, $post_id, $taxonomy){
 
1067
 
1068
- if( is_ajax() && isset($_POST['action']) && $_POST['action'] == 'woocommerce_update_order_review' ){
1069
- return $terms;
1070
- }
1071
-
1072
- if( !is_admin() && ( get_post_type($post_id) == 'product' || get_post_type($post_id) == 'product_variation' ) && $taxonomy == 'product_shipping_class'){
1073
  global $sitepress;
1074
  remove_filter('get_the_terms',array($this,'shipping_terms'), 10, 3);
1075
  $terms = get_the_terms(apply_filters( 'translate_object_id',$post_id,get_post_type($post_id),true,$sitepress->get_default_language()),'product_shipping_class');
141
  $taxonomies = array('product_cat', 'product_tag');
142
 
143
  foreach($taxonomies as $taxonomy ){
144
+ $slug_details = $this->get_translated_tax_slug($taxonomy);
 
 
 
 
145
 
146
+ if($slug_details) {
147
+ $buff_value = array();
148
+ foreach ((array)$value as $k => $v) {
149
+ if ( $slug_details['slug'] != $slug_details['translated_slug'] && preg_match('#^[^/]*/?' . $slug_details['slug'] . '/#', $k)) {
150
+ $k = preg_replace('#^([^/]*)(/?)' . $slug_details['slug'] . '/#', '$1$2' . $slug_details['translated_slug'] . '/', $k);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
152
+ $buff_value[$k] = $v;
 
153
  }
154
+ $value = $buff_value;
155
+ unset($buff_value);
156
  }
157
 
158
  }
166
 
167
  foreach($wc_taxonomies_wc_format as $taxonomy ){
168
  $taxonomy_obj = get_taxonomy($taxonomy);
169
+
170
  if(isset($taxonomy_obj->rewrite['slug'])){
171
  $exp = explode('/', trim($taxonomy_obj->rewrite['slug'],'/'));
172
  $slug = join('/', array_slice($exp, 0, count($exp) - 1));
244
  return $value;
245
  }
246
 
247
+
248
+ function get_translated_tax_slug( $taxonomy, $language = false ){
249
+ global $sitepress, $woocommerce_wpml, $wpdb;
250
+
251
+ $strings_language = $woocommerce_wpml->strings->get_wc_context_language();
252
+
253
+ $permalinks = get_option( 'woocommerce_permalinks' );
254
+
255
+ switch($taxonomy){
256
+ case 'product_tag':
257
+ $slug = !empty( $permalinks['tag_base'] ) ? trim($permalinks['tag_base'],'/') : 'product-tag';
258
+ break;
259
+
260
+ case 'product_cat':
261
+ $slug = !empty( $permalinks['category_base'] ) ? trim($permalinks['category_base'],'/') : 'product-category';
262
+ break;
263
+
264
+ default:
265
+ $slug = trim( $permalinks['attribute_base'], '/' );
266
+ break;
267
+ }
268
+
269
+ if( !$language ){
270
+ $language = $sitepress->get_current_language();
271
+ }
272
+
273
+ if($slug && $language != $strings_language) {
274
+
275
+ $slug_translation = $wpdb->get_var($wpdb->prepare("
276
+ SELECT t.value
277
+ FROM {$wpdb->prefix}icl_string_translations t
278
+ JOIN {$wpdb->prefix}icl_strings s ON t.string_id = s.id
279
+ WHERE t.language = %s AND t.status = %s AND s.name = %s AND s.value = %s
280
+ ", $language, ICL_STRING_TRANSLATION_COMPLETE, 'URL ' . $taxonomy . ' slug: ' . $slug, $slug));
281
+
282
+ if ( is_null( $slug_translation ) ) {
283
+ // handle exception - default woocommerce category and tag bases used
284
+ $slug_translation = $this->get_translation_from_woocommerce_mo_file( 'product-category', $language );
285
+
286
+ }
287
+
288
+ return array( 'slug' => $slug, 'translated_slug' => $slug_translation );
289
+ }
290
+
291
+ return array( 'slug' => $slug, 'translated_slug' => $slug );
292
+
293
+ }
294
+
295
+ function get_translation_from_woocommerce_mo_file( $string, $language ){
296
+ global $sitepress;
297
+
298
+ $mo = new MO();
299
+ $mo_file = WP_LANG_DIR . '/plugins/woocommerce-' . $sitepress->get_locale( $language ) . '.mo';
300
+ if( !file_exists( $mo_file ) ){
301
+ return $string;
302
+ }
303
+
304
+ $mo->import_from_file( $mo_file );
305
+ $translations = $mo->entries;
306
+
307
+ if( in_array( $string, array( 'product','product-category','product-tag' ) ) ){
308
+ $string = 'slug'. chr(4) .$string;
309
+ }
310
+
311
+ if( isset( $translations[$string] ) ){
312
+ return $translations[$string]->translations[0];
313
+ }
314
+
315
+ return $string;
316
+
317
+ }
318
+
319
  function _switch_wc_locale(){
320
  global $sitepress;
321
  $locale = !empty($this->_tmp_locale_val) ? $this->_tmp_locale_val : $sitepress->get_locale($sitepress->get_current_language());
322
  return $locale;
323
  }
324
+
325
  function translate_category_base($termlink, $term, $taxonomy){
326
+ global $wp_rewrite,$woocommerce_wpml,$wpml_term_translations;
327
  static $no_recursion_flag;
328
+
329
  // handles product categories, product tags and attributes
330
+
331
  $wc_taxonomies = wc_get_attribute_taxonomies();
332
  foreach($wc_taxonomies as $k => $v){
333
+ $wc_taxonomies_wc_format[] = 'pa_' . $v->attribute_name;
334
  }
335
+
336
+ if(($taxonomy == 'product_cat' || $taxonomy == 'product_tag' || (!empty($wc_taxonomies_wc_format) && in_array($taxonomy, $wc_taxonomies_wc_format))) && !$no_recursion_flag){
337
+
338
  $cache_key = 'termlink#' . $taxonomy .'#' . $term->term_id;
339
+ if( false && $link = wp_cache_get($cache_key, 'terms')){
340
  $termlink = $link;
341
+
342
+ }else{
343
+
344
  $no_recursion_flag = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
 
346
+ $term_language = $term->term_id ? $wpml_term_translations->get_element_lang_code($term->term_id) : false;
347
 
348
+ if( $term_language ){
 
 
 
 
 
349
 
350
+ $taxonomy_obj = get_taxonomy( $taxonomy );
351
+ $base = isset($taxonomy_obj->rewrite['slug']) ? trim($taxonomy_obj->rewrite['slug'], '/') : false;
 
 
352
 
353
+ $slug_details = $this->get_translated_tax_slug( $taxonomy, $term_language );
354
+ $base_translated = $slug_details['translated_slug'];
 
355
 
356
+ $string_identifier = $taxonomy == 'product_tag' || $taxonomy == 'product_cat' ? $taxonomy : 'attribute';
 
 
 
 
357
 
358
  if(!empty($base_translated) && $base_translated != $base && isset( $wp_rewrite->extra_permastructs[$taxonomy] ) ){
359
 
361
  $wp_rewrite->extra_permastructs[$taxonomy]['struct'] = str_replace($base, $base_translated, $wp_rewrite->extra_permastructs[$taxonomy]['struct']);
362
  $no_recursion_flag = true;
363
  $termlink = get_term_link($term, $taxonomy);
364
+
365
  $wp_rewrite->extra_permastructs[$taxonomy]['struct'] = $buff;
366
+
367
+ }
368
+
369
  }
370
+
371
+ $no_recursion_flag = false;
372
+
373
  wp_cache_add($cache_key, $termlink, 'terms', 0);
374
+ }
375
+
376
  }
377
 
378
  return $termlink;
1083
  }
1084
 
1085
  function shipping_terms($terms, $post_id, $taxonomy){
1086
+ global $pagenow;
1087
 
1088
+ if( $pagenow != 'post.php' && ( get_post_type($post_id) == 'product' || get_post_type($post_id) == 'product_variation' ) && $taxonomy == 'product_shipping_class'){
 
 
 
 
1089
  global $sitepress;
1090
  remove_filter('get_the_terms',array($this,'shipping_terms'), 10, 3);
1091
  $terms = get_the_terms(apply_filters( 'translate_object_id',$post_id,get_post_type($post_id),true,$sitepress->get_default_language()),'product_shipping_class');
inc/wc-strings.class.php CHANGED
@@ -8,7 +8,7 @@ class WCML_WC_Strings{
8
  add_action('init', array($this, 'pre_init'));
9
  add_filter('query_vars', array($this, 'translate_query_var_for_product'));
10
  add_filter('wp_redirect', array($this, 'encode_shop_slug'),10,2);
11
-
12
  }
13
 
14
  function pre_init(){
@@ -48,12 +48,11 @@ class WCML_WC_Strings{
48
 
49
  add_filter('woocommerce_rate_label',array($this,'translate_woocommerce_rate_label'));
50
 
51
- add_action( 'woocommerce_before_template_part', array( $this, 'woocommerce_before_template_part' ), 10, 4 );
52
-
53
  add_action( 'woocommerce_product_options_attributes', array ( $this, 'notice_after_woocommerce_product_options_attributes' ) );
54
 
55
  add_filter( 'woocommerce_attribute_taxonomies', array( $this, 'translate_attribute_taxonomies_labels') );
56
 
 
57
  }
58
 
59
  function translated_attribute_label($label, $name, $product_obj = false){
@@ -103,7 +102,7 @@ class WCML_WC_Strings{
103
 
104
  }
105
 
106
- $trnsl_label = icl_t('WordPress','taxonomy singular name: '.$label,$label);
107
 
108
  if( $label != $trnsl_label ){
109
  return $trnsl_label;
@@ -122,22 +121,23 @@ class WCML_WC_Strings{
122
  function translated_cart_item_name($title, $values, $cart_item_key){
123
 
124
  if($values){
 
125
  $parent = $values['data']->post->post_parent;
126
  $tr_product_id = apply_filters( 'translate_object_id', $values['product_id'], 'product', true );
127
- $title = get_the_title($tr_product_id);
128
 
129
  if($parent){
130
  $tr_parent = apply_filters( 'translate_object_id', $parent, 'product', true );
131
- $title = get_the_title( $tr_parent ) . ' &rarr; ' . $title;
132
  }
133
 
134
- if( wc_get_product( $tr_product_id )->is_visible() ){
135
- $title = sprintf( '<a href="%s">%s</a>', $values['data']->get_permalink(), $title );
136
  }else{
137
- $title = $title. '&nbsp;';
138
  }
139
 
140
-
141
  }
142
 
143
  return $title;
@@ -155,7 +155,7 @@ class WCML_WC_Strings{
155
  }
156
 
157
 
158
- function translate_query_var_for_product($public_query_vars){
159
  global $wpdb, $sitepress, $sitepress_settings;
160
 
161
  $strings_language = $this->get_wc_context_language();
@@ -189,11 +189,17 @@ class WCML_WC_Strings{
189
 
190
  global $wpdb;
191
 
192
- $translated_slug = $wpdb->get_var($wpdb->prepare("
193
- SELECT t.value FROM {$wpdb->prefix}icl_string_translations t
194
- JOIN {$wpdb->prefix}icl_strings s ON t.string_id = s.id
195
- WHERE s.name=%s AND s.value = %s AND t.language = %s AND t.status = %d",
196
- 'URL slug: ' . $product_permalink, $product_permalink, $language, ICL_STRING_TRANSLATION_COMPLETE ));
 
 
 
 
 
 
197
 
198
  return $translated_slug;
199
  }
@@ -241,7 +247,7 @@ class WCML_WC_Strings{
241
  function register_shipping_methods($available_methods){
242
  foreach($available_methods as $key => $method){
243
  do_action('wpml_register_single_string', 'woocommerce', $key .'_shipping_method_title', $method->label );
244
- $method->label = icl_t('woocommerce', $key .'_shipping_method_title', $method->label);
245
  }
246
 
247
  return $available_methods;
@@ -250,7 +256,8 @@ class WCML_WC_Strings{
250
  function translate_tax_rates($rates){
251
  if (!empty($rates)) {
252
  foreach ($rates as &$rate) {
253
- $rate['label'] = icl_translate('woocommerce', 'tax_label_' . esc_url_raw($rate['label']), $rate['label']);
 
254
  }
255
  }
256
 
@@ -258,17 +265,17 @@ class WCML_WC_Strings{
258
  }
259
 
260
  function translate_gateway_title($title, $gateway_title) {
261
- if (function_exists('icl_translate')) {
262
- $title = icl_translate('woocommerce', $gateway_title .'_gateway_title', $title);
263
- }
264
 
265
  return $title;
266
  }
267
 
268
  function translate_gateway_description($description, $gateway_title) {
269
- if (function_exists('icl_translate')) {
270
- $description = icl_translate('woocommerce', $gateway_title .'_gateway_description', $description);
271
- }
272
 
273
  return $description;
274
  }
@@ -286,23 +293,23 @@ class WCML_WC_Strings{
286
  }
287
 
288
  function translate_payment_instructions($id){
289
- if (function_exists('icl_translate')) {
290
- $gateways = WC()->payment_gateways();
291
- foreach($gateways->payment_gateways as $key => $gateway){
292
- if($gateway->id == $id && isset(WC_Payment_Gateways::instance()->payment_gateways[$key]->instructions)){
293
- WC_Payment_Gateways::instance()->payment_gateways[$key]->instructions = icl_translate('woocommerce', $gateway->id .'_gateway_instructions', $gateway->instructions);
294
- break;
295
- }
296
  }
297
  }
 
298
  }
299
 
300
  function register_tax_label($label){
301
  global $sitepress;
302
 
303
- if(function_exists('icl_translate')){
304
- $label = icl_translate('woocommerce', 'VAT_tax_label', $label);
305
- }
306
 
307
  return $label;
308
  }
@@ -401,9 +408,10 @@ class WCML_WC_Strings{
401
 
402
 
403
  function translate_woocommerce_rate_label($label){
404
- if (function_exists('icl_translate')) {
405
- $label = icl_translate('woocommerce taxes', $label , $label);
406
- }
 
407
  return $label;
408
  }
409
 
@@ -433,7 +441,12 @@ class WCML_WC_Strings{
433
  $slug = $this->product_permalink_slug();
434
  $default_language = $sitepress->get_default_language();
435
 
436
- $slug_translation_languages = $wpdb->get_col($wpdb->prepare("SELECT tr.language FROM {$wpdb->prefix}icl_strings AS s LEFT JOIN {$wpdb->prefix}icl_string_translations AS tr ON s.id = tr.string_id WHERE s.name = %s AND s.value = %s AND tr.status = %s", 'URL slug: ' . $slug, $slug, ICL_STRING_TRANSLATION_COMPLETE));
 
 
 
 
 
437
  $miss_slug_lang = array();
438
 
439
  if ( WPML_SUPPORT_STRINGS_IN_DIFF_LANG ) {
@@ -485,33 +498,36 @@ class WCML_WC_Strings{
485
 
486
  }
487
 
488
-
489
  /*
490
- * Add filter before include global/breadcrumb.php template
491
  *
492
  */
493
- function woocommerce_before_template_part( $template_name, $template_path, $located, $args ){
494
- if( $template_name == 'global/breadcrumb.php'){
495
- add_filter('option_woocommerce_permalinks', array($this, 'filter_woocommerce_permalinks_option_breadcrumb_page' ), 11 );
496
- }
497
-
498
- }
499
-
500
-
501
- /*
502
- * Filter product base only on global/breadcrumb.php template page
503
- *
504
- */
505
- function filter_woocommerce_permalinks_option_breadcrumb_page( $value ){
506
  global $sitepress;
507
 
508
- if(isset($value['product_base']) && !is_admin() && $sitepress->get_current_language() != $this->get_wc_context_language() ){
509
- remove_filter('option_woocommerce_permalinks', array($this, 'filter_woocommerce_permalinks_option_breadcrumb_page'), 11);
510
- $value['product_base'] = '/'.strtolower(urlencode($this->get_translated_product_base_by_lang()));
511
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
  }
513
 
514
- return $value;
515
  }
516
 
517
  /*
@@ -545,4 +561,5 @@ class WCML_WC_Strings{
545
 
546
  return $attribute_taxonomies;
547
  }
 
548
  }
8
  add_action('init', array($this, 'pre_init'));
9
  add_filter('query_vars', array($this, 'translate_query_var_for_product'));
10
  add_filter('wp_redirect', array($this, 'encode_shop_slug'),10,2);
11
+
12
  }
13
 
14
  function pre_init(){
48
 
49
  add_filter('woocommerce_rate_label',array($this,'translate_woocommerce_rate_label'));
50
 
 
 
51
  add_action( 'woocommerce_product_options_attributes', array ( $this, 'notice_after_woocommerce_product_options_attributes' ) );
52
 
53
  add_filter( 'woocommerce_attribute_taxonomies', array( $this, 'translate_attribute_taxonomies_labels') );
54
 
55
+ add_filter('woocommerce_get_breadcrumb', array($this, 'filter_woocommerce_breadcrumbs' ), 10, 2 );
56
  }
57
 
58
  function translated_attribute_label($label, $name, $product_obj = false){
102
 
103
  }
104
 
105
+ $trnsl_label = apply_filters( 'wpml_translate_single_string', $label, 'WordPress','taxonomy singular name: '.$label, $lang );
106
 
107
  if( $label != $trnsl_label ){
108
  return $trnsl_label;
121
  function translated_cart_item_name($title, $values, $cart_item_key){
122
 
123
  if($values){
124
+
125
  $parent = $values['data']->post->post_parent;
126
  $tr_product_id = apply_filters( 'translate_object_id', $values['product_id'], 'product', true );
127
+ $trnsl_title = get_the_title($tr_product_id);
128
 
129
  if($parent){
130
  $tr_parent = apply_filters( 'translate_object_id', $parent, 'product', true );
131
+ $trnsl_title = get_the_title( $tr_parent ) . ' &rarr; ' . $trnsl_title;
132
  }
133
 
134
+ if( strstr( $title,'</a>' ) ){
135
+ $trnsl_title = sprintf( '<a href="%s">%s</a>', $values['data']->get_permalink(), $trnsl_title );
136
  }else{
137
+ $trnsl_title = $trnsl_title. '&nbsp;';
138
  }
139
 
140
+ $title = $trnsl_title;
141
  }
142
 
143
  return $title;
155
  }
156
 
157
 
158
+ function translate_query_var_for_product($public_query_vars){
159
  global $wpdb, $sitepress, $sitepress_settings;
160
 
161
  $strings_language = $this->get_wc_context_language();
189
 
190
  global $wpdb;
191
 
192
+ // Use new API for WPML >= 3.2.3
193
+ if ( apply_filters( 'wpml_slug_translation_available', false) ) {
194
+ $translated_slug = apply_filters( 'wpml_get_translated_slug', $product_permalink, $language );
195
+ } else {
196
+ // Try the old way.
197
+ $translated_slug = $wpdb->get_var($wpdb->prepare("
198
+ SELECT t.value FROM {$wpdb->prefix}icl_string_translations t
199
+ JOIN {$wpdb->prefix}icl_strings s ON t.string_id = s.id
200
+ WHERE s.name=%s AND s.value = %s AND t.language = %s AND t.status = %d",
201
+ 'URL slug: ' . $product_permalink, $product_permalink, $language, ICL_STRING_TRANSLATION_COMPLETE ));
202
+ }
203
 
204
  return $translated_slug;
205
  }
247
  function register_shipping_methods($available_methods){
248
  foreach($available_methods as $key => $method){
249
  do_action('wpml_register_single_string', 'woocommerce', $key .'_shipping_method_title', $method->label );
250
+ $method->label = apply_filters( 'wpml_translate_single_string', $method->label, 'woocommerce', $key .'_shipping_method_title');
251
  }
252
 
253
  return $available_methods;
256
  function translate_tax_rates($rates){
257
  if (!empty($rates)) {
258
  foreach ($rates as &$rate) {
259
+ do_action('wpml_register_single_string', 'woocommerce', 'tax_label_' . esc_url_raw($rate['label']), $rate['label'] );
260
+ $rate['label'] = apply_filters( 'wpml_translate_single_string', $rate['label'], 'woocommerce', 'tax_label_' . esc_url_raw($rate['label']) );
261
  }
262
  }
263
 
265
  }
266
 
267
  function translate_gateway_title($title, $gateway_title) {
268
+
269
+ do_action('wpml_register_single_string', 'woocommerce', $gateway_title .'_gateway_title', $title );
270
+ $title = apply_filters( 'wpml_translate_single_string', $title, 'woocommerce', $gateway_title .'_gateway_title' );
271
 
272
  return $title;
273
  }
274
 
275
  function translate_gateway_description($description, $gateway_title) {
276
+
277
+ do_action('wpml_register_single_string', 'woocommerce', $gateway_title .'_gateway_description', $description );
278
+ $description =apply_filters( 'wpml_translate_single_string', $description, 'woocommerce', $gateway_title .'_gateway_description' );
279
 
280
  return $description;
281
  }
293
  }
294
 
295
  function translate_payment_instructions($id){
296
+
297
+ $gateways = WC()->payment_gateways();
298
+ foreach($gateways->payment_gateways as $key => $gateway){
299
+ if($gateway->id == $id && isset(WC_Payment_Gateways::instance()->payment_gateways[$key]->instructions)){
300
+ do_action('wpml_register_single_string', 'woocommerce', $gateway->id .'_gateway_instructions', $gateway->instructions );
301
+ WC_Payment_Gateways::instance()->payment_gateways[$key]->instructions = apply_filters( 'wpml_translate_single_string', $gateway->instructions, 'woocommerce', $gateway->id .'_gateway_instructions' );
302
+ break;
303
  }
304
  }
305
+
306
  }
307
 
308
  function register_tax_label($label){
309
  global $sitepress;
310
 
311
+ do_action('wpml_register_single_string', 'woocommerce', 'VAT_tax_label', $label );
312
+ $label = apply_filters( 'wpml_translate_single_string', $label, 'woocommerce', 'VAT_tax_label' );
 
313
 
314
  return $label;
315
  }
408
 
409
 
410
  function translate_woocommerce_rate_label($label){
411
+
412
+ do_action('wpml_register_single_string', 'woocommerce taxes', $label , $label );
413
+ $label = apply_filters( 'wpml_translate_single_string', $label, 'woocommerce taxes', $label );
414
+
415
  return $label;
416
  }
417
 
441
  $slug = $this->product_permalink_slug();
442
  $default_language = $sitepress->get_default_language();
443
 
444
+ if ( apply_filters( 'wpml_slug_translation_available', false) ) {
445
+ // Use new API for WPML >= 3.2.3
446
+ $slug_translation_languages = apply_filters( 'wpml_get_slug_translation_languages', array(), $slug );
447
+ } else {
448
+ $slug_translation_languages = $wpdb->get_col($wpdb->prepare("SELECT tr.language FROM {$wpdb->prefix}icl_strings AS s LEFT JOIN {$wpdb->prefix}icl_string_translations AS tr ON s.id = tr.string_id WHERE s.name = %s AND s.value = %s AND tr.status = %s", 'URL slug: ' . $slug, $slug, ICL_STRING_TRANSLATION_COMPLETE));
449
+ }
450
  $miss_slug_lang = array();
451
 
452
  if ( WPML_SUPPORT_STRINGS_IN_DIFF_LANG ) {
498
 
499
  }
500
 
 
501
  /*
502
+ * Filter breadcrumbs
503
  *
504
  */
505
+ function filter_woocommerce_breadcrumbs( $breadcrumbs, $object ){
 
 
 
 
 
 
 
 
 
 
 
 
506
  global $sitepress;
507
 
508
+ if( $sitepress->get_current_language() != $this->get_wc_context_language() ){
509
+
510
+ $permalinks = get_option( 'woocommerce_permalinks' );
511
+ $shop_page_id = wc_get_page_id( 'shop' );
512
+ $orig_shop_page = get_post( apply_filters( 'translate_object_id', $shop_page_id, 'page', true, $this->get_wc_context_language() ) );
513
+
514
+ // If permalinks contain the shop page in the URI prepend the breadcrumb with shop
515
+ if ( $shop_page_id && $orig_shop_page && strstr( $permalinks['product_base'], '/' . $orig_shop_page->post_name ) && get_option( 'page_on_front' ) != $shop_page_id ) {
516
+ $breadcrumbs_buff = array();
517
+ $i =0;
518
+ foreach( $breadcrumbs as $key => $breadcrumb ){
519
+ $breadcrumbs_buff[ $i ] = $breadcrumb;
520
+ if( $key === 0 ){
521
+ $i++;
522
+ $breadcrumbs_buff[ $i ] = array( get_the_title( $shop_page_id ), get_permalink( $shop_page_id ) );
523
+ }
524
+ $i++;
525
+ }
526
+ $breadcrumbs = $breadcrumbs_buff;
527
+ }
528
  }
529
 
530
+ return $breadcrumbs;
531
  }
532
 
533
  /*
561
 
562
  return $attribute_taxonomies;
563
  }
564
+
565
  }
inc/woocommerce-2.0-backward-compatibility.php CHANGED
@@ -48,7 +48,8 @@ if(version_compare(preg_replace('#-(.+)$#', '', $woocommerce->version), '2.1', '
48
  //
49
  function wcml_wc_2_0_backward_compatibility_register_shipping_methods($available_methods){
50
  foreach($available_methods as $method){
51
- $method->label = icl_translate('woocommerce', $method->label .'_shipping_method_title', $method->label);
 
52
  }
53
  return $available_methods;
54
  }
48
  //
49
  function wcml_wc_2_0_backward_compatibility_register_shipping_methods($available_methods){
50
  foreach($available_methods as $method){
51
+ do_action('wpml_register_single_string', 'woocommerce', $method->label .'_shipping_method_title', $method->label );
52
+ $method->label = apply_filters( 'wpml_translate_single_string', $method->label, 'woocommerce', $method->label .'_shipping_method_title' );
53
  }
54
  return $available_methods;
55
  }
inc/xdomain-data.class.php CHANGED
@@ -13,7 +13,7 @@ class xDomain_Data{
13
 
14
  $wcml_session_id = md5( microtime() . uniqid(rand(), TRUE) );
15
 
16
- $data[ ] = 'wcml_'.$wcml_session_id;
17
 
18
  $session_data = array();
19
 
@@ -40,12 +40,9 @@ class xDomain_Data{
40
  function check_request(){
41
 
42
  if( isset($_GET['xdomain_data']) ){
43
- $xdomain_data = explode( '=', $_GET['xdomain_data'] );
44
-
45
- foreach( $xdomain_data as $data){
46
- if( substr( $data, 0, 5 ) == 'wcml_' ){
47
- $this->set_session_data( substr( $data, 5 ) );
48
- }
49
  }
50
  }
51
 
13
 
14
  $wcml_session_id = md5( microtime() . uniqid(rand(), TRUE) );
15
 
16
+ $data[ 'wcsid' ] = $wcml_session_id;
17
 
18
  $session_data = array();
19
 
40
  function check_request(){
41
 
42
  if( isset($_GET['xdomain_data']) ){
43
+ $xdomain_data = json_decode( base64_decode( $_GET['xdomain_data'] ), JSON_OBJECT_AS_ARRAY );
44
+ if(isset($xdomain_data[ 'wcsid' ])){
45
+ $this->set_session_data( $xdomain_data[ 'wcsid' ] );
 
 
 
46
  }
47
  }
48
 
menu/sub/settings.php CHANGED
@@ -56,7 +56,12 @@ if( ( !WPML_SUPPORT_STRINGS_IN_DIFF_LANG && $default_language != 'en' && empty(
56
 
57
  <?php if( !empty( $miss_slug_lang ) ): ?>
58
 
59
- <p><i class="icon-warning-sign"></i><?php printf(__("Your product permalink base is not translated in %s. The urls for the translated products will not work. Go to the %sString Translation%s to translate.", 'wpml-wcml'), '<b>'. implode(', ',$miss_slug_lang).'</b>' ,'<a href="'.admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php&search='.$prod_slug.'&context=WordPress&em=1').'">', '</a>') ?> </p>
 
 
 
 
 
60
 
61
  <?php endif;?>
62
 
56
 
57
  <?php if( !empty( $miss_slug_lang ) ): ?>
58
 
59
+ <?php if ( apply_filters( 'wpml_slug_translation_available', false ) ): ?>
60
+ <?php // Use new API for WPML >= 3.2.3 ?>
61
+ <p><i class="icon-warning-sign"></i><?php printf(__("Your product permalink base is not translated in %s. The urls for the translated products will not work. Go to the %sSlugs Translation%s to translate.", 'wpml-wcml'), '<b>'. implode(', ',$miss_slug_lang).'</b>' ,'<a href="' . apply_filters( 'wpml_get_slug_translation_url' , '' ) . '">', '</a>') ?> </p>
62
+ <?php else:?>
63
+ <p><i class="icon-warning-sign"></i><?php printf(__("Your product permalink base is not translated in %s. The urls for the translated products will not work. Go to the %sString Translation%s to translate.", 'wpml-wcml'), '<b>'. implode(', ',$miss_slug_lang).'</b>' ,'<a href="'.admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php&search='.$prod_slug.'&context=WordPress&em=1').'">', '</a>') ?> </p>
64
+ <?php endif;?>
65
 
66
  <?php endif;?>
67
 
readme.txt CHANGED
@@ -1,507 +1,528 @@
1
- === WooCommerce Multilingual - run WooCommerce with WPML ===
2
- Contributors: AmirHelzer, dominykasgel, dgwatkins, adelval
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: 4.2.2
8
- Stable tag: 3.6.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](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
- = Features =
17
-
18
- * Lets you translate different kinds of WooCommerce product types
19
- * Central management for translating product categories, tags and custom attributes
20
- * Automatically synchronizes product variations and images
21
- * Keeps the same language through the checkout process
22
- * Sends emails to clients and admins in their selected language
23
- * Allows inventory tracking without breaking products into languages
24
- * Enables running a single WooCommerce store with multiple currencies
25
-
26
- = Usage Instructions =
27
-
28
- For step by step instructions on setting up a multilingual shop, please go to [WooCommerce Multilingual Manual](http://wpml.org/documentation/related-projects/woocommerce-multilingual/) page.
29
-
30
- After installing, go to WPML->WooCommerce Multilingual. The 'General settings' tab will let you translate the store pages and report what taxonomy requires translation.
31
-
32
- Then, continue to the 'Products' and any categories, tags and custom taxonomy that you use.
33
-
34
- When you need help, go to [WooCommerce Multilingual support forum](http://wpml.org/forums/topic-tag/woocommerce/).
35
-
36
- = Downloads =
37
-
38
- This version of WooCommerce Multilingual works with WooCommerce 2.x.
39
-
40
- You will also need [WPML](http://wpml.org), together with the String Translation and the Translation Management modules, which are part of the [Multilingual CMS](http://wpml.org/purchase/) package.
41
-
42
- = Minimum versions for WPML and modules =
43
-
44
- WooCommerce Multilingual checks that the following versions of WPML and their components are active:
45
-
46
- * WPML Multilingual CMS - 3.1.5
47
- * WPML String Translation - 2.0
48
- * WPML Translation Management - 1.9
49
- * WPML Media - 2.1
50
-
51
- Without having all these running, WooCommerce Multilingual will not be able to run.
52
-
53
- == Installation ==
54
-
55
- 1. Upload 'woocommerce-multilingual' to the '/wp-content/plugins/' directory
56
- 2. Activate the plugin through the 'Plugins' menu in WordPress
57
- 3. Translate the shop pages
58
-
59
- == Frequently Asked Questions ==
60
-
61
- = Does this work with other e-commerce plugins? =
62
-
63
- No. This plugin is tailored for WooCommerce.
64
-
65
- = What do I need to do in my theme? =
66
-
67
- Make sure that your theme is not hard-coding any URL. Always use API calls to receive URLs to pages and you'll be fine.
68
-
69
- = My checkout page displays in the same language =
70
-
71
- In order for the checkout and store pages to appear translated, you need to create several WordPress pages and insert the WooCommerce shortcodes into them. You'll have to go over the [documentation](http://wpml.org/documentation/related-projects/woocommerce-multilingual/) and see that you performed all steps on the way.
72
-
73
- == Screenshots ==
74
-
75
- 1. Translation controls for products
76
- 2. Product categories translations
77
- 3. Multiple currencies
78
-
79
- == Changelog ==
80
-
81
- = 3.6.4 =
82
- * Bug fix: Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM (introduced in 3.6.1)
83
- * Bug fix: In some conditions it was not possible to load product pages in other languages than the default.
84
- * Bug fix: Fixed some compatibility issues with Product Bundles
85
-
86
- = 3.6.3 =
87
- * Fixed a bug causing a PHP warning when using an older version of WPML String Translation
88
-
89
- = 3.6.2 =
90
- * Bug fix: A product could appear multiple times in the cart when added in different languages
91
- * Bug fix: Product attribute labels translations were not showing on the frontend in some circumstances
92
- * Bug fix: Attributes labels translations not showing on the 'Add product' admin panel
93
- * Bug fix: The flags for custom languages were not showing correctly on the products editor screen
94
- * Bug fix: The currency switcher was missing from the WooCommerce Status dashboard widget (in version 3.6.1)
95
- * Bug fix: The auto-adjust ids functionality from WPML was not working with wc_get_product_terms
96
- * Bug fix: The 'shop' link was stripped out of the breadcrumb in the Woocommerce product page.
97
- * Bug fix: The product category template was not working correctly in secondary languages
98
- * Bug fix: Fixed a problem with sanitize_title for variations in Danish and German
99
- * Moved the Tab manager settings to separate file from the WCML config
100
- * Duplicates for media are now being created, if missing, when product translations are created.
101
- * Bug fix: Fixed a fatal error that was occurring when the WPML was not updated to version 3.2 while the WPML addons were updated to the latest versions.
102
-
103
- = 3.6.1 =
104
- * Updated the taxonomy translation synchronization to be compatible with WPML 3.2
105
- * Bug fix: the notice that shows up on the general settings page when the default language is not English did not hide when it was dismissed.
106
- * Bug fix: after adding a new currency and reloading the page, the new currency was gone. Also the exchange rate was wrong after re-adding teh currency.
107
- * Bug fix: an incorrect currency was being passed to the payment gateway when paying for an order created in the backend.
108
- * Bug fix: the prices in the custom currencies were not saved when a product was published.
109
- * Bug fix: extra backslashes were added when translating custom attribute name in products.
110
- * Bug fix: custom product categories template was not working as expected
111
- * Bug fix: updating WordPress language packs was not working when using custom locale codes in WPML
112
- * Bug fix: Variable products returned error in secondary language "This product is currently out of stock and unavailable."
113
- * Bug fix: The publishing date was not updating on translation when changed on the product in the original language
114
- * Bug fix: Attributes with the value "0" value were not displayed on the front end
115
- * Bug fix: Modified Free shipping label could not be translated
116
- * Bug fix: When editing product translations it was possible to save an empty slug.
117
-
118
- = 3.6 =
119
- * Added the ability to edit the slugs of the translated products in the products editor
120
- * Added the option to show only products with custom prices on the front end
121
- * Performance improvements: fewer db queries, caching. Up to 40% faster on large sites.
122
- * Support for the 'lang' parameter in WooCommerce REST API calls
123
- * Option to hide the default currency selector on the product page
124
- * Bug fix: Fixed a design issue on the 'connect with translation' pop-up on products.
125
- * Bug fix: Accessing the source content in the WooCommerce Multilingual product translation content editor was not possible sometimes.
126
- * Bug fix: 'Invisible' products were showing as links in the cart instead of just names.
127
- * Bug fix: The cart_widget.js code was always loaded.
128
- * Bug fix: Screen Options & Check All not working on WooCommerce Orders page
129
- * Bug fix: Sometimes the IPN Url sent to Paypal was wrong causing a 404 error after the payment was complete
130
- * Bug fix: Translated endpoint pages were sometimes returning 404
131
- * Bug fix: When using a default language different than English, the product permalink base was not in English.
132
-
133
- = 3.5.5 =
134
- * Bug fixed: Custom attributes were disappearing after updating a product in the WooCommerce native product editor
135
- * Tested compatibility with WordPress 4.2
136
- * Security review and fixes
137
- * Made the key "woocommerce_cancelled_order_settings" translatable
138
- * Email heading and subject sent after placing an order were not translated when using �Complete� button on orders page
139
- * Bug fixed: warning about minimum order requirement always showing in some conditions when using a child theme
140
-
141
- = 3.5.4 =
142
- * Bug fixed: Can't access source content in WCML product translation table
143
- * Bug fixed: Custom Post Types leads to 404 error
144
-
145
- = 3.5.3 =
146
- * Bug fixed: Redirection issues with "Your latest posts" as a front page
147
- * Bug fixed: Yoast fileds not saved in WooCommerce Multilingual products table
148
- * Bug fixed: Translated endpoints returns page not found
149
- * Bug fixed: Custom fields are locked in variation section
150
-
151
- = 3.5.2 =
152
- * Compatibility with WooCommerce 2.3.x
153
- * Bug fixed: Redirection issues with "Shop" page as front page
154
- * Bug fixed: Language column was missing from the products list page
155
- * Bug fixed: Product tags disappeared after updating the product attribute 'size'
156
- * Bug fixed: Featured image title and text were not editable in the WooCommerce Multilingual Translation Table
157
- * Bug fixed: Only first three attributes were available for translation
158
- * Bug fixed: The shipping fee was not converted correctly when using the multi-currency mode
159
- * Bug fixed: The default currency configuration (decimal & thousand separator) was ignored when the multi-currency was active
160
- * Bug fixed: Subsequent request to product preview page lead to a 404 page.
161
- * Bug fixed: 'Insert link' button on the visual editor of the products translations screen was not working.
162
- * Bug fixed: Fixed another compatibility problem with WooCommerce Product Tabs
163
- * Bug fixed: A variable product was showing an incorrect price in the cart
164
- * Bug fixed: The flat rate shipping was showing the wrong price on the checkout page in certain conditions
165
-
166
- = 3.5.1 =
167
- * Bug fixed: Performance issue with queries number
168
-
169
- = 3.5 =
170
- * Added support for creating products in secondary languages only.
171
- * Added enhancements for the Woocommerce Multilingual products table (filter by original language, display language flag).
172
- * Added option to synchronize the products and product taxonomies order.
173
- * Bug fixed: The cart was not updating quantities for variable product (when have more than one variable in the cart).
174
- * Bug fixed: The cart total was not updating when using get_cart_total() and get_cart_subtotal() functions in other plugins or themes.
175
- * Bug fixed: Wrong price format and order total were displayed on the new order page in the WP admin
176
- * Bug fixed: The featured image and the gallery images were overridden when updating translations
177
- * Bug fixed: Fixed the 'Keep' option that allows keeping the same currency on teh front end, when switching the language.
178
- * Bug fixed: Fixed a javascript error that was showing when changing currencies order
179
- * Bug fixed: The decimal number was not working correctly for the default currency
180
- * Bug fixed: Fixed a compatibility problem with WooCommerce Product Tabs
181
- * Bug fixed: A coupon was applied incorrectly to all products in the cart when they were defined for specific product variations.
182
- * Bug fixed: WooCommerce note email language was not correct
183
- * Bug fixed: WooCommerce reports were showing duplicate products
184
- * Bug fixed: When using WordPress in a folder, the checkout showed an 'expired session' error message.
185
- * Added support currency argument in raw_price_filter
186
-
187
- = 3.4.3 =
188
- * Bug fixed: Incorrect decimal separator for prices on WordPress admin
189
- * Bug fixed: �Insert link� button not working on products translator interface.
190
- * Bug fixed: Switching currency after adding to cart was adding an additional item
191
- * Bug fixed: Review setting not preserved on translation of variable product
192
- * Bug fixed: �Visible on the products page� option for product attributes was still selectable for product translation.
193
- * Bug fixed: Translation status icon not updated on products translator page
194
- * Bug fixed: Shipping rate was lost when WPML is activated
195
- * Bug fixed: WooCommerce �sort by� links going to blog not products
196
- * Bug fixed: Option to select currency position was missing immediately after a new currency was added
197
-
198
- = 3.4.2 =
199
- * Accommodated taxonomy translation changes in WPML
200
-
201
- = 3.4.1 =
202
- * Bug fix: A variable product was somtimes breaking the shopping cart
203
- * Fixes added for translating custom fields that are textareas
204
-
205
- = 3.4 =
206
- * Additional support for updating the WooCommerce translations.
207
- * Added currency switcher for the WooCommerce status widget on the WordPress admin dashboard.
208
- * Usability fixes for the translation of custom attributes in the WooCommerce native editor.
209
- * Added validation for the sale amount when using custom prices with multi-currency.
210
- * Bug fixed: Incorrect currency symbol position on edit order page.
211
- * Bug fixed: Incorrect currency displayed for order when editing an order in the backend.
212
- * Bug fixed: Coupon option 'Exclude sale items' was not being applied correctly. Sale items were not excluded.
213
- * Bug fixed: Currency switcher widget was not showing under the available widgets list in the backend.
214
- * Bug fixed: The breadcrumbs structure dropped the shop page when WooCommerce Multilingual was activated.
215
- * Bug fixed: Manually adding a product to an order is not taking a custom price (secondary currency) if set.
216
- * Bug fixed: Error when trying to add a category when �All languages� was selected in the admin language switcher.
217
-
218
- = 3.3.4 =
219
- * Fixed bug related to back-compatibility with WooCommerce versions < 2.2.*
220
-
221
- = 3.3.3 =
222
- * Compatibility with WooCommerce 2.2.x
223
- * Auto-download WooCommerce translations for active and new languages
224
- * Page titles translations for WooCommerce pages taken from WooCommerce Multilingual .mo files
225
- * Product base, product category slug, product tag slug and product attribute bases will always have to be translated via String Translation (not using WooCommerce translations from the mo files)
226
- * Added warning message on settings page when product base not translated to all languages
227
- * Fixed: Base currency format ignored after adding additional currency
228
- * Fixed: Shipping class names were displayed wrong on the WooCommerce settings page when switching the admin language
229
- * Fixed: WooCommerce pages were not working correctly after changing the default language
230
- * Fixed: WooCommerce native interface doesn't copy the variations prices
231
-
232
- = 3.3.2 =
233
- * Fixed: 'Language warning' appears when editing product translations using the native WooCommerce editor
234
- * Fixed: Variation cannot be added to an existing order
235
- * Fixed: Media Attachment controls for products missing
236
- * Prevented disabling of option to use slugs in different language for products
237
- * Fixed: Slashes not stripped correctly in product translation editor
238
- * Fixed: 'Copy content' button not working on product translations
239
- * Disable admin language switcher on the Product => Attributes screen
240
- * Allow 'woocommerce_price_display_suffix' to be translated with String Translation
241
- * Allow 'woocommerce_email_from_name' and 'woocommerce_email_from_address' to be translated with String Translation
242
- * Fixed: Menu order is not synced when using "drag and drop" in Products => Sort Products
243
- * Fixed: One WooCommerce attribute field won't translate
244
- * Fixed: Variations not showing in the correct language in some circumstances
245
- * Optimizations for the WooCommerce Multilingual products admin page - faster when a large number of products exist
246
- * Duplicate translations too when duplicating a WooCommerce product
247
- * Fixed: WC Price Filter showing the wrong currency
248
- * Ability to use any currency when creating an order in the backend.
249
-
250
- = 3.3.1 =
251
- * Some strings were showing in the wrong language on the cart and checkout page.
252
- * Product category urls - in some cases the product category urls didn t work on sites with the default language different than English.
253
- * Products gallery images synchronization - sometimes, when synchronizing products "gallery images" and categories, the result was not updated correctly on the Troubleshooting page
254
- * Fixed issues related to WooCOmmerce Dynamic Pricing
255
- * Supoprt for translating WooCommerce 2.1+ endpoints
256
- * 'Continue Shopping' button pointing to the wrong url
257
- * Problem with short links
258
- * Fixed some issues with Table Rate Shipping
259
-
260
- = 3.3 =
261
- * Performance improvements: optimized database queries
262
- * Support rounding rules for converted prices
263
- * More advanced GUI for Multi-currency options
264
- * GUI for currency switchers (including widget)
265
- * Added option to synchronize product category display type & thumbnail
266
- * Performance improvement for WCML_Terms::translate_category_base (avoid switching locales)
267
- * Send admin notifications to admin default language
268
- * Dependencies update: WooCommerce Multilingual requires WPML 3.1.5
269
- * Set language information for existing products when installing WCML the first time.
270
- * Do not allow disabling all currencies for a language
271
- * Removed clean up test content and send to translation dropdown on products editor page
272
- * Message about overwritten settings in wpml-config made more explicit
273
- * Lock Default variation select field in product translations
274
- * After change shipping method on cart page we will see not translated strings
275
- * Fixed bug related to shipping cost calculation in multi-currency mode
276
- * With php magic quotes on, products translations with quotes have backslashes
277
- * Bug related to translation of grouped products simple product not showing up on front end
278
- * Stock actions on the order page don t work correct with translated products
279
- * For Orders save attributes in default language and display them on order page in admin language
280
- * Attribute Label appearing untranslated in backend order
281
- * Memory issues on the Products tab when we have a large number of products
282
- * product-category not translated in the default language.
283
- * WCML_Products does not have a method translated_cart_item_name
284
- * Order completed emails sent in default currency
285
- * Language suffix (e.g. @en) not hidden for product attributes on the front end
286
- * Quick edit functionality issues fixed
287
- * Fixed Call to undefined method WC_Session_Handler::get()
288
- * Fatal error when updating the order status to complete
289
- * Currency is not converted when you switch language until you refresh the page.
290
- * Super Admin not able to see the WCML menu
291
- * Checkout validation errors in default language instead of user language
292
- * Fixes for compatibility with Tab manager: Can t translate Additional Information tab title
293
- * Bug: SEO title & meta description changed to original
294
- * Bug: 404 on view my order on secondary language using language name added as a parameter
295
- * Bug: Permalink placeholders appear translated when using default language different than English
296
- * Fixes for compatibility with Table Rate shipping: shipping classes not decoded correctly in multi-currency mode
297
- * Bug: show all products link on WCML products page points to the wrong page no products
298
- * Bug fix: product page redirecting to homepage when the product post type slug was identical in different languages and language added as a parameter was set
299
- * Bug fixes related to File paths functionality (WooComemrce 2.1.x)
300
- * Bug: Product parents not synced between translations (grouped products)
301
- * Bug: Grouped products title incomplete
302
- * Bug: Db Error when saving translation of variable products with custom attributes
303
- * Bug: WooCommerce translated product attributes with spaces not showing
304
- * Bug: Deactivated currency still appears if you maintain the default currency for that language to Keep .
305
- * Bug: Incorrect shipping value on translated page
306
- * Bug: Reports for products including only products in the current language (WooCommerce 2.1.x)
307
- * Bug: WooCommerce translated product attributes with spaces not showing
308
- * Bug: Problems creating translations for shop pages when existing pages were trashed
309
- * Bug fix: Fatal error when Multi-currency is not enabled and Table Rate Shipping plugin is active
310
- * Fixed bug in compatibility with Tab Manager
311
- * Bug fix: Cart strings falling to default language after updating chosen shipping method
312
- * Bug fix: Reports not including selected product/category translations
313
-
314
-
315
- = 3.2.1 =
316
- * Fixed bug related to product category urls translaiton
317
- * Fixed bug related to back-compatibility with WooCommerce 2.0.20
318
-
319
- = 3.2 =
320
- * Compatibility with upcoming WooCommerce 2.1
321
- * Multi-currency support: configure currencies per languages
322
- * Multi-currency support: custom prices for different currencies
323
- * Support translation for the attribute base (permalinks)
324
- * Bug: Emails not sent in the correct language when uses bulk action on orders list page
325
- * Bug: Order notes email in wrong language in certain circumstances
326
- * Bug: Shipping method names are being registered in the wrong language
327
- * Bug: WooCommerce Multilingual menu doesn't display for translators
328
- * Bug: Using 'category' for products cat slug conflicts with posts 'category'
329
- * Bug: Paypal rejects payments with decimals on certain currencies
330
-
331
- = 3.1 =
332
- * Support for multi-currency (independent of language) BETA
333
- * Support for translating products via ICanLocalize (professional translation)
334
- * Option to synchronize product translation dates
335
- * Compatibility with Table Rate Shipping and other extensions
336
- * Better handling for couponse
337
- * Fixed bug: product attributes not saved on orders
338
- * Fixed bug: Can't get to the cart & checkout pages if they are set as child pages
339
- * Fixed bug: Style conflicts in Dashboard for Arabic
340
- * Fixed various issues with notification emails
341
- * Fixed bug: Variable products default selection is not copied to translations.
342
- * Fixed bug: Product Table is not showing Product Draft count
343
-
344
- = 3.0.1 =
345
- * Replaced deprecated jQuery function live()
346
- * Fixed bug: language names not localized on products editor page
347
- * Fixed bug: Can't set "Custom post type" to translate
348
- * Fixed bug: Translation fields not visible - In certain circumstances (e.g. search) the translation fields corresponding to the translated languages were missing
349
- * Fixed alignment for Update/Save button in the products translation editor
350
- * Fixed bug: Default selection not copied to duplicate products
351
- * Fixed bug: Price doesn't change when change language on the cart page when set "I will manage the pricing in each currency myself"
352
- * Resolved one compatibility issue with Woosidebars
353
- * Direct translators to the products translation editor automatically (instead of the standard post translation editor)
354
- * Fixed bug: In some situations (different child categories with the same name) the wrong categories were set to a duplicated product.
355
- * Enhancement: Add icons for products in the products translation editor
356
- * Register WooCommerce strings (defined as admin texts in the wpml config file) automatically on plugin activation
357
- * WPML (+addons) - new versions required.
358
- * lcfirst is only available since php 5.3
359
- * Identify fields on known plugins and show their human name in our product translation table (support for WordPress SEO for now)
360
-
361
- = 3.0 =
362
- * Brand new GUI and workflow
363
- * Support for easy taxonomy translation
364
- * Bariations synchronization
365
- * Product images synchronization
366
-
367
-
368
- = 2.3.3 =
369
- * Fix logout link not working in secondary language
370
- * Fix accepting orders in backend leading to 404
371
- * Set email headings & subjects as translatable
372
- * Set order language when sending order emails from admin
373
- * Sync product tags the same way as categories
374
- * Fix bug in ajax product search filter
375
- * Support for WooCommerce Brands extension (http://www.woothemes.com/products/brands/)
376
- * Initial support for Translation Editor
377
- * Fix bug with cart currency updates and variations
378
- * Fix language in new customer note notifications
379
-
380
- = 2.3.2 =
381
- * Sync also default options for custom attributes.
382
- * Global resync (done only once) of the orderings of product attribute values and categories across all languages.
383
- * Fixed a bug and a corner case in variation synchronization.
384
-
385
- = 2.3.1 =
386
- * Fixed incompatibility with PHP 5.2
387
-
388
- = 2.3 =
389
- * Refactor translation and currency conversion of products & variations in cart
390
- * A problem we had with shipping selection was resolved in WooCommerce itself
391
- * Improved synchronization of global product attributes, whether used for variations or not
392
- * Custom product attributes registered as strings when defined in the backend
393
- * Don't adjust the currency symbol in WooCommerce settings page
394
- * Term and product category order is synchronized among languages
395
- * Additional filters for WooCommerce emails
396
- * Fixed layered nav widgets in translated shop page
397
- * Synchronize Product Categories
398
-
399
- = 2.2 =
400
- * Price in mini-cart refreshed when changing language
401
- * Fix bug in multilingual currency setting that slipped in 2.1
402
-
403
- = 2.1 =
404
- * Add admin notices for required plugins
405
- * Add support for 'Review Order' and 'Lost Password' pages
406
- * Fix rounding issues in currency conversion
407
- * Variations: pick translated terms using 'trid' gives better results
408
- * Variations: sync to all languages when there are more than 2 languages
409
- * Improvement: load JS/CSS only when needed
410
-
411
- = 2.0 =
412
- * Fix variation sync to more than one language
413
- * Fix custom field sync for new variations
414
- * Fix rounding of amounts in PayPal
415
- * Adjust product stock sync to WC 2.x
416
- * Add automatic id translation of logout page
417
- * Adjust permalink warnings to WC 2.x
418
- * Clean up code
419
-
420
- = 1.5 =
421
- * Fixed manually setting prices in translated products.
422
- * Take advantage of WPML's new slug translation feature.
423
- * Added the possibility of translating custom attributes.
424
- * Improvements to product variation synchronization.
425
- * Fixed product stock sync for variable products .
426
- * Fix and improve checks made to incompatible permalink configurations.
427
- * Fix tax label translation when there is more than one of them.
428
- * Send order notifications in the language the order was made.
429
- * Removed several warnings and updated deprecated code.
430
- * Cleanup language configuration file and add missing strings.
431
-
432
- = 1.4 =
433
- * Allow translating the 'Terms & Conditions' page.
434
- * Register shipping methods strings for translation.
435
- * Register several tax-related strings for translation.
436
- * Fix registration of payment gateway titles and descriptions.
437
- * Synchronize the default attribute of a variable product across its translations.
438
- * Allow saving WooCommerce/Settings while using a non-default language.
439
- * Fix problems when the shop page is at the home page.
440
- * Allow using Wordpress default permalink structure aswell.
441
- * Fix amount sent to payment gateway when using multiple currencies.
442
- * Fix for language switcher in shop pages (fixed in WPML)
443
- * Fix for subscriptions module price not showing (fixed in WPML)
444
- * Rewrite product variation sync: each variation is related to its translations, sync becomes easier
445
- * Remove several PHP warnings and notices.
446
- * Send order status update emails in the language the order was made.
447
-
448
- = 1.3 =
449
- * Fixed all custom fields synchronization between translations
450
- * Fixed the stock issue for translations
451
- * Fixed the price filter widget for multiple currencies feature
452
- * Fixed product duplication to a second language
453
- * Payment gateways texts now are translatable
454
- * Custom variables translations now will be shown in the correct language
455
-
456
- = 1.2 =
457
- * Added helpful documentation buttons
458
- * Added makes new attributes translatable automatically
459
- * Added payment gateways translations
460
- * Fixed order statuses disappeared in the orders page
461
- * Fixed attributes translations in duplicated variations
462
- * Fixed PHP warning when adding variations is in question
463
-
464
- = 1.1 =
465
- * Added multi-currency feature
466
- * Fixed synchronization of attributes and variations
467
- * Fixed translation of attributes
468
- * Fixed JS error in the checkout page
469
- * Fixed enable guest checkout (no account required) issue
470
- * Fixed Up-sells/Cross-sells search (showed all translated products)
471
- * Fixed 'Show post translation link' repeating issue
472
-
473
- = 1.0 =
474
- * Fixed 'Return to store' URL
475
- * Fixed language selector for the translated shop base pages
476
- * Fixed the product remove URL in the translated language
477
- * Fixed the checkout URL in the translated language
478
- * Fix to prevent incorrect product URL in the shop base page when the permalink is not 'shop'
479
-
480
- = 0.9 =
481
- * First release
482
-
483
- == Upgrade Notice ==
484
-
485
- = 2.0 =
486
- More variation fixes and compatibility with WooCommerce 2.x
487
-
488
- = 1.5 =
489
- Variation translation works a lot better now. This version runs best with WooCommerce 1.6.6.
490
-
491
- = 1.4 =
492
- This version runs with WooCommerce 1.6.5.x and 1.7.x. Recommeded WPML version is 2.6.2 and above.
493
-
494
- = 1.3 =
495
- Fixed compatibility between WooCommerce 1.5.8 and WPML 2.5.2
496
-
497
- = 1.2 =
498
- Added a few improvements and fixed bugs.
499
-
500
- = 1.1 =
501
- Fixed a few bugs. Added multi-currency mode.
502
-
503
- = 1.0 =
504
- Recommended update! Fixed a few bugs;
505
-
506
- = 0.9 =
507
- * First release
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === WooCommerce Multilingual - run WooCommerce with WPML ===
2
+ Contributors: AmirHelzer, dominykasgel, dgwatkins, adelval
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: 4.2.2
8
+ Stable tag: 3.6.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
+ = Features =
17
+
18
+ * Lets you translate different kinds of WooCommerce product types
19
+ * Central management for translating product categories, tags and custom attributes
20
+ * Automatically synchronizes product variations and images
21
+ * Keeps the same language through the checkout process
22
+ * Sends emails to clients and admins in their selected language
23
+ * Allows inventory tracking without breaking products into languages
24
+ * Enables running a single WooCommerce store with multiple currencies
25
+
26
+ = Usage Instructions =
27
+
28
+ For step by step instructions on setting up a multilingual shop, please go to [WooCommerce Multilingual Manual](http://wpml.org/documentation/related-projects/woocommerce-multilingual/) page.
29
+
30
+ After installing, go to WPML->WooCommerce Multilingual. The 'General settings' tab will let you translate the store pages and report what taxonomy requires translation.
31
+
32
+ Then, continue to the 'Products' and any categories, tags and custom taxonomy that you use.
33
+
34
+ When you need help, go to [WooCommerce Multilingual support forum](http://wpml.org/forums/topic-tag/woocommerce/).
35
+
36
+ = Downloads =
37
+
38
+ This version of WooCommerce Multilingual works with WooCommerce 2.x.
39
+
40
+ You will also need [WPML](http://wpml.org), together with the String Translation and the Translation Management modules, which are part of the [Multilingual CMS](http://wpml.org/purchase/) package.
41
+
42
+ = Minimum versions for WPML and modules =
43
+
44
+ WooCommerce Multilingual checks that the following versions of WPML and their components are active:
45
+
46
+ * WPML Multilingual CMS - 3.1.5
47
+ * WPML String Translation - 2.0
48
+ * WPML Translation Management - 1.9
49
+ * WPML Media - 2.1
50
+
51
+ Without having all these running, WooCommerce Multilingual will not be able to run.
52
+
53
+ == Installation ==
54
+
55
+ 1. Upload 'woocommerce-multilingual' to the '/wp-content/plugins/' directory
56
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
57
+ 3. Translate the shop pages
58
+
59
+ == Frequently Asked Questions ==
60
+
61
+ = Does this work with other e-commerce plugins? =
62
+
63
+ No. This plugin is tailored for WooCommerce.
64
+
65
+ = What do I need to do in my theme? =
66
+
67
+ Make sure that your theme is not hard-coding any URL. Always use API calls to receive URLs to pages and you'll be fine.
68
+
69
+ = My checkout page displays in the same language =
70
+
71
+ In order for the checkout and store pages to appear translated, you need to create several WordPress pages and insert the WooCommerce shortcodes into them. You'll have to go over the [documentation](http://wpml.org/documentation/related-projects/woocommerce-multilingual/) and see that you performed all steps on the way.
72
+
73
+ == Screenshots ==
74
+
75
+ 1. Translation controls for products
76
+ 2. Product categories translations
77
+ 3. Multiple currencies
78
+
79
+ == Changelog ==
80
+
81
+ = 3.6.5 =
82
+ * Enabled the WooCommerce Bookings compatibility support
83
+ * Bug fix: Fixed a bug that caused a wrong price to be displayed when adding a product in the cart from two different languages
84
+ * Bug fix: After a product translation was edited in the standard product editor, the WooCommerce custom attribute translations were lost
85
+ * Bug fix: The product variations failed to sync when the term_id was different than the term_taxonomy_id for the terms used to create the variations
86
+ * Bug fix: Some product translations were showing non existing discounted prices
87
+ * Fixed a couple of compatibility issues with WooCommerce Product Bundles (e.g. with using the Flatsome theme)
88
+ * Fixed a small usability issue related to Sensei
89
+ * Bug fix: Stock quantity not synchronized when items were used in orders created in the backend
90
+ * Bug fix: Payment gateways strings were not registered for string translation
91
+ * Bug fix: Global Attributes were not translated in the WooCommerce Mail
92
+ * Bug fix: In some cases the WooCommerce endpoints were not translated correctly
93
+ * Bug fix: An extra 'a' tag was added to products in the mini-cart
94
+ * Bug fix: A 404 error was returned on the translated product category archive page
95
+ * Bug fix: Some shipping methods were displayed incorrectly on the cart page when using Table Rate Shipping
96
+ * Bug fix: In some cases prices showing the Paypal order summary included decimals even if the prices were supposed to be rounded to integers
97
+ * Bug fix: When adding different variations of a product, a single variation was added more times
98
+ * Bug fix: Urls in the secondary languages were not working properly when using the deafault translations (from teh mo files) instead of translating tehm with string translation
99
+ * Bug fix: In some cases some email notification strings were not registered
100
+ * Fixed a compatibility problem with Dynamic Pricing: in a specific context, based on a price rule, the end price was multiplied by a factor with each page reload
101
+
102
+ = 3.6.4 =
103
+ * Bug fix: Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM (introduced in 3.6.1)
104
+ * Bug fix: In some conditions it was not possible to load product pages in other languages than the default.
105
+ * Bug fix: Fixed some compatibility issues with Product Bundles
106
+
107
+ = 3.6.3 =
108
+ * Fixed a bug causing a PHP warning when using an older version of WPML String Translation
109
+
110
+ = 3.6.2 =
111
+ * Bug fix: A product could appear multiple times in the cart when added in different languages
112
+ * Bug fix: Product attribute labels translations were not showing on the frontend in some circumstances
113
+ * Bug fix: Attributes labels translations not showing on the 'Add product' admin panel
114
+ * Bug fix: The flags for custom languages were not showing correctly on the products editor screen
115
+ * Bug fix: The currency switcher was missing from the WooCommerce Status dashboard widget (in version 3.6.1)
116
+ * Bug fix: The auto-adjust ids functionality from WPML was not working with wc_get_product_terms
117
+ * Bug fix: The 'shop' link was stripped out of the breadcrumb in the Woocommerce product page.
118
+ * Bug fix: The product category template was not working correctly in secondary languages
119
+ * Bug fix: Fixed a problem with sanitize_title for variations in Danish and German
120
+ * Moved the Tab manager settings to separate file from the WCML config
121
+ * Duplicates for media are now being created, if missing, when product translations are created.
122
+ * Bug fix: Fixed a fatal error that was occurring when the WPML was not updated to version 3.2 while the WPML addons were updated to the latest versions.
123
+
124
+ = 3.6.1 =
125
+ * Updated the taxonomy translation synchronization to be compatible with WPML 3.2
126
+ * Bug fix: the notice that shows up on the general settings page when the default language is not English did not hide when it was dismissed.
127
+ * Bug fix: after adding a new currency and reloading the page, the new currency was gone. Also the exchange rate was wrong after re-adding teh currency.
128
+ * Bug fix: an incorrect currency was being passed to the payment gateway when paying for an order created in the backend.
129
+ * Bug fix: the prices in the custom currencies were not saved when a product was published.
130
+ * Bug fix: extra backslashes were added when translating custom attribute name in products.
131
+ * Bug fix: custom product categories template was not working as expected
132
+ * Bug fix: updating WordPress language packs was not working when using custom locale codes in WPML
133
+ * Bug fix: Variable products returned error in secondary language "This product is currently out of stock and unavailable."
134
+ * Bug fix: The publishing date was not updating on translation when changed on the product in the original language
135
+ * Bug fix: Attributes with the value "0" value were not displayed on the front end
136
+ * Bug fix: Modified Free shipping label could not be translated
137
+ * Bug fix: When editing product translations it was possible to save an empty slug.
138
+
139
+ = 3.6 =
140
+ * Added the ability to edit the slugs of the translated products in the products editor
141
+ * Added the option to show only products with custom prices on the front end
142
+ * Performance improvements: fewer db queries, caching. Up to 40% faster on large sites.
143
+ * Support for the 'lang' parameter in WooCommerce REST API calls
144
+ * Option to hide the default currency selector on the product page
145
+ * Bug fix: Fixed a design issue on the 'connect with translation' pop-up on products.
146
+ * Bug fix: Accessing the source content in the WooCommerce Multilingual product translation content editor was not possible sometimes.
147
+ * Bug fix: 'Invisible' products were showing as links in the cart instead of just names.
148
+ * Bug fix: The cart_widget.js code was always loaded.
149
+ * Bug fix: Screen Options & Check All not working on WooCommerce Orders page
150
+ * Bug fix: Sometimes the IPN Url sent to Paypal was wrong causing a 404 error after the payment was complete
151
+ * Bug fix: Translated endpoint pages were sometimes returning 404
152
+ * Bug fix: When using a default language different than English, the product permalink base was not in English.
153
+
154
+ = 3.5.5 =
155
+ * Bug fixed: Custom attributes were disappearing after updating a product in the WooCommerce native product editor
156
+ * Tested compatibility with WordPress 4.2
157
+ * Security review and fixes
158
+ * Made the key "woocommerce_cancelled_order_settings" translatable
159
+ * Email heading and subject sent after placing an order were not translated when using ‘Complete’ button on orders page
160
+ * Bug fixed: warning about minimum order requirement always showing in some conditions when using a child theme
161
+
162
+ = 3.5.4 =
163
+ * Bug fixed: Can't access source content in WCML product translation table
164
+ * Bug fixed: Custom Post Types leads to 404 error
165
+
166
+ = 3.5.3 =
167
+ * Bug fixed: Redirection issues with "Your latest posts" as a front page
168
+ * Bug fixed: Yoast fileds not saved in WooCommerce Multilingual products table
169
+ * Bug fixed: Translated endpoints returns page not found
170
+ * Bug fixed: Custom fields are locked in variation section
171
+
172
+ = 3.5.2 =
173
+ * Compatibility with WooCommerce 2.3.x
174
+ * Bug fixed: Redirection issues with "Shop" page as front page
175
+ * Bug fixed: Language column was missing from the products list page
176
+ * Bug fixed: Product tags disappeared after updating the product attribute 'size'
177
+ * Bug fixed: Featured image title and text were not editable in the WooCommerce Multilingual Translation Table
178
+ * Bug fixed: Only first three attributes were available for translation
179
+ * Bug fixed: The shipping fee was not converted correctly when using the multi-currency mode
180
+ * Bug fixed: The default currency configuration (decimal & thousand separator) was ignored when the multi-currency was active
181
+ * Bug fixed: Subsequent request to product preview page lead to a 404 page.
182
+ * Bug fixed: 'Insert link' button on the visual editor of the products translations screen was not working.
183
+ * Bug fixed: Fixed another compatibility problem with WooCommerce Product Tabs
184
+ * Bug fixed: A variable product was showing an incorrect price in the cart
185
+ * Bug fixed: The flat rate shipping was showing the wrong price on the checkout page in certain conditions
186
+
187
+ = 3.5.1 =
188
+ * Bug fixed: Performance issue with queries number
189
+
190
+ = 3.5 =
191
+ * Added support for creating products in secondary languages only.
192
+ * Added enhancements for the Woocommerce Multilingual products table (filter by original language, display language flag).
193
+ * Added option to synchronize the products and product taxonomies order.
194
+ * Bug fixed: The cart was not updating quantities for variable product (when have more than one variable in the cart).
195
+ * Bug fixed: The cart total was not updating when using get_cart_total() and get_cart_subtotal() functions in other plugins or themes.
196
+ * Bug fixed: Wrong price format and order total were displayed on the new order page in the WP admin
197
+ * Bug fixed: The featured image and the gallery images were overridden when updating translations
198
+ * Bug fixed: Fixed the 'Keep' option that allows keeping the same currency on teh front end, when switching the language.
199
+ * Bug fixed: Fixed a javascript error that was showing when changing currencies order
200
+ * Bug fixed: The decimal number was not working correctly for the default currency
201
+ * Bug fixed: Fixed a compatibility problem with WooCommerce Product Tabs
202
+ * Bug fixed: A coupon was applied incorrectly to all products in the cart when they were defined for specific product variations.
203
+ * Bug fixed: WooCommerce note email language was not correct
204
+ * Bug fixed: WooCommerce reports were showing duplicate products
205
+ * Bug fixed: When using WordPress in a folder, the checkout showed an 'expired session' error message.
206
+ * Added support currency argument in raw_price_filter
207
+
208
+ = 3.4.3 =
209
+ * Bug fixed: Incorrect decimal separator for prices on WordPress admin
210
+ * Bug fixed: ‘Insert link’ button not working on products translator interface.
211
+ * Bug fixed: Switching currency after adding to cart was adding an additional item
212
+ * Bug fixed: Review setting not preserved on translation of variable product
213
+ * Bug fixed: “Visible on the products page” option for product attributes was still selectable for product translation.
214
+ * Bug fixed: Translation status icon not updated on products translator page
215
+ * Bug fixed: Shipping rate was lost when WPML is activated
216
+ * Bug fixed: WooCommerce ‘sort by’ links going to blog not products
217
+ * Bug fixed: Option to select currency position was missing immediately after a new currency was added
218
+
219
+ = 3.4.2 =
220
+ * Accommodated taxonomy translation changes in WPML
221
+
222
+ = 3.4.1 =
223
+ * Bug fix: A variable product was somtimes breaking the shopping cart
224
+ * Fixes added for translating custom fields that are textareas
225
+
226
+ = 3.4 =
227
+ * Additional support for updating the WooCommerce translations.
228
+ * Added currency switcher for the WooCommerce status widget on the WordPress admin dashboard.
229
+ * Usability fixes for the translation of custom attributes in the WooCommerce native editor.
230
+ * Added validation for the sale amount when using custom prices with multi-currency.
231
+ * Bug fixed: Incorrect currency symbol position on edit order page.
232
+ * Bug fixed: Incorrect currency displayed for order when editing an order in the backend.
233
+ * Bug fixed: Coupon option 'Exclude sale items' was not being applied correctly. Sale items were not excluded.
234
+ * Bug fixed: Currency switcher widget was not showing under the available widgets list in the backend.
235
+ * Bug fixed: The breadcrumbs structure dropped the shop page when WooCommerce Multilingual was activated.
236
+ * Bug fixed: Manually adding a product to an order is not taking a custom price (secondary currency) if set.
237
+ * Bug fixed: Error when trying to add a category when “All languages” was selected in the admin language switcher.
238
+
239
+ = 3.3.4 =
240
+ * Fixed bug related to back-compatibility with WooCommerce versions < 2.2.*
241
+
242
+ = 3.3.3 =
243
+ * Compatibility with WooCommerce 2.2.x
244
+ * Auto-download WooCommerce translations for active and new languages
245
+ * Page titles translations for WooCommerce pages taken from WooCommerce Multilingual .mo files
246
+ * Product base, product category slug, product tag slug and product attribute bases will always have to be translated via String Translation (not using WooCommerce translations from the mo files)
247
+ * Added warning message on settings page when product base not translated to all languages
248
+ * Fixed: Base currency format ignored after adding additional currency
249
+ * Fixed: Shipping class names were displayed wrong on the WooCommerce settings page when switching the admin language
250
+ * Fixed: WooCommerce pages were not working correctly after changing the default language
251
+ * Fixed: WooCommerce native interface doesn't copy the variations prices
252
+
253
+ = 3.3.2 =
254
+ * Fixed: 'Language warning' appears when editing product translations using the native WooCommerce editor
255
+ * Fixed: Variation cannot be added to an existing order
256
+ * Fixed: Media Attachment controls for products missing
257
+ * Prevented disabling of option to use slugs in different language for products
258
+ * Fixed: Slashes not stripped correctly in product translation editor
259
+ * Fixed: 'Copy content' button not working on product translations
260
+ * Disable admin language switcher on the Product => Attributes screen
261
+ * Allow 'woocommerce_price_display_suffix' to be translated with String Translation
262
+ * Allow 'woocommerce_email_from_name' and 'woocommerce_email_from_address' to be translated with String Translation
263
+ * Fixed: Menu order is not synced when using "drag and drop" in Products => Sort Products
264
+ * Fixed: One WooCommerce attribute field won't translate
265
+ * Fixed: Variations not showing in the correct language in some circumstances
266
+ * Optimizations for the WooCommerce Multilingual products admin page - faster when a large number of products exist
267
+ * Duplicate translations too when duplicating a WooCommerce product
268
+ * Fixed: WC Price Filter showing the wrong currency
269
+ * Ability to use any currency when creating an order in the backend.
270
+
271
+ = 3.3.1 =
272
+ * Some strings were showing in the wrong language on the cart and checkout page.
273
+ * Product category urls - in some cases the product category urls didn�t work on sites with the default language different than English.
274
+ * Products gallery images synchronization - sometimes, when synchronizing products "gallery images" and categories, the result was not updated correctly on the Troubleshooting page
275
+ * Fixed issues related to WooCOmmerce Dynamic Pricing
276
+ * Supoprt for translating WooCommerce 2.1+ endpoints
277
+ * 'Continue Shopping' button pointing to the wrong url
278
+ * Problem with short links
279
+ * Fixed some issues with Table Rate Shipping
280
+
281
+ = 3.3 =
282
+ * Performance improvements: optimized database queries
283
+ * Support rounding rules for converted prices
284
+ * More advanced GUI for Multi-currency options
285
+ * GUI for currency switchers (including widget)
286
+ * Added option to synchronize product category display type & thumbnail
287
+ * Performance improvement for WCML_Terms::translate_category_base (avoid switching locales)
288
+ * Send admin notifications to admin default language
289
+ * Dependencies update: WooCommerce Multilingual requires WPML 3.1.5
290
+ * Set language information for existing products when installing WCML the first time.
291
+ * Do not allow disabling all currencies for a language
292
+ * Removed �clean up test content� and �send to translation� dropdown on products editor page
293
+ * Message about overwritten settings in wpml-config made more explicit
294
+ * Lock �Default variation� select field in product translations
295
+ * After change shipping method on cart page we will see not translated strings
296
+ * Fixed bug related to shipping cost calculation in multi-currency mode
297
+ * With php magic quotes on, products translations with quotes have backslashes
298
+ * Bug related to translation of grouped products simple product not showing up on front end
299
+ * Stock actions on the order page don�t work correct with translated products
300
+ * For Orders save attributes in default language and display them on order page in admin language
301
+ * Attribute Label appearing untranslated in backend order
302
+ * Memory issues on the Products tab when we have a large number of products
303
+ * �product-category� not translated in the default language.
304
+ * �WCML_Products� does not have a method �translated_cart_item_name�
305
+ * Order completed emails sent in default currency
306
+ * Language suffix (e.g. @en) not hidden for product attributes on the front end
307
+ * Quick edit functionality issues fixed
308
+ * Fixed �Call to undefined method WC_Session_Handler::get()�
309
+ * Fatal error when updating the order status to �complete�
310
+ * Currency is not converted when you switch language until you refresh the page.
311
+ * �Super Admin� not able to see the WCML menu
312
+ * Checkout validation errors in default language instead of user language
313
+ * Fixes for compatibility with Tab manager: Can�t translate �Additional Information� tab title
314
+ * Bug: SEO title & meta description changed to original
315
+ * Bug: 404 on �view my order� on secondary language using �language name added as a parameter�
316
+ * Bug: Permalink placeholders appear translated when using default language different than English
317
+ * Fixes for compatibility with Table Rate shipping: shipping classes not decoded correctly in multi-currency mode
318
+ * Bug: �show all products� link on WCML products page points to the wrong page � no products
319
+ * Bug fix: product page redirecting to homepage when the product post type slug was identical in different languages and �language added as a parameter� was set
320
+ * Bug fixes related to File paths functionality (WooComemrce 2.1.x)
321
+ * Bug: Product parents not synced between translations (grouped products)
322
+ * Bug: Grouped products title incomplete
323
+ * Bug: Db Error when saving translation of variable products with custom attributes
324
+ * Bug: WooCommerce translated product attributes with spaces not showing
325
+ * Bug: Deactivated currency still appears if you maintain the default currency for that language to �Keep�.
326
+ * Bug: Incorrect shipping value on translated page
327
+ * Bug: Reports for products including only products in the current language (WooCommerce 2.1.x)
328
+ * Bug: WooCommerce translated product attributes with spaces not showing
329
+ * Bug: Problems creating translations for shop pages when existing pages were trashed
330
+ * Bug fix: Fatal error when Multi-currency is not enabled and �Table Rate Shipping� plugin is active
331
+ * Fixed bug in compatibility with Tab Manager
332
+ * Bug fix: Cart strings falling to default language after updating chosen shipping method
333
+ * Bug fix: Reports not including selected product/category translations
334
+
335
+
336
+ = 3.2.1 =
337
+ * Fixed bug related to product category urls translaiton
338
+ * Fixed bug related to back-compatibility with WooCommerce 2.0.20
339
+
340
+ = 3.2 =
341
+ * Compatibility with upcoming WooCommerce 2.1
342
+ * Multi-currency support: configure currencies per languages
343
+ * Multi-currency support: custom prices for different currencies
344
+ * Support translation for the attribute base (permalinks)
345
+ * Bug: Emails not sent in the correct language when uses bulk action on orders list page
346
+ * Bug: Order notes email in wrong language in certain circumstances
347
+ * Bug: Shipping method names are being registered in the wrong language
348
+ * Bug: WooCommerce Multilingual menu doesn't display for translators
349
+ * Bug: Using 'category' for products cat slug conflicts with posts 'category'
350
+ * Bug: Paypal rejects payments with decimals on certain currencies
351
+
352
+ = 3.1 =
353
+ * Support for multi-currency (independent of language) BETA
354
+ * Support for translating products via ICanLocalize (professional translation)
355
+ * Option to synchronize product translation dates
356
+ * Compatibility with Table Rate Shipping and other extensions
357
+ * Better handling for couponse
358
+ * Fixed bug: product attributes not saved on orders
359
+ * Fixed bug: Can't get to the cart & checkout pages if they are set as child pages
360
+ * Fixed bug: Style conflicts in Dashboard for Arabic
361
+ * Fixed various issues with notification emails
362
+ * Fixed bug: Variable products default selection is not copied to translations.
363
+ * Fixed bug: Product Table is not showing Product Draft count
364
+
365
+ = 3.0.1 =
366
+ * Replaced deprecated jQuery function live()
367
+ * Fixed bug: language names not localized on products editor page
368
+ * Fixed bug: Can't set "Custom post type" to translate
369
+ * Fixed bug: Translation fields not visible - In certain circumstances (e.g. search) the translation fields corresponding to the translated languages were missing
370
+ * Fixed alignment for �Update/Save� button in the products translation editor
371
+ * Fixed bug: Default selection not copied to duplicate products
372
+ * Fixed bug: Price doesn't change when change language on the cart page when set "I will manage the pricing in each currency myself"
373
+ * Resolved one compatibility issue with Woosidebars
374
+ * Direct translators to the products translation editor automatically (instead of the standard post translation editor)
375
+ * Fixed bug: In some situations (different child categories with the same name) the wrong categories were set to a duplicated product.
376
+ * Enhancement: Add icons for products in the products translation editor
377
+ * Register WooCommerce strings (defined as admin texts in the wpml config file) automatically on plugin activation
378
+ * WPML (+addons) - new versions required.
379
+ * lcfirst is only available since php 5.3
380
+ * Identify fields on known plugins and show their human name in our product translation table (support for WordPress SEO for now)
381
+
382
+ = 3.0 =
383
+ * Brand new GUI and workflow
384
+ * Support for easy taxonomy translation
385
+ * Bariations synchronization
386
+ * Product images synchronization
387
+
388
+
389
+ = 2.3.3 =
390
+ * Fix logout link not working in secondary language
391
+ * Fix accepting orders in backend leading to 404
392
+ * Set email headings & subjects as translatable
393
+ * Set order language when sending order emails from admin
394
+ * Sync product tags the same way as categories
395
+ * Fix bug in ajax product search filter
396
+ * Support for WooCommerce Brands extension (http://www.woothemes.com/products/brands/)
397
+ * Initial support for Translation Editor
398
+ * Fix bug with cart currency updates and variations
399
+ * Fix language in new customer note notifications
400
+
401
+ = 2.3.2 =
402
+ * Sync also default options for custom attributes.
403
+ * Global resync (done only once) of the orderings of product attribute values and categories across all languages.
404
+ * Fixed a bug and a corner case in variation synchronization.
405
+
406
+ = 2.3.1 =
407
+ * Fixed incompatibility with PHP 5.2
408
+
409
+ = 2.3 =
410
+ * Refactor translation and currency conversion of products & variations in cart
411
+ * A problem we had with shipping selection was resolved in WooCommerce itself
412
+ * Improved synchronization of global product attributes, whether used for variations or not
413
+ * Custom product attributes registered as strings when defined in the backend
414
+ * Don't adjust the currency symbol in WooCommerce settings page
415
+ * Term and product category order is synchronized among languages
416
+ * Additional filters for WooCommerce emails
417
+ * Fixed layered nav widgets in translated shop page
418
+ * Synchronize Product Categories
419
+
420
+ = 2.2 =
421
+ * Price in mini-cart refreshed when changing language
422
+ * Fix bug in multilingual currency setting that slipped in 2.1
423
+
424
+ = 2.1 =
425
+ * Add admin notices for required plugins
426
+ * Add support for 'Review Order' and 'Lost Password' pages
427
+ * Fix rounding issues in currency conversion
428
+ * Variations: pick translated terms using 'trid' gives better results
429
+ * Variations: sync to all languages when there are more than 2 languages
430
+ * Improvement: load JS/CSS only when needed
431
+
432
+ = 2.0 =
433
+ * Fix variation sync to more than one language
434
+ * Fix custom field sync for new variations
435
+ * Fix rounding of amounts in PayPal
436
+ * Adjust product stock sync to WC 2.x
437
+ * Add automatic id translation of logout page
438
+ * Adjust permalink warnings to WC 2.x
439
+ * Clean up code
440
+
441
+ = 1.5 =
442
+ * Fixed manually setting prices in translated products.
443
+ * Take advantage of WPML's new slug translation feature.
444
+ * Added the possibility of translating custom attributes.
445
+ * Improvements to product variation synchronization.
446
+ * Fixed product stock sync for variable products .
447
+ * Fix and improve checks made to incompatible permalink configurations.
448
+ * Fix tax label translation when there is more than one of them.
449
+ * Send order notifications in the language the order was made.
450
+ * Removed several warnings and updated deprecated code.
451
+ * Cleanup language configuration file and add missing strings.
452
+
453
+ = 1.4 =
454
+ * Allow translating the 'Terms & Conditions' page.
455
+ * Register shipping methods strings for translation.
456
+ * Register several tax-related strings for translation.
457
+ * Fix registration of payment gateway titles and descriptions.
458
+ * Synchronize the default attribute of a variable product across its translations.
459
+ * Allow saving WooCommerce/Settings while using a non-default language.
460
+ * Fix problems when the shop page is at the home page.
461
+ * Allow using Wordpress default permalink structure aswell.
462
+ * Fix amount sent to payment gateway when using multiple currencies.
463
+ * Fix for language switcher in shop pages (fixed in WPML)
464
+ * Fix for subscriptions module price not showing (fixed in WPML)
465
+ * Rewrite product variation sync: each variation is related to its translations, sync becomes easier
466
+ * Remove several PHP warnings and notices.
467
+ * Send order status update emails in the language the order was made.
468
+
469
+ = 1.3 =
470
+ * Fixed all custom fields synchronization between translations
471
+ * Fixed the stock issue for translations
472
+ * Fixed the price filter widget for multiple currencies feature
473
+ * Fixed product duplication to a second language
474
+ * Payment gateways texts now are translatable
475
+ * Custom variables translations now will be shown in the correct language
476
+
477
+ = 1.2 =
478
+ * Added helpful documentation buttons
479
+ * Added makes new attributes translatable automatically
480
+ * Added payment gateways translations
481
+ * Fixed order statuses disappeared in the orders page
482
+ * Fixed attributes translations in duplicated variations
483
+ * Fixed PHP warning when adding variations is in question
484
+
485
+ = 1.1 =
486
+ * Added multi-currency feature
487
+ * Fixed synchronization of attributes and variations
488
+ * Fixed translation of attributes
489
+ * Fixed JS error in the checkout page
490
+ * Fixed enable guest checkout (no account required) issue
491
+ * Fixed Up-sells/Cross-sells search (showed all translated products)
492
+ * Fixed 'Show post translation link' repeating issue
493
+
494
+ = 1.0 =
495
+ * Fixed 'Return to store' URL
496
+ * Fixed language selector for the translated shop base pages
497
+ * Fixed the product remove URL in the translated language
498
+ * Fixed the checkout URL in the translated language
499
+ * Fix to prevent incorrect product URL in the shop base page when the permalink is not 'shop'
500
+
501
+ = 0.9 =
502
+ * First release
503
+
504
+ == Upgrade Notice ==
505
+
506
+ = 2.0 =
507
+ More variation fixes and compatibility with WooCommerce 2.x
508
+
509
+ = 1.5 =
510
+ Variation translation works a lot better now. This version runs best with WooCommerce 1.6.6.
511
+
512
+ = 1.4 =
513
+ This version runs with WooCommerce 1.6.5.x and 1.7.x. Recommeded WPML version is 2.6.2 and above.
514
+
515
+ = 1.3 =
516
+ Fixed compatibility between WooCommerce 1.5.8 and WPML 2.5.2
517
+
518
+ = 1.2 =
519
+ Added a few improvements and fixed bugs.
520
+
521
+ = 1.1 =
522
+ Fixed a few bugs. Added multi-currency mode.
523
+
524
+ = 1.0 =
525
+ Recommended update! Fixed a few bugs;
526
+
527
+ = 0.9 =
528
+ * First release
woocommerce_wpml.class.php CHANGED
@@ -143,11 +143,19 @@ class woocommerce_wpml {
143
 
144
  $slug = $this->get_woocommerce_product_slug();
145
 
146
- $string = $wpdb->get_row($wpdb->prepare("SELECT id,status FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'URL slug: ' . $slug, $slug));
147
-
148
- if(!$string){
149
- do_action('wpml_register_single_string', 'WordPress', 'URL slug: ' . $slug, $slug);
 
 
150
  $string = $wpdb->get_row($wpdb->prepare("SELECT id,status FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'URL slug: ' . $slug, $slug));
 
 
 
 
 
 
151
  }
152
 
153
  if(empty($sitepress_settings['posts_slug_translation']['on']) || empty($sitepress_settings['posts_slug_translation']['types']['product'])){
@@ -426,6 +434,11 @@ class woocommerce_wpml {
426
  wp_enqueue_script('wpml_tm');
427
  }
428
  }
 
 
 
 
 
429
  }
430
 
431
  //load Tooltip js and styles from WC
@@ -554,23 +567,20 @@ class woocommerce_wpml {
554
  function filter_woocommerce_permalinks_option($value){
555
  global $sitepress_settings;
556
 
557
- if( function_exists('icl_t') ) {
558
-
559
- if (WPML_SUPPORT_STRINGS_IN_DIFF_LANG && isset($value['product_base']) && $value['product_base']) {
560
- do_action('wpml_register_single_string', 'URL slugs', 'URL slug: ' . trim($value['product_base'], '/'), trim($value['product_base'], '/'));
561
- // only register. it'll have to be translated via the string translation
562
- }
563
 
564
- $category_base = !empty($value['category_base']) ? $value['category_base'] : 'product-category';
565
- do_action('wpml_register_single_string', 'URL product_cat slugs - ' . $category_base, 'Url product_cat slug: ' . $category_base, $category_base);
566
 
567
- $tag_base = !empty($value['tag_base']) ? $value['tag_base'] : 'product-tag';
568
- do_action('wpml_register_single_string', 'URL product_tag slugs - ' . $tag_base, 'Url product_tag slug: ' . $tag_base, $tag_base);
569
 
570
- if (isset($value['attribute_base']) && $value['attribute_base']) {
571
- $attr_base = trim($value['attribute_base'], '/');
572
- do_action('wpml_register_single_string', 'URL attribute slugs - ' . $attr_base, 'Url attribute slug: ' . $attr_base, $attr_base);
573
- }
574
  }
575
 
576
  return $value;
143
 
144
  $slug = $this->get_woocommerce_product_slug();
145
 
146
+ if ( apply_filters( 'wpml_slug_translation_available', false) ) {
147
+ // Use new API for WPML >= 3.2.3
148
+ do_action( 'wpml_activate_slug_translation', $slug );
149
+
150
+ } else {
151
+ // Pre WPML 3.2.3
152
  $string = $wpdb->get_row($wpdb->prepare("SELECT id,status FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'URL slug: ' . $slug, $slug));
153
+
154
+ if(!$string){
155
+ do_action('wpml_register_single_string', 'WordPress', 'URL slug: ' . $slug, $slug);
156
+ $string = $wpdb->get_row($wpdb->prepare("SELECT id,status FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'URL slug: ' . $slug, $slug));
157
+ }
158
+
159
  }
160
 
161
  if(empty($sitepress_settings['posts_slug_translation']['on']) || empty($sitepress_settings['posts_slug_translation']['types']['product'])){
434
  wp_enqueue_script('wpml_tm');
435
  }
436
  }
437
+
438
+ if( !is_admin() ){
439
+ wp_register_script('cart-widget', WCML_PLUGIN_URL . '/assets/js/cart_widget.js', array('jquery'), WCML_VERSION);
440
+ wp_enqueue_script('cart-widget');
441
+ }
442
  }
443
 
444
  //load Tooltip js and styles from WC
567
  function filter_woocommerce_permalinks_option($value){
568
  global $sitepress_settings;
569
 
570
+ if (WPML_SUPPORT_STRINGS_IN_DIFF_LANG && isset($value['product_base']) && $value['product_base']) {
571
+ do_action('wpml_register_single_string', 'URL slugs', 'URL slug: ' . trim($value['product_base'], '/'), trim($value['product_base'], '/'));
572
+ // only register. it'll have to be translated via the string translation
573
+ }
 
 
574
 
575
+ $category_base = !empty($value['category_base']) ? $value['category_base'] : 'product-category';
576
+ do_action('wpml_register_single_string', 'URL product_cat slugs - ' . $category_base, 'Url product_cat slug: ' . $category_base, $category_base);
577
 
578
+ $tag_base = !empty($value['tag_base']) ? $value['tag_base'] : 'product-tag';
579
+ do_action('wpml_register_single_string', 'URL product_tag slugs - ' . $tag_base, 'Url product_tag slug: ' . $tag_base, $tag_base);
580
 
581
+ if (isset($value['attribute_base']) && $value['attribute_base']) {
582
+ $attr_base = trim($value['attribute_base'], '/');
583
+ do_action('wpml_register_single_string', 'URL attribute slugs - ' . $attr_base, 'Url attribute slug: ' . $attr_base, $attr_base);
 
584
  }
585
 
586
  return $value;
wpml-config.xml CHANGED
@@ -35,6 +35,13 @@
35
  <custom-field action="translate">_button_text</custom-field>
36
  <custom-field action="translate">_purchase_note</custom-field>
37
  <custom-field action="ignore">_wcml_custom_prices_status</custom-field>
 
 
 
 
 
 
 
38
  <custom-field action="copy">_per_product_pricing_active</custom-field>
39
  <custom-field action="copy">_pricing_rules</custom-field>
40
  </custom-fields>
35
  <custom-field action="translate">_button_text</custom-field>
36
  <custom-field action="translate">_purchase_note</custom-field>
37
  <custom-field action="ignore">_wcml_custom_prices_status</custom-field>
38
+ <custom-field action="ignore">_min_price_variation_id</custom-field>
39
+ <custom-field action="ignore">_min_regular_price_variation_id</custom-field>
40
+ <custom-field action="ignore">_min_sale_price_variation_id</custom-field>
41
+ <custom-field action="ignore">_max_price_variation_id</custom-field>
42
+ <custom-field action="ignore">_max_regular_price_variation_id</custom-field>
43
+ <custom-field action="ignore">_max_sale_price_variation_id</custom-field>
44
+ <custom-field action="ignore">attr_label_translations</custom-field>
45
  <custom-field action="copy">_per_product_pricing_active</custom-field>
46
  <custom-field action="copy">_pricing_rules</custom-field>
47
  </custom-fields>
wpml-woocommerce.php CHANGED
@@ -5,12 +5,12 @@
5
  Description: Allows running fully multilingual e-Commerce sites with WooCommerce and WPML. <a href="http://wpml.org/documentation/related-projects/woocommerce-multilingual/">Documentation</a>.
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
- Version: 3.6.4
9
  */
10
 
11
 
12
  if(defined('WCML_VERSION')) return;
13
- define('WCML_VERSION', '3.6.4');
14
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
15
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
16
  define('WCML_PLUGIN_URL', plugins_url() . '/' . WCML_PLUGIN_FOLDER);
5
  Description: Allows running fully multilingual e-Commerce sites with WooCommerce and WPML. <a href="http://wpml.org/documentation/related-projects/woocommerce-multilingual/">Documentation</a>.
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
+ Version: 3.6.5
9
  */
10
 
11
 
12
  if(defined('WCML_VERSION')) return;
13
+ define('WCML_VERSION', '3.6.5');
14
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
15
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
16
  define('WCML_PLUGIN_URL', plugins_url() . '/' . WCML_PLUGIN_FOLDER);