WooCommerce Multilingual – run WooCommerce with WPML - Version 4.7.5

Version Description

  • Skip Currency Switcher caching for NginxCache.
  • Improve performance on plugin page.
  • Fixed missing products on shop page in second language for some themes when slug is identical to default language.
  • Fixed wrong strings localization on some WooCommerce ajax actions.
  • Fixed Cash on delivery "Payment method instructions" not translated in the customer order emails.
  • Fixed RTL styling on WCML Status Tab.
  • Fixed notice for Product-Addon and specific field settings.
  • Composite products fixed a wrong displayed discounted price.
  • Fixed not pre-selected custom attributes for variable Bundle product.
  • Fixed missed images for product translation created via REST API.
  • Added new setting option for synchronizing not translated media on translated product front page.
  • Fixed not duplicated variation description while duplicating variable product to another language.
  • Fixed not matched variation on translated variable product page when "Translatable - use translation if available or fallback to default language" mode enabled for products and global attribute terms are translated.
  • Fixed overlapping columns on WooCommerce Order Statuses table.
  • WooCommerce Bookings compatibility - fixed availability count duplication while updating original product and bookings were made in the second language.
  • wcml_client_currency hook not applied in some cases
  • Fixed variation product title modifying after switching language on cart page in specific situations.
  • Fixed mixed strings language on variable product admin edit page in not admin language.
  • Fixed performance when a large number of shipping methods are defined.
  • Long query to get currencies removed from WCML to optimise performance.
  • Fixed cart total shipping converted twice when enabled custom settings for gateways and use not default currency as a currency for gateway.
  • Fixed converted product price when using custom gateway settings for second currency.
  • Fixed notice while importing xliff translations with custom attributes in some specific cases.
Download this release

Release Info

Developer sergey.r
Plugin Icon 128x128 WooCommerce Multilingual – run WooCommerce with WPML
Version 4.7.5
Comparing to
See all releases

Code changes from version 4.7.4 to 4.7.5

Files changed (59) hide show
  1. changelog/4.7.0.md +12 -12
  2. changelog/4.7.4.md +0 -2
  3. changelog/4.7.5.md +34 -0
  4. classes/Container/Config.php +14 -0
  5. classes/Email/OrderItems/Hooks.php +83 -0
  6. classes/Email/Settings/Hooks.php +188 -0
  7. classes/class-woocommerce-wpml.php +17 -2
  8. classes/currencies/class-wcml-admin-currency-selector.php +6 -9
  9. classes/media/Wrapper/IMedia.php +0 -7
  10. classes/media/Wrapper/NonTranslatable.php +0 -9
  11. classes/media/Wrapper/Translatable.php +45 -22
  12. classes/media/class-wcml-product-gallery-filter-factory.php +4 -2
  13. classes/media/class-wcml-product-gallery-filter.php +1 -1
  14. classes/media/class-wcml-product-image-filter-factory.php +4 -2
  15. classes/media/class-wcml-product-image-filter.php +1 -1
  16. classes/multi-currency/payment-gateways/class-wcml-currencies-payment-gateways.php +54 -31
  17. classes/multi-currency/payment-gateways/class-wcml-payment-gateway-paypal.php +3 -2
  18. classes/rest-api-support/class-wcml-rest-api-support.php +29 -0
  19. compatibility/class-wcml-bookings.php +76 -110
  20. compatibility/class-wcml-composite-products.php +2 -2
  21. compatibility/class-wcml-product-addons.php +7 -7
  22. compatibility/class-wcml-product-bundles.php +13 -7
  23. compatibility/class-wcml-variation-swatches-and-photos.php +67 -44
  24. compatibility/{class-wcml-yikes-custom-product-tabs-pro.php → class-wcml-yikes-custom-product-tabs.php} +2 -2
  25. inc/class-wcml-ajax-setup.php +0 -46
  26. inc/class-wcml-attributes.php +35 -14
  27. inc/class-wcml-cart.php +13 -8
  28. inc/class-wcml-compatibility.php +6 -6
  29. inc/class-wcml-dependencies.php +3 -27
  30. inc/class-wcml-emails.php +105 -234
  31. inc/class-wcml-install.php +0 -1
  32. inc/class-wcml-languages-upgrader.php +1 -2
  33. inc/class-wcml-requests.php +3 -0
  34. inc/class-wcml-store-pages.php +24 -17
  35. inc/class-wcml-terms.php +1 -1
  36. inc/class-wcml-tp-support.php +9 -15
  37. inc/class-wcml-troubleshooting.php +1 -1
  38. inc/class-wcml-upgrade.php +3 -3
  39. inc/class-wcml-wc-gateways.php +46 -20
  40. inc/currencies/class-wcml-multi-currency-orders.php +7 -38
  41. inc/currencies/class-wcml-multi-currency-prices.php +49 -44
  42. inc/currencies/class-wcml-multi-currency-reports.php +13 -22
  43. inc/currencies/class-wcml-multi-currency-resources.php +6 -9
  44. inc/currencies/class-wcml-multi-currency.php +23 -7
  45. inc/template-classes/class-wcml-settings-ui.php +9 -0
  46. inc/template-classes/status/class-wcml-status-config-warnings-ui.php +0 -3
  47. inc/translation-editor/class-wcml-editor-ui-product-job.php +11 -1
  48. inc/translation-editor/class-wcml-synchronize-product-data.php +5 -3
  49. inc/translation-editor/class-wcml-synchronize-variations-data.php +22 -12
  50. readme.txt +40 -826
  51. res/css/admin.css +1 -1
  52. res/css/management.css +1 -1
  53. templates/settings-ui.twig +23 -0
  54. vendor/autoload.php +1 -1
  55. vendor/composer/autoload_classmap.php +4 -1
  56. vendor/composer/autoload_real.php +7 -7
  57. vendor/composer/autoload_static.php +8 -5
  58. wpml-dependencies.json +4 -4
  59. wpml-woocommerce.php +6 -2
changelog/4.7.0.md CHANGED
@@ -1,35 +1,30 @@
1
  # Features
2
  * [wcml-2836] Replaced some Twig templates with pure PHP templates as the first step towards the removal of Twig dependencies.
 
3
  * [wcml-2740] Added compatibility class for WooCommerce order status Manager plugin
4
 
5
  # Fixes
6
- * [wcml-2965] Fixed PHP Notice for WC Variations Swatches And Photos compatibility.
7
- * [wcml-2963] WooCommerce Bookings compatibility : Fixed notice when trying to cancel booking.
8
- * [wcml-2954] Fixed a JavaScript error on the Store URLs tab.
9
- * [wcml-2947] Fixed an issue where the "Fix translated variations relationships" troubleshooting option was removing translated variations.
10
  * [wcml-2944] Fixed an issue where the strings for the default payment methods were not properly translated on the Checkout page.
11
- * [wcml-2941] Fixed an issue where product names were not translated in the admin emails.
12
- * [wcml-2931] Fixed an issue with the WooCommerce Subscriptions availability in the secondary language after purchasing the subscription in the original language.
13
  * [wcml-2929] Fixed an issue with the cache flush during language switching.
14
  * [wcml-2928] Fixed in the original ticket.
15
  * [wcml-2923] Fixed an issue where the gateway strings would always register in English instead of the site's default language.
16
- * [wcml-2914] Fixed an issue with the price filter widget not showing results in a secondary language.
17
- * [wcml-2864] Fixed an issue where customers would not receive notifications in the correct language.
18
- * [wcml-2838] Fixed an issue where the shipping classes in secondary languages were not calculated during checkout.
19
- * [wcml-2827] Fixed error while sending WooCoomerce Bookings email for bookings which didn't have orders assigned.
20
- * [wcml-2798] added comp. class to cover price update when products are edited with WOOBE plugin
21
- * [wcml-2792] Updated compatibility class for WC Checkout Addons
22
 
23
  # Compatibility
 
 
24
  * [wcml-2938] Fixed an issue where the total price on the Composite product page was not rounded.
25
  * [wcml-2937] Fixed an issue causing wrong rewrite rules after saving the settings and visiting a page in a language other than the default.
26
  * [wcml-2936] Fixed an issue with incorrect price converting for the Product add-ons.
 
27
  * [wcml-2922] Fixed an issue with the currency reverting to the default one during checkout.
28
  * [wcml-2921] Fixed removed meta from original product not synchronized to translation.
29
  * [wcml-2918] Fixed an issue where the BACS gateway instructions were not translated when re-sending the customer notification email from the admin.
30
  * [wcml-2896] Fixed an issue with missing language information for attribute terms that happened after changing the attribute slug.
31
  * [wcml-2878] Removed the Twig Composer dependency as it now relies on Twig from the WPML core plugin.
 
32
  * [wcml-2854] Fixed an issue where the Products shortcode was not working in the secondary language.
 
 
33
  * [wcml-2612] Fixed the images that were wrongly inserted in the translation job when attachments are not translatable.
34
 
35
  # Performances
@@ -37,6 +32,11 @@
37
  * [wcml-2917] Added the "wp_" prefix to all cookies so that hosting and caching layers can properly handle them.
38
 
39
  # Usability
 
 
 
 
 
40
  * [wcml-1365] Display larger images when hovering thumbnails in the WooCommerce Multilingual Products admin page.
41
 
42
  # API
1
  # Features
2
  * [wcml-2836] Replaced some Twig templates with pure PHP templates as the first step towards the removal of Twig dependencies.
3
+ * [wcml-2798] added comp. class to cover price update when products are edited with WOOBE plugin
4
  * [wcml-2740] Added compatibility class for WooCommerce order status Manager plugin
5
 
6
  # Fixes
 
 
 
 
7
  * [wcml-2944] Fixed an issue where the strings for the default payment methods were not properly translated on the Checkout page.
 
 
8
  * [wcml-2929] Fixed an issue with the cache flush during language switching.
9
  * [wcml-2928] Fixed in the original ticket.
10
  * [wcml-2923] Fixed an issue where the gateway strings would always register in English instead of the site's default language.
 
 
 
 
 
 
11
 
12
  # Compatibility
13
+ * [wcml-2965] Fixed PHP Notice for WC Variations Swatches And Photos compatibility.
14
+ * [wcml-2963] WooCommerce Bookings compatibility : Fixed notice when trying to cancel booking.
15
  * [wcml-2938] Fixed an issue where the total price on the Composite product page was not rounded.
16
  * [wcml-2937] Fixed an issue causing wrong rewrite rules after saving the settings and visiting a page in a language other than the default.
17
  * [wcml-2936] Fixed an issue with incorrect price converting for the Product add-ons.
18
+ * [wcml-2931] Fixed an issue with the WooCommerce Subscriptions availability in the secondary language after purchasing the subscription in the original language.
19
  * [wcml-2922] Fixed an issue with the currency reverting to the default one during checkout.
20
  * [wcml-2921] Fixed removed meta from original product not synchronized to translation.
21
  * [wcml-2918] Fixed an issue where the BACS gateway instructions were not translated when re-sending the customer notification email from the admin.
22
  * [wcml-2896] Fixed an issue with missing language information for attribute terms that happened after changing the attribute slug.
23
  * [wcml-2878] Removed the Twig Composer dependency as it now relies on Twig from the WPML core plugin.
24
+ * [wcml-2864] Fixed an issue where customers would not receive notifications in the correct language.
25
  * [wcml-2854] Fixed an issue where the Products shortcode was not working in the secondary language.
26
+ * [wcml-2827] Fixed error while sending WooCoomerce Bookings email for bookings which didn't have orders assigned.
27
+ * [wcml-2792] Updated compatibility class for WC Checkout Addons
28
  * [wcml-2612] Fixed the images that were wrongly inserted in the translation job when attachments are not translatable.
29
 
30
  # Performances
32
  * [wcml-2917] Added the "wp_" prefix to all cookies so that hosting and caching layers can properly handle them.
33
 
34
  # Usability
35
+ * [wcml-2954] Fixed a JavaScript error on the Store URLs tab.
36
+ * [wcml-2947] Fixed an issue where the "Fix translated variations relationships" troubleshooting option was removing translated variations.
37
+ * [wcml-2941] Fixed an issue where product names were not translated in the admin emails.
38
+ * [wcml-2914] Fixed an issue with the price filter widget not showing results in a secondary language.
39
+ * [wcml-2838] Fixed an issue where the shipping classes in secondary languages were not calculated during checkout.
40
  * [wcml-1365] Display larger images when hovering thumbnails in the WooCommerce Multilingual Products admin page.
41
 
42
  # API
changelog/4.7.4.md DELETED
@@ -1,2 +0,0 @@
1
- # Fixes
2
- * [wcml-3009] Fixed warning when some plugins using `get_terms` without `taxonomy` argument.
 
 
changelog/4.7.5.md ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Features
2
+ * [wcml-2988] Skip Currency Switcher caching for NginxCache.
3
+ * [wcml-2985] Improve performance on plugin page.
4
+
5
+ # Fixes
6
+ * [wcml-3020] Fixed missing products on shop page in second language for some themes when slug is identical to default language.
7
+ * [wcml-3013] Fixed wrong strings localization on some WooCommerce ajax actions.
8
+ * [wcml-3005] Fixed Cash on delivery "Payment method instructions" not translated in the customer order emails.
9
+ * [wcml-2939] Fixed RTL styling on WCML Status Tab.
10
+
11
+ # Compatibility
12
+ * [wcml-3027] Fixed notice for Product-Addon and specific field settings.
13
+ * [wcml-2990] Composite products fixed a wrong displayed discounted price.
14
+ * [wcml-2913] Fixed not pre-selected custom attributes for variable Bundle product.
15
+ * [wcml-2888] Fixed missed images for product translation created via REST API.
16
+ * [wcml-2873] Added new setting option for synchronizing not translated media on translated product front page.
17
+ * [wcml-2857] Fixed not duplicated variation description while duplicating variable product to another language.
18
+ * [wcml-2850] Fixed not matched variation on translated variable product page when "Translatable - use translation if available or fallback to default language" mode enabled for products and global attribute terms are translated.
19
+ * [wcml-2824] Fixed overlapping columns on WooCommerce Order Statuses table.
20
+ * [wcml-2799] WooCommerce Bookings compatibility - fixed availability count duplication while updating original product and bookings were made in the second language.
21
+ * [wcml-2691] wcml_client_currency hook not applied in some cases
22
+ * [wcml-2645] Fixed variation product title modifying after switching language on cart page in specific situations.
23
+ * [wcml-2553] Fixed mixed strings language on variable product admin edit page in not admin language.
24
+
25
+ # Performances
26
+ * [wcml-2992] Fixed performance when a large number of shipping methods are defined.
27
+ * [wcml-2957] Long query to get currencies removed from WCML to optimise performance.
28
+
29
+ # Usability
30
+ * [wcml-2984] Fixed cart total shipping converted twice when enabled custom settings for gateways and use not default currency as a currency for gateway.
31
+ * [wcml-2983] Fixed converted product price when using custom gateway settings for second currency.
32
+
33
+ # API
34
+ * [wcml-3003] Fixed notice while importing xliff translations with custom attributes in some specific cases.
classes/Container/Config.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Container;
4
+
5
+ class Config {
6
+
7
+ static public function getSharedInstances() {
8
+ global $woocommerce_wpml;
9
+
10
+ return [
11
+ $woocommerce_wpml,
12
+ ];
13
+ }
14
+ }
classes/Email/OrderItems/Hooks.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Email\OrderItems;
4
+
5
+ use IWPML_Backend_Action;
6
+ use IWPML_DIC_Action;
7
+ use IWPML_Frontend_Action;
8
+ use SitePress;
9
+ use WCML_Attributes;
10
+ use WCML_Terms;
11
+
12
+ class Hooks implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_Action {
13
+
14
+ /** @var SitePress */
15
+ private $sitepress;
16
+
17
+ /** @var WCML_Terms */
18
+ private $wcmlTerms;
19
+
20
+ /** @var WCML_Attributes */
21
+ private $wcmlAttributes;
22
+
23
+ public function __construct( SitePress $sitepress, WCML_Terms $wcmlTerms, WCML_Attributes $wcmlAttributes ) {
24
+ $this->sitepress = $sitepress;
25
+ $this->wcmlTerms = $wcmlTerms;
26
+ $this->wcmlAttributes = $wcmlAttributes;
27
+ }
28
+
29
+ public function add_hooks() {
30
+ if ( ! $this->isMarkingStatusForShopOrder() ) {
31
+ add_filter( 'woocommerce_order_items_meta_get_formatted', [ $this, 'filterFormattedItems' ], 10, 2 );
32
+ }
33
+ }
34
+
35
+ private function isMarkingStatusForShopOrder() {
36
+ return filter_input( INPUT_GET, 'post_type' ) === 'shop_order'
37
+ && filter_input( INPUT_GET, 'action' ) === 'woocommerce_mark_order_status';
38
+ }
39
+
40
+ /**
41
+ * @param array $formattedMeta
42
+ * @param object $object Should be an instance of \WC_Order_Item_Meta (but not explicitly defined)
43
+ *
44
+ * @return array
45
+ */
46
+ function filterFormattedItems( array $formattedMeta, $object ) {
47
+
48
+ if ( isset( $object->product->variation_id ) ) {
49
+
50
+ $currentProductVariationId = $this->sitepress->get_object_id( $object->product->variation_id, 'product_variation' );
51
+
52
+ if ( ! is_null( $currentProductVariationId ) ) {
53
+
54
+ foreach ( $formattedMeta as $key => $formattedItem ) {
55
+
56
+ if ( substr( $formattedItem['key'], 0, 3 ) ) {
57
+
58
+ $attribute = wc_sanitize_taxonomy_name( $formattedItem['key'] );
59
+
60
+ if ( taxonomy_exists( $attribute ) ) {
61
+ $attributeTerm = get_term_by( 'name', $formattedMeta[ $key ]['value'], $attribute );
62
+ $translatedTermId = $this->sitepress->get_object_id( $attributeTerm->term_id, $attribute );
63
+
64
+ if ( $translatedTermId ) {
65
+ $translatedTerm = $this->wcmlTerms->wcml_get_term_by_id( $translatedTermId, $attribute );
66
+ $formattedMeta[ $key ]['value'] = $translatedTerm->name;
67
+ }
68
+
69
+ } else {
70
+ $customAttrTranslation = $this->wcmlAttributes->get_custom_attribute_translation( $object->product->id, $formattedItem['key'], [ 'is_taxonomy' => false ], $this->sitepress->get_current_language() );
71
+
72
+ if ( false !== $customAttrTranslation ) {
73
+ $formattedMeta[ $key ]['label'] = $customAttrTranslation['name'];
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ return $formattedMeta;
82
+ }
83
+ }
classes/Email/Settings/Hooks.php ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Email\Settings;
4
+
5
+ use IWPML_Backend_Action;
6
+ use IWPML_DIC_Action;
7
+ use SitePress;
8
+ use WCML_WC_Strings;
9
+ use WPML_Simple_Language_Selector;
10
+
11
+ class Hooks implements IWPML_Backend_Action, IWPML_DIC_Action {
12
+
13
+ const KEY_PREFIX = 'wcml_lang';
14
+
15
+ /** @var SitePress */
16
+ private $sitepress;
17
+
18
+ /** @var WCML_WC_Strings */
19
+ private $wcmlStrings;
20
+
21
+ public function __construct( SitePress $sitepress, WCML_WC_Strings $wcmlStrings ) {
22
+ $this->sitepress = $sitepress;
23
+ $this->wcmlStrings = $wcmlStrings;
24
+ }
25
+
26
+ public function add_hooks() {
27
+ if ( $this->isEmailSettingsPage() ) {
28
+ add_action( 'admin_footer', [ $this, 'showLanguageLinksForWcEmails' ] );
29
+ $this->setEmailsStringLanguage();
30
+ }
31
+ }
32
+
33
+ /**
34
+ * @return bool
35
+ */
36
+ private function isEmailSettingsPage() {
37
+ global $pagenow;
38
+
39
+ return is_admin()
40
+ && $pagenow === 'admin.php'
41
+ && isset( $_GET['page'], $_GET['tab'] )
42
+ && $_GET['page'] === 'wc-settings'
43
+ && $_GET['tab'] === 'email';
44
+ }
45
+
46
+ function showLanguageLinksForWcEmails() {
47
+ $emailOptions = array(
48
+ 'woocommerce_new_order_settings',
49
+ 'woocommerce_cancelled_order_settings',
50
+ 'woocommerce_failed_order_settings',
51
+ 'woocommerce_customer_on_hold_order_settings',
52
+ 'woocommerce_customer_processing_order_settings',
53
+ 'woocommerce_customer_completed_order_settings',
54
+ 'woocommerce_customer_refunded_order_settings',
55
+ 'woocommerce_customer_invoice_settings',
56
+ 'woocommerce_customer_note_settings',
57
+ 'woocommerce_customer_reset_password_settings',
58
+ 'woocommerce_customer_new_account_settings'
59
+ );
60
+
61
+ $emailOptions = apply_filters( 'wcml_emails_options_to_translate', $emailOptions );
62
+
63
+ $textKeys = array(
64
+ 'subject',
65
+ 'heading',
66
+ 'subject_downloadable',
67
+ 'heading_downloadable',
68
+ 'subject_full',
69
+ 'subject_partial',
70
+ 'heading_full',
71
+ 'heading_partial',
72
+ 'subject_paid',
73
+ 'heading_paid'
74
+ );
75
+
76
+ $textKeys = apply_filters( 'wcml_emails_text_keys_to_translate', $textKeys );
77
+
78
+ foreach ( $emailOptions as $emailOption ) {
79
+ $sectionPrefix = apply_filters( 'wcml_emails_section_name_prefix', 'wc_email_', $emailOption );
80
+ $sectionName = str_replace( 'woocommerce_', $sectionPrefix, $emailOption );
81
+ $sectionName = apply_filters( 'wcml_emails_section_name_to_translate', str_replace( '_settings', '', $sectionName ) );
82
+
83
+ if ( isset( $_GET['section'] ) && $_GET['section'] === $sectionName ) {
84
+
85
+ $emailSettings = get_option( $emailOption );
86
+
87
+ if ( $emailSettings ) {
88
+
89
+ foreach ( $emailSettings as $settingsKey => $settingsValue ) {
90
+
91
+ if ( in_array( $settingsKey, $textKeys ) ) {
92
+
93
+ $emailInputKey = self::getEmailInputKey( $emailOption, $settingsKey );
94
+ $langSelector = new WPML_Simple_Language_Selector( $this->sitepress );
95
+ $language = $this->wcmlStrings->get_string_language(
96
+ $settingsValue,
97
+ self::getStringDomain( $emailOption ),
98
+ self::getStringName( $emailOption, $settingsKey )
99
+ );
100
+
101
+ if ( is_null( $language ) ) {
102
+ $language = $this->sitepress->get_default_language();
103
+ }
104
+
105
+ $langSelector->render(
106
+ [
107
+ 'id' => $emailOption . '_' . $settingsKey . '_language_selector',
108
+ 'name' => self::KEY_PREFIX . '-' . $emailOption . '-' . $settingsKey,
109
+ 'selected' => $language,
110
+ 'show_please_select' => false,
111
+ 'echo' => true,
112
+ 'style' => 'width: 18%;float: left',
113
+ ]
114
+ );
115
+
116
+ $stPage = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=admin_texts_' . $emailOption . '&search=' . $settingsValue );
117
+
118
+ ?>
119
+ <script>
120
+ var input = jQuery('input[name="<?php echo $emailInputKey ?>"]');
121
+ if (input.length) {
122
+ input.parent().append('<div class="translation_controls"></div>');
123
+ input.parent().find('.translation_controls').append('<a href="<?php echo $stPage; ?>" style="margin-left: 10px"><?php _e( 'translations', 'woocommerce-multilingual' ); ?></a>');
124
+ jQuery('#<?php echo $emailOption . '_' . $settingsKey . '_language_selector'; ?>').prependTo(input.parent().find('.translation_controls'));
125
+ }
126
+ </script>
127
+ <?php }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+
134
+ function setEmailsStringLanguage() {
135
+ foreach ( $_POST as $key => $language ) {
136
+
137
+ if ( substr( $key, 0, 9 ) === self::KEY_PREFIX ) {
138
+
139
+ $keyParts = explode( '-', $key );
140
+
141
+ if ( isset( $keyParts[2] ) ) {
142
+ list( , $emailType, $emailElement ) = $keyParts;
143
+
144
+ $emailInputKey = self::getEmailInputKey( $emailType, $emailElement );
145
+ $emailSettings = get_option( $emailType, true );
146
+ $optionStringValue = $emailSettings[ $emailElement ];
147
+
148
+ $stringValue = isset( $_POST[ $emailInputKey ] ) ? $_POST[ $emailInputKey ] : $optionStringValue;
149
+ $domain = self::getStringDomain( $emailType );
150
+ $name = self::getStringName( $emailType, $emailElement );
151
+
152
+ do_action( 'wpml_register_single_string', $domain, $name, $stringValue, false, $this->wcmlStrings->get_string_language( $optionStringValue, $domain ) );
153
+
154
+ $this->wcmlStrings->set_string_language( $stringValue, $domain, $name, $language );
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ /**
161
+ * @param string $emailType
162
+ * @param string $emailElement
163
+ *
164
+ * @return string
165
+ */
166
+ private static function getEmailInputKey( $emailType, $emailElement ) {
167
+ return str_replace( '_settings', '', $emailType ) . '_' . $emailElement;
168
+ }
169
+
170
+ /**
171
+ * @param string $emailType
172
+ *
173
+ * @return string
174
+ */
175
+ private static function getStringDomain( $emailType ) {
176
+ return 'admin_texts_' . $emailType;
177
+ }
178
+
179
+ /**
180
+ * @param string $emailType
181
+ * @param string $emailElement
182
+ *
183
+ * @return string
184
+ */
185
+ private static function getStringName( $emailType, $emailElement ) {
186
+ return '[' . $emailType . ']' . $emailElement;
187
+ }
188
+ }
classes/class-woocommerce-wpml.php CHANGED
@@ -219,7 +219,7 @@ class woocommerce_wpml {
219
  $this->store->add_hooks();
220
  $this->strings = new WCML_WC_Strings( $this, $sitepress );
221
  $this->strings->add_hooks();
222
- $this->emails = new WCML_Emails( $this, $sitepress, $woocommerce, $wpdb );
223
  $this->emails->add_hooks();
224
  $this->terms = new WCML_Terms( $this, $sitepress, $wpdb );
225
  $this->terms->add_hooks();
@@ -323,7 +323,7 @@ class woocommerce_wpml {
323
  if ( array_key_exists( $key, $this->settings ) ) {
324
  return $this->settings[ $key ];
325
  }
326
- return $default;
327
  }
328
 
329
  /**
@@ -338,6 +338,21 @@ class woocommerce_wpml {
338
  update_option( '_wcml_settings', $this->settings );
339
  }
340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  public function update_setting_ajx() {
342
  $nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
343
  if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wcml_settings' ) ) {
219
  $this->store->add_hooks();
220
  $this->strings = new WCML_WC_Strings( $this, $sitepress );
221
  $this->strings->add_hooks();
222
+ $this->emails = new WCML_Emails( $this->strings, $sitepress, WC_Emails::instance(), $wpdb );
223
  $this->emails->add_hooks();
224
  $this->terms = new WCML_Terms( $this, $sitepress, $wpdb );
225
  $this->terms->add_hooks();
323
  if ( array_key_exists( $key, $this->settings ) ) {
324
  return $this->settings[ $key ];
325
  }
326
+ return get_option( 'wcml_' . $key, $default );
327
  }
328
 
329
  /**
338
  update_option( '_wcml_settings', $this->settings );
339
  }
340
 
341
+ /**
342
+ * @param string $key
343
+ * @param mixed $value
344
+ * @param bool|false $autoload It only applies to these settings stored as separate options.
345
+ */
346
+ public function update_setting( $key, $value, $autoload = false ) {
347
+ if ( array_key_exists( $key, $this->settings ) ) {
348
+ $this->settings [ $key ] = $value;
349
+ $this->update_settings( $this->settings );
350
+ } else {
351
+ update_option( 'wcml_' . $key, $value, $autoload );
352
+ }
353
+ }
354
+
355
+
356
  public function update_setting_ajx() {
357
  $nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
358
  if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wcml_settings' ) ) {
classes/currencies/class-wcml-admin-currency-selector.php CHANGED
@@ -74,14 +74,14 @@ class WCML_Admin_Currency_Selector {
74
 
75
  $current_dashboard_currency = $this->get_cookie_dashboard_currency();
76
 
77
- $wc_currencies = get_woocommerce_currencies();
78
- $order_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
79
  ?>
80
  <select id="dropdown_dashboard_currency" style="display: none; margin : 10px; ">
81
- <?php if ( empty( $order_currencies ) ): ?>
82
  <option value=""><?php _e( 'Currency - no orders found', 'woocommerce-multilingual' ) ?></option>
83
  <?php else: ?>
84
- <?php foreach ( $order_currencies as $currency => $count ): ?>
85
 
86
  <option value="<?php echo $currency ?>" <?php echo $current_dashboard_currency == $currency ? 'selected="selected"' : ''; ?>>
87
  <?php echo $wc_currencies[ $currency ]; ?>
@@ -106,17 +106,14 @@ class WCML_Admin_Currency_Selector {
106
 
107
  /**
108
  * Set dashboard currency cookie
 
109
  * @param string $currency_code
110
  */
111
  public function set_dashboard_currency( $currency_code = '' ) {
112
  global $pagenow;
113
 
114
  if ( ! $currency_code && 'index.php' === $pagenow && ! headers_sent() ) {
115
- $order_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
116
- $currency_code = wcml_get_woocommerce_currency_option();
117
- if ( ! isset( $order_currencies[ $currency_code ] ) ) {
118
- $currency_code = key( $order_currencies );
119
- }
120
  }
121
 
122
  if ( $currency_code ) {
74
 
75
  $current_dashboard_currency = $this->get_cookie_dashboard_currency();
76
 
77
+ $wc_currencies = get_woocommerce_currencies();
78
+ $currency_codes = $this->woocommerce_wpml->multi_currency->get_currency_codes();
79
  ?>
80
  <select id="dropdown_dashboard_currency" style="display: none; margin : 10px; ">
81
+ <?php if ( empty( $currency_codes ) ): ?>
82
  <option value=""><?php _e( 'Currency - no orders found', 'woocommerce-multilingual' ) ?></option>
83
  <?php else: ?>
84
+ <?php foreach ( $currency_codes as $currency ): ?>
85
 
86
  <option value="<?php echo $currency ?>" <?php echo $current_dashboard_currency == $currency ? 'selected="selected"' : ''; ?>>
87
  <?php echo $wc_currencies[ $currency ]; ?>
106
 
107
  /**
108
  * Set dashboard currency cookie
109
+ *
110
  * @param string $currency_code
111
  */
112
  public function set_dashboard_currency( $currency_code = '' ) {
113
  global $pagenow;
114
 
115
  if ( ! $currency_code && 'index.php' === $pagenow && ! headers_sent() ) {
116
+ $currency_code = $this->woocommerce_wpml->multi_currency->get_currency_code();
 
 
 
 
117
  }
118
 
119
  if ( $currency_code ) {
classes/media/Wrapper/IMedia.php CHANGED
@@ -48,11 +48,4 @@ interface IMedia {
48
  * @param int $dup_att_id
49
  */
50
  public function sync_product_gallery_duplicate_attachment( $att_id, $dup_att_id );
51
-
52
- /**
53
- * @param int $product_id
54
- *
55
- * @return bool
56
- */
57
- public function is_media_duplication_enabled( $product_id );
58
  }
48
  * @param int $dup_att_id
49
  */
50
  public function sync_product_gallery_duplicate_attachment( $att_id, $dup_att_id );
 
 
 
 
 
 
 
51
  }
classes/media/Wrapper/NonTranslatable.php CHANGED
@@ -50,13 +50,4 @@ class NonTranslatable implements IMedia {
50
  * @param int $dup_att_id
51
  */
52
  public function sync_product_gallery_duplicate_attachment( $att_id, $dup_att_id ) {}
53
-
54
- /**
55
- * @param int $product_id
56
- *
57
- * @return bool
58
- */
59
- public function is_media_duplication_enabled( $product_id ) {
60
- return false;
61
- }
62
  }
50
  * @param int $dup_att_id
51
  */
52
  public function sync_product_gallery_duplicate_attachment( $att_id, $dup_att_id ) {}
 
 
 
 
 
 
 
 
 
53
  }
classes/media/Wrapper/Translatable.php CHANGED
@@ -80,32 +80,47 @@ class Translatable implements IMedia {
80
  return $product_images_ids;
81
  }
82
 
83
- public function sync_thumbnail_id( $orig_post_id, $trnsl_post_id, $lang ) {
84
- if ( method_exists( 'WPML_Media_Attachments_Duplication', 'sync_post_thumbnail' ) ) {
85
- $factory = new WPML_Media_Attachments_Duplication_Factory();
86
- $media_duplicate = $factory->create();
87
- if ( $media_duplicate ) {
88
- $media_duplicate->sync_post_thumbnail( $orig_post_id );
89
  }
90
  }
91
  }
92
 
93
- public function sync_variation_thumbnail_id( $variation_id, $translated_variation_id, $lang ) {
94
- $thumbnail_id = get_post_meta( $variation_id, '_thumbnail_id', true );
95
- $translated_thumbnail = apply_filters( 'translate_object_id', $thumbnail_id, 'attachment', false, $lang );
96
 
97
- if ( is_null( $translated_thumbnail ) && $thumbnail_id ) {
98
- $factory = new WPML_Media_Attachments_Duplication_Factory();
99
- $media_duplicate = $factory->create();
100
- $translated_thumbnail = $media_duplicate->create_duplicate_attachment( $thumbnail_id,
101
- wp_get_post_parent_id( $thumbnail_id ),
102
- $lang );
 
103
  }
104
- if ( $translated_thumbnail ) {
105
- update_post_meta( $translated_variation_id, '_thumbnail_id', $translated_thumbnail );
106
- update_post_meta( $variation_id, '_wpml_media_duplicate', 1 );
107
- update_post_meta( $variation_id, '_wpml_media_featured', 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  }
 
 
109
  }
110
 
111
  public function sync_product_gallery( $product_id ) {
@@ -161,11 +176,19 @@ class Translatable implements IMedia {
161
  unset( $this->products_being_synced[ $product_id ] );
162
  }
163
 
164
- public function is_media_duplication_enabled( $product_id ) {
 
 
 
 
 
 
 
 
165
 
166
  $setting_value = get_post_meta( $product_id,
167
  $this->sitepress->get_wp_api()
168
- ->constant( 'WPML_Admin_Post_Actions::DUPLICATE_MEDIA_META_KEY' ),
169
  true );
170
 
171
  if ( '' === $setting_value ) {
@@ -173,7 +196,7 @@ class Translatable implements IMedia {
173
  $media_options = get_option( '_wpml_media', [] );
174
 
175
  $global_setting_key = $this->sitepress->get_wp_api()
176
- ->constant( 'WPML_Admin_Post_Actions::DUPLICATE_MEDIA_GLOBAL_KEY' );
177
  if ( isset( $media_options['new_content_settings'][ $global_setting_key ] ) ) {
178
  $setting_value = $media_options['new_content_settings'][ $global_setting_key ];
179
  }
80
  return $product_images_ids;
81
  }
82
 
83
+ public function sync_thumbnail_id( $original_product_id, $translated_product_id, $language ) {
84
+
85
+ if ( $this->is_thumbnail_image_duplication_enabled( $original_product_id ) ) {
86
+ $translated_thumbnail_id = $this->get_translated_thumbnail_id( $original_product_id, $language );
87
+ if ( $translated_thumbnail_id ) {
88
+ update_post_meta( $translated_product_id, '_thumbnail_id', $translated_thumbnail_id );
89
  }
90
  }
91
  }
92
 
93
+ public function sync_variation_thumbnail_id( $variation_id, $translated_variation_id, $language ) {
 
 
94
 
95
+ if ( $this->is_thumbnail_image_duplication_enabled( wp_get_post_parent_id( $variation_id ) ) ) {
96
+ $translated_thumbnail_id = $this->get_translated_thumbnail_id( $variation_id, $language );
97
+ if ( $translated_thumbnail_id ) {
98
+ update_post_meta( $translated_variation_id, '_thumbnail_id', $translated_thumbnail_id );
99
+ update_post_meta( $variation_id, '_wpml_media_duplicate', 1 );
100
+ update_post_meta( $variation_id, '_wpml_media_featured', 1 );
101
+ }
102
  }
103
+ }
104
+
105
+ /**
106
+ * @param int|string $post_id
107
+ * @param string $language
108
+ *
109
+ * @return int|null
110
+ */
111
+ private function get_translated_thumbnail_id( $post_id, $language ) {
112
+ $thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true );
113
+ $translated_thumbnail_id = $this->sitepress->get_object_id( $thumbnail_id, 'attachment', false, $language );
114
+
115
+ if ( is_null( $translated_thumbnail_id ) && $thumbnail_id ) {
116
+ $factory = new WPML_Media_Attachments_Duplication_Factory();
117
+ $media_duplicate = $factory->create();
118
+ $translated_thumbnail_id = $media_duplicate->create_duplicate_attachment( $thumbnail_id,
119
+ wp_get_post_parent_id( $thumbnail_id ),
120
+ $language );
121
  }
122
+
123
+ return $translated_thumbnail_id;
124
  }
125
 
126
  public function sync_product_gallery( $product_id ) {
176
  unset( $this->products_being_synced[ $product_id ] );
177
  }
178
 
179
+ private function is_thumbnail_image_duplication_enabled( $product_id ){
180
+ return $this->is_duplication_enabled( $product_id, 'WPML_Admin_Post_Actions::DUPLICATE_FEATURED_META_KEY', 'WPML_Admin_Post_Actions::DUPLICATE_FEATURED_GLOBAL_KEY' );
181
+ }
182
+
183
+ private function is_media_duplication_enabled( $product_id ){
184
+ return $this->is_duplication_enabled( $product_id, 'WPML_Admin_Post_Actions::DUPLICATE_MEDIA_META_KEY', 'WPML_Admin_Post_Actions::DUPLICATE_MEDIA_GLOBAL_KEY' );
185
+ }
186
+
187
+ private function is_duplication_enabled( $product_id, $meta_key, $global_key ) {
188
 
189
  $setting_value = get_post_meta( $product_id,
190
  $this->sitepress->get_wp_api()
191
+ ->constant( $meta_key ),
192
  true );
193
 
194
  if ( '' === $setting_value ) {
196
  $media_options = get_option( '_wpml_media', [] );
197
 
198
  $global_setting_key = $this->sitepress->get_wp_api()
199
+ ->constant( $global_key );
200
  if ( isset( $media_options['new_content_settings'][ $global_setting_key ] ) ) {
201
  $setting_value = $media_options['new_content_settings'][ $global_setting_key ];
202
  }
classes/media/class-wcml-product-gallery-filter-factory.php CHANGED
@@ -3,9 +3,11 @@
3
  class WCML_Product_Gallery_Filter_Factory implements IWPML_Frontend_Action_Loader {
4
 
5
  public function create() {
6
- global $sitepress;
7
 
8
- return new WCML_Product_Gallery_Filter( new WPML_Translation_Element_Factory( $sitepress ) );
 
 
9
  }
10
 
11
  }
3
  class WCML_Product_Gallery_Filter_Factory implements IWPML_Frontend_Action_Loader {
4
 
5
  public function create() {
6
+ global $sitepress, $woocommerce_wpml;
7
 
8
+ if( $woocommerce_wpml->get_setting( 'sync_media', true ) ){
9
+ return new WCML_Product_Gallery_Filter( new WPML_Translation_Element_Factory( $sitepress ) );
10
+ }
11
  }
12
 
13
  }
classes/media/class-wcml-product-gallery-filter.php CHANGED
@@ -70,7 +70,7 @@ class WCML_Product_Gallery_Filter implements IWPML_Action {
70
 
71
  }
72
 
73
- return $image_ids ? $image_ids : $value;
74
  }
75
 
76
  }
70
 
71
  }
72
 
73
+ return $image_ids ? [ $image_ids ] : $value;
74
  }
75
 
76
  }
classes/media/class-wcml-product-image-filter-factory.php CHANGED
@@ -3,9 +3,11 @@
3
  class WCML_Product_Image_Filter_Factory implements IWPML_Frontend_Action_Loader {
4
 
5
  public function create() {
6
- global $sitepress;
7
 
8
- return new WCML_Product_Image_Filter( new WPML_Translation_Element_Factory( $sitepress ) );
 
 
9
  }
10
 
11
  }
3
  class WCML_Product_Image_Filter_Factory implements IWPML_Frontend_Action_Loader {
4
 
5
  public function create() {
6
+ global $sitepress, $woocommerce_wpml;
7
 
8
+ if( $woocommerce_wpml->get_setting( 'sync_media', true ) ) {
9
+ return new WCML_Product_Image_Filter( new WPML_Translation_Element_Factory( $sitepress ) );
10
+ }
11
  }
12
 
13
  }
classes/media/class-wcml-product-image-filter.php CHANGED
@@ -59,7 +59,7 @@ class WCML_Product_Image_Filter implements IWPML_Action {
59
  }
60
  }
61
 
62
- return $image_id ? $image_id : $value;
63
  }
64
 
65
  }
59
  }
60
  }
61
 
62
+ return $image_id ? [ $image_id ] : $value;
63
  }
64
 
65
  }
classes/multi-currency/payment-gateways/class-wcml-currencies-payment-gateways.php CHANGED
@@ -5,35 +5,42 @@
5
  */
6
  class WCML_Currencies_Payment_Gateways {
7
 
8
- const OPTION_KEY = 'wcml_custom_payment_gateways_for_currencies';
9
  const TEMPLATE_FOLDER = '/templates/multi-currency/payment-gateways/';
10
 
11
- private $available_gateways = array();
12
- private $supported_gateways = array();
13
- private $payment_gateways = array();
 
 
 
 
 
14
 
15
  /** @var woocommerce_wpml */
16
  private $woocommerce_wpml;
 
17
  /** @var WPML_WP_API */
18
  private $wp_api;
19
 
20
  /**
21
  * @param woocommerce_wpml $woocommerce_wpml
22
- * @param WPML_WP_API $wp_api
23
  */
24
  public function __construct( woocommerce_wpml $woocommerce_wpml, WPML_WP_API $wp_api ) {
25
  $this->woocommerce_wpml = $woocommerce_wpml;
26
  $this->wp_api = $wp_api;
27
  }
28
 
29
- public function add_hooks(){
30
- add_action( 'init', array( $this, 'init_gateways' ) );
 
31
 
32
- add_filter( 'woocommerce_gateway_description', array( $this, 'filter_gateway_description' ), 10, 2 );
33
- add_filter( 'option_woocommerce_stripe_settings', array( 'WCML_Payment_Gateway_Stripe', 'filter_stripe_settings' ) );
34
-
35
- if( !is_admin() ){
36
- add_filter( 'woocommerce_paypal_supported_currencies', array( 'WCML_Payment_Gateway_PayPal', 'filter_supported_currencies' ) );
37
  }
38
  }
39
 
@@ -43,10 +50,9 @@ class WCML_Currencies_Payment_Gateways {
43
  * @return bool
44
  */
45
  public function is_enabled( $currency ) {
46
-
47
  $gateway_enabled_settings = $this->get_settings();
48
 
49
- if( isset( $gateway_enabled_settings[ $currency ] ) ) {
50
  return $gateway_enabled_settings[ $currency ];
51
  }
52
 
@@ -55,10 +61,9 @@ class WCML_Currencies_Payment_Gateways {
55
 
56
  /**
57
  * @param string $currency
58
- * @param bool $value
59
  */
60
  public function set_enabled( $currency, $value ) {
61
-
62
  $gateway_enabled_settings = $this->get_settings();
63
  $gateway_enabled_settings[ $currency ] = $value;
64
 
@@ -69,20 +74,27 @@ class WCML_Currencies_Payment_Gateways {
69
  * @return array
70
  */
71
  private function get_settings() {
72
- return get_option( self::OPTION_KEY, array() );
73
  }
74
 
75
- public function init_gateways(){
 
 
 
 
 
 
 
76
 
77
  do_action( 'wcml_before_init_currency_payment_gateways' );
78
 
79
  $this->available_gateways = $this->get_available_payment_gateways();
80
 
81
- $this->supported_gateways = array(
82
- 'bacs' => 'WCML_Payment_Gateway_Bacs',
83
  'paypal' => 'WCML_Payment_Gateway_PayPal',
84
- 'stripe' => 'WCML_Payment_Gateway_Stripe'
85
- );
86
  $this->supported_gateways = apply_filters( 'wcml_supported_currency_payment_gateways', $this->supported_gateways );
87
 
88
  $this->store_supported_gateways();
@@ -93,6 +105,7 @@ class WCML_Currencies_Payment_Gateways {
93
  * @return array
94
  */
95
  public function get_gateways() {
 
96
 
97
  return $this->payment_gateways;
98
  }
@@ -101,6 +114,7 @@ class WCML_Currencies_Payment_Gateways {
101
  * @return array
102
  */
103
  public function get_supported_gateways() {
 
104
 
105
  return $this->supported_gateways;
106
  }
@@ -112,13 +126,14 @@ class WCML_Currencies_Payment_Gateways {
112
  * @return string
113
  */
114
  public function filter_gateway_description( $description, $id ) {
 
115
 
116
  if ( in_array( $id, array_keys( $this->supported_gateways ), true ) ) {
117
 
118
- $client_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
119
- $default_currency = wcml_get_woocommerce_currency_option();
120
 
121
- if( $client_currency === $default_currency ){
122
  return $description;
123
  }
124
 
@@ -129,12 +144,17 @@ class WCML_Currencies_Payment_Gateways {
129
  $this->is_enabled( $client_currency ) &&
130
  $gateway_setting &&
131
  $client_currency !== $gateway_setting['currency'] &&
132
- in_array( $gateway_setting['currency'], $active_currencies )
133
  ) {
134
  $cart_total = $this->woocommerce_wpml->cart->get_formatted_cart_total_in_currency( $gateway_setting['currency'] );
135
 
136
  $description .= '<p>';
137
- $description .= sprintf( __( 'Please note that the payment will be made in %1$s. %2$s will be debited from your account.', 'woocommerce-multilingual' ), $gateway_setting['currency'], $cart_total );
 
 
 
 
 
138
  $description .= '</p>';
139
  }
140
  }
@@ -158,7 +178,11 @@ class WCML_Currencies_Payment_Gateways {
158
  $client_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
159
  foreach ( $this->supported_gateways as $id => $supported_gateway ) {
160
  if ( $this->is_a_valid_gateway( $id, $supported_gateway ) ) {
161
- $this->payment_gateways[ $id ] = new $supported_gateway( $this->available_gateways[ $id ], $this->get_template_service(), $this->woocommerce_wpml );
 
 
 
 
162
  if ( $this->is_enabled( $client_currency ) ) {
163
  $this->payment_gateways[ $id ]->add_hooks();
164
  }
@@ -180,7 +204,7 @@ class WCML_Currencies_Payment_Gateways {
180
  * @return \WPML_Twig_Template
181
  */
182
  private function get_template_service() {
183
- $twig_loader = new WPML_Twig_Template_Loader( array( $this->wp_api->constant( 'WCML_PLUGIN_PATH' ) . self::TEMPLATE_FOLDER ) );
184
 
185
  return $twig_loader->get_template();
186
  }
@@ -191,5 +215,4 @@ class WCML_Currencies_Payment_Gateways {
191
  private function get_available_payment_gateways() {
192
  return WC()->payment_gateways()->get_available_payment_gateways();
193
  }
194
-
195
- }
5
  */
6
  class WCML_Currencies_Payment_Gateways {
7
 
8
+ const OPTION_KEY = 'wcml_custom_payment_gateways_for_currencies';
9
  const TEMPLATE_FOLDER = '/templates/multi-currency/payment-gateways/';
10
 
11
+ /** @var array */
12
+ private $payment_gateways;
13
+
14
+ /** @var array */
15
+ private $available_gateways;
16
+
17
+ /** @var array */
18
+ private $supported_gateways;
19
 
20
  /** @var woocommerce_wpml */
21
  private $woocommerce_wpml;
22
+
23
  /** @var WPML_WP_API */
24
  private $wp_api;
25
 
26
  /**
27
  * @param woocommerce_wpml $woocommerce_wpml
28
+ * @param WPML_WP_API $wp_api
29
  */
30
  public function __construct( woocommerce_wpml $woocommerce_wpml, WPML_WP_API $wp_api ) {
31
  $this->woocommerce_wpml = $woocommerce_wpml;
32
  $this->wp_api = $wp_api;
33
  }
34
 
35
+ public function add_hooks() {
36
+ add_filter( 'woocommerce_gateway_description', [ $this, 'filter_gateway_description' ], 10, 2 );
37
+ add_filter( 'option_woocommerce_stripe_settings', [ 'WCML_Payment_Gateway_Stripe', 'filter_stripe_settings' ] );
38
 
39
+ if ( ! is_admin() ) {
40
+ add_filter(
41
+ 'woocommerce_paypal_supported_currencies',
42
+ [ 'WCML_Payment_Gateway_PayPal', 'filter_supported_currencies' ]
43
+ );
44
  }
45
  }
46
 
50
  * @return bool
51
  */
52
  public function is_enabled( $currency ) {
 
53
  $gateway_enabled_settings = $this->get_settings();
54
 
55
+ if ( isset( $gateway_enabled_settings[ $currency ] ) ) {
56
  return $gateway_enabled_settings[ $currency ];
57
  }
58
 
61
 
62
  /**
63
  * @param string $currency
64
+ * @param bool $value
65
  */
66
  public function set_enabled( $currency, $value ) {
 
67
  $gateway_enabled_settings = $this->get_settings();
68
  $gateway_enabled_settings[ $currency ] = $value;
69
 
74
  * @return array
75
  */
76
  private function get_settings() {
77
+ return get_option( self::OPTION_KEY, [] );
78
  }
79
 
80
+ public function init_gateways() {
81
+ if ( null !== $this->payment_gateways ) {
82
+ return;
83
+ }
84
+
85
+ $this->payment_gateways = [];
86
+ $this->available_gateways = [];
87
+ $this->supported_gateways = [];
88
 
89
  do_action( 'wcml_before_init_currency_payment_gateways' );
90
 
91
  $this->available_gateways = $this->get_available_payment_gateways();
92
 
93
+ $this->supported_gateways = [
94
+ 'bacs' => 'WCML_Payment_Gateway_Bacs',
95
  'paypal' => 'WCML_Payment_Gateway_PayPal',
96
+ 'stripe' => 'WCML_Payment_Gateway_Stripe',
97
+ ];
98
  $this->supported_gateways = apply_filters( 'wcml_supported_currency_payment_gateways', $this->supported_gateways );
99
 
100
  $this->store_supported_gateways();
105
  * @return array
106
  */
107
  public function get_gateways() {
108
+ $this->init_gateways();
109
 
110
  return $this->payment_gateways;
111
  }
114
  * @return array
115
  */
116
  public function get_supported_gateways() {
117
+ $this->init_gateways();
118
 
119
  return $this->supported_gateways;
120
  }
126
  * @return string
127
  */
128
  public function filter_gateway_description( $description, $id ) {
129
+ $this->init_gateways();
130
 
131
  if ( in_array( $id, array_keys( $this->supported_gateways ), true ) ) {
132
 
133
+ $client_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
134
+ $default_currency = wcml_get_woocommerce_currency_option();
135
 
136
+ if ( $client_currency === $default_currency ) {
137
  return $description;
138
  }
139
 
144
  $this->is_enabled( $client_currency ) &&
145
  $gateway_setting &&
146
  $client_currency !== $gateway_setting['currency'] &&
147
+ in_array( $gateway_setting['currency'], $active_currencies, true )
148
  ) {
149
  $cart_total = $this->woocommerce_wpml->cart->get_formatted_cart_total_in_currency( $gateway_setting['currency'] );
150
 
151
  $description .= '<p>';
152
+ $description .= sprintf(
153
+ // translators: 1: Currency, 2: Cart total.
154
+ __( 'Please note that the payment will be made in %1$s. %2$s will be debited from your account.', 'woocommerce-multilingual' ),
155
+ $gateway_setting['currency'],
156
+ $cart_total
157
+ );
158
  $description .= '</p>';
159
  }
160
  }
178
  $client_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
179
  foreach ( $this->supported_gateways as $id => $supported_gateway ) {
180
  if ( $this->is_a_valid_gateway( $id, $supported_gateway ) ) {
181
+ $this->payment_gateways[ $id ] = new $supported_gateway(
182
+ $this->available_gateways[ $id ],
183
+ $this->get_template_service(),
184
+ $this->woocommerce_wpml
185
+ );
186
  if ( $this->is_enabled( $client_currency ) ) {
187
  $this->payment_gateways[ $id ]->add_hooks();
188
  }
204
  * @return \WPML_Twig_Template
205
  */
206
  private function get_template_service() {
207
+ $twig_loader = new WPML_Twig_Template_Loader( [ $this->wp_api->constant( 'WCML_PLUGIN_PATH' ) . self::TEMPLATE_FOLDER ] );
208
 
209
  return $twig_loader->get_template();
210
  }
215
  private function get_available_payment_gateways() {
216
  return WC()->payment_gateways()->get_available_payment_gateways();
217
  }
218
+ }
 
classes/multi-currency/payment-gateways/class-wcml-payment-gateway-paypal.php CHANGED
@@ -147,11 +147,12 @@ class WCML_Payment_Gateway_PayPal extends WCML_Payment_Gateway {
147
  $item_id = 1;
148
 
149
  foreach ( $cart_items as $item ) {
150
- $args[ 'amount_' . $item_id ] = $this->woocommerce_wpml->multi_currency->prices->get_product_price_in_currency( $item['product_id'], $gateway_setting['currency'] );
 
151
  $item_id ++;
152
  }
153
 
154
- $args['shipping_1'] = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount_by_currencies( WC()->cart->get_shipping_total(), $client_currency, $gateway_setting['currency'] );
155
  }
156
  }
157
 
147
  $item_id = 1;
148
 
149
  foreach ( $cart_items as $item ) {
150
+ $item_product_id = $item['variation_id'] ?: $item['product_id'];
151
+ $args[ 'amount_' . $item_id ] = $this->woocommerce_wpml->multi_currency->prices->get_product_price_in_currency( $item_product_id, $gateway_setting['currency'] );
152
  $item_id ++;
153
  }
154
 
155
+ $args['shipping_1'] = $this->woocommerce_wpml->cart->get_cart_shipping_in_currency( $gateway_setting['currency'] );
156
  }
157
  }
158
 
classes/rest-api-support/class-wcml-rest-api-support.php CHANGED
@@ -54,6 +54,7 @@ class WCML_REST_API_Support{
54
 
55
  add_action( 'woocommerce_rest_insert_product_object', array( $this, 'set_product_language' ), 10, 2 );
56
  add_action( 'woocommerce_rest_insert_product_object', array( $this, 'set_product_custom_prices' ), 10, 2 );
 
57
 
58
  add_action( 'woocommerce_rest_insert_product_object', array( $this, 'copy_custom_fields_from_original' ), 10, 1 );
59
  add_action( 'woocommerce_rest_prepare_product_object', array( $this, 'copy_product_custom_fields' ), 10 , 3 );
@@ -283,6 +284,34 @@ class WCML_REST_API_Support{
283
 
284
  }
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  /**
287
  * @param WC_Product|WP_Post $product
288
  */
54
 
55
  add_action( 'woocommerce_rest_insert_product_object', array( $this, 'set_product_language' ), 10, 2 );
56
  add_action( 'woocommerce_rest_insert_product_object', array( $this, 'set_product_custom_prices' ), 10, 2 );
57
+ add_action( 'woocommerce_rest_insert_product_object', array( $this, 'set_product_images' ), 10, 2 );
58
 
59
  add_action( 'woocommerce_rest_insert_product_object', array( $this, 'copy_custom_fields_from_original' ), 10, 1 );
60
  add_action( 'woocommerce_rest_prepare_product_object', array( $this, 'copy_product_custom_fields' ), 10 , 3 );
284
 
285
  }
286
 
287
+
288
+ /**
289
+ * Set product images
290
+ *
291
+ * @param WC_Product|WP_Post $product
292
+ * @param WP_REST_Request $request
293
+ *
294
+ * @throws WC_API_Exception
295
+ *
296
+ */
297
+ public function set_product_images( $product, $request ) {
298
+
299
+ $data = $request->get_params();
300
+
301
+ if ( isset( $data['translation_of'] ) ) {
302
+ $product_id = $this->get_product_id( $product );
303
+
304
+ $this->woocommerce_wpml->media->sync_thumbnail_id( $data['translation_of'], $product_id, $data['lang'] );
305
+ $this->woocommerce_wpml->media->sync_product_gallery( $data['translation_of'] );
306
+
307
+ if ( isset( $data['variations'] ) ) {
308
+ foreach ( $data['variations'] as $variation_id ) {
309
+ $this->woocommerce_wpml->media->sync_variation_thumbnail_id( $this->woocommerce_wpml->products->get_original_product_id( $variation_id ), $variation_id, $data['lang'] );
310
+ }
311
+ }
312
+ }
313
+ }
314
+
315
  /**
316
  * @param WC_Product|WP_Post $product
317
  */
compatibility/class-wcml-bookings.php CHANGED
@@ -25,6 +25,11 @@ class WCML_Bookings {
25
  */
26
  private $woocommerce;
27
 
 
 
 
 
 
28
  /**
29
  * @var wpdb
30
  */
@@ -37,13 +42,15 @@ class WCML_Bookings {
37
  * @param woocommerce $woocommerce
38
  * @param wpdb $wpdb
39
  * @param WPML_Element_Translation_Package $tp
 
40
  */
41
- function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml, woocommerce $woocommerce, wpdb $wpdb, WPML_Element_Translation_Package $tp ) {
42
- $this->sitepress = $sitepress;
43
- $this->woocommerce_wpml = $woocommerce_wpml;
44
- $this->woocommerce = $woocommerce;
45
- $this->wpdb = $wpdb;
46
- $this->tp = $tp;
 
47
  }
48
 
49
  /**
@@ -575,64 +582,50 @@ class WCML_Bookings {
575
  }
576
 
577
  // sync existing product bookings for translations
578
- function sync_bookings( $original_product_id, $product_id, $lang ) {
579
  $all_bookings_for_product = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT post_id as id FROM {$this->wpdb->postmeta} WHERE meta_key = '_booking_product_id' AND meta_value = %d", $original_product_id ) );
580
 
581
  foreach ( $all_bookings_for_product as $booking ) {
582
- $check_if_exists = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT pm3.* FROM {$this->wpdb->postmeta} AS pm1
583
- LEFT JOIN {$this->wpdb->postmeta} AS pm2 ON pm1.post_id = pm2.post_id
584
- LEFT JOIN {$this->wpdb->postmeta} AS pm3 ON pm1.post_id = pm3.post_id
585
- 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'"
586
- , $booking->id, $lang ) );
587
-
588
- if ( is_null( $check_if_exists ) ) {
589
- $this->duplicate_booking_for_translations( $booking->id, $lang );
590
- } elseif ( '' === $check_if_exists->meta_value ) {
591
- update_post_meta( $check_if_exists->post_id, '_booking_product_id', $this->get_translated_booking_product_id( $booking->id, $lang ) );
592
- update_post_meta( $check_if_exists->post_id, '_booking_resource_id', $this->get_translated_booking_resource_id( $booking->id, $lang ) );
593
- update_post_meta( $check_if_exists->post_id, '_booking_persons', $this->get_translated_booking_persons_ids( $booking->id, $lang ) );
594
  }
595
  }
596
  }
597
 
 
 
 
 
 
 
 
 
 
 
 
598
  function sync_booking_data( $original_product_id, $current_product_id ) {
599
 
600
  if ( has_term( 'booking', 'product_type', $original_product_id ) ) {
601
- global $pagenow, $iclTranslationManagement;
602
-
603
- // get language code
604
- $language_details = $this->sitepress->get_element_language_details( $original_product_id, 'post_product' );
605
- if ( $pagenow == 'admin.php' && empty( $language_details ) ) {
606
- //translation editor support: sidestep icl_translations_cache
607
- $language_details = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT element_id, trid, language_code, source_language_code FROM {$this->wpdb->prefix}icl_translations WHERE element_id = %d AND element_type = 'post_product'", $original_product_id ) );
608
- }
609
- if ( empty( $language_details ) ) {
610
- return;
611
- }
612
-
613
- // pick posts to sync
614
- $posts = array();
615
- $translations = $this->sitepress->get_element_translations( $language_details->trid, 'post_product' );
616
  foreach ( $translations as $translation ) {
 
617
 
618
- if ( ! $translation->original ) {
619
- $posts[ $translation->element_id ] = $translation;
620
- }
621
- }
622
-
623
- foreach ( $posts as $post_id => $translation ) {
624
-
625
- $trn_lang = $this->sitepress->get_language_for_element( $post_id, 'post_product' );
626
 
627
- //sync_resources
628
- $this->sync_resources( $original_product_id, $post_id, $trn_lang );
629
-
630
- //sync_persons
631
- $this->sync_persons( $original_product_id, $post_id, $trn_lang );
632
  }
633
-
634
  }
635
-
636
  }
637
 
638
  function sync_resources( $original_product_id, $translated_product_id, $lang_code, $duplicate = true ) {
@@ -988,28 +981,26 @@ class WCML_Bookings {
988
 
989
  if ( $object_id == $original_product_id ) {
990
 
991
- $trid = $this->sitepress->get_element_trid( $object_id, 'post_product' );
992
- $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
993
 
994
  foreach ( $translations as $translation ) {
995
-
996
- if ( ! $translation->original ) {
997
-
998
- $this->sync_resource_costs( $original_product_id, $translation->element_id, $meta_key, $translation->language_code );
999
-
1000
- }
1001
  }
1002
 
1003
  return $check;
1004
-
1005
  } else {
1006
-
1007
- $language_code = $this->sitepress->get_language_for_element( $object_id, 'post_product' );
1008
-
1009
- $this->sync_resource_costs( $original_product_id, $object_id, $meta_key, $language_code );
1010
-
 
1011
  return true;
1012
-
1013
  }
1014
 
1015
  }
@@ -1280,32 +1271,22 @@ class WCML_Bookings {
1280
  die();
1281
  }
1282
 
1283
- function set_booking_currency( $currency_code = false ) {
1284
-
1285
  $cookie_name = '_wcml_booking_currency';
1286
- if ( ! isset( $_COOKIE [ $cookie_name ] ) && ! headers_sent() ) {
1287
-
1288
 
 
1289
  $currency_code = wcml_get_woocommerce_currency_option();
1290
 
1291
- if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
1292
- $order_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
1293
-
1294
- if ( ! isset( $order_currencies[ $currency_code ] ) ) {
1295
- foreach ( $order_currencies as $currency_code => $count ) {
1296
- $currency_code = $currency_code;
1297
- break;
1298
- }
1299
- }
1300
  }
1301
  }
1302
 
1303
  if ( $currency_code ) {
1304
  // @todo uncomment or delete when #wpmlcore-5796 is resolved
1305
- //do_action( 'wpsc_add_cookie', $cookie_name );
1306
  setcookie( $cookie_name, $currency_code, time() + 86400, COOKIEPATH, COOKIE_DOMAIN );
1307
  }
1308
-
1309
  }
1310
 
1311
  function get_cookie_booking_currency() {
@@ -1755,12 +1736,11 @@ class WCML_Bookings {
1755
  }
1756
 
1757
  function update_status_for_translations( $booking_id ) {
1758
- $translated_bookings = $this->get_translated_bookings( $booking_id );
1759
 
1760
- foreach ( $translated_bookings as $booking ) {
1761
 
1762
  $status = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT post_status FROM {$this->wpdb->posts} WHERE ID = %d", $booking_id ) ); //get_post_status( $booking_id );
1763
- $language = get_post_meta( $booking->post_id, '_language_code', true );
1764
 
1765
  $this->wpdb->update(
1766
  $this->wpdb->posts,
@@ -1769,22 +1749,18 @@ class WCML_Bookings {
1769
  'post_parent' => wp_get_post_parent_id( $booking_id ),
1770
  ),
1771
  array(
1772
- 'ID' => $booking->post_id
1773
  )
1774
  );
1775
 
1776
- update_post_meta( $booking->post_id, '_booking_product_id', $this->get_translated_booking_product_id( $booking_id, $language ) );
1777
- update_post_meta( $booking->post_id, '_booking_resource_id', $this->get_translated_booking_resource_id( $booking_id, $language ) );
1778
- update_post_meta( $booking->post_id, '_booking_persons', $this->get_translated_booking_persons_ids( $booking_id, $language ) );
1779
-
1780
  }
1781
 
1782
  }
1783
 
1784
  function get_translated_bookings( $booking_id ) {
1785
- $translated_bookings = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT post_id FROM {$this->wpdb->postmeta} WHERE meta_key = '_booking_duplicate_of' AND meta_value = %d", $booking_id ) );
1786
 
1787
- return $translated_bookings;
1788
  }
1789
 
1790
  public function booking_filters_query( $query ) {
@@ -1858,23 +1834,20 @@ class WCML_Bookings {
1858
  && $booking_id
1859
  && get_post_type( $booking_id ) == 'wc_booking'
1860
  ) {
1861
-
1862
- $translated_bookings = $this->get_translated_bookings( $booking_id );
1863
-
1864
  remove_action( 'before_delete_post', array( $this, 'delete_bookings' ) );
1865
 
1866
- foreach ( $translated_bookings as $booking ) {
1867
  $this->wpdb->update(
1868
  $this->wpdb->posts,
1869
  array(
1870
  'post_parent' => 0
1871
  ),
1872
  array(
1873
- 'ID' => $booking->post_id
1874
  )
1875
  );
1876
 
1877
- wp_delete_post( $booking->post_id );
1878
 
1879
  }
1880
 
@@ -1890,9 +1863,7 @@ class WCML_Bookings {
1890
 
1891
  if ( $booking_id > 0 && get_post_type( $booking_id ) == 'wc_booking' ) {
1892
 
1893
- $translated_bookings = $this->get_translated_bookings( $booking_id );
1894
-
1895
- foreach ( $translated_bookings as $booking ) {
1896
 
1897
  $this->wpdb->update(
1898
  $this->wpdb->posts,
@@ -1900,7 +1871,7 @@ class WCML_Bookings {
1900
  'post_status' => 'trash'
1901
  ),
1902
  array(
1903
- 'ID' => $booking->post_id
1904
  )
1905
  );
1906
 
@@ -2427,17 +2398,12 @@ class WCML_Bookings {
2427
 
2428
  if( $post->post_type === 'wc_booking' && $update ){
2429
 
2430
- $trid = $this->sitepress->get_element_trid( $post_id, 'post_wc_booking' );
2431
- $translations = $this->sitepress->get_element_translations( $trid, 'post_wc_booking' );
2432
-
2433
- foreach( $translations as $translation ){
2434
- if( $translation->element_id != $post_id ){
2435
- $this->wpdb->update(
2436
- $this->wpdb->posts,
2437
- array( 'post_status' => $post->post_status ),
2438
- array( 'ID' => $translation->element_id )
2439
- );
2440
- }
2441
  }
2442
 
2443
  }
25
  */
26
  private $woocommerce;
27
 
28
+ /**
29
+ * @var WPML_Post_Translation
30
+ */
31
+ private $wpml_post_translations;
32
+
33
  /**
34
  * @var wpdb
35
  */
42
  * @param woocommerce $woocommerce
43
  * @param wpdb $wpdb
44
  * @param WPML_Element_Translation_Package $tp
45
+ * @param WPML_Post_Translation $wpml_post_translations
46
  */
47
+ function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml, woocommerce $woocommerce, wpdb $wpdb, WPML_Element_Translation_Package $tp, WPML_Post_Translation $wpml_post_translations ) {
48
+ $this->sitepress = $sitepress;
49
+ $this->woocommerce_wpml = $woocommerce_wpml;
50
+ $this->woocommerce = $woocommerce;
51
+ $this->wpdb = $wpdb;
52
+ $this->tp = $tp;
53
+ $this->wpml_post_translations = $wpml_post_translations;
54
  }
55
 
56
  /**
582
  }
583
 
584
  // sync existing product bookings for translations
585
+ function sync_bookings( $original_product_id, $product_id, $language ) {
586
  $all_bookings_for_product = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT post_id as id FROM {$this->wpdb->postmeta} WHERE meta_key = '_booking_product_id' AND meta_value = %d", $original_product_id ) );
587
 
588
  foreach ( $all_bookings_for_product as $booking ) {
589
+
590
+ if( $language === $this->wpml_post_translations->get_source_lang_code( $booking->id ) ){
591
+ continue;
592
+ }
593
+
594
+ $booking_translations = $this->get_translated_bookings( $booking->id );
595
+
596
+ if ( !isset( $booking_translations[ $language ] ) ) {
597
+ $this->duplicate_booking_for_translations( $booking->id, $language );
598
+ } elseif ( !get_post_meta( $booking_translations[ $language ], '_booking_product_id', true ) ) {
599
+ $this->update_translated_booking_meta( $booking_translations[ $language ], $booking->id, $language );
 
600
  }
601
  }
602
  }
603
 
604
+ /**
605
+ * @param int $translated_booking_id
606
+ * @param int $original_booking_id
607
+ * @param string $language
608
+ */
609
+ private function update_translated_booking_meta( $translated_booking_id, $original_booking_id, $language ){
610
+ update_post_meta( $translated_booking_id, '_booking_product_id', $this->get_translated_booking_product_id( $original_booking_id, $language ) );
611
+ update_post_meta( $translated_booking_id, '_booking_resource_id', $this->get_translated_booking_resource_id( $original_booking_id, $language ) );
612
+ update_post_meta( $translated_booking_id, '_booking_persons', $this->get_translated_booking_persons_ids( $original_booking_id, $language ) );
613
+ }
614
+
615
  function sync_booking_data( $original_product_id, $current_product_id ) {
616
 
617
  if ( has_term( 'booking', 'product_type', $original_product_id ) ) {
618
+ $translations = $this->wpml_post_translations->get_element_translations( $original_product_id, false, true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
619
  foreach ( $translations as $translation ) {
620
+ $language = $this->wpml_post_translations->get_element_lang_code( $translation );
621
 
622
+ //sync_resources
623
+ $this->sync_resources( $original_product_id, $translation, $language );
 
 
 
 
 
 
624
 
625
+ //sync_persons
626
+ $this->sync_persons( $original_product_id, $translation, $language );
 
 
 
627
  }
 
628
  }
 
629
  }
630
 
631
  function sync_resources( $original_product_id, $translated_product_id, $lang_code, $duplicate = true ) {
981
 
982
  if ( $object_id == $original_product_id ) {
983
 
984
+ $translations = $this->wpml_post_translations->get_element_translations( $object_id, false, true );
 
985
 
986
  foreach ( $translations as $translation ) {
987
+ $this->sync_resource_costs(
988
+ $original_product_id,
989
+ $translation,
990
+ $meta_key,
991
+ $this->wpml_post_translations->get_element_lang_code( $translation )
992
+ );
993
  }
994
 
995
  return $check;
 
996
  } else {
997
+ $this->sync_resource_costs(
998
+ $original_product_id,
999
+ $object_id,
1000
+ $meta_key,
1001
+ $this->wpml_post_translations->get_element_lang_code( $object_id )
1002
+ );
1003
  return true;
 
1004
  }
1005
 
1006
  }
1271
  die();
1272
  }
1273
 
1274
+ public function set_booking_currency( $currency_code = false ) {
 
1275
  $cookie_name = '_wcml_booking_currency';
 
 
1276
 
1277
+ if ( ! isset( $_COOKIE[ $cookie_name ] ) && ! headers_sent() ) {
1278
  $currency_code = wcml_get_woocommerce_currency_option();
1279
 
1280
+ if ( WCML_MULTI_CURRENCIES_INDEPENDENT === $this->woocommerce_wpml->settings['enable_multi_currency'] ) {
1281
+ $currency_code = $this->woocommerce_wpml->multi_currency->get_currency_code();
 
 
 
 
 
 
 
1282
  }
1283
  }
1284
 
1285
  if ( $currency_code ) {
1286
  // @todo uncomment or delete when #wpmlcore-5796 is resolved
1287
+ // do_action( 'wpsc_add_cookie', $cookie_name );
1288
  setcookie( $cookie_name, $currency_code, time() + 86400, COOKIEPATH, COOKIE_DOMAIN );
1289
  }
 
1290
  }
1291
 
1292
  function get_cookie_booking_currency() {
1736
  }
1737
 
1738
  function update_status_for_translations( $booking_id ) {
 
1739
 
1740
+ foreach ( $this->get_translated_bookings( $booking_id ) as $translated_booking_id ) {
1741
 
1742
  $status = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT post_status FROM {$this->wpdb->posts} WHERE ID = %d", $booking_id ) ); //get_post_status( $booking_id );
1743
+ $language = get_post_meta( $translated_booking_id, '_language_code', true );
1744
 
1745
  $this->wpdb->update(
1746
  $this->wpdb->posts,
1749
  'post_parent' => wp_get_post_parent_id( $booking_id ),
1750
  ),
1751
  array(
1752
+ 'ID' => $translated_booking_id
1753
  )
1754
  );
1755
 
1756
+ $this->update_translated_booking_meta( $translated_booking_id, $booking_id, $language );
 
 
 
1757
  }
1758
 
1759
  }
1760
 
1761
  function get_translated_bookings( $booking_id ) {
 
1762
 
1763
+ return $this->wpml_post_translations->get_element_translations( $booking_id, false, true );
1764
  }
1765
 
1766
  public function booking_filters_query( $query ) {
1834
  && $booking_id
1835
  && get_post_type( $booking_id ) == 'wc_booking'
1836
  ) {
 
 
 
1837
  remove_action( 'before_delete_post', array( $this, 'delete_bookings' ) );
1838
 
1839
+ foreach ( $this->get_translated_bookings( $booking_id ) as $translated_booking_id ) {
1840
  $this->wpdb->update(
1841
  $this->wpdb->posts,
1842
  array(
1843
  'post_parent' => 0
1844
  ),
1845
  array(
1846
+ 'ID' => $translated_booking_id
1847
  )
1848
  );
1849
 
1850
+ wp_delete_post( $translated_booking_id );
1851
 
1852
  }
1853
 
1863
 
1864
  if ( $booking_id > 0 && get_post_type( $booking_id ) == 'wc_booking' ) {
1865
 
1866
+ foreach ( $this->get_translated_bookings( $booking_id ) as $translated_booking_id ) {
 
 
1867
 
1868
  $this->wpdb->update(
1869
  $this->wpdb->posts,
1871
  'post_status' => 'trash'
1872
  ),
1873
  array(
1874
+ 'ID' => $translated_booking_id
1875
  )
1876
  );
1877
 
2398
 
2399
  if( $post->post_type === 'wc_booking' && $update ){
2400
 
2401
+ foreach( $this->get_translated_bookings( $post_id ) as $translated_booking_id ){
2402
+ $this->wpdb->update(
2403
+ $this->wpdb->posts,
2404
+ array( 'post_status' => $post->post_status ),
2405
+ array( 'ID' => $translated_booking_id )
2406
+ );
 
 
 
 
 
2407
  }
2408
 
2409
  }
compatibility/class-wcml-composite-products.php CHANGED
@@ -511,7 +511,7 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
511
  }
512
 
513
  public function get_composite_data( $product_id ){
514
- return get_post_meta( $product_id, '_bto_data', true );
515
  }
516
 
517
 
@@ -586,7 +586,7 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
586
 
587
  public function apply_rounding_rules( $price ) {
588
 
589
- if ( is_composite_product() && wcml_is_multi_currency_on() ) {
590
  $current_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
591
  if( $current_currency !== wcml_get_woocommerce_currency_option() ) {
592
  $price = $this->woocommerce_wpml->multi_currency->prices->apply_rounding_rules( $price, $current_currency );
511
  }
512
 
513
  public function get_composite_data( $product_id ){
514
+ return get_post_meta( $product_id, '_bto_data', true ) ?: [];
515
  }
516
 
517
 
586
 
587
  public function apply_rounding_rules( $price ) {
588
 
589
+ if ( $price && is_composite_product() && wcml_is_multi_currency_on() ) {
590
  $current_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
591
  if( $current_currency !== wcml_get_woocommerce_currency_option() ) {
592
  $price = $this->woocommerce_wpml->multi_currency->prices->apply_rounding_rules( $price, $current_currency );
compatibility/class-wcml-product-addons.php CHANGED
@@ -193,23 +193,23 @@ class WCML_Product_Addons {
193
  */
194
  private function converted_addon_price( $addon, $post_id ){
195
 
196
- $client_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
 
197
  $is_custom_prices_on = $this->is_product_custom_prices_on( $post_id );
198
  $field = 'price_' . $this->woocommerce_wpml->multi_currency->get_client_currency();
199
 
200
  if (
201
  $is_custom_prices_on &&
202
- isset( $addon[ $field ] ) &&
203
- $addon[ $field ]
204
  ) {
205
- return $addon[ $field ];
206
  }
207
 
208
- if( wpml_collect( [ 'flat_fee', 'quantity_based' ] )->contains( $addon['price_type'] ) ) {
209
- return apply_filters( 'wcml_raw_price_amount', $addon['price'] );
210
  }
211
 
212
- return $addon['price'];
213
  }
214
 
215
  /**
193
  */
194
  private function converted_addon_price( $addon, $post_id ){
195
 
196
+ $addonData = wpml_collect( $addon );
197
+
198
  $is_custom_prices_on = $this->is_product_custom_prices_on( $post_id );
199
  $field = 'price_' . $this->woocommerce_wpml->multi_currency->get_client_currency();
200
 
201
  if (
202
  $is_custom_prices_on &&
203
+ $addonData->get( $field )
 
204
  ) {
205
+ return $addonData->get( $field );
206
  }
207
 
208
+ if( wpml_collect( [ 'flat_fee', 'quantity_based' ] )->contains( $addonData->get( 'price_type' ) ) ) {
209
+ return apply_filters( 'wcml_raw_price_amount', $addonData->get( 'price' ) );
210
  }
211
 
212
+ return $addonData->get( 'price' );
213
  }
214
 
215
  /**
compatibility/class-wcml-product-bundles.php CHANGED
@@ -152,7 +152,7 @@ class WCML_Product_Bundles {
152
  }
153
 
154
  if ( isset( $item_meta['default_variation_attributes'] ) ) {
155
- $default_variation_attributes = $this->translate_default_variation_attributes( $item_meta['default_variation_attributes'], $target_lang );
156
  $this->product_bundles_items->update_item_meta( $translated_item, 'default_variation_attributes', $default_variation_attributes );
157
  }
158
 
@@ -217,19 +217,25 @@ class WCML_Product_Bundles {
217
  /**
218
  * @param array $original_default_variation_attributes
219
  * @param string $target_lang
 
 
220
  *
221
  * @return array
222
  */
223
- public function translate_default_variation_attributes( $original_default_variation_attributes, $target_lang ) {
224
  $default_variation_attributes = array();
225
 
226
  if ( is_array( $original_default_variation_attributes ) ) {
227
  foreach ( $original_default_variation_attributes as $attribute_taxonomy => $attribute_slug ) {
228
- $attribute_term_id = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $attribute_taxonomy, $attribute_slug );
229
- $translated_attribute_term_id = apply_filters( 'translate_object_id', $attribute_term_id, $attribute_taxonomy, true, $target_lang );
230
- $translated_term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $translated_attribute_term_id, $attribute_taxonomy );
231
-
232
- $default_variation_attributes[ $attribute_taxonomy ] = $translated_term->slug;
 
 
 
 
233
  }
234
  }
235
 
152
  }
153
 
154
  if ( isset( $item_meta['default_variation_attributes'] ) ) {
155
+ $default_variation_attributes = $this->translate_default_variation_attributes( $item_meta['default_variation_attributes'], $target_lang, $item_meta['product_id'], $translated_product_id );
156
  $this->product_bundles_items->update_item_meta( $translated_item, 'default_variation_attributes', $default_variation_attributes );
157
  }
158
 
217
  /**
218
  * @param array $original_default_variation_attributes
219
  * @param string $target_lang
220
+ * @param int $product_id
221
+ * @param int $translated_product_id
222
  *
223
  * @return array
224
  */
225
+ public function translate_default_variation_attributes( $original_default_variation_attributes, $target_lang, $product_id, $translated_product_id ) {
226
  $default_variation_attributes = array();
227
 
228
  if ( is_array( $original_default_variation_attributes ) ) {
229
  foreach ( $original_default_variation_attributes as $attribute_taxonomy => $attribute_slug ) {
230
+ if ( 'pa_' === substr( $attribute_taxonomy, 0, 3 ) ) {
231
+ $attribute_term_id = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $attribute_taxonomy, $attribute_slug );
232
+ $translated_attribute_term_id = apply_filters( 'translate_object_id', $attribute_term_id, $attribute_taxonomy, true, $target_lang );
233
+ $translated_term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $translated_attribute_term_id, $attribute_taxonomy );
234
+
235
+ $default_variation_attributes[ $attribute_taxonomy ] = $translated_term->slug;
236
+ }else{
237
+ $default_variation_attributes[ $attribute_taxonomy ] = $this->woocommerce_wpml->attributes->get_custom_attr_translation( $product_id, $translated_product_id, $attribute_taxonomy, $attribute_slug );
238
+ }
239
  }
240
  }
241
 
compatibility/class-wcml-variation-swatches-and-photos.php CHANGED
@@ -5,78 +5,101 @@
5
  */
6
  class WCML_Variation_Swatches_And_Photos {
7
 
8
- /** @var SitePress */
9
- private $sitepress;
10
 
11
- function __construct( SitePress $sitepress ) {
12
- $this->sitepress = $sitepress;
13
  }
14
 
15
  public function add_hooks() {
16
- add_action( 'wcml_after_duplicate_product_post_meta', array(
17
- $this,
18
- 'sync_variation_swatches_and_photos'
19
- ), 10, 3 );
20
  }
21
 
22
  /**
23
  * Synchronize Variation Swatches and Photos
24
  *
25
  * @param int $original_product_id Original product ID.
26
- * @param int $trnsl_product_id Translated product ID.
27
- * @param array $data Product data.
28
  */
29
- public function sync_variation_swatches_and_photos( $original_product_id, $trnsl_product_id, $data = false ) {
30
 
31
- $atts = maybe_unserialize( get_post_meta( $original_product_id, '_swatch_type_options', true ) );
 
32
 
33
- if ( ! is_array( $atts ) ) {
34
- return;
35
- }
36
-
37
- $lang = $this->sitepress->get_language_for_element( $trnsl_product_id, 'post_product' );
38
- $tr_atts = $atts;
39
-
40
- $original_product_post = get_post( $original_product_id );
41
-
42
- $original_product_taxonomies = get_object_taxonomies( $original_product_post );
43
-
44
- $original_product_terms = get_terms( $original_product_taxonomies );
45
 
46
- if ( is_array( $original_product_terms ) ) {
 
 
 
 
 
 
 
 
 
47
 
48
- remove_filter( 'get_term', array( $this->sitepress, 'get_term_adjust_id' ), 1 );
49
 
50
- foreach ( $atts as $att_name => $att_opts ) {
 
51
 
52
- $attributes_hashed_names = array_keys( $att_opts['attributes'] );
 
53
 
54
- foreach ( $original_product_terms as $original_product_term ) {
55
- $original_product_term_slug_md5 = md5( $original_product_term->slug );
 
 
 
 
56
 
57
- if ( in_array( $original_product_term_slug_md5, $attributes_hashed_names, true ) ) {
 
58
 
59
- $translated_product_term_id = apply_filters( 'wpml_object_id', $original_product_term->term_id, $original_product_term->taxonomy, false, $lang );
 
 
 
 
 
 
 
 
 
60
 
61
- $translated_product_term = get_term( $translated_product_term_id, $original_product_term->taxonomy );
 
62
 
63
- if ( isset( $translated_product_term->slug ) ) {
 
64
 
65
- $translated_product_term_slug_md5 = md5( $translated_product_term->slug );
 
 
 
 
 
 
66
 
67
- $tr_atts[ $att_name ]['attributes'][ $translated_product_term_slug_md5 ] = $tr_atts[ $att_name ]['attributes'][ $original_product_term_slug_md5 ];
 
68
 
69
- unset( $tr_atts[ $att_name ]['attributes'][ $original_product_term_slug_md5 ] );
70
- }
71
- }
 
 
 
 
72
  }
73
  }
 
74
 
75
- add_filter( 'get_term', array( $this->sitepress, 'get_term_adjust_id' ), 1, 1 );
76
-
77
- }
78
-
79
- update_post_meta( $trnsl_product_id, '_swatch_type_options', $tr_atts ); // Meta gets overwritten.
80
  }
81
 
82
  }
5
  */
6
  class WCML_Variation_Swatches_And_Photos {
7
 
8
+ /** @var woocommerce_wpml */
9
+ private $woocommerce_wpml;
10
 
11
+ function __construct( woocommerce_wpml $woocommerce_wpml ) {
12
+ $this->woocommerce_wpml = $woocommerce_wpml;
13
  }
14
 
15
  public function add_hooks() {
16
+ add_action( 'wcml_after_sync_product_data', [ $this, 'sync_variation_swatches_and_photos' ], 10, 3 );
 
 
 
17
  }
18
 
19
  /**
20
  * Synchronize Variation Swatches and Photos
21
  *
22
  * @param int $original_product_id Original product ID.
23
+ * @param int $translated_product_id Translated product ID.
24
+ * @param string $language
25
  */
26
+ public function sync_variation_swatches_and_photos( $original_product_id, $translated_product_id, $language ) {
27
 
28
+ $swatch_options = maybe_unserialize( get_post_meta( $original_product_id, '_swatch_type_options', true ) );
29
+ $translated_swatch_options = $swatch_options;
30
 
31
+ if ( $swatch_options ) {
32
+ $original_product_attributes = $this->woocommerce_wpml->attributes->get_product_attributes( $original_product_id );
 
 
 
 
 
 
 
 
 
 
33
 
34
+ wpml_collect( $original_product_attributes )->each(
35
+ function ( $attribute, $attribute_key ) use ( $swatch_options, &$translated_swatch_options, $language, $original_product_id, $translated_product_id ) {
36
+ $attribute_name_hash = md5( sanitize_title( $attribute['name'] ) );
37
+ if ( $this->woocommerce_wpml->attributes->is_a_taxonomy( $attribute ) ) {
38
+ $translated_swatch_options = $this->translate_taxonomy_attributes( $attribute_key, $attribute_name_hash, $swatch_options, $translated_swatch_options, $language );
39
+ } else {
40
+ $translated_swatch_options = $this->translate_custom_attributes( $attribute_key, $attribute, $attribute_name_hash, $swatch_options, $translated_swatch_options, $original_product_id, $translated_product_id );
41
+ }
42
+ }
43
+ );
44
 
45
+ }
46
 
47
+ update_post_meta( $translated_product_id, '_swatch_type_options', $translated_swatch_options );
48
+ }
49
 
50
+ private function translate_taxonomy_attributes( $taxonomy, $attribute_name_hash, $swatch_options, $translated_swatch_options, $language ) {
51
+ $attribute_terms = get_terms( [ 'taxonomy' => $taxonomy ] );
52
 
53
+ wpml_collect( $attribute_terms )->each(
54
+ function ( $term ) use ( $taxonomy, $attribute_name_hash, $swatch_options, &$translated_swatch_options, $language ) {
55
+ $attribute_term_slug_md5 = md5( $term->slug );
56
+ $translated_swatch_options = $this->translate_taxonomy_term( $term, $attribute_term_slug_md5, $taxonomy, $attribute_name_hash, $swatch_options, $translated_swatch_options, $language );
57
+ }
58
+ );
59
 
60
+ return $translated_swatch_options;
61
+ }
62
 
63
+ private function translate_taxonomy_term( $term, $attribute_term_slug_md5, $taxonomy, $attribute_name_hash, $swatch_options, $translated_swatch_options, $language ) {
64
+ wpml_collect( $swatch_options[ $attribute_name_hash ]['attributes'] )->each(
65
+ function ( $swatch_attribute, $swatch_attribute_key ) use ( $term, $attribute_term_slug_md5, $taxonomy, $attribute_name_hash, &$translated_swatch_options, $language ) {
66
+ if ( $attribute_term_slug_md5 === $swatch_attribute_key ) {
67
+ $translated_term = $this->woocommerce_wpml->terms->wcml_get_translated_term( $term->term_id, $taxonomy, $language );
68
+ $translated_swatch_options[ $attribute_name_hash ]['attributes'][ md5( $translated_term->slug ) ] = $swatch_attribute;
69
+ unset( $translated_swatch_options[ $attribute_name_hash ]['attributes'][ $swatch_attribute_key ] );
70
+ }
71
+ }
72
+ );
73
 
74
+ return $translated_swatch_options;
75
+ }
76
 
77
+ private function translate_custom_attributes( $attribute_key, $attribute, $attribute_name_hash, $swatch_options, $translated_swatch_options, $original_product_id, $translated_product_id ) {
78
+ $attribute_values = explode( '|', $attribute['value'] );
79
 
80
+ wpml_collect( $attribute_values )->each(
81
+ function ( $attribute_value ) use ( $attribute_key, $attribute, $attribute_name_hash, $swatch_options, &$translated_swatch_options, $original_product_id, $translated_product_id ) {
82
+ $attribute_value = trim( $attribute_value, " " );
83
+ $attribute_value_md5 = md5( sanitize_title( strtolower( $attribute_value ) ) );
84
+ $translated_swatch_options = $this->translate_custom_attribute_value( $attribute_key, $attribute_value, $attribute_value_md5, $attribute_name_hash, $swatch_options, $translated_swatch_options, $original_product_id, $translated_product_id );
85
+ }
86
+ );
87
 
88
+ return $translated_swatch_options;
89
+ }
90
 
91
+ private function translate_custom_attribute_value( $attribute_key, $attribute_value, $attribute_value_md5, $attribute_name_hash, $swatch_options, $translated_swatch_options, $original_product_id, $translated_product_id ) {
92
+ wpml_collect( $swatch_options[ $attribute_name_hash ]['attributes'] )->each(
93
+ function ( $swatch_attribute, $swatch_attribute_key ) use ( $attribute_key, $attribute_value, $attribute_value_md5, $attribute_name_hash, &$translated_swatch_options, $original_product_id, $translated_product_id ) {
94
+ if ( $attribute_value_md5 === $swatch_attribute_key ) {
95
+ $translated_attribute_value = $this->woocommerce_wpml->attributes->get_custom_attr_translation( $original_product_id, $translated_product_id, $attribute_key, $attribute_value );
96
+ $translated_swatch_options[ $attribute_name_hash ]['attributes'][ md5( sanitize_title( strtolower( $translated_attribute_value ) ) ) ] = $swatch_attribute;
97
+ unset( $translated_swatch_options[ $attribute_name_hash ]['attributes'][ $swatch_attribute_key ] );
98
  }
99
  }
100
+ );
101
 
102
+ return $translated_swatch_options;
 
 
 
 
103
  }
104
 
105
  }
compatibility/{class-wcml-yikes-custom-product-tabs-pro.php → class-wcml-yikes-custom-product-tabs.php} RENAMED
@@ -1,9 +1,9 @@
1
  <?php
2
 
3
  /**
4
- * Class WCML_YIKES_Custom_Product_Tabs_Pro
5
  */
6
- class WCML_YIKES_Custom_Product_Tabs_Pro {
7
 
8
  const CUSTOM_TABS_FIELD = 'yikes_woo_products_tabs';
9
 
1
  <?php
2
 
3
  /**
4
+ * Class WCML_YIKES_Custom_Product_Tabs
5
  */
6
+ class WCML_YIKES_Custom_Product_Tabs {
7
 
8
  const CUSTOM_TABS_FIELD = 'yikes_woo_products_tabs';
9
 
inc/class-wcml-ajax-setup.php CHANGED
@@ -14,27 +14,13 @@ class WCML_Ajax_Setup {
14
  }
15
 
16
  public function add_hooks() {
17
-
18
  add_action( 'init', [ $this, 'init' ] );
19
- add_action( 'wcml_localize_woocommerce_on_ajax', [ $this, 'wcml_localize_woocommerce_on_ajax' ] );
20
-
21
- // @deprecated 3.9 Use 'wcml_localize_woocommerce_on_ajax' instead
22
- add_action( 'localize_woocommerce_on_ajax', [ $this, 'localize_woocommerce_on_ajax' ] );
23
-
24
  add_action( 'woocommerce_ajax_get_endpoint', [ $this, 'add_language_to_endpoint' ] );
25
  }
26
 
27
  public function init() {
28
- if ( wpml_is_ajax() ) {
29
- /**
30
- * @since 3.9.0
31
- */
32
- do_action( 'wcml_localize_woocommerce_on_ajax' );
33
- }
34
-
35
  add_filter( 'woocommerce_get_script_data', array( $this, 'add_language_parameter_to_ajax_url' ) );
36
  add_action( 'woocommerce_checkout_order_review', array( $this, 'add_hidden_language_field' ) );
37
-
38
  }
39
 
40
  function add_hidden_language_field() {
@@ -50,28 +36,6 @@ class WCML_Ajax_Setup {
50
  return $woocommerce_params;
51
  }
52
 
53
- public function wcml_localize_woocommerce_on_ajax() {
54
- $action = isset( $_POST['action'] ) ? filter_var( $_POST['action'], FILTER_SANITIZE_STRING ) : false;
55
- $is_ajax_action = $action
56
- && in_array(
57
- $action,
58
- [
59
- 'wcml_product_data',
60
- 'wpml_translation_dialog_save_job',
61
- 'edit-theme-plugin-file',
62
- 'search-install-plugins',
63
- ],
64
- true
65
- );
66
- if ( $action && ( $is_ajax_action || ! apply_filters( 'wcml_is_localize_woocommerce_on_ajax', true, $action ) ) ) {
67
- return;
68
- }
69
-
70
- $current_language = $this->sitepress->get_current_language();
71
-
72
- $this->sitepress->switch_lang( $current_language, true );
73
- }
74
-
75
  /**
76
  * @param $endpoint string
77
  *
@@ -91,14 +55,4 @@ class WCML_Ajax_Setup {
91
 
92
  return $endpoint;
93
  }
94
-
95
-
96
- /**
97
- * @deprecated 3.9
98
- */
99
- function localize_woocommerce_on_ajax() {
100
- $this->wcml_localize_woocommerce_on_ajax();
101
- }
102
-
103
-
104
  }
14
  }
15
 
16
  public function add_hooks() {
 
17
  add_action( 'init', [ $this, 'init' ] );
 
 
 
 
 
18
  add_action( 'woocommerce_ajax_get_endpoint', [ $this, 'add_language_to_endpoint' ] );
19
  }
20
 
21
  public function init() {
 
 
 
 
 
 
 
22
  add_filter( 'woocommerce_get_script_data', array( $this, 'add_language_parameter_to_ajax_url' ) );
23
  add_action( 'woocommerce_checkout_order_review', array( $this, 'add_hidden_language_field' ) );
 
24
  }
25
 
26
  function add_hidden_language_field() {
36
  return $woocommerce_params;
37
  }
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  /**
40
  * @param $endpoint string
41
  *
55
 
56
  return $endpoint;
57
  }
 
 
 
 
 
 
 
 
 
 
58
  }
inc/class-wcml-attributes.php CHANGED
@@ -32,6 +32,14 @@ class WCML_Attributes{
32
  $this->wpdb = $wpdb;
33
  }
34
 
 
 
 
 
 
 
 
 
35
  public function add_hooks(){
36
 
37
  add_action( 'init', array( $this, 'init' ) );
@@ -42,10 +50,9 @@ class WCML_Attributes{
42
  if( isset( $_POST['icl_ajx_action'] ) && $_POST['icl_ajx_action'] == 'icl_custom_tax_sync_options' ){
43
  $this->icl_custom_tax_sync_options();
44
  }
45
-
46
  add_filter( 'woocommerce_product_get_attributes', array( $this, 'filter_adding_to_cart_product_attributes_names' ) );
47
 
48
- if ( $this->woocommerce_wpml->products->is_product_display_as_translated_post_type() ) {
49
  add_filter( 'woocommerce_available_variation', array(
50
  $this,
51
  'filter_available_variation_attribute_values_in_current_language'
@@ -60,6 +67,7 @@ class WCML_Attributes{
60
  ) );
61
  }
62
  add_action( 'update_post_meta', array( $this, 'set_translation_status_as_needs_update' ), 10, 3 );
 
63
  }
64
 
65
  public function init() {
@@ -140,7 +148,7 @@ class WCML_Attributes{
140
  $this->set_attribute_config_in_wcml_settings( $attribute_name, $is_translatable );
141
  $this->set_attribute_config_in_wpml_settings( $attribute_name, $is_translatable );
142
 
143
- $this->woocommerce_wpml->terms->update_terms_translated_status( $attribute_name );
144
  }
145
 
146
  public function set_attribute_config_in_wcml_settings( $attribute_name, $is_translatable ){
@@ -262,8 +270,8 @@ class WCML_Attributes{
262
  public function sync_product_attr( $original_product_id, $tr_product_id, $language = false, $data = false ){
263
 
264
  //get "_product_attributes" from original product
265
- $orig_product_attrs = $this->get_product_atributes( $original_product_id );
266
- $trnsl_product_attrs = $this->get_product_atributes( $tr_product_id );
267
 
268
  $trnsl_labels = $this->get_attr_label_translations( $tr_product_id );
269
 
@@ -309,7 +317,7 @@ class WCML_Attributes{
309
  update_post_meta( $tr_product_id, '_product_attributes', $orig_product_attrs );
310
  }
311
 
312
- public function get_product_atributes( $product_id ){
313
  $attributes = get_post_meta( $product_id, '_product_attributes', true );
314
  if( !is_array( $attributes ) ){
315
  $attributes = array();
@@ -342,11 +350,11 @@ class WCML_Attributes{
342
  //attr is taxonomy
343
  if( $this->is_translatable_attribute( $attribute ) ){
344
  $sanitized_attribute_name = wc_sanitize_taxonomy_name( $attribute );
345
- $default_term_id = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $sanitized_attribute_name, $default_term_slug );
346
  $tr_id = apply_filters( 'translate_object_id', $default_term_id, $sanitized_attribute_name, false, $lang );
347
 
348
  if( $tr_id ){
349
- $translated_term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $tr_id, $sanitized_attribute_name );
350
  $unserialized_default_attributes[ $attribute ] = $translated_term->slug;
351
  }
352
  }else{
@@ -487,7 +495,7 @@ class WCML_Attributes{
487
 
488
  if( $product_attributes ){
489
  foreach( $product_attributes as $attribute ){
490
- $is_fully_translated = $this->woocommerce_wpml->terms->is_fully_translated( 'pa_' . $attribute->attribute_name );
491
  if( !$is_fully_translated ){
492
  $fully_translated = false;
493
  break;
@@ -505,14 +513,14 @@ class WCML_Attributes{
505
 
506
  $tax = wc_sanitize_taxonomy_name ( substr( $meta_key, 10 ) );
507
  if( taxonomy_exists( $tax ) ){
508
- $attid = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $tax, $meta_value );
509
  if( $this->is_translatable_attribute( $tax ) && $attid ){
510
 
511
- $term_obj = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $attid, $tax );
512
  $trnsl_term_id = apply_filters( 'translate_object_id', $term_obj->term_id, $tax, false, $lang );
513
 
514
  if( $trnsl_term_id ) {
515
- $trnsl_term_obj = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $trnsl_term_id, $tax );
516
  $meta_value = $trnsl_term_obj->slug;
517
  }
518
  }
@@ -553,7 +561,7 @@ class WCML_Attributes{
553
  if( isset( $args['attribute'] ) && isset( $args['product'] ) ){
554
  $args['attribute'] = $this->filter_attribute_name( $args['attribute'], $args['product']->get_id() );
555
 
556
- if( $this->woocommerce_wpml->products->is_product_display_as_translated_post_type() ){
557
  foreach( $args[ 'options' ] as $key => $attribute_value ){
558
  $args[ 'options' ][ $key ] = $this->get_attribute_term_translation_in_current_language( $args[ 'attribute' ], $attribute_value );
559
  }
@@ -571,7 +579,7 @@ class WCML_Attributes{
571
  function filter_attribute_name( $attribute_name, $product_id, $return_sanitized = false ) {
572
 
573
  if ( $product_id ) {
574
- $orig_lang = $this->woocommerce_wpml->products->get_original_product_language( $product_id );
575
  $current_language = $this->sitepress->get_current_language();
576
 
577
  if ( in_array( $orig_lang, array( 'de', 'da' ) ) && $current_language !== $orig_lang ) {
@@ -755,4 +763,17 @@ class WCML_Attributes{
755
  }
756
  }
757
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
  }
32
  $this->wpdb = $wpdb;
33
  }
34
 
35
+ private function get_wcml_terms_instance(){
36
+ return $this->woocommerce_wpml->terms;
37
+ }
38
+
39
+ private function get_wcml_products_instance(){
40
+ return $this->woocommerce_wpml->products;
41
+ }
42
+
43
  public function add_hooks(){
44
 
45
  add_action( 'init', array( $this, 'init' ) );
50
  if( isset( $_POST['icl_ajx_action'] ) && $_POST['icl_ajx_action'] == 'icl_custom_tax_sync_options' ){
51
  $this->icl_custom_tax_sync_options();
52
  }
 
53
  add_filter( 'woocommerce_product_get_attributes', array( $this, 'filter_adding_to_cart_product_attributes_names' ) );
54
 
55
+ if ( $this->get_wcml_products_instance()->is_product_display_as_translated_post_type() ) {
56
  add_filter( 'woocommerce_available_variation', array(
57
  $this,
58
  'filter_available_variation_attribute_values_in_current_language'
67
  ) );
68
  }
69
  add_action( 'update_post_meta', array( $this, 'set_translation_status_as_needs_update' ), 10, 3 );
70
+ add_action( 'wc_ajax_get_variation', array( $this, 'maybe_filter_get_variation' ), 9 );
71
  }
72
 
73
  public function init() {
148
  $this->set_attribute_config_in_wcml_settings( $attribute_name, $is_translatable );
149
  $this->set_attribute_config_in_wpml_settings( $attribute_name, $is_translatable );
150
 
151
+ $this->get_wcml_terms_instance()->update_terms_translated_status( $attribute_name );
152
  }
153
 
154
  public function set_attribute_config_in_wcml_settings( $attribute_name, $is_translatable ){
270
  public function sync_product_attr( $original_product_id, $tr_product_id, $language = false, $data = false ){
271
 
272
  //get "_product_attributes" from original product
273
+ $orig_product_attrs = $this->get_product_attributes( $original_product_id );
274
+ $trnsl_product_attrs = $this->get_product_attributes( $tr_product_id );
275
 
276
  $trnsl_labels = $this->get_attr_label_translations( $tr_product_id );
277
 
317
  update_post_meta( $tr_product_id, '_product_attributes', $orig_product_attrs );
318
  }
319
 
320
+ public function get_product_attributes( $product_id ){
321
  $attributes = get_post_meta( $product_id, '_product_attributes', true );
322
  if( !is_array( $attributes ) ){
323
  $attributes = array();
350
  //attr is taxonomy
351
  if( $this->is_translatable_attribute( $attribute ) ){
352
  $sanitized_attribute_name = wc_sanitize_taxonomy_name( $attribute );
353
+ $default_term_id = $this->get_wcml_terms_instance()->wcml_get_term_id_by_slug( $sanitized_attribute_name, $default_term_slug );
354
  $tr_id = apply_filters( 'translate_object_id', $default_term_id, $sanitized_attribute_name, false, $lang );
355
 
356
  if( $tr_id ){
357
+ $translated_term = $this->get_wcml_terms_instance()->wcml_get_term_by_id( $tr_id, $sanitized_attribute_name );
358
  $unserialized_default_attributes[ $attribute ] = $translated_term->slug;
359
  }
360
  }else{
495
 
496
  if( $product_attributes ){
497
  foreach( $product_attributes as $attribute ){
498
+ $is_fully_translated = $this->get_wcml_terms_instance()->is_fully_translated( 'pa_' . $attribute->attribute_name );
499
  if( !$is_fully_translated ){
500
  $fully_translated = false;
501
  break;
513
 
514
  $tax = wc_sanitize_taxonomy_name ( substr( $meta_key, 10 ) );
515
  if( taxonomy_exists( $tax ) ){
516
+ $attid = $this->get_wcml_terms_instance()->wcml_get_term_id_by_slug( $tax, $meta_value );
517
  if( $this->is_translatable_attribute( $tax ) && $attid ){
518
 
519
+ $term_obj = $this->get_wcml_terms_instance()->wcml_get_term_by_id( $attid, $tax );
520
  $trnsl_term_id = apply_filters( 'translate_object_id', $term_obj->term_id, $tax, false, $lang );
521
 
522
  if( $trnsl_term_id ) {
523
+ $trnsl_term_obj = $this->get_wcml_terms_instance()->wcml_get_term_by_id( $trnsl_term_id, $tax );
524
  $meta_value = $trnsl_term_obj->slug;
525
  }
526
  }
561
  if( isset( $args['attribute'] ) && isset( $args['product'] ) ){
562
  $args['attribute'] = $this->filter_attribute_name( $args['attribute'], $args['product']->get_id() );
563
 
564
+ if( $this->get_wcml_products_instance()->is_product_display_as_translated_post_type() ){
565
  foreach( $args[ 'options' ] as $key => $attribute_value ){
566
  $args[ 'options' ][ $key ] = $this->get_attribute_term_translation_in_current_language( $args[ 'attribute' ], $attribute_value );
567
  }
579
  function filter_attribute_name( $attribute_name, $product_id, $return_sanitized = false ) {
580
 
581
  if ( $product_id ) {
582
+ $orig_lang = $this->get_wcml_products_instance()->get_original_product_language( $product_id );
583
  $current_language = $this->sitepress->get_current_language();
584
 
585
  if ( in_array( $orig_lang, array( 'de', 'da' ) ) && $current_language !== $orig_lang ) {
763
  }
764
  }
765
 
766
+ public function maybe_filter_get_variation() {
767
+ if ( isset( $_POST['product_id'] ) ) {
768
+ foreach ( wp_unslash( $_POST ) as $key => $value ) {
769
+ if ( substr( $key, 0, 13 ) == 'attribute_pa_' ) {
770
+ $taxonomy = substr( $key, 10 );
771
+ $term_id = $this->get_wcml_terms_instance()->wcml_get_term_id_by_slug( $taxonomy, $value );
772
+ $translated_term = $this->get_wcml_terms_instance()->wcml_get_translated_term( $term_id, $taxonomy, $this->get_wcml_products_instance()->get_original_product_language( $_POST['product_id'] ) );
773
+ $_POST[ $key ] = $translated_term->slug;
774
+ }
775
+ }
776
+ }
777
+ }
778
+
779
  }
inc/class-wcml-cart.php CHANGED
@@ -317,8 +317,8 @@ class WCML_Cart {
317
  if ( ! is_null( $tr_variation_id ) ) {
318
  $cart->cart_contents[ $key ]['product_id'] = intval( $tr_product_id );
319
  $cart->cart_contents[ $key ]['variation_id'] = intval( $tr_variation_id );
320
- $cart->cart_contents[ $key ]['data']->set_id( intval( $tr_product_id ) );
321
- $cart->cart_contents[ $key ]['data']->post = get_post( $tr_product_id );
322
  }
323
  } else {
324
  if ( ! is_null( $tr_product_id ) ) {
@@ -664,11 +664,12 @@ class WCML_Cart {
664
  $cart_items = WC()->cart->get_cart_contents();
665
 
666
  //items total
667
- foreach( $cart_items as $item ){
668
- $cart_total += $this->woocommerce_wpml->multi_currency->prices->get_product_price_in_currency( $item['product_id'], $currency ) * $item['quantity'];
 
669
  }
670
 
671
- $cart_total += $this->woocommerce_wpml->multi_currency->prices->convert_price_amount_by_currencies( WC()->cart->get_shipping_total(), $client_currency, $currency );
672
 
673
  $cart_total = $this->woocommerce_wpml->multi_currency->prices->apply_rounding_rules( $cart_total, $currency );
674
 
@@ -680,11 +681,15 @@ class WCML_Cart {
680
  *
681
  * @return string
682
  */
683
- public function get_formatted_cart_total_in_currency( $currency ){
 
 
684
 
685
- $cart_total = $this->woocommerce_wpml->multi_currency->prices->formatted_price( $this->get_cart_total_in_currency( $currency ), $currency );
 
686
 
687
- return $cart_total;
688
  }
689
 
 
690
  }
317
  if ( ! is_null( $tr_variation_id ) ) {
318
  $cart->cart_contents[ $key ]['product_id'] = intval( $tr_product_id );
319
  $cart->cart_contents[ $key ]['variation_id'] = intval( $tr_variation_id );
320
+ $cart->cart_contents[ $key ]['data']->set_id( intval( $tr_variation_id ) );
321
+ $cart->cart_contents[ $key ]['data']->post = get_post( $tr_variation_id );
322
  }
323
  } else {
324
  if ( ! is_null( $tr_product_id ) ) {
664
  $cart_items = WC()->cart->get_cart_contents();
665
 
666
  //items total
667
+ foreach ( $cart_items as $item ) {
668
+ $item_product_id = $item['variation_id'] ?: $item['product_id'];
669
+ $cart_total += $this->woocommerce_wpml->multi_currency->prices->get_product_price_in_currency( $item_product_id, $currency ) * $item['quantity'];
670
  }
671
 
672
+ $cart_total += $this->get_cart_shipping_in_currency( $currency );
673
 
674
  $cart_total = $this->woocommerce_wpml->multi_currency->prices->apply_rounding_rules( $cart_total, $currency );
675
 
681
  *
682
  * @return string
683
  */
684
+ public function get_formatted_cart_total_in_currency( $currency ) {
685
+ return $this->woocommerce_wpml->multi_currency->prices->format_price_in_currency( $this->get_cart_total_in_currency( $currency ), $currency );
686
+ }
687
 
688
+ public function get_cart_shipping_in_currency( $currency ) {
689
+ $shipping_amount_in_default_currency = $this->woocommerce_wpml->multi_currency->prices->unconvert_price_amount( WC()->cart->get_shipping_total() );
690
 
691
+ return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $shipping_amount_in_default_currency, $currency );
692
  }
693
 
694
+
695
  }
inc/class-wcml-compatibility.php CHANGED
@@ -27,7 +27,7 @@ class WCML_Compatibility {
27
  */
28
  private $tp;
29
  /**
30
- * @var WPML_Element_Translation
31
  */
32
  private $wpml_post_translations;
33
 
@@ -39,7 +39,7 @@ class WCML_Compatibility {
39
  * @param wpdb $wpdb Database object.
40
  * @param WPML_Element_Translation_Package $tp Element Translation Package.
41
  */
42
- function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml, wpdb $wpdb, WPML_Element_Translation_Package $tp, WPML_Element_Translation $wpml_post_translations ) {
43
  $this->sitepress = $sitepress;
44
  $this->woocommerce_wpml = $woocommerce_wpml;
45
  $this->wpdb = $wpdb;
@@ -87,7 +87,7 @@ class WCML_Compatibility {
87
 
88
  // WooCommerce Variation Swatches and Photos.
89
  if ( class_exists( 'WC_SwatchesPlugin' ) ) {
90
- $this->variation_sp = new WCML_Variation_Swatches_And_Photos( $this->sitepress );
91
  $this->variation_sp->add_hooks();
92
  }
93
 
@@ -136,7 +136,7 @@ class WCML_Compatibility {
136
 
137
  // WooCommerce Bookings.
138
  if ( defined( 'WC_BOOKINGS_VERSION' ) && version_compare( WC_BOOKINGS_VERSION, '1.7.8', '>=' ) ) {
139
- $this->bookings = new WCML_Bookings( $this->sitepress, $this->woocommerce_wpml, $woocommerce, $this->wpdb, $this->tp );
140
  $this->bookings->add_hooks();
141
 
142
  // WooCommerce Accommodation Bookings.
@@ -293,8 +293,8 @@ class WCML_Compatibility {
293
  }
294
 
295
  // Custom Product Tabs PRO.
296
- if ( class_exists( 'YIKES_Custom_Product_Tabs_Pro' ) ) {
297
- $this->custom_product_tabs = new WCML_YIKES_Custom_Product_Tabs_Pro( $this->woocommerce_wpml, $this->sitepress, $this->tp );
298
  $this->custom_product_tabs->add_hooks();
299
  }
300
 
27
  */
28
  private $tp;
29
  /**
30
+ * @var WPML_Post_Translation
31
  */
32
  private $wpml_post_translations;
33
 
39
  * @param wpdb $wpdb Database object.
40
  * @param WPML_Element_Translation_Package $tp Element Translation Package.
41
  */
42
+ function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml, wpdb $wpdb, WPML_Element_Translation_Package $tp, WPML_Post_Translation $wpml_post_translations ) {
43
  $this->sitepress = $sitepress;
44
  $this->woocommerce_wpml = $woocommerce_wpml;
45
  $this->wpdb = $wpdb;
87
 
88
  // WooCommerce Variation Swatches and Photos.
89
  if ( class_exists( 'WC_SwatchesPlugin' ) ) {
90
+ $this->variation_sp = new WCML_Variation_Swatches_And_Photos( $this->woocommerce_wpml );
91
  $this->variation_sp->add_hooks();
92
  }
93
 
136
 
137
  // WooCommerce Bookings.
138
  if ( defined( 'WC_BOOKINGS_VERSION' ) && version_compare( WC_BOOKINGS_VERSION, '1.7.8', '>=' ) ) {
139
+ $this->bookings = new WCML_Bookings( $this->sitepress, $this->woocommerce_wpml, $woocommerce, $this->wpdb, $this->tp, $this->wpml_post_translations );
140
  $this->bookings->add_hooks();
141
 
142
  // WooCommerce Accommodation Bookings.
293
  }
294
 
295
  // Custom Product Tabs PRO.
296
+ if ( class_exists( 'YIKES_Custom_Product_Tabs' ) ) {
297
+ $this->custom_product_tabs = new WCML_YIKES_Custom_Product_Tabs( $this->woocommerce_wpml, $this->sitepress, $this->tp );
298
  $this->custom_product_tabs->add_hooks();
299
  }
300
 
inc/class-wcml-dependencies.php CHANGED
@@ -2,9 +2,9 @@
2
 
3
  class WCML_Dependencies {
4
 
5
- const MIN_WPML = '4.0.0';
6
- const MIN_WPML_TM = '2.6';
7
- const MIN_WPML_ST = '2.8';
8
  const MIN_WOOCOMMERCE = '3.3.0';
9
 
10
  private $missing = array();
@@ -19,11 +19,6 @@ class WCML_Dependencies {
19
  function __construct() {
20
 
21
  if ( is_admin() ) {
22
- add_action( 'wp_ajax_wcml_fix_strings_language', array(
23
- $this,
24
- 'fix_strings_language'
25
- ) ); // TODO: remove after WPML release with support strings in different languages
26
-
27
  add_action( 'init', array( $this, 'check_wpml_config' ), 100 );
28
  }
29
 
@@ -238,25 +233,6 @@ class WCML_Dependencies {
238
  echo $this->err_message;
239
  }
240
 
241
- public function fix_strings_language() {
242
- $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
243
- if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wcml_fix_strings_language' ) ) {
244
- die( 'Invalid nonce' );
245
- }
246
-
247
- $ret = array();
248
-
249
- $ret['_wpnonce'] = wp_create_nonce( 'icl_sw_form' );
250
-
251
- $ret['success_1'] = '&nbsp;' . sprintf( __( 'Finished! You can visit the %sstrings translation%s screen to translate the strings now.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php' ) . '">', '</a>' );
252
-
253
-
254
- echo json_encode( $ret );
255
-
256
- exit;
257
-
258
- }
259
-
260
  public function check_wpml_config() {
261
  global $sitepress_settings, $sitepress, $woocommerce_wpml;
262
 
2
 
3
  class WCML_Dependencies {
4
 
5
+ const MIN_WPML = '4.3.5';
6
+ const MIN_WPML_TM = '2.9.1';
7
+ const MIN_WPML_ST = '3.0.5';
8
  const MIN_WOOCOMMERCE = '3.3.0';
9
 
10
  private $missing = array();
19
  function __construct() {
20
 
21
  if ( is_admin() ) {
 
 
 
 
 
22
  add_action( 'init', array( $this, 'check_wpml_config' ), 100 );
23
  }
24
 
233
  echo $this->err_message;
234
  }
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  public function check_wpml_config() {
237
  global $sitepress_settings, $sitepress, $woocommerce_wpml;
238
 
inc/class-wcml-emails.php CHANGED
@@ -5,32 +5,23 @@ class WCML_Emails {
5
  private $order_id = false;
6
  private $locale = false;
7
  private $admin_language = false;
8
- /** @var woocommerce_wpml */
9
- private $woocommerce_wpml;
10
  /** @var Sitepress */
11
  private $sitepress;
12
- /** @var WooCommerce */
13
- private $woocommerce;
14
  /** @var wpdb */
15
  private $wpdb;
16
 
17
- /**
18
- * WCML_Emails constructor.
19
- *
20
- * @param woocommerce_wpml $woocommerce_wpml
21
- * @param SitePress $sitepress
22
- * @param WooCommerce $woocommerce
23
- * @param wpdb $wpdb
24
- */
25
- function __construct( woocommerce_wpml $woocommerce_wpml, SitePress $sitepress, WooCommerce $woocommerce, wpdb $wpdb ) {
26
- $this->woocommerce_wpml = $woocommerce_wpml;
27
- $this->sitepress = $sitepress;
28
- $this->woocommerce = $woocommerce;
29
- $this->wpdb = $wpdb;
30
  }
31
 
32
  function add_hooks() {
33
- global $pagenow;
34
  //wrappers for email's header
35
  if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
36
  add_action( 'woocommerce_order_status_completed_notification', array(
@@ -95,26 +86,6 @@ class WCML_Emails {
95
  add_filter( 'plugin_locale', array( $this, 'set_locale_for_emails' ), 10, 2 );
96
  add_filter( 'woocommerce_countries', array( $this, 'translate_woocommerce_countries' ) );
97
 
98
- if ( is_admin() && $pagenow == 'admin.php' && isset( $_GET['page'] ) && $_GET['page'] == 'wc-settings' && isset( $_GET['tab'] ) && $_GET['tab'] == 'email' ) {
99
- add_action( 'admin_footer', array( $this, 'show_language_links_for_wc_emails' ) );
100
- $this->set_emails_string_language();
101
- }
102
-
103
- if (
104
- (
105
- ! isset( $_GET['post_type'] ) ||
106
- $_GET['post_type'] != 'shop_order'
107
- ) &&
108
- (
109
- ! isset( $_GET['action'] ) ||
110
- ! in_array( $_GET['action'], array(
111
- 'woocommerce_mark_order_status'
112
- ) )
113
- )
114
- ) {
115
- add_filter( 'woocommerce_order_items_meta_get_formatted', array( $this, 'filter_formatted_items' ), 10, 2 );
116
- }
117
-
118
  add_filter( 'woocommerce_allow_send_queued_transactional_email', array(
119
  $this,
120
  'send_queued_transactional_email'
@@ -216,27 +187,28 @@ class WCML_Emails {
216
  if ( is_admin() && false !== $this->admin_language ) {
217
  $this->change_email_language( $this->admin_language );
218
  } else {
219
- $this->change_email_language( $this->woocommerce_wpml->strings->get_domain_language( 'woocommerce' ) );
220
  }
221
  }
222
 
223
 
224
  function email_heading_completed( $order_id, $no_checking = false ) {
225
-
226
- if ( ( class_exists( 'WC_Email_Customer_Completed_Order' ) || $no_checking ) && isset( $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order'] ) ) {
227
-
228
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->heading = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_completed_order_settings', '[woocommerce_customer_completed_order_settings]heading' );
229
-
230
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->subject = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_completed_order_settings', '[woocommerce_customer_completed_order_settings]subject' );
231
-
232
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->heading_downloadable = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_completed_order_settings', '[woocommerce_customer_completed_order_settings]heading_downloadable' );
233
-
234
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->subject_downloadable = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_completed_order_settings', '[woocommerce_customer_completed_order_settings]subject_downloadable' );
235
-
236
- $enabled = $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->enabled;
237
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->enabled = false;
238
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->trigger( $order_id );
239
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Completed_Order']->enabled = $enabled;
 
240
  }
241
  }
242
 
@@ -263,13 +235,21 @@ class WCML_Emails {
263
  * @param string $string_name
264
  */
265
  private function translate_email_headings( $order_id, $class_name, $string_name ) {
266
- if ( class_exists( $class_name ) && isset( $this->woocommerce->mailer()->emails[ $class_name ] ) ) {
267
- $this->woocommerce->mailer()->emails[ $class_name ]->heading = $this->wcml_get_translated_email_string( 'admin_texts_' . $string_name, '[' . $string_name . ']heading', $order_id );
268
- $this->woocommerce->mailer()->emails[ $class_name ]->subject = $this->wcml_get_translated_email_string( 'admin_texts_' . $string_name, '[' . $string_name . ']subject', $order_id );
269
- $enabled = $this->woocommerce->mailer()->emails[ $class_name ]->enabled;
270
- $this->woocommerce->mailer()->emails[ $class_name ]->enabled = false;
271
- $this->woocommerce->mailer()->emails[ $class_name ]->trigger( $order_id );
272
- $this->woocommerce->mailer()->emails[ $class_name ]->enabled = $enabled;
 
 
 
 
 
 
 
 
273
  }
274
  }
275
 
@@ -282,17 +262,20 @@ class WCML_Emails {
282
  }
283
 
284
  function email_heading_note( $args ) {
285
-
286
- if ( class_exists( 'WC_Email_Customer_Note' ) && isset( $this->woocommerce->mailer()->emails['WC_Email_Customer_Note'] ) ) {
287
-
288
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Note']->heading = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_note_settings', '[woocommerce_customer_note_settings]heading' );
289
-
290
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Note']->subject = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_note_settings', '[woocommerce_customer_note_settings]subject' );
291
-
292
- $enabled = $this->woocommerce->mailer()->emails['WC_Email_Customer_Note']->enabled;
293
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Note']->enabled = false;
294
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Note']->trigger( $args );
295
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Note']->enabled = $enabled;
 
 
 
296
  }
297
  }
298
 
@@ -318,9 +301,10 @@ class WCML_Emails {
318
  }
319
 
320
  function new_order_admin_email( $order_id ) {
 
321
 
322
- if ( isset( $this->woocommerce->mailer()->emails['WC_Email_New_Order'] ) ) {
323
- $recipients = explode( ',', $this->woocommerce->mailer()->emails['WC_Email_New_Order']->get_recipient() );
324
  foreach ( $recipients as $recipient ) {
325
  $user = get_user_by( 'email', $recipient );
326
  if ( $user ) {
@@ -342,15 +326,20 @@ class WCML_Emails {
342
 
343
  $this->change_email_language( $admin_language );
344
 
345
- $this->woocommerce->mailer()->emails['WC_Email_New_Order']->heading = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_new_order_settings', '[woocommerce_new_order_settings]heading', $order_id, $admin_language );
346
-
347
- $this->woocommerce->mailer()->emails['WC_Email_New_Order']->subject = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_new_order_settings', '[woocommerce_new_order_settings]subject', $order_id, $admin_language );
 
 
 
348
 
349
- $this->woocommerce->mailer()->emails['WC_Email_New_Order']->recipient = $recipient;
 
 
350
 
351
- $this->woocommerce->mailer()->emails['WC_Email_New_Order']->trigger( $order_id );
352
  }
353
- $this->woocommerce->mailer()->emails['WC_Email_New_Order']->enabled = false;
354
  $this->refresh_email_lang( $order_id );
355
  }
356
  }
@@ -371,15 +360,17 @@ class WCML_Emails {
371
  * @return string
372
  */
373
  private function get_translated_order_strings( $type, $string, $class_name ) {
 
 
374
  if ( 'heading' === $type ) {
375
- $translated_string = $this->woocommerce->mailer()->emails[ $class_name ]->heading;
376
  } elseif ( 'subject' === $type ) {
377
- $translated_string = $this->woocommerce->mailer()->emails[ $class_name ]->subject;
378
  } else {
379
  return $string;
380
  }
381
 
382
- return $translated_string ? $this->woocommerce->mailer()->emails[ $class_name ]->format_string( $translated_string ) : $string;
383
  }
384
 
385
  public function backend_new_order_admin_email( $order_id ) {
@@ -391,46 +382,6 @@ class WCML_Emails {
391
  }
392
  }
393
 
394
- function filter_formatted_items( $formatted_meta, $object ) {
395
-
396
- if ( isset( $object->product->variation_id ) ) {
397
-
398
- $current_prod_variation_id = apply_filters( 'translate_object_id', $object->product->variation_id, 'product_variation', false );
399
-
400
- if ( ! is_null( $current_prod_variation_id ) ) {
401
-
402
- foreach ( $formatted_meta as $key => $formatted_var ) {
403
-
404
- if ( substr( $formatted_var['key'], 0, 3 ) ) {
405
-
406
- $attribute = wc_sanitize_taxonomy_name( $formatted_var['key'] );
407
-
408
- if ( taxonomy_exists( $attribute ) ) {
409
- $attr_term = get_term_by( 'name', $formatted_meta[ $key ]['value'], $attribute );
410
- $tr_id = apply_filters( 'translate_object_id', $attr_term->term_id, $attribute, false, $this->sitepress->get_current_language() );
411
-
412
- if ( $tr_id ) {
413
- $translated_term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $tr_id, $attribute );
414
- $formatted_meta[ $key ]['value'] = $translated_term->name;
415
- }
416
-
417
- } else {
418
-
419
- $custom_attr_trnsl = $this->woocommerce_wpml->attributes->get_custom_attribute_translation( $object->product->id, $formatted_var['key'], array( 'is_taxonomy' => false ), $this->sitepress->get_current_language() );
420
-
421
- if ( false !== $custom_attr_trnsl ) {
422
- $formatted_meta[ $key ]['label'] = $custom_attr_trnsl['name'];
423
- }
424
- }
425
- }
426
- }
427
- }
428
- }
429
-
430
- return $formatted_meta;
431
-
432
- }
433
-
434
  function change_email_language( $lang ) {
435
  if ( ! $this->admin_language ) {
436
  $this->admin_language = $this->sitepress->get_user_admin_language( get_current_user_id(), true );
@@ -479,7 +430,7 @@ class WCML_Emails {
479
  $email_option = get_option( $email_string[0], true );
480
  $context = 'admin_texts_' . $email_string[0];
481
 
482
- $current_language = $this->woocommerce_wpml->strings->get_string_language( $email_option[ $email_string[1] ], $context, $name );
483
  } elseif ( $this->order_id ) {
484
  $order_id = $this->order_id;
485
  }
@@ -508,116 +459,6 @@ class WCML_Emails {
508
  return $locale;
509
  }
510
 
511
- function show_language_links_for_wc_emails() {
512
-
513
- $emails_options = array(
514
- 'woocommerce_new_order_settings',
515
- 'woocommerce_cancelled_order_settings',
516
- 'woocommerce_failed_order_settings',
517
- 'woocommerce_customer_on_hold_order_settings',
518
- 'woocommerce_customer_processing_order_settings',
519
- 'woocommerce_customer_completed_order_settings',
520
- 'woocommerce_customer_refunded_order_settings',
521
- 'woocommerce_customer_invoice_settings',
522
- 'woocommerce_customer_note_settings',
523
- 'woocommerce_customer_reset_password_settings',
524
- 'woocommerce_customer_new_account_settings'
525
- );
526
-
527
- $emails_options = apply_filters( 'wcml_emails_options_to_translate', $emails_options );
528
-
529
- $text_keys = array(
530
- 'subject',
531
- 'heading',
532
- 'subject_downloadable',
533
- 'heading_downloadable',
534
- 'subject_full',
535
- 'subject_partial',
536
- 'heading_full',
537
- 'heading_partial',
538
- 'subject_paid',
539
- 'heading_paid'
540
- );
541
-
542
- $text_keys = apply_filters( 'wcml_emails_text_keys_to_translate', $text_keys );
543
-
544
-
545
- foreach ( $emails_options as $emails_option ) {
546
-
547
- $section_prefix = apply_filters( 'wcml_emails_section_name_prefix', 'wc_email_', $emails_option );
548
-
549
- $section_name = str_replace( 'woocommerce_', $section_prefix, $emails_option );
550
- $section_name = apply_filters( 'wcml_emails_section_name_to_translate', str_replace( '_settings', '', $section_name ) );
551
- if ( isset( $_GET['section'] ) && $_GET['section'] == $section_name ) {
552
-
553
- $option_settings = get_option( $emails_option );
554
- if ( $option_settings ) {
555
- foreach ( $option_settings as $setting_key => $setting_value ) {
556
- if ( in_array( $setting_key, $text_keys ) ) {
557
- $input_name = str_replace( '_settings', '', $emails_option ) . '_' . $setting_key;
558
-
559
- $lang_selector = new WPML_Simple_Language_Selector( $this->sitepress );
560
- $language = $this->woocommerce_wpml->strings->get_string_language( $setting_value, 'admin_texts_' . $emails_option, '[' . $emails_option . ']' . $setting_key );
561
- if ( is_null( $language ) ) {
562
- $language = $this->sitepress->get_default_language();
563
- }
564
-
565
- $lang_selector->render( array(
566
- 'id' => $emails_option . '_' . $setting_key . '_language_selector',
567
- 'name' => 'wcml_lang-' . $emails_option . '-' . $setting_key,
568
- 'selected' => $language,
569
- 'show_please_select' => false,
570
- 'echo' => true,
571
- 'style' => 'width: 18%;float: left'
572
- )
573
- );
574
-
575
- $st_page = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=admin_texts_' . $emails_option . '&search=' . $setting_value );
576
- ?>
577
- <script>
578
- var input = jQuery('input[name="<?php echo $input_name ?>"]');
579
- if (input.length) {
580
- input.parent().append('<div class="translation_controls"></div>');
581
- input.parent().find('.translation_controls').append('<a href="<?php echo $st_page ?>" style="margin-left: 10px"><?php _e( 'translations', 'woocommerce-multilingual' ) ?></a>');
582
- jQuery('#<?php echo $emails_option . '_' . $setting_key . '_language_selector' ?>').prependTo(input.parent().find('.translation_controls'));
583
- }
584
- </script>
585
- <?php }
586
- }
587
- }
588
- }
589
- }
590
- }
591
-
592
- function set_emails_string_language() {
593
-
594
- foreach ( $_POST as $key => $language ) {
595
-
596
- if ( substr( $key, 0, 9 ) == 'wcml_lang' ) {
597
-
598
- $email_string = explode( '-', $key );
599
-
600
- if ( isset( $email_string[2] ) ) {
601
-
602
- $email_key = str_replace( '_settings', '', $email_string[1] );
603
- $email_key .= '_' . $email_string[2];
604
-
605
- $email_settings = get_option( $email_string[1], true );
606
- $opt_string_value = $email_settings[ $email_string[2] ];
607
-
608
- $string_value = isset( $_POST[ $email_key ] ) ? $_POST[ $email_key ] : $opt_string_value;
609
-
610
- $context = 'admin_texts_' . $email_string[1];
611
- $name = '[' . $email_string[1] . ']' . $email_string[2];
612
-
613
- do_action( 'wpml_register_single_string', $context, $name, $string_value, false, $this->woocommerce_wpml->strings->get_string_language( $opt_string_value, $context ) );
614
-
615
- $this->woocommerce_wpml->strings->set_string_language( $string_value, $context, $name, $language );
616
- }
617
- }
618
- }
619
- }
620
-
621
  function translate_woocommerce_countries( $countries ) {
622
 
623
  if ( isset( $_POST['wc_order_action'] ) && $_POST['wc_order_action'] !== 'send_email_new_order' && isset( $_POST['post_ID'] ) ) {
@@ -637,4 +478,34 @@ class WCML_Emails {
637
  return $allow;
638
  }
639
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
640
  }
5
  private $order_id = false;
6
  private $locale = false;
7
  private $admin_language = false;
8
+ /** @var WCML_WC_Strings */
9
+ private $wcmlStrings;
10
  /** @var Sitepress */
11
  private $sitepress;
12
+ /** @var \WC_Emails $wcEmails */
13
+ private $wcEmails;
14
  /** @var wpdb */
15
  private $wpdb;
16
 
17
+ function __construct( WCML_WC_Strings $wcmlStrings, SitePress $sitepress, WC_Emails $wcEmails, wpdb $wpdb ) {
18
+ $this->wcmlStrings = $wcmlStrings;
19
+ $this->sitepress = $sitepress;
20
+ $this->wcEmails = $wcEmails;
21
+ $this->wpdb = $wpdb;
 
 
 
 
 
 
 
 
22
  }
23
 
24
  function add_hooks() {
 
25
  //wrappers for email's header
26
  if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
27
  add_action( 'woocommerce_order_status_completed_notification', array(
86
  add_filter( 'plugin_locale', array( $this, 'set_locale_for_emails' ), 10, 2 );
87
  add_filter( 'woocommerce_countries', array( $this, 'translate_woocommerce_countries' ) );
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  add_filter( 'woocommerce_allow_send_queued_transactional_email', array(
90
  $this,
91
  'send_queued_transactional_email'
187
  if ( is_admin() && false !== $this->admin_language ) {
188
  $this->change_email_language( $this->admin_language );
189
  } else {
190
+ $this->change_email_language( $this->wcmlStrings->get_domain_language( 'woocommerce' ) );
191
  }
192
  }
193
 
194
 
195
  function email_heading_completed( $order_id, $no_checking = false ) {
196
+ $email = $this->getEmailObject( 'WC_Email_Customer_Completed_Order', $no_checking );
197
+
198
+ if ( $email ) {
199
+ $translate = $this->getTranslatorFor(
200
+ 'admin_texts_woocommerce_customer_completed_order_settings',
201
+ '[woocommerce_customer_completed_order_settings]'
202
+ );
203
+
204
+ $email->heading = $translate( 'heading' );
205
+ $email->subject = $translate( 'subject' );
206
+ $email->heading_downloadable = $translate( 'heading_downloadable' );
207
+ $email->subject_downloadable = $translate( 'subject_downloadable' );
208
+ $original_enabled_state = $email->enabled;
209
+ $email->enabled = false;
210
+ $email->trigger( $order_id );
211
+ $email->enabled = $original_enabled_state;
212
  }
213
  }
214
 
235
  * @param string $string_name
236
  */
237
  private function translate_email_headings( $order_id, $class_name, $string_name ) {
238
+ $email = $this->getEmailObject( $class_name );
239
+
240
+ if ( $email ) {
241
+ $translate = $this->getTranslatorFor(
242
+ 'admin_texts_' . $string_name,
243
+ '[' . $string_name . ']',
244
+ $order_id
245
+ );
246
+
247
+ $email->heading = $translate( 'heading' );
248
+ $email->subject = $translate( 'subject' );
249
+ $original_enabled_state = $email->enabled;
250
+ $email->enabled = false;
251
+ $email->trigger( $order_id );
252
+ $email->enabled = $original_enabled_state;
253
  }
254
  }
255
 
262
  }
263
 
264
  function email_heading_note( $args ) {
265
+ $email = $this->getEmailObject( 'WC_Email_Customer_Note' );
266
+
267
+ if ( $email ) {
268
+ $translate = $this->getTranslatorFor(
269
+ 'admin_texts_woocommerce_customer_note_settings',
270
+ '[woocommerce_customer_note_settings]'
271
+ );
272
+
273
+ $email->heading = $translate( 'heading' );
274
+ $email->subject = $translate( 'subject' );
275
+ $original_enabled_state = $email->enabled;
276
+ $email->enabled = false;
277
+ $email->trigger( $args );
278
+ $email->enabled = $original_enabled_state;
279
  }
280
  }
281
 
301
  }
302
 
303
  function new_order_admin_email( $order_id ) {
304
+ $email = $this->getEmailObject( 'WC_Email_New_Order', true );
305
 
306
+ if ( $email ) {
307
+ $recipients = explode( ',', $email->get_recipient() );
308
  foreach ( $recipients as $recipient ) {
309
  $user = get_user_by( 'email', $recipient );
310
  if ( $user ) {
326
 
327
  $this->change_email_language( $admin_language );
328
 
329
+ $translate = $this->getTranslatorFor(
330
+ 'admin_texts_woocommerce_new_order_settings',
331
+ '[woocommerce_new_order_settings]',
332
+ $order_id,
333
+ $admin_language
334
+ );
335
 
336
+ $email->heading = $translate( 'heading' );
337
+ $email->subject = $translate( 'subject' );
338
+ $email->recipient = $recipient;
339
 
340
+ $email->trigger( $order_id );
341
  }
342
+ $email->enabled = false;
343
  $this->refresh_email_lang( $order_id );
344
  }
345
  }
360
  * @return string
361
  */
362
  private function get_translated_order_strings( $type, $string, $class_name ) {
363
+ $email = $this->getEmailObject( $class_name );
364
+
365
  if ( 'heading' === $type ) {
366
+ $translated_string = $email->heading;
367
  } elseif ( 'subject' === $type ) {
368
+ $translated_string = $email->subject;
369
  } else {
370
  return $string;
371
  }
372
 
373
+ return $translated_string ? $email->format_string( $translated_string ) : $string;
374
  }
375
 
376
  public function backend_new_order_admin_email( $order_id ) {
382
  }
383
  }
384
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  function change_email_language( $lang ) {
386
  if ( ! $this->admin_language ) {
387
  $this->admin_language = $this->sitepress->get_user_admin_language( get_current_user_id(), true );
430
  $email_option = get_option( $email_string[0], true );
431
  $context = 'admin_texts_' . $email_string[0];
432
 
433
+ $current_language = $this->wcmlStrings->get_string_language( $email_option[ $email_string[1] ], $context, $name );
434
  } elseif ( $this->order_id ) {
435
  $order_id = $this->order_id;
436
  }
459
  return $locale;
460
  }
461
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  function translate_woocommerce_countries( $countries ) {
463
 
464
  if ( isset( $_POST['wc_order_action'] ) && $_POST['wc_order_action'] !== 'send_email_new_order' && isset( $_POST['post_ID'] ) ) {
478
  return $allow;
479
  }
480
 
481
+ /**
482
+ * @param string $emailClass
483
+ * @param bool $ignoreClassExists
484
+ *
485
+ * @return WC_Email|null
486
+ */
487
+ private function getEmailObject( $emailClass, $ignoreClassExists = false ) {
488
+ if (
489
+ ( $ignoreClassExists || class_exists( $emailClass ) )
490
+ && isset( $this->wcEmails->emails[ $emailClass ] )
491
+ ) {
492
+ return $this->wcEmails->emails[ $emailClass ];
493
+ }
494
+
495
+ return null;
496
+ }
497
+
498
+ /**
499
+ * @param string $domain
500
+ * @param string $namePrefix
501
+ * @param int|false $orderId
502
+ * @param string|null $languageCode
503
+ *
504
+ * @return Closure
505
+ */
506
+ private function getTranslatorFor( $domain, $namePrefix, $orderId = false, $languageCode = null ) {
507
+ return function( $field ) use ( $domain, $namePrefix, $orderId, $languageCode ) {
508
+ return $this->wcml_get_translated_email_string( $domain, $namePrefix . $field, $orderId, $languageCode );
509
+ };
510
+ }
511
  }
inc/class-wcml-install.php CHANGED
@@ -61,7 +61,6 @@ class WCML_Install{
61
 
62
  $woocommerce_wpml->settings['set_up'] = 1;
63
  $woocommerce_wpml->update_settings();
64
-
65
  }
66
 
67
  if ( empty( $woocommerce_wpml->settings['downloaded_translations_for_wc'] ) ) { //from 3.3.3
61
 
62
  $woocommerce_wpml->settings['set_up'] = 1;
63
  $woocommerce_wpml->update_settings();
 
64
  }
65
 
66
  if ( empty( $woocommerce_wpml->settings['downloaded_translations_for_wc'] ) ) { //from 3.3.3
inc/class-wcml-languages-upgrader.php CHANGED
@@ -106,7 +106,6 @@ class WCML_Languages_Upgrader{
106
  global $sitepress;
107
 
108
  $active_languages = $sitepress->get_active_languages();
109
- $current_language = $sitepress->get_current_language();
110
 
111
  foreach( $active_languages as $language ){
112
  if( $language['code'] == 'en' )
@@ -114,7 +113,7 @@ class WCML_Languages_Upgrader{
114
 
115
  $locale = $sitepress->get_locale( $language['code'] );
116
 
117
- if ( $this->has_available_update( $locale ) && isset( $data->translations ) ) {
118
 
119
  $data->translations[] = array(
120
  'type' => 'plugin',
106
  global $sitepress;
107
 
108
  $active_languages = $sitepress->get_active_languages();
 
109
 
110
  foreach( $active_languages as $language ){
111
  if( $language['code'] == 'en' )
113
 
114
  $locale = $sitepress->get_locale( $language['code'] );
115
 
116
+ if ( isset( $data->translations ) ) {
117
 
118
  $data->translations[] = array(
119
  'type' => 'plugin',
inc/class-wcml-requests.php CHANGED
@@ -37,6 +37,9 @@ class WCML_Requests{
37
  $woocommerce_wpml->settings['products_sync_date'] = empty($_POST['products_sync_date']) ? 0 : 1;
38
  $woocommerce_wpml->settings['products_sync_order'] = empty($_POST['products_sync_order']) ? 0 : 1;
39
 
 
 
 
40
  $wcml_file_path_sync = filter_input( INPUT_POST, 'wcml_file_path_sync', FILTER_SANITIZE_NUMBER_INT );
41
 
42
  $woocommerce_wpml->settings['file_path_sync'] = $wcml_file_path_sync;
37
  $woocommerce_wpml->settings['products_sync_date'] = empty($_POST['products_sync_date']) ? 0 : 1;
38
  $woocommerce_wpml->settings['products_sync_order'] = empty($_POST['products_sync_order']) ? 0 : 1;
39
 
40
+ $wcml_sync_media = empty( $_POST['sync_media'] ) ? 0 : 1;
41
+ $woocommerce_wpml->update_setting( 'sync_media', $wcml_sync_media, true );
42
+
43
  $wcml_file_path_sync = filter_input( INPUT_POST, 'wcml_file_path_sync', FILTER_SANITIZE_NUMBER_INT );
44
 
45
  $woocommerce_wpml->settings['file_path_sync'] = $wcml_file_path_sync;
inc/class-wcml-store-pages.php CHANGED
@@ -193,12 +193,8 @@ class WCML_Store_Pages {
193
  return;
194
  }
195
 
196
- //do not alter query_object and query_object_id (part 1 of 2)
197
- global $wp_query;
198
- $queried_object_original = isset( $wp_query->queried_object ) ? $wp_query->queried_object : null;
199
- $queried_object_id_original = isset( $wp_query->queried_object_id ) ? $wp_query->queried_object_id : null;
200
-
201
  if (
 
202
  ! empty( $this->shop_page ) &&
203
  $this->shop_page->post_status == 'publish' &&
204
  ! empty( $this->front_page_id ) &&
@@ -206,12 +202,20 @@ class WCML_Store_Pages {
206
  $q->get( 'page_id' ) !== $this->front_page_id &&
207
  $this->shop_page_id == $q->get( 'page_id' )
208
  ) {
 
 
 
 
 
209
  $q->set( 'post_type', 'product' );
210
  $q->set( 'page_id', '' );
211
  if ( isset( $q->query['paged'] ) ) {
212
  $q->set( 'paged', $q->query['paged'] );
213
  }
214
 
 
 
 
215
  // Get the actual WP page to avoid errors
216
  // This is hacky but works. Awaiting http://core.trac.wordpress.org/ticket/21096
217
  global $wp_post_types;
@@ -221,25 +225,28 @@ class WCML_Store_Pages {
221
  $wp_post_types['product']->ID = $this->shop_page->ID;
222
  $wp_post_types['product']->post_title = $this->shop_page->post_title;
223
  $wp_post_types['product']->post_name = $this->shop_page->post_name;
 
 
224
 
225
  // Fix conditional functions
226
  $q->is_singular = false;
227
  $q->is_post_type_archive = true;
228
  $q->is_archive = true;
229
- }
230
 
231
- //do not alter query_object and query_object_id (part 2 of 2)
232
- if ( is_null( $queried_object_original ) ) {
233
- unset( $wp_query->queried_object );
234
- } else {
235
- $wp_query->queried_object = $queried_object_original;
236
- }
237
- if ( is_null( $queried_object_id_original ) ) {
238
- unset( $wp_query->queried_object_id );
239
- } else {
240
- $wp_query->queried_object_id = $queried_object_id_original;
241
- }
242
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  }
244
 
245
 
193
  return;
194
  }
195
 
 
 
 
 
 
196
  if (
197
+ current_theme_supports( 'woocommerce' ) &&
198
  ! empty( $this->shop_page ) &&
199
  $this->shop_page->post_status == 'publish' &&
200
  ! empty( $this->front_page_id ) &&
202
  $q->get( 'page_id' ) !== $this->front_page_id &&
203
  $this->shop_page_id == $q->get( 'page_id' )
204
  ) {
205
+ //do not alter query_object and query_object_id (part 1 of 2)
206
+ global $wp_query;
207
+ $queried_object_original = isset( $wp_query->queried_object ) ? $wp_query->queried_object : null;
208
+ $queried_object_id_original = isset( $wp_query->queried_object_id ) ? $wp_query->queried_object_id : null;
209
+
210
  $q->set( 'post_type', 'product' );
211
  $q->set( 'page_id', '' );
212
  if ( isset( $q->query['paged'] ) ) {
213
  $q->set( 'paged', $q->query['paged'] );
214
  }
215
 
216
+ // Define a variable so we know this is the front page shop later on.
217
+ wc_maybe_define_constant( 'SHOP_IS_ON_FRONT', true );
218
+
219
  // Get the actual WP page to avoid errors
220
  // This is hacky but works. Awaiting http://core.trac.wordpress.org/ticket/21096
221
  global $wp_post_types;
225
  $wp_post_types['product']->ID = $this->shop_page->ID;
226
  $wp_post_types['product']->post_title = $this->shop_page->post_title;
227
  $wp_post_types['product']->post_name = $this->shop_page->post_name;
228
+ $wp_post_types['product']->post_type = $this->shop_page->post_type;
229
+ $wp_post_types['product']->ancestors = get_ancestors( $this->shop_page->ID, $this->shop_page->post_type );
230
 
231
  // Fix conditional functions
232
  $q->is_singular = false;
233
  $q->is_post_type_archive = true;
234
  $q->is_archive = true;
 
235
 
236
+ add_filter( 'post_type_archive_title', '__return_empty_string', 5 );
 
 
 
 
 
 
 
 
 
 
237
 
238
+ //do not alter query_object and query_object_id (part 2 of 2)
239
+ if ( is_null( $queried_object_original ) ) {
240
+ unset( $wp_query->queried_object );
241
+ } else {
242
+ $wp_query->queried_object = $queried_object_original;
243
+ }
244
+ if ( is_null( $queried_object_id_original ) ) {
245
+ unset( $wp_query->queried_object_id );
246
+ } else {
247
+ $wp_query->queried_object_id = $queried_object_id_original;
248
+ }
249
+ }
250
  }
251
 
252
 
inc/class-wcml-terms.php CHANGED
@@ -424,7 +424,7 @@ class WCML_Terms{
424
 
425
  if($i > $languages_processed && $translation->element_id != $post_id){
426
  $this->woocommerce_wpml->sync_product_data->sync_product_taxonomies($post_id, $translation->element_id, $translation->language_code);
427
- $this->woocommerce_wpml->sync_variations_data->sync_product_variations($post_id, $translation->element_id, $translation->language_code, false, true);
428
  $this->woocommerce_wpml->translation_editor->create_product_translation_package($post_id,$trid, $translation->language_code,ICL_TM_COMPLETE);
429
  $variations_processed += $terms_count*2;
430
  $response['languages_processed'] = $i;
424
 
425
  if($i > $languages_processed && $translation->element_id != $post_id){
426
  $this->woocommerce_wpml->sync_product_data->sync_product_taxonomies($post_id, $translation->element_id, $translation->language_code);
427
+ $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $post_id, $translation->element_id, $translation->language_code, [ 'is_troubleshooting' => true ] );
428
  $this->woocommerce_wpml->translation_editor->create_product_translation_package($post_id,$trid, $translation->language_code,ICL_TM_COMPLETE);
429
  $variations_processed += $terms_count*2;
430
  $response['languages_processed'] = $i;
inc/class-wcml-tp-support.php CHANGED
@@ -87,7 +87,7 @@ class WCML_TP_Support {
87
 
88
  public function save_custom_attribute_translations( $post_id, $data, $job ) {
89
 
90
- $translated_attributes = array();
91
  $translated_labels = $this->woocommerce_wpml->attributes->get_attr_label_translations( $post_id );
92
 
93
  foreach ( $data as $data_key => $value ) {
@@ -117,7 +117,7 @@ class WCML_TP_Support {
117
 
118
  if ( $translated_attributes ) {
119
 
120
- $product_attributes = get_post_meta( $post_id, '_product_attributes', true );
121
 
122
  if( isset( $job->original_doc_id ) ){
123
  $original_post_id = $job->original_doc_id;
@@ -125,26 +125,20 @@ class WCML_TP_Support {
125
  $original_post_id = $this->woocommerce_wpml->products->get_original_product_id( $post_id );
126
  }
127
 
128
- $original_attributes = get_post_meta( $original_post_id, '_product_attributes', true );
129
 
130
  foreach ( $translated_attributes as $attribute_key => $attribute ) {
 
 
 
 
131
 
132
- $product_attributes[ $attribute_key ] = array(
133
- 'name' => $attribute['name'],
134
- 'value' => join( ' | ', $attribute['values'] ),
135
- 'is_taxonomy' => 0,
136
- 'is_visible' => $original_attributes[ $attribute_key ]['is_visible'],
137
- 'position' => $original_attributes[ $attribute_key ]['position']
138
- );
139
-
140
- $translated_labels[ $job->language_code ][ $attribute_key ] = $attribute['name'];
141
-
142
  }
143
 
144
  update_post_meta( $post_id, '_product_attributes', $product_attributes );
145
-
146
  update_post_meta( $post_id, 'attr_label_translations', $translated_labels );
147
-
148
  }
149
 
150
  }
87
 
88
  public function save_custom_attribute_translations( $post_id, $data, $job ) {
89
 
90
+ $translated_attributes = [];
91
  $translated_labels = $this->woocommerce_wpml->attributes->get_attr_label_translations( $post_id );
92
 
93
  foreach ( $data as $data_key => $value ) {
117
 
118
  if ( $translated_attributes ) {
119
 
120
+ $product_attributes = get_post_meta( $post_id, '_product_attributes', true ) ?: [];
121
 
122
  if( isset( $job->original_doc_id ) ){
123
  $original_post_id = $job->original_doc_id;
125
  $original_post_id = $this->woocommerce_wpml->products->get_original_product_id( $post_id );
126
  }
127
 
128
+ $original_attributes = get_post_meta( $original_post_id, '_product_attributes', true ) ?: [];
129
 
130
  foreach ( $translated_attributes as $attribute_key => $attribute ) {
131
+ if( isset( $original_attributes[ $attribute_key ] ) ){
132
+ $product_attributes[ $attribute_key ] = $original_attributes[ $attribute_key ];
133
+ $product_attributes[ $attribute_key ]['name'] = $attribute['name'];
134
+ $product_attributes[ $attribute_key ]['value'] = join( ' | ', $attribute['values'] );
135
 
136
+ $translated_labels[ $job->language_code ][ $attribute_key ] = $attribute['name'];
137
+ }
 
 
 
 
 
 
 
 
138
  }
139
 
140
  update_post_meta( $post_id, '_product_attributes', $product_attributes );
 
141
  update_post_meta( $post_id, 'attr_label_translations', $translated_labels );
 
142
  }
143
 
144
  }
inc/class-wcml-troubleshooting.php CHANGED
@@ -100,7 +100,7 @@ class WCML_Troubleshooting{
100
  $tr_product_id = apply_filters( 'translate_object_id',$product['id'],'product',false,$language['code']);
101
 
102
  if(!is_null($tr_product_id)){
103
- $this->woocommerce_wpml->sync_variations_data->sync_product_variations($product['id'],$tr_product_id,$language['code'],false,true);
104
  }
105
  if(!in_array($key,$unset_keys)){
106
  $unset_keys[] = $key;
100
  $tr_product_id = apply_filters( 'translate_object_id',$product['id'],'product',false,$language['code']);
101
 
102
  if(!is_null($tr_product_id)){
103
+ $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $product['id'], $tr_product_id, $language['code'], [ 'is_troubleshooting' => true ] );
104
  }
105
  if(!in_array($key,$unset_keys)){
106
  $unset_keys[] = $key;
inc/class-wcml-upgrade.php CHANGED
@@ -734,9 +734,9 @@ class WCML_Upgrade {
734
 
735
  private function upgrade_4_4_3() {
736
  if ( class_exists( 'WC_SwatchesPlugin' ) ) {
737
- global $wpdb, $sitepress, $wpml_post_translations;
738
 
739
- $variation_sp = new WCML_Variation_Swatches_And_Photos( $sitepress );
740
  $original_products = $wpdb->get_results(
741
  "
742
  SELECT element_id
@@ -759,7 +759,7 @@ class WCML_Upgrade {
759
  }
760
  }
761
 
762
- private function upgrade_4_6_8() {
763
  global $wpdb;
764
 
765
  $wpdb->query(
734
 
735
  private function upgrade_4_4_3() {
736
  if ( class_exists( 'WC_SwatchesPlugin' ) ) {
737
+ global $wpdb, $sitepress, $wpml_post_translations, $woocommerce_wpml;
738
 
739
+ $variation_sp = new WCML_Variation_Swatches_And_Photos( $woocommerce_wpml );
740
  $original_products = $wpdb->get_results(
741
  "
742
  SELECT element_id
759
  }
760
  }
761
 
762
+ private function upgrade_4_7_0() {
763
  global $wpdb;
764
 
765
  $wpdb->query(
inc/class-wcml-wc-gateways.php CHANGED
@@ -3,6 +3,7 @@
3
  class WCML_WC_Gateways{
4
 
5
  const WCML_BACS_ACCOUNTS_CURRENCIES_OPTION = 'wcml_bacs_accounts_currencies';
 
6
  private $current_language;
7
 
8
  /** @var woocommerce_wpml */
@@ -69,7 +70,7 @@ class WCML_WC_Gateways{
69
  foreach ( $this->get_gateway_text_keys_to_translate() as $text_key ) {
70
  if ( isset( $settings[ $text_key ] ) && !$this->get_gateway_string_id( $settings[ $text_key ], $gateway_id, $text_key ) ) {
71
  $language = $this->gateway_setting_language( $settings[ $text_key ], $gateway_id, $text_key );
72
- icl_register_string( 'admin_texts_woocommerce_gateways', $gateway_id . '_gateway_' . $text_key, $settings[ $text_key ], false, $language );
73
  }
74
  }
75
  }
@@ -121,7 +122,7 @@ class WCML_WC_Gateways{
121
  $translated_string = apply_filters(
122
  'wpml_translate_single_string',
123
  $string,
124
- 'admin_texts_woocommerce_gateways',
125
  $gateway_id . '_gateway_' . $name,
126
  $this->get_current_gateway_language()
127
  );
@@ -139,26 +140,51 @@ class WCML_WC_Gateways{
139
  /**
140
  * @return string
141
  */
142
- private function get_current_gateway_language(){
143
-
144
- $language = $this->current_language;
145
-
146
- $is_saving_new_order = isset( $_POST['action'] ) && 'editpost' === $_POST['action'] && isset( $_POST['save'] ) && $_POST['save'];
147
- $is_send_order_details_action = isset( $_POST['wc_order_action'] ) && 'send_order_details' === $_POST['wc_order_action'];
148
- $is_order_on_hold = isset( $_POST ['order_status'] ) && 'wc-on-hold' === $_POST ['order_status'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
- if ( $is_order_on_hold && isset( $_POST['post_ID'] ) ) {
151
- if( $is_send_order_details_action ){
152
- $language = get_post_meta( $_POST['post_ID'], 'wpml_language', true );
153
- }elseif( $is_saving_new_order && isset( $_COOKIE[ WCML_Orders::DASHBOARD_COOKIE_NAME ] ) ){
154
- $language = $_COOKIE[ WCML_Orders::DASHBOARD_COOKIE_NAME ];
155
  }
156
  }
157
 
158
- return $language;
159
- }
160
 
161
- function show_language_links_for_gateways(){
162
 
163
  $text_keys = $this->get_gateway_text_keys_to_translate();
164
 
@@ -194,7 +220,7 @@ class WCML_WC_Gateways{
194
  )
195
  );
196
 
197
- $st_page = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=woocommerce&search='.esc_attr( preg_replace("/[\n\r]/","",$setting_value) ) );
198
  ?>
199
  <script>
200
  var input = jQuery('#<?php echo esc_js( $input_name ); ?>');
@@ -214,7 +240,7 @@ class WCML_WC_Gateways{
214
  private function gateway_setting_language( $setting_value, $gateway_id, $text_key ){
215
 
216
  if( $this->get_gateway_string_id( $setting_value, $gateway_id, $text_key ) ){
217
- return $this->woocommerce_wpml->strings->get_string_language( $setting_value, 'admin_texts_woocommerce_gateways', $gateway_id .'_gateway_'. $text_key );
218
  }else{
219
  return $this->sitepress->get_default_language();
220
  }
@@ -222,7 +248,7 @@ class WCML_WC_Gateways{
222
  }
223
 
224
  private function get_gateway_string_id( $value, $gateway_id, $name ){
225
- return icl_get_string_id( $value, 'admin_texts_woocommerce_gateways', $gateway_id .'_gateway_'. $name );
226
  }
227
 
228
  function set_bacs_gateway_currency(){
3
  class WCML_WC_Gateways{
4
 
5
  const WCML_BACS_ACCOUNTS_CURRENCIES_OPTION = 'wcml_bacs_accounts_currencies';
6
+ const STRINGS_CONTEXT = 'admin_texts_woocommerce_gateways';
7
  private $current_language;
8
 
9
  /** @var woocommerce_wpml */
70
  foreach ( $this->get_gateway_text_keys_to_translate() as $text_key ) {
71
  if ( isset( $settings[ $text_key ] ) && !$this->get_gateway_string_id( $settings[ $text_key ], $gateway_id, $text_key ) ) {
72
  $language = $this->gateway_setting_language( $settings[ $text_key ], $gateway_id, $text_key );
73
+ icl_register_string( self::STRINGS_CONTEXT, $gateway_id . '_gateway_' . $text_key, $settings[ $text_key ], false, $language );
74
  }
75
  }
76
  }
122
  $translated_string = apply_filters(
123
  'wpml_translate_single_string',
124
  $string,
125
+ self::STRINGS_CONTEXT,
126
  $gateway_id . '_gateway_' . $name,
127
  $this->get_current_gateway_language()
128
  );
140
  /**
141
  * @return string
142
  */
143
+ private function get_current_gateway_language() {
144
+
145
+ $postData = wpml_collect( $_POST );
146
+ if( $postData->isNotEmpty() ){
147
+
148
+ $is_user_order_note = 'woocommerce_add_order_note' === $postData->get( 'action' ) && 'customer' === $postData->get( 'note_type' );
149
+ if( $is_user_order_note ){
150
+ return get_post_meta( $postData->get( 'post_id' ), 'wpml_language', true );
151
+ }
152
+
153
+ $is_refund_line_item = 'woocommerce_refund_line_items' === $postData->get( 'action' );
154
+ if( $is_refund_line_item ){
155
+ return get_post_meta( $postData->get( 'order_id' ), 'wpml_language', true );
156
+ }
157
+
158
+ if ( $postData->get( 'post_ID' ) ) {
159
+ $is_saving_new_order = wpml_collect( ['auto-draft', 'draft'] )->contains( $postData->get( 'post_status' ) )
160
+ && 'editpost' === $postData->get( 'action' )
161
+ && $postData->get( 'save' );
162
+ if ( $is_saving_new_order && isset( $_COOKIE[ WCML_Orders::DASHBOARD_COOKIE_NAME ] ) ) {
163
+ return $_COOKIE[ WCML_Orders::DASHBOARD_COOKIE_NAME ];
164
+ }
165
+
166
+ $is_order_emails_status = wpml_collect( ['wc-completed', 'wc-processing', 'wc-refunded', 'wc-on-hold'] )->contains( $postData->get( 'order_status' ) );
167
+ $is_send_order_details_action = 'send_order_details' === $postData->get( 'wc_order_action' );
168
+ if ( $is_order_emails_status || $is_send_order_details_action ) {
169
+ return get_post_meta( $postData->get( 'post_ID' ), 'wpml_language', true );
170
+ }
171
+
172
+ return $this->current_language;
173
+ }
174
+ }
175
 
176
+ $getData = wpml_collect( $_GET );
177
+ if( $getData->isNotEmpty() ) {
178
+ $is_order_ajax_action = 'woocommerce_mark_order_status' === $getData->get( 'action' ) && wpml_collect( ['completed', 'processing'] )->contains( $getData->get( 'status' ) );
179
+ if ( $is_order_ajax_action && $getData->get( 'order_id' ) ) {
180
+ return get_post_meta( $getData->get( 'order_id' ), 'wpml_language', true );
181
  }
182
  }
183
 
184
+ return $this->current_language;
185
+ }
186
 
187
+ function show_language_links_for_gateways(){
188
 
189
  $text_keys = $this->get_gateway_text_keys_to_translate();
190
 
220
  )
221
  );
222
 
223
+ $st_page = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context='.self::STRINGS_CONTEXT.'&search='.esc_attr( preg_replace("/[\n\r]/","",$setting_value) ) );
224
  ?>
225
  <script>
226
  var input = jQuery('#<?php echo esc_js( $input_name ); ?>');
240
  private function gateway_setting_language( $setting_value, $gateway_id, $text_key ){
241
 
242
  if( $this->get_gateway_string_id( $setting_value, $gateway_id, $text_key ) ){
243
+ return $this->woocommerce_wpml->strings->get_string_language( $setting_value, self::STRINGS_CONTEXT, $gateway_id .'_gateway_'. $text_key );
244
  }else{
245
  return $this->sitepress->get_default_language();
246
  }
248
  }
249
 
250
  private function get_gateway_string_id( $value, $gateway_id, $name ){
251
+ return icl_get_string_id( $value, self::STRINGS_CONTEXT, $gateway_id .'_gateway_'. $name );
252
  }
253
 
254
  function set_bacs_gateway_currency(){
inc/currencies/class-wcml-multi-currency-orders.php CHANGED
@@ -54,59 +54,29 @@ class WCML_Multi_Currency_Orders {
54
  if ( is_admin() ) {
55
  add_filter( 'woocommerce_order_get_currency', array( $this, 'get_currency_for_new_order' ), 10, 2 );
56
  }
57
-
58
- }
59
-
60
- public function get_orders_currencies() {
61
- global $wpdb;
62
-
63
- $cache_key = 'wcml_get_orders_currencies';
64
- $temp_orders_currencies = wp_cache_get( $cache_key );
65
- if ( $temp_orders_currencies ) {
66
- return $temp_orders_currencies;
67
- }
68
-
69
- $currencies = array();
70
-
71
- $results = $wpdb->get_results( "
72
- SELECT LEFT(m.meta_value, 3) AS currency, COUNT(*) AS c
73
- FROM {$wpdb->postmeta} m
74
- INNER JOIN {$wpdb->posts} p on p.ID = m.post_id
75
- WHERE m.meta_key='_order_currency' AND p.post_type='shop_order'
76
- GROUP BY currency
77
- " );
78
-
79
- foreach ( $results as $row ) {
80
- $currencies[ $row->currency ] = (int) $row->c;
81
- }
82
-
83
- wp_cache_set( $cache_key, $currencies );
84
-
85
- return $currencies;
86
  }
87
 
88
  public function show_orders_currencies_selector() {
89
  global $wp_query, $typenow;
90
 
91
- if ( $typenow != 'shop_order' ) {
92
- return false;
93
  }
94
 
95
- $order_currencies = $this->get_orders_currencies();
96
- $currencies = get_woocommerce_currencies();
97
  ?>
98
  <select id="dropdown_shop_order_currency" name="_order_currency">
99
  <option value=""><?php _e( 'Show all currencies', 'woocommerce-multilingual' ) ?></option>
100
- <?php foreach ( $order_currencies as $currency => $count ): ?>
101
  <option value="<?php echo $currency ?>" <?php
102
  if ( isset( $wp_query->query['_order_currency'] ) ) {
103
  selected( $currency, $wp_query->query['_order_currency'] );
104
  }
105
- ?> ><?php printf( "%s (%s) (%d)", $currencies[ $currency ], get_woocommerce_currency_symbol( $currency ), $count ) ?></option>
106
  <?php endforeach; ?>
107
  </select>
108
  <?php
109
-
110
  }
111
 
112
  public function filter_orders_by_currency_join( $join ) {
@@ -328,9 +298,8 @@ class WCML_Multi_Currency_Orders {
328
  }
329
 
330
  if ( ! isset( $this->multi_currency->prices ) ) {
331
- $this->multi_currency->prices = new WCML_Multi_Currency_Prices( $this->multi_currency );
332
  $this->multi_currency->prices->add_hooks();
333
- $this->multi_currency->prices->prices_init();
334
  }
335
 
336
  $product_id = $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id();
54
  if ( is_admin() ) {
55
  add_filter( 'woocommerce_order_get_currency', array( $this, 'get_currency_for_new_order' ), 10, 2 );
56
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
58
 
59
  public function show_orders_currencies_selector() {
60
  global $wp_query, $typenow;
61
 
62
+ if ( 'shop_order' !== $typenow ) {
63
+ return;
64
  }
65
 
66
+ $currency_codes = $this->multi_currency->get_currency_codes();
67
+ $currencies = get_woocommerce_currencies();
68
  ?>
69
  <select id="dropdown_shop_order_currency" name="_order_currency">
70
  <option value=""><?php _e( 'Show all currencies', 'woocommerce-multilingual' ) ?></option>
71
+ <?php foreach ( $currency_codes as $currency ): ?>
72
  <option value="<?php echo $currency ?>" <?php
73
  if ( isset( $wp_query->query['_order_currency'] ) ) {
74
  selected( $currency, $wp_query->query['_order_currency'] );
75
  }
76
+ ?> ><?php printf( "%s (%s)", $currencies[ $currency ], get_woocommerce_currency_symbol( $currency ) ) ?></option>
77
  <?php endforeach; ?>
78
  </select>
79
  <?php
 
80
  }
81
 
82
  public function filter_orders_by_currency_join( $join ) {
298
  }
299
 
300
  if ( ! isset( $this->multi_currency->prices ) ) {
301
+ $this->multi_currency->prices = new WCML_Multi_Currency_Prices( $this->multi_currency, $this->woocommerce_wpml->get_setting( 'currency_options' ) );
302
  $this->multi_currency->prices->add_hooks();
 
303
  }
304
 
305
  $product_id = $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id();
inc/currencies/class-wcml-multi-currency-prices.php CHANGED
@@ -5,9 +5,9 @@ class WCML_Multi_Currency_Prices {
5
  const WC_DEFAULT_STEP = 10;
6
 
7
  /**
8
- * @var woocommerce_wpml
9
  */
10
- private $woocommerce_wpml;
11
  /**
12
  * @var WCML_Multi_Currency
13
  */
@@ -17,28 +17,24 @@ class WCML_Multi_Currency_Prices {
17
  */
18
  private $orders_list_currency;
19
 
20
- public function __construct( $multi_currency ) {
21
  $this->multi_currency = $multi_currency;
 
22
  }
23
 
24
  public function add_hooks() {
25
- add_filter( 'wcml_raw_price_amount', array( $this, 'raw_price_filter' ), 10, 2 ); // WCML filters
26
 
27
- if ( $this->multi_currency->load_filters ) {
28
- add_filter( 'init', array( $this, 'prices_init' ), 5 );
29
-
30
- // Currency and Amount filters
31
- add_filter( 'woocommerce_currency', array( $this, 'currency_filter' ) );
32
 
33
- add_filter( 'wcml_price_currency', array( $this, 'price_currency_filter' ) ); // WCML filters
34
  add_filter( 'wcml_product_price_by_currency', array(
35
  $this,
36
  'get_product_price_in_currency'
37
  ), 10, 2 ); // WCML filters
38
-
39
- add_filter( 'get_post_metadata', array( $this, 'product_price_filter' ), 10, 4 );
40
- add_filter( 'get_post_metadata', array( $this, 'variation_prices_filter' ), 12, 4 ); // second
41
-
42
  add_filter( 'woocommerce_price_filter_widget_max_amount', array( $this, 'filter_widget_max_amount' ), 99 );
43
  add_filter( 'woocommerce_price_filter_widget_min_amount', array( $this, 'filter_widget_min_amount' ), 99 );
44
 
@@ -66,7 +62,6 @@ class WCML_Multi_Currency_Prices {
66
  ) );
67
 
68
  add_filter( 'wc_price_args', array( $this, 'filter_wc_price_args' ) );
69
-
70
  }
71
 
72
  // formatting options
@@ -79,25 +74,23 @@ class WCML_Multi_Currency_Prices {
79
  add_filter( 'get_post_metadata', array( $this, 'save_order_currency_for_filter' ), 10, 4 );
80
  }
81
 
82
- public function prices_init() {
83
- global $woocommerce_wpml;
84
- $this->woocommerce_wpml =& $woocommerce_wpml;
85
-
86
- }
87
-
88
  public function currency_filter( $currency ) {
89
 
90
- $currency = apply_filters( 'wcml_price_currency', $currency );
 
 
91
 
92
  return $currency;
93
  }
94
 
95
  public function price_currency_filter( $currency ) {
96
 
97
- if ( isset( $this->order_currency ) ) {
98
- $currency = $this->order_currency;
99
- } else {
100
- $currency = $this->multi_currency->get_client_currency();
 
 
101
  }
102
 
103
  return $currency;
@@ -153,7 +146,7 @@ class WCML_Multi_Currency_Prices {
153
  }
154
 
155
  remove_filter( 'get_post_metadata', array(
156
- $this->woocommerce_wpml->multi_currency->prices,
157
  'product_price_filter'
158
  ), 10, 4 );
159
 
@@ -171,7 +164,7 @@ class WCML_Multi_Currency_Prices {
171
  }
172
 
173
  add_filter( 'get_post_metadata', array(
174
- $this->woocommerce_wpml->multi_currency->prices,
175
  'product_price_filter'
176
  ), 10, 4 );
177
 
@@ -188,7 +181,7 @@ class WCML_Multi_Currency_Prices {
188
 
189
  $price_keys = wcml_price_custom_fields( $object_id );
190
 
191
- if ( is_array( $price_keys ) && in_array( $meta_key, $price_keys ) ) {
192
  $no_filter = true;
193
 
194
  // exception for products migrated from before WCML 3.1 with independent prices
@@ -237,7 +230,7 @@ class WCML_Multi_Currency_Prices {
237
  if ( empty( $meta_key ) && get_post_type( $object_id ) == 'product_variation' ) {
238
  static $no_filter = false;
239
 
240
- if ( empty( $no_filter ) ) {
241
  $no_filter = true;
242
 
243
  $variation_fields = get_post_meta( $object_id );
@@ -376,16 +369,16 @@ class WCML_Multi_Currency_Prices {
376
 
377
  public function apply_rounding_rules( $price, $currency = false ) {
378
 
379
- if ( is_null( $this->woocommerce_wpml ) ) {
380
  global $woocommerce_wpml;
381
- $this->woocommerce_wpml = $woocommerce_wpml;
382
  }
383
 
384
  if ( ! $currency ) {
385
  $currency = $this->multi_currency->get_client_currency();
386
  }
387
 
388
- $currency_options = $this->woocommerce_wpml->settings['currency_options'][ $currency ];
389
 
390
  if ( $currency_options['rounding'] != 'disabled' ) {
391
 
@@ -458,7 +451,12 @@ class WCML_Multi_Currency_Prices {
458
 
459
  $amount = $this->raw_price_filter( $amount, $currency );
460
 
461
- $currency_details = $this->woocommerce_wpml->multi_currency->get_currency_details_by_code( $currency );
 
 
 
 
 
462
 
463
  switch ( $currency_details['position'] ) {
464
  case 'left' :
@@ -473,39 +471,36 @@ class WCML_Multi_Currency_Prices {
473
  case 'right_space' :
474
  $format = '%2$s&nbsp;%1$s';
475
  break;
 
 
476
  }
477
 
478
  $wc_price_args = array(
479
-
480
  'currency' => $currency,
481
  'decimal_separator' => $currency_details['decimal_sep'],
482
  'thousand_separator' => $currency_details['thousand_sep'],
483
  'decimals' => $currency_details['num_decimals'],
484
  'price_format' => $format,
485
-
486
-
487
  );
488
 
489
- $price = wc_price( $amount, $wc_price_args );
490
-
491
- return $price;
492
  }
493
 
494
  // Exposed function
495
  public function apply_currency_position( $price, $currency_code ) {
496
 
497
- $currencies = $this->woocommerce_wpml->multi_currency->get_currencies();
498
 
499
  if ( isset( $currencies[ $currency_code ]['position'] ) ) {
500
  $position = $currencies[ $currency_code ]['position'];
501
  } else {
502
  remove_filter( 'option_woocommerce_currency_pos', array(
503
- $this->woocommerce_wpml->multi_currency->prices,
504
  'filter_currency_position_option'
505
  ) );
506
  $position = get_option( 'woocommerce_currency_pos' );
507
  add_filter( 'option_woocommerce_currency_pos', array(
508
- $this->woocommerce_wpml->multi_currency->prices,
509
  'filter_currency_position_option'
510
  ) );
511
  }
@@ -533,7 +528,7 @@ class WCML_Multi_Currency_Prices {
533
  foreach ( $args as $key => $value ) {
534
  if ( substr( $key, 0, 7 ) == 'amount_' ) {
535
 
536
- $currency_details = $this->woocommerce_wpml->multi_currency->get_currency_details_by_code( $args['currency_code'] );
537
 
538
  $args[ $key ] = number_format( $value, $currency_details['num_decimals'], '.', '' );
539
  }
@@ -805,4 +800,14 @@ class WCML_Multi_Currency_Prices {
805
  return get_post_meta( $product->get_id(), '_price', 1 );
806
  }
807
 
 
 
 
 
 
 
 
 
 
 
808
  }
5
  const WC_DEFAULT_STEP = 10;
6
 
7
  /**
8
+ * @var array
9
  */
10
+ private $currency_options;
11
  /**
12
  * @var WCML_Multi_Currency
13
  */
17
  */
18
  private $orders_list_currency;
19
 
20
+ public function __construct( WCML_Multi_Currency $multi_currency, array $currency_options ) {
21
  $this->multi_currency = $multi_currency;
22
+ $this->currency_options = $currency_options;
23
  }
24
 
25
  public function add_hooks() {
26
+ add_filter( 'wcml_raw_price_amount', array( $this, 'raw_price_filter' ), 10, 2 );
27
 
28
+ add_filter( 'woocommerce_currency', array( $this, 'currency_filter' ) );
29
+ add_filter( 'wcml_price_currency', array( $this, 'price_currency_filter' ) );
30
+ add_filter( 'get_post_metadata', array( $this, 'product_price_filter' ), 10, 4 );
31
+ add_filter( 'get_post_metadata', array( $this, 'variation_prices_filter' ), 12, 4 );
 
32
 
33
+ if ( $this->multi_currency->load_filters ) {
34
  add_filter( 'wcml_product_price_by_currency', array(
35
  $this,
36
  'get_product_price_in_currency'
37
  ), 10, 2 ); // WCML filters
 
 
 
 
38
  add_filter( 'woocommerce_price_filter_widget_max_amount', array( $this, 'filter_widget_max_amount' ), 99 );
39
  add_filter( 'woocommerce_price_filter_widget_min_amount', array( $this, 'filter_widget_min_amount' ), 99 );
40
 
62
  ) );
63
 
64
  add_filter( 'wc_price_args', array( $this, 'filter_wc_price_args' ) );
 
65
  }
66
 
67
  // formatting options
74
  add_filter( 'get_post_metadata', array( $this, 'save_order_currency_for_filter' ), 10, 4 );
75
  }
76
 
 
 
 
 
 
 
77
  public function currency_filter( $currency ) {
78
 
79
+ if( $this->is_multi_currency_filters_loaded() ){
80
+ $currency = apply_filters( 'wcml_price_currency', $currency );
81
+ }
82
 
83
  return $currency;
84
  }
85
 
86
  public function price_currency_filter( $currency ) {
87
 
88
+ if( $this->is_multi_currency_filters_loaded() ){
89
+ if ( isset( $this->order_currency ) ) {
90
+ $currency = $this->order_currency;
91
+ } else {
92
+ $currency = $this->multi_currency->get_client_currency();
93
+ }
94
  }
95
 
96
  return $currency;
146
  }
147
 
148
  remove_filter( 'get_post_metadata', array(
149
+ $this,
150
  'product_price_filter'
151
  ), 10, 4 );
152
 
164
  }
165
 
166
  add_filter( 'get_post_metadata', array(
167
+ $this,
168
  'product_price_filter'
169
  ), 10, 4 );
170
 
181
 
182
  $price_keys = wcml_price_custom_fields( $object_id );
183
 
184
+ if ( is_array( $price_keys ) && in_array( $meta_key, $price_keys ) && $this->is_multi_currency_filters_loaded() ) {
185
  $no_filter = true;
186
 
187
  // exception for products migrated from before WCML 3.1 with independent prices
230
  if ( empty( $meta_key ) && get_post_type( $object_id ) == 'product_variation' ) {
231
  static $no_filter = false;
232
 
233
+ if ( empty( $no_filter ) && $this->is_multi_currency_filters_loaded() ) {
234
  $no_filter = true;
235
 
236
  $variation_fields = get_post_meta( $object_id );
369
 
370
  public function apply_rounding_rules( $price, $currency = false ) {
371
 
372
+ if ( is_null( $this->currency_options ) ) {
373
  global $woocommerce_wpml;
374
+ $this->currency_options = $woocommerce_wpml->get_setting( 'currency_options' );
375
  }
376
 
377
  if ( ! $currency ) {
378
  $currency = $this->multi_currency->get_client_currency();
379
  }
380
 
381
+ $currency_options = $this->currency_options[ $currency ];
382
 
383
  if ( $currency_options['rounding'] != 'disabled' ) {
384
 
451
 
452
  $amount = $this->raw_price_filter( $amount, $currency );
453
 
454
+ return $this->format_price_in_currency( $amount, $currency );
455
+ }
456
+
457
+ public function format_price_in_currency( $price, $currency ){
458
+
459
+ $currency_details = $this->multi_currency->get_currency_details_by_code( $currency );
460
 
461
  switch ( $currency_details['position'] ) {
462
  case 'left' :
471
  case 'right_space' :
472
  $format = '%2$s&nbsp;%1$s';
473
  break;
474
+ default:
475
+ $format = get_woocommerce_price_format();
476
  }
477
 
478
  $wc_price_args = array(
 
479
  'currency' => $currency,
480
  'decimal_separator' => $currency_details['decimal_sep'],
481
  'thousand_separator' => $currency_details['thousand_sep'],
482
  'decimals' => $currency_details['num_decimals'],
483
  'price_format' => $format,
 
 
484
  );
485
 
486
+ return wc_price( $price, $wc_price_args );
 
 
487
  }
488
 
489
  // Exposed function
490
  public function apply_currency_position( $price, $currency_code ) {
491
 
492
+ $currencies = $this->multi_currency->get_currencies();
493
 
494
  if ( isset( $currencies[ $currency_code ]['position'] ) ) {
495
  $position = $currencies[ $currency_code ]['position'];
496
  } else {
497
  remove_filter( 'option_woocommerce_currency_pos', array(
498
+ $this,
499
  'filter_currency_position_option'
500
  ) );
501
  $position = get_option( 'woocommerce_currency_pos' );
502
  add_filter( 'option_woocommerce_currency_pos', array(
503
+ $this,
504
  'filter_currency_position_option'
505
  ) );
506
  }
528
  foreach ( $args as $key => $value ) {
529
  if ( substr( $key, 0, 7 ) == 'amount_' ) {
530
 
531
+ $currency_details = $this->multi_currency->get_currency_details_by_code( $args['currency_code'] );
532
 
533
  $args[ $key ] = number_format( $value, $currency_details['num_decimals'], '.', '' );
534
  }
800
  return get_post_meta( $product->get_id(), '_price', 1 );
801
  }
802
 
803
+ private function is_multi_currency_filters_loaded(){
804
+ static $filters_loaded;
805
+
806
+ if( !$filters_loaded ){
807
+ $filters_loaded = $this->multi_currency->are_filters_need_loading();
808
+ }
809
+
810
+ return $filters_loaded;
811
+ }
812
+
813
  }
inc/currencies/class-wcml-multi-currency-reports.php CHANGED
@@ -12,7 +12,7 @@ class WCML_Multi_Currency_Reports {
12
  private $wpml_cache;
13
 
14
  /** @var string $reports_currency */
15
- private $reports_currency;
16
 
17
  /**
18
  * WCML_Multi_Currency_Reports constructor.
@@ -74,8 +74,7 @@ class WCML_Multi_Currency_Reports {
74
  }
75
 
76
  public function reports_init() {
77
-
78
- if ( isset( $_GET['page'] ) && $_GET['page'] == 'wc-reports' ) { //wc-reports - 2.1.x, woocommerce_reports 2.0.x
79
 
80
  add_filter( 'woocommerce_reports_get_order_report_query', array( $this, 'admin_reports_query_filter' ) );
81
 
@@ -105,15 +104,11 @@ class WCML_Multi_Currency_Reports {
105
  " );
106
 
107
  $this->reports_currency = isset( $_COOKIE['_wcml_reports_currency'] ) ? $_COOKIE['_wcml_reports_currency'] : wcml_get_woocommerce_currency_option();
108
- //validation
109
- $orders_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
110
- if ( ! isset( $orders_currencies[ $this->reports_currency ] ) ) {
111
- $this->reports_currency = ! empty( $orders_currencies ) ? key( $orders_currencies ) : false;
112
- }
113
-
114
- add_filter( 'woocommerce_currency_symbol', array( $this, '_set_reports_currency_symbol' ) );
115
 
 
 
116
 
 
117
  }
118
  }
119
 
@@ -147,7 +142,7 @@ class WCML_Multi_Currency_Reports {
147
 
148
  $cookie_name = '_wcml_reports_currency';
149
  // @todo uncomment or delete when #wpmlcore-5796 is resolved
150
- //do_action( 'wpsc_add_cookie', $cookie_name );
151
  setcookie( $cookie_name, filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS ),
152
  time() + 86400, COOKIEPATH, COOKIE_DOMAIN );
153
 
@@ -156,31 +151,27 @@ class WCML_Multi_Currency_Reports {
156
  }
157
 
158
  public function reports_currency_selector() {
 
 
159
 
160
- $orders_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
161
- $currencies = get_woocommerce_currencies();
162
-
163
- // remove temporary
164
  remove_filter( 'woocommerce_currency_symbol', array( $this, '_set_reports_currency_symbol' ) );
165
-
166
  ?>
167
-
168
  <select id="dropdown_shop_report_currency" style="margin-left:5px;">
169
- <?php if ( empty( $orders_currencies ) ): ?>
170
  <option value=""><?php _e( 'Currency - no orders found', 'woocommerce-multilingual' ) ?></option>
171
  <?php else: ?>
172
- <?php foreach ( $orders_currencies as $currency => $count ): ?>
173
  <option value="<?php echo $currency ?>" <?php selected( $currency, $this->reports_currency ); ?>>
174
  <?php printf( "%s (%s)", $currencies[ $currency ], get_woocommerce_currency_symbol( $currency ) ) ?>
175
  </option>
176
  <?php endforeach; ?>
177
  <?php endif; ?>
178
  </select>
179
-
180
  <?php
181
- // add back
182
- add_filter( 'woocommerce_currency_symbol', array( $this, '_set_reports_currency_symbol' ) );
183
 
 
 
184
  }
185
 
186
  /*
12
  private $wpml_cache;
13
 
14
  /** @var string $reports_currency */
15
+ protected $reports_currency;
16
 
17
  /**
18
  * WCML_Multi_Currency_Reports constructor.
74
  }
75
 
76
  public function reports_init() {
77
+ if ( isset( $_GET['page'] ) && 'wc-reports' === $_GET['page'] ) { //wc-reports - 2.1.x, woocommerce_reports 2.0.x
 
78
 
79
  add_filter( 'woocommerce_reports_get_order_report_query', array( $this, 'admin_reports_query_filter' ) );
80
 
104
  " );
105
 
106
  $this->reports_currency = isset( $_COOKIE['_wcml_reports_currency'] ) ? $_COOKIE['_wcml_reports_currency'] : wcml_get_woocommerce_currency_option();
 
 
 
 
 
 
 
107
 
108
+ // Validation.
109
+ $this->reports_currency = $this->woocommerce_wpml->multi_currency->get_currency_code();
110
 
111
+ add_filter( 'woocommerce_currency_symbol', array( $this, '_set_reports_currency_symbol' ) );
112
  }
113
  }
114
 
142
 
143
  $cookie_name = '_wcml_reports_currency';
144
  // @todo uncomment or delete when #wpmlcore-5796 is resolved
145
+ // do_action( 'wpsc_add_cookie', $cookie_name );
146
  setcookie( $cookie_name, filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS ),
147
  time() + 86400, COOKIEPATH, COOKIE_DOMAIN );
148
 
151
  }
152
 
153
  public function reports_currency_selector() {
154
+ $currency_codes = $this->woocommerce_wpml->multi_currency->get_currency_codes();
155
+ $currencies = get_woocommerce_currencies();
156
 
157
+ // Remove filter temporary.
 
 
 
158
  remove_filter( 'woocommerce_currency_symbol', array( $this, '_set_reports_currency_symbol' ) );
 
159
  ?>
 
160
  <select id="dropdown_shop_report_currency" style="margin-left:5px;">
161
+ <?php if ( empty( $currency_codes ) ): ?>
162
  <option value=""><?php _e( 'Currency - no orders found', 'woocommerce-multilingual' ) ?></option>
163
  <?php else: ?>
164
+ <?php foreach ( $currency_codes as $currency ): ?>
165
  <option value="<?php echo $currency ?>" <?php selected( $currency, $this->reports_currency ); ?>>
166
  <?php printf( "%s (%s)", $currencies[ $currency ], get_woocommerce_currency_symbol( $currency ) ) ?>
167
  </option>
168
  <?php endforeach; ?>
169
  <?php endif; ?>
170
  </select>
 
171
  <?php
 
 
172
 
173
+ // Add filter back.
174
+ add_filter( 'woocommerce_currency_symbol', array( $this, '_set_reports_currency_symbol' ) );
175
  }
176
 
177
  /*
inc/currencies/class-wcml-multi-currency-resources.php CHANGED
@@ -43,19 +43,16 @@ class WCML_Multi_Currency_Resources{
43
  }
44
 
45
  private static function set_cache_compatibility_variables( $script_vars ) {
 
46
 
47
  $script_vars['cache_enabled'] = false;
48
 
49
- if (
50
- (int) ! empty( self::$multi_currency->W3TC ) ||
51
- ( function_exists( 'wp_cache_is_enabled' ) && wp_cache_is_enabled() )
52
- ) {
 
53
  $script_vars['cache_enabled'] = true;
54
- }else{
55
- global $sg_cachepress_environment;
56
- if ( $sg_cachepress_environment && $sg_cachepress_environment->cache_is_enabled() ) {
57
- $script_vars['cache_enabled'] = true;
58
- }
59
  }
60
 
61
  $script_vars['cache_enabled'] = apply_filters( 'wcml_is_cache_enabled_for_switching_currency', $script_vars['cache_enabled'] );
43
  }
44
 
45
  private static function set_cache_compatibility_variables( $script_vars ) {
46
+ global $sg_cachepress_environment;
47
 
48
  $script_vars['cache_enabled'] = false;
49
 
50
+ $w3tc_enabled = ! empty( self::$multi_currency->W3TC ) || ( function_exists( 'wp_cache_is_enabled' ) && wp_cache_is_enabled() );
51
+ $nginx_enabled = class_exists( 'NginxCache' );
52
+ $sg_cache_enabled = $sg_cachepress_environment && $sg_cachepress_environment->cache_is_enabled();
53
+
54
+ if ( $w3tc_enabled || $nginx_enabled || $sg_cache_enabled ) {
55
  $script_vars['cache_enabled'] = true;
 
 
 
 
 
56
  }
57
 
58
  $script_vars['cache_enabled'] = apply_filters( 'wcml_is_cache_enabled_for_switching_currency', $script_vars['cache_enabled'] );
inc/currencies/class-wcml-multi-currency.php CHANGED
@@ -1,9 +1,12 @@
1
  <?php
2
 
3
- // Our case:
4
- // Muli-currency can be enabled by an option in wp_options - wcml_multi_currency_enabled
5
- // User currency will be set in the woocommerce session as 'client_currency'
6
- //
 
 
 
7
  class WCML_Multi_Currency {
8
 
9
  /** @var array */
@@ -102,8 +105,8 @@ class WCML_Multi_Currency {
102
 
103
  $this->init_currencies();
104
 
105
- $this->load_filters = $this->_load_filters();
106
- $this->prices = new WCML_Multi_Currency_Prices( $this );
107
  $this->prices->add_hooks();
108
  if ( $this->load_filters ) {
109
  $table_rate_shipping_multi_currency = new WCML_Multi_Currency_Table_Rate_Shipping();
@@ -152,7 +155,7 @@ class WCML_Multi_Currency {
152
 
153
  }
154
 
155
- private function _load_filters() {
156
  $load = false;
157
 
158
  if ( ! is_admin() && $this->get_client_currency() !== wcml_get_woocommerce_currency_option() ) {
@@ -328,6 +331,19 @@ class WCML_Multi_Currency {
328
  return $this->currency_codes;
329
  }
330
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  public function get_currency_details_by_code( $code ) {
332
 
333
  if ( isset( $this->currencies[ $code ] ) ) {
1
  <?php
2
 
3
+ /**
4
+ * Class WCML_Multi_Currency
5
+ *
6
+ * Our case:
7
+ * Multi-currency can be enabled by an option in wp_options - wcml_multi_currency_enabled
8
+ * User currency will be set in the woocommerce session as 'client_currency'
9
+ */
10
  class WCML_Multi_Currency {
11
 
12
  /** @var array */
105
 
106
  $this->init_currencies();
107
 
108
+ $this->load_filters = $this->are_filters_need_loading();
109
+ $this->prices = new WCML_Multi_Currency_Prices( $this, $woocommerce_wpml->get_setting( 'currency_options' ) );
110
  $this->prices->add_hooks();
111
  if ( $this->load_filters ) {
112
  $table_rate_shipping_multi_currency = new WCML_Multi_Currency_Table_Rate_Shipping();
155
 
156
  }
157
 
158
+ public function are_filters_need_loading() {
159
  $load = false;
160
 
161
  if ( ! is_admin() && $this->get_client_currency() !== wcml_get_woocommerce_currency_option() ) {
331
  return $this->currency_codes;
332
  }
333
 
334
+ /**
335
+ * @return mixed|string
336
+ */
337
+ public function get_currency_code() {
338
+ $currency_code = wcml_get_woocommerce_currency_option();
339
+ $currency_codes = $this->get_currency_codes();
340
+ if ( ! in_array( $currency_code, $currency_codes, true ) ) {
341
+ $currency_code = $this->woocommerce_wpml->multi_currency->get_default_currency();
342
+ }
343
+
344
+ return $currency_code;
345
+ }
346
+
347
  public function get_currency_details_by_code( $code ) {
348
 
349
  if ( isset( $this->currencies[ $code ] ) ) {
inc/template-classes/class-wcml-settings-ui.php CHANGED
@@ -50,6 +50,15 @@ class WCML_Settings_UI extends WCML_Templates_Factory {
50
  ),
51
  ),
52
 
 
 
 
 
 
 
 
 
 
53
  'file_sync' => array(
54
  'heading' => __('Products Download Files', 'woocommerce-multilingual'),
55
  'tip' => __( 'If you are using downloadable products, you can choose to have their paths
50
  ),
51
  ),
52
 
53
+ 'media_synchronization' => array(
54
+ 'heading' => __( 'Products Media Synchronization', 'woocommerce-multilingual' ),
55
+ 'tip' => __( 'Configure thumbnail and gallery synchronization to translations.', 'woocommerce-multilingual' ),
56
+ 'sync_media' => array(
57
+ 'value' => $this->woocommerce_wpml->get_setting( 'sync_media', true ),
58
+ 'label' => __( 'Display original images on the translated product front page if images not specified', 'woocommerce-multilingual' )
59
+ )
60
+ ),
61
+
62
  'file_sync' => array(
63
  'heading' => __('Products Download Files', 'woocommerce-multilingual'),
64
  'tip' => __( 'If you are using downloadable products, you can choose to have their paths
inc/template-classes/status/class-wcml-status-config-warnings-ui.php CHANGED
@@ -46,9 +46,6 @@ class WCML_Status_Config_Warnings_UI extends WCML_Templates_Factory {
46
  'check_conf' => __( 'You should check WPML configuration files added by other plugins or manual settings on the %s section.', 'woocommerce-multilingual' ),
47
  'cont_set' => '<a href="' . admin_url( 'admin.php?page=' . WPML_TM_FOLDER . '/menu/main.php&sm=mcsetup' ) . '">'. __( 'Multilingual Content Setup', 'woocommerce-multilingual' ) .'</a>'
48
  ),
49
- 'nonces' => array(
50
- 'fix_strings' => wp_create_nonce( 'wcml_fix_strings_language' )
51
- )
52
  );
53
 
54
  return $model;
46
  'check_conf' => __( 'You should check WPML configuration files added by other plugins or manual settings on the %s section.', 'woocommerce-multilingual' ),
47
  'cont_set' => '<a href="' . admin_url( 'admin.php?page=' . WPML_TM_FOLDER . '/menu/main.php&sm=mcsetup' ) . '">'. __( 'Multilingual Content Setup', 'woocommerce-multilingual' ) .'</a>'
48
  ),
 
 
 
49
  );
50
 
51
  return $model;
inc/translation-editor/class-wcml-editor-ui-product-job.php CHANGED
@@ -721,7 +721,15 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
721
  $this->woocommerce_wpml->attributes->sync_default_product_attr( $this->product_id, $tr_product_id, $this->get_target_language() );
722
 
723
  // synchronize post variations
724
- $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $this->product_id, $tr_product_id, $this->get_target_language(), $translations, true );
 
 
 
 
 
 
 
 
725
 
726
  $this->woocommerce_wpml->sync_product_data->sync_linked_products( $this->product_id, $tr_product_id, $this->get_target_language() );
727
 
@@ -760,6 +768,8 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
760
  }
761
  }
762
 
 
 
763
  if( $product_translations ){
764
  $iclTranslationManagement->update_translation_status(
765
  array(
721
  $this->woocommerce_wpml->attributes->sync_default_product_attr( $this->product_id, $tr_product_id, $this->get_target_language() );
722
 
723
  // synchronize post variations
724
+ $this->woocommerce_wpml->sync_variations_data->sync_product_variations(
725
+ $this->product_id,
726
+ $tr_product_id,
727
+ $this->get_target_language(),
728
+ [
729
+ 'editor_translations' => $translations,
730
+ 'is_troubleshooting' => true
731
+ ]
732
+ );
733
 
734
  $this->woocommerce_wpml->sync_product_data->sync_linked_products( $this->product_id, $tr_product_id, $this->get_target_language() );
735
 
768
  }
769
  }
770
 
771
+ do_action( 'wcml_after_sync_product_data', $this->product_id, $tr_product_id, $this->get_target_language() );
772
+
773
  if( $product_translations ){
774
  $iclTranslationManagement->update_translation_status(
775
  array(
inc/translation-editor/class-wcml-synchronize-product-data.php CHANGED
@@ -146,7 +146,7 @@ class WCML_Synchronize_Product_Data{
146
 
147
  }
148
 
149
- public function sync_product_data( $original_product_id, $tr_product_id, $lang ){
150
 
151
  do_action( 'wcml_before_sync_product_data', $original_product_id, $tr_product_id, $lang );
152
 
@@ -166,7 +166,7 @@ class WCML_Synchronize_Product_Data{
166
  $this->sync_product_taxonomies( $original_product_id, $tr_product_id, $lang );
167
 
168
  //duplicate variations
169
- $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $original_product_id, $tr_product_id, $lang );
170
 
171
  $this->sync_linked_products( $original_product_id, $tr_product_id, $lang );
172
 
@@ -174,6 +174,8 @@ class WCML_Synchronize_Product_Data{
174
 
175
  // Clear any unwanted data
176
  wc_delete_product_transients( $tr_product_id );
 
 
177
  }
178
 
179
  public function sync_product_taxonomies( $original_product_id, $tr_product_id, $lang ) {
@@ -505,7 +507,7 @@ class WCML_Synchronize_Product_Data{
505
 
506
  $master_post_id = $this->woocommerce_wpml->products->get_original_product_id( $master_post_id );
507
 
508
- $this->sync_product_data( $master_post_id, $id, $lang );
509
  }
510
  }
511
 
146
 
147
  }
148
 
149
+ public function sync_product_data( $original_product_id, $tr_product_id, $lang, $duplicate = false ){
150
 
151
  do_action( 'wcml_before_sync_product_data', $original_product_id, $tr_product_id, $lang );
152
 
166
  $this->sync_product_taxonomies( $original_product_id, $tr_product_id, $lang );
167
 
168
  //duplicate variations
169
+ $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $original_product_id, $tr_product_id, $lang, [ 'is_duplicate' => $duplicate ] );
170
 
171
  $this->sync_linked_products( $original_product_id, $tr_product_id, $lang );
172
 
174
 
175
  // Clear any unwanted data
176
  wc_delete_product_transients( $tr_product_id );
177
+
178
+ do_action( 'wcml_after_sync_product_data', $original_product_id, $tr_product_id, $lang );
179
  }
180
 
181
  public function sync_product_taxonomies( $original_product_id, $tr_product_id, $lang ) {
507
 
508
  $master_post_id = $this->woocommerce_wpml->products->get_original_product_id( $master_post_id );
509
 
510
+ $this->sync_product_data( $master_post_id, $id, $lang, true );
511
  }
512
  }
513
 
inc/translation-editor/class-wcml-synchronize-variations-data.php CHANGED
@@ -90,16 +90,22 @@ class WCML_Synchronize_Variations_Data{
90
  }
91
  }
92
 
93
- /*
94
- * sync product variations
95
- * $product_id - original product id
96
- * $tr_product_id - translated product id
97
- * $lang - trnsl language
98
- * $data - array of values (when we save original product this array is empty, but when we update translation in this array we have price values and etc.) *
99
- * */
100
- public function sync_product_variations( $product_id, $tr_product_id, $lang, $data = false, $trbl = false ){
101
  global $wpml_post_translations;
102
 
 
 
 
 
 
 
 
103
  $is_variable_product = $this->woocommerce_wpml->products->is_variable_product( $product_id );
104
 
105
  if( $is_variable_product ){
@@ -166,20 +172,24 @@ class WCML_Synchronize_Variations_Data{
166
  }
167
 
168
  //sync description
169
- if( isset( $data[ md5( '_variation_description'.$original_variation_id ) ] ) ){
170
- update_post_meta( $variation_id, '_variation_description', $data[ md5( '_variation_description'.$original_variation_id ) ] );
 
 
 
 
171
  }
172
 
173
  //sync media
174
  $this->woocommerce_wpml->media->sync_variation_thumbnail_id( $original_variation_id, $variation_id, $lang );
175
 
176
  //sync file_paths
177
- $this->woocommerce_wpml->downloadable->sync_files_to_translations( $original_variation_id, $variation_id, $data );
178
 
179
  //sync taxonomies
180
  $this->sync_variations_taxonomies( $original_variation_id, $variation_id, $lang );
181
 
182
- $this->duplicate_variation_data( $original_variation_id, $variation_id, $data, $lang, $trbl );
183
 
184
  $this->delete_removed_variation_attributes( $product_id, $variation_id );
185
 
90
  }
91
  }
92
 
93
+ /**
94
+ * @param int $product_id
95
+ * @param int $tr_product_id
96
+ * @param string $lang
97
+ * @param array $args
98
+ */
99
+ public function sync_product_variations( $product_id, $tr_product_id, $lang, $args = [] ){
 
100
  global $wpml_post_translations;
101
 
102
+ $default_args = array(
103
+ 'editor_translations' => array(),
104
+ 'is_troubleshooting' => false,
105
+ 'is_duplicate' => false,
106
+ );
107
+ $args = wp_parse_args( $args, $default_args );
108
+
109
  $is_variable_product = $this->woocommerce_wpml->products->is_variable_product( $product_id );
110
 
111
  if( $is_variable_product ){
172
  }
173
 
174
  //sync description
175
+ if( $args['is_duplicate'] ){
176
+ update_post_meta( $variation_id, '_variation_description', get_post_meta( $original_variation_id, '_variation_description', true ) );
177
+ }
178
+
179
+ if( isset( $args['editor_translations'][ md5( '_variation_description'.$original_variation_id ) ] ) ){
180
+ update_post_meta( $variation_id, '_variation_description', $args['editor_translations'][ md5( '_variation_description'.$original_variation_id ) ] );
181
  }
182
 
183
  //sync media
184
  $this->woocommerce_wpml->media->sync_variation_thumbnail_id( $original_variation_id, $variation_id, $lang );
185
 
186
  //sync file_paths
187
+ $this->woocommerce_wpml->downloadable->sync_files_to_translations( $original_variation_id, $variation_id, $args['editor_translations'] );
188
 
189
  //sync taxonomies
190
  $this->sync_variations_taxonomies( $original_variation_id, $variation_id, $lang );
191
 
192
+ $this->duplicate_variation_data( $original_variation_id, $variation_id, $args['editor_translations'], $lang, $args['is_troubleshooting'] );
193
 
194
  $this->delete_removed_variation_attributes( $product_id, $variation_id );
195
 
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multili
5
  License: GPLv2
6
  Requires at least: 4.7
7
  Tested up to: 5.3
8
- Stable tag: 4.7.3
9
  Requires PHP: 5.6
10
 
11
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
@@ -66,9 +66,9 @@ If the checks fail, WooCommerce Multilingual will not be able to run.
66
  * MySQL version 5.6 or later
67
 
68
  * WooCommerce 3.3.0 or later
69
- * WPML Multilingual CMS 4.3.0 or later
70
- * WPML String Translation 3.0.0 or later
71
- * WPML Translation Management 2.9.0 or later
72
 
73
  = WordPress automatic installation =
74
  In your WordPress dashboard, go to the Plugins section and click 'Add new'.
@@ -137,40 +137,62 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
137
 
138
  == Changelog ==
139
 
140
- = 4.7.4 =
141
- * Fixed warning when some plugins using `get_terms` without `taxonomy` argument.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  = 4.7.0 =
144
  * Replaced some Twig templates with pure PHP templates as the first step towards the removal of Twig dependencies.
 
145
  * Added compatibility class for WooCommerce order status Manager plugin
146
- * Fixed PHP Notice for WC Variations Swatches And Photos compatibility.
147
- * WooCommerce Bookings compatibility : Fixed notice when trying to cancel booking.
148
- * Fixed a JavaScript error on the Store URLs tab.
149
- * Fixed an issue where the "Fix translated variations relationships" troubleshooting option was removing translated variations.
150
  * Fixed an issue where the strings for the default payment methods were not properly translated on the Checkout page.
151
- * Fixed an issue where product names were not translated in the admin emails.
152
- * Fixed an issue with the WooCommerce Subscriptions availability in the secondary language after purchasing the subscription in the original language.
153
  * Fixed an issue with the cache flush during language switching.
154
  * Fixed in the original ticket.
155
  * Fixed an issue where the gateway strings would always register in English instead of the site's default language.
156
- * Fixed an issue with the price filter widget not showing results in a secondary language.
157
- * Fixed an issue where customers would not receive notifications in the correct language.
158
- * Fixed an issue where the shipping classes in secondary languages were not calculated during checkout.
159
- * Fixed error while sending WooCoomerce Bookings email for bookings which didn't have orders assigned.
160
- * added comp. class to cover price update when products are edited with WOOBE plugin
161
- * Updated compatibility class for WC Checkout Addons
162
  * Fixed an issue where the total price on the Composite product page was not rounded.
163
  * Fixed an issue causing wrong rewrite rules after saving the settings and visiting a page in a language other than the default.
164
  * Fixed an issue with incorrect price converting for the Product add-ons.
 
165
  * Fixed an issue with the currency reverting to the default one during checkout.
166
  * Fixed removed meta from original product not synchronized to translation.
167
  * Fixed an issue where the BACS gateway instructions were not translated when re-sending the customer notification email from the admin.
168
  * Fixed an issue with missing language information for attribute terms that happened after changing the attribute slug.
169
  * Removed the Twig Composer dependency as it now relies on Twig from the WPML core plugin.
 
170
  * Fixed an issue where the Products shortcode was not working in the secondary language.
 
 
171
  * Fixed the images that were wrongly inserted in the translation job when attachments are not translatable.
172
  * Significantly improved the site performance on when updating the page, post, or a WooCommerce product page in the admin.
173
  * Added the "wp_" prefix to all cookies so that hosting and caching layers can properly handle them.
 
 
 
 
 
174
  * Display larger images when hovering thumbnails in the WooCommerce Multilingual Products admin page.
175
  * Added the "wcml_new_order_admin_email_language" filter to allow setting the language of emails sent to admins for new or updated orders.
176
 
@@ -269,811 +291,3 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
269
  * Fix small issue in product stock sync
270
  * Refund and restock - not working properly when refunding the variation in second language
271
  * WooCommerce Product Bundles -> original overwrites translation (visible when using title/description override)
272
-
273
- = 4.1.0 =
274
- * Enhanced language switchers
275
- * Improved REST API support
276
- * Updated WooCommerce 2.7 compatibiilty
277
- * Added the ability to translate product terms in the products translation editor
278
- * Enhanced the translation of rich text custom fields in the products translation editor.
279
- * Compatibility with WooCommerce Product Bundles (updated, not for WooCommerce 2.7)
280
- * Compatibility with ACF Pro (fixes)
281
- * Compatibility with WooCommerce Bookings (fixes)
282
- * Compatibility with WP Simple Survey (fixes)
283
- * Fix: Translations for custom attributes containing the umlaut character were not showing on the frontend.
284
- * Fix: Some gallery images were not synchronized when using the corresponding option on the troubleshooting page.
285
- * Fix: Incorrect country name translations were used in the order confirmation email is some situations.
286
- * Fix: Some endpoints were not accessible when using the ‘Different languages in directories’ configuration.
287
- * Fix: Order screen displayed ‘Variation # of Product name’ instead of just the product name.
288
- * Fix: The custom prices were not displayed correctly on the front end when using ‘,’ as a decimal separator.
289
- * Fix: In specific circumstances, the product category URLs were returning a 404 error.
290
- * Fix: New lines were not copied correctly when using the products translation editor.
291
- * Fix: In some circumstances, accessing product categories without a trailing slash generated PHP notices.
292
- * Fix: The stock status was not synchronized correctly for variable products.
293
- * Fix: By removing an attribute, only the terms in the default language were removed from the database.
294
- * Fix: When using the option to display only products with custom prices in the secondary currencies and the price was 0, the products variations were not visible on the front end.
295
- * Fix: The option to set separate download files for each translation was not working correctly for variable products
296
-
297
- = 4.0.4 =
298
- * Bug fix: empty shipping class was shown on the Quick Editor when using WooCommerce Table Rate Shipping
299
- * Bug fix: the Translation Editor could not save the same slug for translations of the same product
300
- * Bug fix: sales by product reports were inorect when filterign by languages including a dash character in their code
301
- * Bug fix: as of version 4.0.2 the option to use custom settings for translations download files was not always working
302
- * Bug fix: a PHP fatal error was shown when WooCommerce Multilingual was active but WooCommerce was not active
303
- * Bug fix: global attributes of variations were not copied to transltions when using the native interface to edit product translations
304
- * Bug fix: it was not possible to add multiple bookings in the cart at one time (when using WooCommerce Bookings)
305
- * Bug fix: custom URL parameters were not preserved when switching the language on the shop page
306
- * Fixed various incompatibilities with PHP 7.1
307
-
308
- = 4.0.3 =
309
- * Fixed fatal error caused by syntax incompatible with PHP versions prior 5.5
310
-
311
- = 4.0.2 =
312
- * Added a troubleshooting option to fix a problem with incorrectly translated product_type terms revealed by upgrading to WordPress 4.7
313
-
314
- = 4.0.1 =
315
- * Fixed various issues introduced by version 4.0.0
316
- * Fixed a problem that was preventing the cart from being updated for some users: items added or removed
317
- * Fixed a problem with product categories not being synchronized for product translations in some cases
318
-
319
- = 4.0.0 =
320
- * Added the option to configure automatic exchange rates for the multi-currency mode
321
- * Optimized the synchronization process between products and their translations when saving products
322
- * Added the option to reset the cart when switching the languages or currencies
323
- * Added compatibility updates for WordPress 4.7
324
- * Improved usability aspects related to popular compatible extensions
325
- * Added compatibility updates for upcoming WooCommerce 2.7
326
- * Fixed a compatibility issue with Yoast SEO premium: Redirects to the original product were created for translated variations
327
- * Fixed a compatibility issue with WooCommerce Tab Manager: HTML was stripped out when saving the translation of a tab
328
- * Bug fix: downloadable products were added multiple times to the cart (instead of quantity change)
329
- * Bug fix: order-pay endpoint string was re-registering itself with a blank value
330
-
331
- = 3.9.5 =
332
- * Fixed a bug introduced in 3.9.4 that prevented translating variable products
333
-
334
- = 3.9.4 =
335
- * Fixed an issue with custom prices (secondary currency) overriding the price in the default currency in some conditions
336
- * Fixed an issue with WooCommerce Authorize.Net AIM Gateway happening when using the credit cart checkout
337
- * Bug fix: the group products were excluded from the order notification emails
338
- * Fixed a compatibility issue with Revolution Slider
339
- * Changed the input field for variation descriptions to textarea in the tranlsation editor
340
- * Fixed an issue related to rates per shipping in secondary currencies when using WooCommerce Table Rate Shipping
341
- * Bug fix: the shipping class was not displayed in the backend when when using WooCommerce Table Rate Shipping and creating the product in a secondary language
342
- * Fixed a compatibility issue with WooCommerce Print Invoices
343
- * Fixed compatibility issues with Sensei
344
- * Added a filter for rounding rules logic
345
- * Added a currencies that do not use decimals
346
-
347
- = 3.9.3 =
348
- * Fixed a bug that was causing the currency switcher to not be displayed on the cart and checkout pages in certain conditions
349
- * Fixed PHP notices on the backend when using PHP 7
350
- * Fixed a bug making the number of decimals for the default currency being overridden in the backend when the multi-currency was on
351
-
352
- = 3.9.2 =
353
- * Bug fix: User with the Shop Manager role was could not access WooCommerce Multilingual menu
354
- * Bug fix: the shipping tax was not applied correctly when using a WooCommerce version prior 2.6
355
- * Bug fix: Translations for variaiton descriptions were not saved correctly
356
- * Bug fix: New order emails sent to admins included incorrectly translated strings
357
- * Bug fix: A fatal error was occurring when upgrading from WooCommerce Multilingual 3.3 (or older)
358
- * Product add-on titles were missing from order pages and emails
359
-
360
- = 3.9.1.1 =
361
- * Bug fix: Fixed a bug causing fatal error on older PHP versions (before 5.6)
362
-
363
- = 3.9.1 =
364
- * Fixed a bug related to the stock information not syncing correctly across translations
365
- * Bug fix: and incorrect value for products out of stock was show on the dashboard
366
- * Bug fix: the link to edit custom prices was not working for variations
367
-
368
- = 3.9 =
369
- * Added compatibility with WooCommerce 2.7 (orders, coupons etc...)
370
- * Included the custom taxonomies associated with products in the WooCommerce Multilingual menu
371
- * Added the possibility to translate the attribute slugs
372
- * Added possibility to include some HTML tags in the currency switcher
373
- * Added the option to show the cart total in the currency switcher
374
- * Import payment methods translations from mo files upon activation
375
- * Many usability improvements
376
- * Moved the WooCommerce Multilingual submenu under the WooCommerce menu
377
- * Added two new subsections to the Status section: products and multi-currency
378
- * Bug fix: table Rates labels were not showing up on the cart page when WCML was active
379
- * Bug fix: the currency order preview was not including the newly added currencies
380
- * Bug fix: number of untranslated terms was sometimes wrong in the Status area
381
- * Bug fix: in some cases a variation description field showed up twice in the Translation Editor
382
- * Bug fix: orders showed the attributes slugs instead of names
383
- * Bug fix: for products without prices (no purchase button), the translations were showing up as 'Free' (with purchase button)
384
- * Fixed a compatibility issue with WooCommerce Bookings: custom prices were not displayed correctly in the second currency
385
- * Added fixed to the compatibility class for WooCommerce Tab Manager
386
- * Fixed a compatibility problem with the recent version W3TC related to the currency switcher
387
- * Fixed compatibility issues with WooCommerce Product Add-ons
388
-
389
-
390
- = 3.8.6 =
391
- * Fix shipping cost conversion issue specific to PHP 5.6
392
- * Bug fix: an incorrect shipping cost was displayed on the backend when the order was placed in a secondary currency
393
- * Bug fix: users with the Shop Manager role were not able to translate products
394
- * Bug fix: changing an order language in the backend did not change the language for attributes in the order
395
- * Bug fix: for every e-mail action took when editing an order a new order e-mail was sent to the admin
396
-
397
- = 3.8.5 =
398
- * Fixed more problems related to converting shipping costs in secondary currencies
399
- * Fixed one compatibility problem with WooCommerce Show Single Variations
400
- * Bug fix: product translations were not synchronized correctly when marking an existing product as a translation of another one
401
- * Bug fix: variation names not displayed in tooltips on the orders screen in the backend
402
- * Updated the wpml-config.xml configuration file: copy prices to product translations also when multi-currency is not on
403
- * Other small fixes for the admin interface
404
-
405
- = 3.8.4 =
406
- * Bug fix: minimum required amount was not calculated correctly for secondary currencies (not included in the previous version)
407
-
408
- = 3.8.3 =
409
- * Added improvements to the Translation Editor for translating custom fields for products and variations
410
- * Added access for translator subscribers to translate content
411
- * Fixed compatibility issues with WooCommerce Visual Products Configurator (wrong amount in cart)
412
- * Fixed a compatibility issue with WooCommerce Product Addons (untranslated labels)
413
- * Fixed compatibility issues with WooCommerce Composite products
414
- * Fixed some new compatibility issues with WooCommerce Bookings
415
- * Bug fix: when using language as parameter and the 'dropdown' option was used for the product categories widget, translated urls were not working
416
- * Bug fix: shipping costs were not showing on the secondary languages in some cases
417
- * Bug fix: the shipping costs were not calculated correctly for currencies using less decimals than the default currency
418
- * Bug fix: adding a product to the cart and then adding its translation too could lead to a fatal error
419
- * Bug fix: switching the language on the cart page when using different domains for different languages was emptying the cart
420
- * Bug fix: minimum required amount was not calculated correctly for secondary currencies
421
- * Bug fix: incorrect currency symbol was displayed on the 'Filter by Price' widget
422
-
423
- = 3.8.2 =
424
- * Bug fix: cart strings not displaying in the correct language in some conditions
425
- * Bug fix: prices in secondary currencies were not updated on the front end after changing the price (the cache was not invalidated)
426
- * Bug fix: shipping classes were not synchronized for translated products in some circumstances
427
- * Bug fix: translated endpoints were missing from teh rewrite rules after updating the permalinks
428
- * Bug fix: stock status was sometimes not synchronized correctly when changing the stock manually
429
- * Bug fix: when using the default category base the language switcher did not show translated urls on the front end
430
- * Updated the cart cache hashes logic according to new WooCommerce logic
431
- * Added a new filter: 'wcml_product_custom_prices'
432
- * Added separate section for translatable fields for external products in the translations editor
433
- * Fixed compatibility issues with WooCommerce Table Rate Shipping 3.0+
434
- * Fixed one compatibility issue with WooCommerce Dynamic Pricing: the discount was not shown on the mini-cart
435
- * Fixed compatibility with Product Add-ons: strings were not translated
436
-
437
- = 3.8.1 =
438
- * Fixed one compatibility issue with WooCommerce Ajax Cart: cart quantities were not updating
439
- * Fixed one compatibility issue with WooCommerce Bookings: incorrect bookings were shown in the backend when toggling between admin languages
440
- * Fixed one compatibility issue with the Adventure Tours theme
441
- * Fixed one compatibility issue with the Aurum theme
442
- * Fixed compatibility issues with the Composite Products plugin
443
- * Bug fix: auto-generated slugs on the products translation editor were not made unique
444
- * Bug fix: sometimes prices with decimals were subtracted 0.01
445
- * Made translation controls on the WooCommerce products page disabled by default
446
- * Optimized autoloading of PHP classes for better performance
447
-
448
- = 3.8 =
449
- * A new design, a new look and feel complementing the new WPML 3.4
450
- * A new translation editor for the products
451
- * New options for translating product attributes
452
- * An enhanced and dedicated configuration screen for multi-currency
453
- * Easier translation of URLs
454
- * Immediate attention to configuration issues on the Status page
455
- * Improved support for the WooCommerce REST API
456
- * Straightforward setup wizard to run WooCommerce Multilingual
457
- * Bundled Installer makes it effortless to add in the required plugins
458
- * Option for downloadable products to share files under each product
459
- * Other price types can be set custom values for secondary currencies
460
- * Translating WooCommerce email strings also got simpler
461
- * Numerous bug fixes and enhancements
462
-
463
- = 3.7.16 =
464
- * Compatibility with WooCommerce 2.6 (woocommerce_term_meta tables removed)
465
- * Fixed a compatibility issue with WooCommerce Table Rate Shipping (shipping class not showing on secondary language)
466
- * Bug fix: Translated shipping classes were sometimes not displayed for secondary languages
467
- * Bug fix: WooCommerce Booking & Appointments causes Fatal Error when Translation Management
468
- * Bug fix: Yoast custom fields were not shown in the translation editor
469
-
470
- = 3.7.15 =
471
- * Fixed a problem with BACS payment gateway strings not being translated in order confirmation page
472
- * Fixed some compatibility issues with WooCommerce Tab Manager
473
-
474
- = 3.7.14 =
475
- * Fixed a problem introduced in the previous version: Mollie payment methods not working when using the 'Mollie Payments for WooCommerce' plugin
476
-
477
- = 3.7.13 =
478
- * Bug fix: When adding a global attribute inline while creating a product in a secondary language, the term was created in the wrong language
479
- * Fixed a compatibility issues with WooCommerce Tab Manager: fatal error when trying to translate a product
480
- * Fixed another compatibility issues with WooCommerce Tab Manager: when a product had only a global tab, the translated tab didn't show up on the translated product
481
- * Improvements for how the gateways strings are registered for translation
482
- * Updated logic for registering and translating Shipping zones and methods according to changes in WooCommerce 2.6
483
-
484
- = 3.7.12 =
485
- * Fixed a bug that made the shop pages return 404 errors on WordPress 4.5
486
- * Fixed warnings caused by terms translated before the WooCommerce Multilingual activation
487
- * Bug fix: WooCommerce Multilingual locales for secondary languages were not loaded correctly
488
-
489
- = 3.7.11 =
490
- * Bug fix: the downloadable products were not synced properly with their translations
491
- * Bug fix: the confirmation for installing WooCommerce translations for the secondary languages was not saved
492
- * Bug fix: The option to "Show only products with custom prices in secondary currencies" was not working well for variable products
493
- * Bug fix: saving custom prices when creating a new product didn't work
494
- * Removed backward compatibility with WooCommerce versions older than 2.1
495
- * Small compatibility fixes for the upcoming WordPress 4.5
496
- * Fixed a problem with the pagination on the products list page under the WooCommerce Multilingual section
497
-
498
- = 3.7.10 =
499
- * Fixed a small issue with the product translations editor (additional toolbar showing)
500
- * Fixed a compatibility issue with Memcached on Siteground: product category archive pages were returning 404
501
- * Bug fix: the price widget was not using the correct values with multi-currency mode on
502
- * Bug fix: in some cases the costs for International Shipping were not calculated correctly in the secondary languages
503
- * Bug fix: When using comma for a decimal separator, for custom prices, the rounded values were not determined correctly
504
- * Bug fix: In some cases, translated product variations were displayed as 'out of stock' on the front end.
505
- * Fixed a fatal error occurring when selecting the WPML admin language to 'All languages' on the WooCommerce settings page
506
- * Compatibility with WooThemes Mix and Match Products
507
- * Fixed a bug preventing a shipping to be set to a variation when the default language of the product was not English
508
- * Fixed a bug that was sometimes preventing the 'incl. vat' suffix to be displayed on prices
509
- * Fixed a compatibility issue with Gravity Forms Product Add-Ons
510
-
511
- = 3.7.9 =
512
- * Fixed an issue prevent the correct plugin activation in some cases
513
- * Fixed an issue potentially causing uncatched errors when using some specific payment gateways
514
-
515
- = 3.7.8 =
516
- * Updated the logic for downloading WooCommerce translations from translate.wordpress.org
517
- * Compatibility with WooCommerce Bookings 1.9 (and fixed othe small compatibility issues with older versions)
518
- * Fixed a compatibility issue with WooCommerce Subscriptions: the sign-up fee was not correct in the 2nd currency
519
- * Fixed a compatibility issue with WooCommerce Subscriptions: a fatal error was triggered during the checkout process in some circumstances
520
- * Fixed other compatibility issues with WooCommerce Subscriptions: endpoints, incorrect signup fee in secondary currency
521
- * Fixed a compatibility issue with WooCommerce Payment Gateways: some strings were registered/changed when on checkout
522
- * Bug fix: variations created with Any were not showing the user selected attribute when added to the cart
523
- * Bug fix: it was not possible to changeor or set the "Set prices in other currencies manually" option for a duplicate product
524
- * Fixed a compatibiilty issue with WooCommerce Bulk Stock Management (the 'out of stock' flag was not synced)
525
- * Bug fix: private products were visible to all users on grouped products
526
- * Bug fix: the tax label could register in the wrong language sometimes and then it was not possible to translate it correctly
527
- * Bug fix: partial the subject and heading for the refund emails were not translated when sent to users who had placed orders in secondary languages
528
-
529
- = 3.7.7 =
530
- * Fixed an issue that was causing a fatal error for sites using the Flatsome theme
531
- * Fixed an issue with translating standard tax rate name
532
- * Fixed an issue with product categories widget
533
- * Fixed issue with variable products in cart ( local attributes not translated after switching language )
534
- * Added filter for _load_filters function in multi-currency class
535
- * Set variations as translatable post type
536
-
537
- = 3.7.6 =
538
- * Fixed several problems with the permalinks when using the slash character in the bases
539
- * Fixed an issue with coupons: the coupons were not applied according to the minimum amount of the cart in the current currency
540
- * Fixed one compatibility issue with the Flatsome theme
541
- * Fixed a bug preventing the shop page link to be translated correctly to the other languages (when using WPML 3.3.1+)
542
-
543
- = 3.7.5 =
544
- * Fixed a backward compatibility with WPML versions prior 3.2 (causing fatal error)
545
- * Bug fix: in some specific cases variations were not created correctly - 'Any %name%' instead of term value
546
- * Bug fix: updating a product for which attached media had been deleted caused a warning (WooCommerce issue: 9681)
547
- * Fixed an issue with completing PayPal payments when using the default permalinks and the language as a parameter in the urls
548
- * Fixed an issue with order notes in the WP admin: 'array' was displayed instead of the actual note
549
-
550
- = 3.7.4 =
551
- * Fixed a problem with the previous version that caused a fatal error when upgrading
552
-
553
- = 3.7.3 =
554
- * Added support for translating custom attributes (for variations) via the professional translation
555
- * Added support for translating products tab information (WooCommerce Tab Manager) via the professional translation
556
- * Added support for translating persons and resources (WooCommerce Bookings) via the professional translation
557
- * Added support for translating products bundle data (WooCommerce Product Bundles) via the professional translation
558
- * Added extended compatibility and support for professional translation for WooCommerce Composite Products
559
- * Bug fix: it was not possible to set a product translation as draft when the original was published
560
- * Bug fix: in some cases the product categories hierarchy (and count) was not sycned across translations
561
- * Bug fix: the custom title and description of a bundle of a translated product was removed after updating the original product
562
- * Bug fix: custom fields that did not have any translation preference were wrongfully copied across translations
563
- * Bug fix: multi-currency was not working properly for product variations when the "Show only products with custom prices in secondary currencies" option was on
564
- * Fixed an important compatibility issue with Yoast SEO (fatal error when using Yoast SEO 3.0+)
565
- * Bug fix: wcml_check_on_duplicate_products_in_cart was incorrectly duplicated specific items in the cart
566
-
567
- = 3.7.2 =
568
- * Added synchronization for the 'featured' flag (star) for products across translations
569
- * Fixed one compatibility problem with WooCommerce Bookings: bookings were not filtered by language on the front end
570
- * Fixed one compatibility problem with WooCommerce Composite Products (causing a fatal error when viewing a composite product)
571
- * Bug fix: in some cases the cart total in a secondary currency was wrongfully rounded instead of showing the decimals
572
- * Bug fix: translated products were not published on the same schedule when using the future publishing
573
- * Bug fix: in some situations variations could not be created for a variable product with global attributes that contained special characters
574
- * Bug fix: wrong currency was used in an order when the currency was changed while placing the order and checkingout with Paypal
575
- * Bug fix: the relationship of a duplicate product with the original was lost when the original was updated.
576
-
577
- = 3.7.1 =
578
- * Compatibility fixes for WooCommerce Bookings and WooCommerce Composite Products
579
- * Fixed a typo in a function that caused a fatal error
580
-
581
- = 3.7 =
582
- * Added support for strings in different languages. Translated strings are not required to be in English (Requires WPML 3.3+)
583
- * Fixed a compatibility issue with WooCommerce Bookings: bookings in all languages showing on calendar (requires WooCommerce Bookings 1.8+)
584
- * Fixed a compatibility issue with WooCommerce Bookings: deleting a reservation did not delete translations too (requires WooCommerce Bookings 1.8+)
585
- * Fixed a PayPal checkout issue when multi-currency was enabled and the decimal separator was set to comma and thousands separator was set to dot
586
- * Fixed a compatibility issue with WooCommerce Product Addons: adding a second item for the same product added the first product again too
587
- * Bug fix: a slash character was missing the in product breadcrumb when the translated page slug was identical to the one in the default language
588
- * Bug fix: incorrect cost for the flat rate shipping was displayed in certain circumstances
589
- * Improved compatibility with Gravity Forms Product Addons for translating the cart data
590
- * Removed a deprecated hook used for the compatibility with WooCommerce Subscriptions
591
- * Bug fix: cart_widget.js code was loaded in places that it wasn't needed
592
- * Bug fix: in a specific case, the price in a secondary currency was not displayed correctly (the amount in the original currency was displayed)
593
- * Bug fix: content was disappearing when switching between the visual and text editors on the product translation editor
594
- * Bug fix: when using attributes that were numeric values a catchable fatal error was triggered
595
-
596
- = 3.6.11 =
597
- * Fixed one issue that was causing a fatal error when an older version WPML was used (3.1.9.7)
598
-
599
- = 3.6.10 =
600
- * Bug fix: Custom prices for variations were not saved when clicking the 'Save changes' button
601
- * Bug fix: Pagination was not working for a category having the term id equal to the id of the account page
602
- * Bug fix: 'Shop' was appearing two times in the breadcrumbs when using the shop base + category for a product url base
603
- * Bug fix: Fixed one issue with WooCommerce Bookings - adding two separate bookings to the cart showed as one item instead of two
604
- * Bug fix: The products menu order was not synced in some situations
605
- * Fixed a compatibility issue with the Peddlar theme
606
- * Fixed a styling issue on the custom prices section for product variations
607
- * Updates for the compatibility with WooCommerce Product Bundles from the plugin author
608
- * Bug fix: Sometimes it was not possible to enable the slug translation for a custom post when WooCommerce Multilingual was active
609
-
610
- = 3.6.9 =
611
- * Bug fix: Prices for variable products were not converted correctly when using multiple currencies after the WooCommerce 2.4 update
612
- * Bug fix: Variations translations were not created when using custom attributes with space characters in them
613
- * Bug fix: When the option to show only products with custom prices in the secondary currencies was on, no products were displayed
614
- * Changed the order in which the products are displayed on the WooCommerce Multilingual products editor: chronological DESC
615
-
616
- = 3.6.8 =
617
- * Added a series of compatibility fixes for WooCommerce 2.4.x (custom attributes, endpoints)
618
- * Bug fix: Incorrect prices were calculated for Table Rate Shipping (bug originally fixed in version 3.6.5)
619
- * Bug fix: WooCommerce Bookings - when you deleted a booking from the backend, the calendar on the front end did not update
620
- * Bug fix: WooCommerce Bookings - translations of a booking post were not deleted when the original post was deleted
621
- * Bug fix: WooCommerce Bookings - booking product appeared multiple times in the cart in some cases
622
- * Bug fix: WooCommerce Bookings - when a booking product was created from the backend, multiple posts were created in some cases
623
- * Bug fix: 'Stock Qty' field was not locked in the translated variations section
624
-
625
- = 3.6.7 =
626
- * Bug fix: Converted prices in secondary currencies were incorrect in some situations. e.g. For VND with an VND:EUR exchange rate of 30,000:1
627
- * Bug fix: Wrong urls were displayed in the language switcher for product category or product tag urls
628
-
629
- = 3.6.6 =
630
- * Fixed a bug that was causing a PHP warning when using a WPML version prior 3.2
631
-
632
- = 3.6.5 =
633
- * Enabled the WooCommerce Bookings compatibility support
634
- * Bug fix: Fixed a bug that caused a wrong price to be displayed when adding a product in the cart from two different languages
635
- * Bug fix: After a product translation was edited in the standard product editor, the WooCommerce custom attribute translations were lost
636
- * 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
637
- * Bug fix: Some product translations were showing non existing discounted prices
638
- * Fixed a couple of compatibility issues with WooCommerce Product Bundles (e.g. with using the Flatsome theme)
639
- * Fixed a small usability issue related to Sensei
640
- * Bug fix: Stock quantity not synchronized when items were used in orders created in the backend
641
- * Bug fix: Payment gateways strings were not registered for string translation
642
- * Bug fix: Global Attributes were not translated in the WooCommerce Mail
643
- * Bug fix: In some cases the WooCommerce endpoints were not translated correctly
644
- * Bug fix: An extra 'a' tag was added to products in the mini-cart
645
- * Bug fix: A 404 error was returned on the translated product category archive page
646
- * Bug fix: Some shipping methods were displayed incorrectly on the cart page when using Table Rate Shipping
647
- * Bug fix: In some cases prices showing the Paypal order summary included decimals even if the prices were supposed to be rounded to integers
648
- * Bug fix: When adding different variations of a product, a single variation was added more times
649
- * 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
650
- * Bug fix: In some cases some email notification strings were not registered
651
- * 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
652
-
653
- = 3.6.4 =
654
- * Bug fix: Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM (introduced in 3.6.1)
655
- * Bug fix: In some conditions it was not possible to load product pages in other languages than the default.
656
- * Bug fix: Fixed some compatibility issues with Product Bundles
657
-
658
- = 3.6.3 =
659
- * Fixed a bug causing a PHP warning when using an older version of WPML String Translation
660
-
661
- = 3.6.2 =
662
- * Bug fix: A product could appear multiple times in the cart when added in different languages
663
- * Bug fix: Product attribute labels translations were not showing on the frontend in some circumstances
664
- * Bug fix: Attributes labels translations not showing on the 'Add product' admin panel
665
- * Bug fix: The flags for custom languages were not showing correctly on the products editor screen
666
- * Bug fix: The currency switcher was missing from the WooCommerce Status dashboard widget (in version 3.6.1)
667
- * Bug fix: The auto-adjust ids functionality from WPML was not working with wc_get_product_terms
668
- * Bug fix: The 'shop' link was stripped out of the breadcrumb in the Woocommerce product page.
669
- * Bug fix: The product category template was not working correctly in secondary languages
670
- * Bug fix: Fixed a problem with sanitize_title for variations in Danish and German
671
- * Moved the Tab manager settings to separate file from the WCML config
672
- * Duplicates for media are now being created, if missing, when product translations are created.
673
- * 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.
674
-
675
- = 3.6.1 =
676
- * Updated the taxonomy translation synchronization to be compatible with WPML 3.2
677
- * 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.
678
- * 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.
679
- * Bug fix: an incorrect currency was being passed to the payment gateway when paying for an order created in the backend.
680
- * Bug fix: the prices in the custom currencies were not saved when a product was published.
681
- * Bug fix: extra backslashes were added when translating custom attribute name in products.
682
- * Bug fix: custom product categories template was not working as expected
683
- * Bug fix: updating WordPress language packs was not working when using custom locale codes in WPML
684
- * Bug fix: Variable products returned error in secondary language "This product is currently out of stock and unavailable."
685
- * Bug fix: The publishing date was not updating on translation when changed on the product in the original language
686
- * Bug fix: Attributes with the value "0" value were not displayed on the front end
687
- * Bug fix: Modified Free shipping label could not be translated
688
- * Bug fix: When editing product translations it was possible to save an empty slug.
689
-
690
- = 3.6 =
691
- * Added the ability to edit the slugs of the translated products in the products editor
692
- * Added the option to show only products with custom prices on the front end
693
- * Performance improvements: fewer db queries, caching. Up to 40% faster on large sites.
694
- * Support for the 'lang' parameter in WooCommerce REST API calls
695
- * Option to hide the default currency selector on the product page
696
- * Bug fix: Fixed a design issue on the 'connect with translation' pop-up on products.
697
- * Bug fix: Accessing the source content in the WooCommerce Multilingual product translation content editor was not possible sometimes.
698
- * Bug fix: 'Invisible' products were showing as links in the cart instead of just names.
699
- * Bug fix: The cart_widget.js code was always loaded.
700
- * Bug fix: Screen Options & Check All not working on WooCommerce Orders page
701
- * Bug fix: Sometimes the IPN Url sent to Paypal was wrong causing a 404 error after the payment was complete
702
- * Bug fix: Translated endpoint pages were sometimes returning 404
703
- * Bug fix: When using a default language different than English, the product permalink base was not in English.
704
-
705
- = 3.5.5 =
706
- * Bug fixed: Custom attributes were disappearing after updating a product in the WooCommerce native product editor
707
- * Tested compatibility with WordPress 4.2
708
- * Security review and fixes
709
- * Made the key "woocommerce_cancelled_order_settings" translatable
710
- * Email heading and subject sent after placing an order were not translated when using ‘Complete’ button on orders page
711
- * Bug fixed: warning about minimum order requirement always showing in some conditions when using a child theme
712
-
713
- = 3.5.4 =
714
- * Bug fixed: Can't access source content in WCML product translation table
715
- * Bug fixed: Custom Post Types leads to 404 error
716
-
717
- = 3.5.3 =
718
- * Bug fixed: Redirection issues with "Your latest posts" as a front page
719
- * Bug fixed: Yoast fileds not saved in WooCommerce Multilingual products table
720
- * Bug fixed: Translated endpoints returns page not found
721
- * Bug fixed: Custom fields are locked in variation section
722
-
723
- = 3.5.2 =
724
- * Compatibility with WooCommerce 2.3.x
725
- * Bug fixed: Redirection issues with "Shop" page as front page
726
- * Bug fixed: Language column was missing from the products list page
727
- * Bug fixed: Product tags disappeared after updating the product attribute 'size'
728
- * Bug fixed: Featured image title and text were not editable in the WooCommerce Multilingual Translation Table
729
- * Bug fixed: Only first three attributes were available for translation
730
- * Bug fixed: The shipping fee was not converted correctly when using the multi-currency mode
731
- * Bug fixed: The default currency configuration (decimal & thousand separator) was ignored when the multi-currency was active
732
- * Bug fixed: Subsequent request to product preview page lead to a 404 page.
733
- * Bug fixed: 'Insert link' button on the visual editor of the products translations screen was not working.
734
- * Bug fixed: Fixed another compatibility problem with WooCommerce Product Tabs
735
- * Bug fixed: A variable product was showing an incorrect price in the cart
736
- * Bug fixed: The flat rate shipping was showing the wrong price on the checkout page in certain conditions
737
-
738
- = 3.5.1 =
739
- * Bug fixed: Performance issue with queries number
740
-
741
- = 3.5 =
742
- * Added support for creating products in secondary languages only.
743
- * Added enhancements for the Woocommerce Multilingual products table (filter by original language, display language flag).
744
- * Added option to synchronize the products and product taxonomies order.
745
- * Bug fixed: The cart was not updating quantities for variable product (when have more than one variable in the cart).
746
- * Bug fixed: The cart total was not updating when using get_cart_total() and get_cart_subtotal() functions in other plugins or themes.
747
- * Bug fixed: Wrong price format and order total were displayed on the new order page in the WP admin
748
- * Bug fixed: The featured image and the gallery images were overridden when updating translations
749
- * Bug fixed: Fixed the 'Keep' option that allows keeping the same currency on teh front end, when switching the language.
750
- * Bug fixed: Fixed a javascript error that was showing when changing currencies order
751
- * Bug fixed: The decimal number was not working correctly for the default currency
752
- * Bug fixed: Fixed a compatibility problem with WooCommerce Product Tabs
753
- * Bug fixed: A coupon was applied incorrectly to all products in the cart when they were defined for specific product variations.
754
- * Bug fixed: WooCommerce note email language was not correct
755
- * Bug fixed: WooCommerce reports were showing duplicate products
756
- * Bug fixed: When using WordPress in a folder, the checkout showed an 'expired session' error message.
757
- * Added support currency argument in raw_price_filter
758
-
759
- = 3.4.3 =
760
- * Bug fixed: Incorrect decimal separator for prices on WordPress admin
761
- * Bug fixed: ‘Insert link’ button not working on products translator interface.
762
- * Bug fixed: Switching currency after adding to cart was adding an additional item
763
- * Bug fixed: Review setting not preserved on translation of variable product
764
- * Bug fixed: “Visible on the products page” option for product attributes was still selectable for product translation.
765
- * Bug fixed: Translation status icon not updated on products translator page
766
- * Bug fixed: Shipping rate was lost when WPML is activated
767
- * Bug fixed: WooCommerce ‘sort by’ links going to blog not products
768
- * Bug fixed: Option to select currency position was missing immediately after a new currency was added
769
-
770
- = 3.4.2 =
771
- * Accommodated taxonomy translation changes in WPML
772
-
773
- = 3.4.1 =
774
- * Bug fix: A variable product was somtimes breaking the shopping cart
775
- * Fixes added for translating custom fields that are textareas
776
-
777
- = 3.4 =
778
- * Additional support for updating the WooCommerce translations.
779
- * Added currency switcher for the WooCommerce status widget on the WordPress admin dashboard.
780
- * Usability fixes for the translation of custom attributes in the WooCommerce native editor.
781
- * Added validation for the sale amount when using custom prices with multi-currency.
782
- * Bug fixed: Incorrect currency symbol position on edit order page.
783
- * Bug fixed: Incorrect currency displayed for order when editing an order in the backend.
784
- * Bug fixed: Coupon option 'Exclude sale items' was not being applied correctly. Sale items were not excluded.
785
- * Bug fixed: Currency switcher widget was not showing under the available widgets list in the backend.
786
- * Bug fixed: The breadcrumbs structure dropped the shop page when WooCommerce Multilingual was activated.
787
- * Bug fixed: Manually adding a product to an order is not taking a custom price (secondary currency) if set.
788
- * Bug fixed: Error when trying to add a category when “All languages” was selected in the admin language switcher.
789
-
790
- = 3.3.4 =
791
- * Fixed bug related to back-compatibility with WooCommerce versions < 2.2.*
792
-
793
- = 3.3.3 =
794
- * Compatibility with WooCommerce 2.2.x
795
- * Auto-download WooCommerce translations for active and new languages
796
- * Page titles translations for WooCommerce pages taken from WooCommerce Multilingual .mo files
797
- * 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)
798
- * Added warning message on settings page when product base not translated to all languages
799
- * Fixed: Base currency format ignored after adding additional currency
800
- * Fixed: Shipping class names were displayed wrong on the WooCommerce settings page when switching the admin language
801
- * Fixed: WooCommerce pages were not working correctly after changing the default language
802
- * Fixed: WooCommerce native interface doesn't copy the variations prices
803
-
804
- = 3.3.2 =
805
- * Fixed: 'Language warning' appears when editing product translations using the native WooCommerce editor
806
- * Fixed: Variation cannot be added to an existing order
807
- * Fixed: Media Attachment controls for products missing
808
- * Prevented disabling of option to use slugs in different language for products
809
- * Fixed: Slashes not stripped correctly in product translation editor
810
- * Fixed: 'Copy content' button not working on product translations
811
- * Disable admin language switcher on the Product => Attributes screen
812
- * Allow 'woocommerce_price_display_suffix' to be translated with String Translation
813
- * Allow 'woocommerce_email_from_name' and 'woocommerce_email_from_address' to be translated with String Translation
814
- * Fixed: Menu order is not synced when using "drag and drop" in Products => Sort Products
815
- * Fixed: One WooCommerce attribute field won't translate
816
- * Fixed: Variations not showing in the correct language in some circumstances
817
- * Optimizations for the WooCommerce Multilingual products admin page - faster when a large number of products exist
818
- * Duplicate translations too when duplicating a WooCommerce product
819
- * Fixed: WC Price Filter showing the wrong currency
820
- * Ability to use any currency when creating an order in the backend.
821
-
822
- = 3.3.1 =
823
- * Some strings were showing in the wrong language on the cart and checkout page.
824
- * Product category urls - in some cases the product category urls didn�t work on sites with the default language different than English.
825
- * Products gallery images synchronization - sometimes, when synchronizing products "gallery images" and categories, the result was not updated correctly on the Troubleshooting page
826
- * Fixed issues related to WooCOmmerce Dynamic Pricing
827
- * Supoprt for translating WooCommerce 2.1+ endpoints
828
- * 'Continue Shopping' button pointing to the wrong url
829
- * Problem with short links
830
- * Fixed some issues with Table Rate Shipping
831
-
832
- = 3.3 =
833
- * Performance improvements: optimized database queries
834
- * Support rounding rules for converted prices
835
- * More advanced GUI for Multi-currency options
836
- * GUI for currency switchers (including widget)
837
- * Added option to synchronize product category display type & thumbnail
838
- * Performance improvement for WCML_Terms::translate_category_base (avoid switching locales)
839
- * Send admin notifications to admin default language
840
- * Dependencies update: WooCommerce Multilingual requires WPML 3.1.5
841
- * Set language information for existing products when installing WCML the first time.
842
- * Do not allow disabling all currencies for a language
843
- * Removed �clean up test content� and �send to translation� dropdown on products editor page
844
- * Message about overwritten settings in wpml-config made more explicit
845
- * Lock �Default variation� select field in product translations
846
- * After change shipping method on cart page we will see not translated strings
847
- * Fixed bug related to shipping cost calculation in multi-currency mode
848
- * With php magic quotes on, products translations with quotes have backslashes
849
- * Bug related to translation of grouped products � simple product not showing up on front end
850
- * Stock actions on the order page don�t work correct with translated products
851
- * For Orders save attributes in default language and display them on order page in admin language
852
- * Attribute Label appearing untranslated in backend order
853
- * Memory issues on the Products tab when we have a large number of products
854
- * �product-category� not translated in the default language.
855
- * �WCML_Products� does not have a method �translated_cart_item_name�
856
- * Order completed emails sent in default currency
857
- * Language suffix (e.g. @en) not hidden for product attributes on the front end
858
- * Quick edit functionality issues fixed
859
- * Fixed �Call to undefined method WC_Session_Handler::get()�
860
- * Fatal error when updating the order status to �complete�
861
- * Currency is not converted when you switch language until you refresh the page.
862
- * �Super Admin� not able to see the WCML menu
863
- * Checkout validation errors in default language instead of user language
864
- * Fixes for compatibility with Tab manager: Can�t translate �Additional Information� tab title
865
- * Bug: SEO title & meta description changed to original
866
- * Bug: 404 on �view my order� on secondary language using �language name added as a parameter�
867
- * Bug: Permalink placeholders appear translated when using default language different than English
868
- * Fixes for compatibility with Table Rate shipping: shipping classes not decoded correctly in multi-currency mode
869
- * Bug: �show all products� link on WCML products page points to the wrong page � no products
870
- * 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
871
- * Bug fixes related to File paths functionality (WooComemrce 2.1.x)
872
- * Bug: Product parents not synced between translations (grouped products)
873
- * Bug: Grouped products title incomplete
874
- * Bug: Db Error when saving translation of variable products with custom attributes
875
- * Bug: WooCommerce translated product attributes with spaces not showing
876
- * Bug: Deactivated currency still appears if you maintain the default currency for that language to �Keep�.
877
- * Bug: Incorrect shipping value on translated page
878
- * Bug: Reports for products including only products in the current language (WooCommerce 2.1.x)
879
- * Bug: WooCommerce translated product attributes with spaces not showing
880
- * Bug: Problems creating translations for shop pages when existing pages were trashed
881
- * Bug fix: Fatal error when Multi-currency is not enabled and �Table Rate Shipping� plugin is active
882
- * Fixed bug in compatibility with Tab Manager
883
- * Bug fix: Cart strings falling to default language after updating chosen shipping method
884
- * Bug fix: Reports not including selected product/category translations
885
-
886
-
887
- = 3.2.1 =
888
- * Fixed bug related to product category urls translaiton
889
- * Fixed bug related to back-compatibility with WooCommerce 2.0.20
890
-
891
- = 3.2 =
892
- * Compatibility with upcoming WooCommerce 2.1
893
- * Multi-currency support: configure currencies per languages
894
- * Multi-currency support: custom prices for different currencies
895
- * Support translation for the attribute base (permalinks)
896
- * Bug: Emails not sent in the correct language when uses bulk action on orders list page
897
- * Bug: Order notes email in wrong language in certain circumstances
898
- * Bug: Shipping method names are being registered in the wrong language
899
- * Bug: WooCommerce Multilingual menu doesn't display for translators
900
- * Bug: Using 'category' for products cat slug conflicts with posts 'category'
901
- * Bug: Paypal rejects payments with decimals on certain currencies
902
-
903
- = 3.1 =
904
- * Support for multi-currency (independent of language) BETA
905
- * Support for translating products via ICanLocalize (professional translation)
906
- * Option to synchronize product translation dates
907
- * Compatibility with Table Rate Shipping and other extensions
908
- * Better handling for couponse
909
- * Fixed bug: product attributes not saved on orders
910
- * Fixed bug: Can't get to the cart & checkout pages if they are set as child pages
911
- * Fixed bug: Style conflicts in Dashboard for Arabic
912
- * Fixed various issues with notification emails
913
- * Fixed bug: Variable products default selection is not copied to translations.
914
- * Fixed bug: Product Table is not showing Product Draft count
915
-
916
- = 3.0.1 =
917
- * Replaced deprecated jQuery function live()
918
- * Fixed bug: language names not localized on products editor page
919
- * Fixed bug: Can't set "Custom post type" to translate
920
- * Fixed bug: Translation fields not visible - In certain circumstances (e.g. search) the translation fields corresponding to the translated languages were missing
921
- * Fixed alignment for �Update/Save� button in the products translation editor
922
- * Fixed bug: Default selection not copied to duplicate products
923
- * Fixed bug: Price doesn't change when change language on the cart page when set "I will manage the pricing in each currency myself"
924
- * Resolved one compatibility issue with Woosidebars
925
- * Direct translators to the products translation editor automatically (instead of the standard post translation editor)
926
- * Fixed bug: In some situations (different child categories with the same name) the wrong categories were set to a duplicated product.
927
- * Enhancement: Add icons for products in the products translation editor
928
- * Register WooCommerce strings (defined as admin texts in the wpml config file) automatically on plugin activation
929
- * WPML (+addons) - new versions required.
930
- * lcfirst is only available since php 5.3
931
- * Identify fields on known plugins and show their human name in our product translation table (support for WordPress SEO for now)
932
-
933
- = 3.0 =
934
- * Brand new GUI and workflow
935
- * Support for easy taxonomy translation
936
- * Variations synchronization
937
- * Product images synchronization
938
-
939
-
940
- = 2.3.3 =
941
- * Fix logout link not working in secondary language
942
- * Fix accepting orders in backend leading to 404
943
- * Set email headings & subjects as translatable
944
- * Set order language when sending order emails from admin
945
- * Sync product tags the same way as categories
946
- * Fix bug in ajax product search filter
947
- * Support for WooCommerce Brands extension (http://www.woothemes.com/products/brands/)
948
- * Initial support for Translation Editor
949
- * Fix bug with cart currency updates and variations
950
- * Fix language in new customer note notifications
951
-
952
- = 2.3.2 =
953
- * Sync also default options for custom attributes.
954
- * Global resync (done only once) of the orderings of product attribute values and categories across all languages.
955
- * Fixed a bug and a corner case in variation synchronization.
956
-
957
- = 2.3.1 =
958
- * Fixed incompatibility with PHP 5.2
959
-
960
- = 2.3 =
961
- * Refactor translation and currency conversion of products & variations in cart
962
- * A problem we had with shipping selection was resolved in WooCommerce itself
963
- * Improved synchronization of global product attributes, whether used for variations or not
964
- * Custom product attributes registered as strings when defined in the backend
965
- * Don't adjust the currency symbol in WooCommerce settings page
966
- * Term and product category order is synchronized among languages
967
- * Additional filters for WooCommerce emails
968
- * Fixed layered nav widgets in translated shop page
969
- * Synchronize Product Categories
970
-
971
- = 2.2 =
972
- * Price in mini-cart refreshed when changing language
973
- * Fix bug in multilingual currency setting that slipped in 2.1
974
-
975
- = 2.1 =
976
- * Add admin notices for required plugins
977
- * Add support for 'Review Order' and 'Lost Password' pages
978
- * Fix rounding issues in currency conversion
979
- * Variations: pick translated terms using 'trid' gives better results
980
- * Variations: sync to all languages when there are more than 2 languages
981
- * Improvement: load JS/CSS only when needed
982
-
983
- = 2.0 =
984
- * Fix variation sync to more than one language
985
- * Fix custom field sync for new variations
986
- * Fix rounding of amounts in PayPal
987
- * Adjust product stock sync to WC 2.x
988
- * Add automatic id translation of logout page
989
- * Adjust permalink warnings to WC 2.x
990
- * Clean up code
991
-
992
- = 1.5 =
993
- * Fixed manually setting prices in translated products.
994
- * Take advantage of WPML's new slug translation feature.
995
- * Added the possibility of translating custom attributes.
996
- * Improvements to product variation synchronization.
997
- * Fixed product stock sync for variable products .
998
- * Fix and improve checks made to incompatible permalink configurations.
999
- * Fix tax label translation when there is more than one of them.
1000
- * Send order notifications in the language the order was made.
1001
- * Removed several warnings and updated deprecated code.
1002
- * Cleanup language configuration file and add missing strings.
1003
-
1004
- = 1.4 =
1005
- * Allow translating the 'Terms & Conditions' page.
1006
- * Register shipping methods strings for translation.
1007
- * Register several tax-related strings for translation.
1008
- * Fix registration of payment gateway titles and descriptions.
1009
- * Synchronize the default attribute of a variable product across its translations.
1010
- * Allow saving WooCommerce/Settings while using a non-default language.
1011
- * Fix problems when the shop page is at the home page.
1012
- * Allow using Wordpress default permalink structure aswell.
1013
- * Fix amount sent to payment gateway when using multiple currencies.
1014
- * Fix for language switcher in shop pages (fixed in WPML)
1015
- * Fix for subscriptions module price not showing (fixed in WPML)
1016
- * Rewrite product variation sync: each variation is related to its translations, sync becomes easier
1017
- * Remove several PHP warnings and notices.
1018
- * Send order status update emails in the language the order was made.
1019
-
1020
- = 1.3 =
1021
- * Fixed all custom fields synchronization between translations
1022
- * Fixed the stock issue for translations
1023
- * Fixed the price filter widget for multiple currencies feature
1024
- * Fixed product duplication to a second language
1025
- * Payment gateways texts now are translatable
1026
- * Custom variables translations now will be shown in the correct language
1027
-
1028
- = 1.2 =
1029
- * Added helpful documentation buttons
1030
- * Added makes new attributes translatable automatically
1031
- * Added payment gateways translations
1032
- * Fixed order statuses disappeared in the orders page
1033
- * Fixed attributes translations in duplicated variations
1034
- * Fixed PHP warning when adding variations is in question
1035
-
1036
- = 1.1 =
1037
- * Added multi-currency feature
1038
- * Fixed synchronization of attributes and variations
1039
- * Fixed translation of attributes
1040
- * Fixed JS error in the checkout page
1041
- * Fixed enable guest checkout (no account required) issue
1042
- * Fixed Up-sells/Cross-sells search (showed all translated products)
1043
- * Fixed 'Show post translation link' repeating issue
1044
-
1045
- = 1.0 =
1046
- * Fixed 'Return to store' URL
1047
- * Fixed language selector for the translated shop base pages
1048
- * Fixed the product remove URL in the translated language
1049
- * Fixed the checkout URL in the translated language
1050
- * Fix to prevent incorrect product URL in the shop base page when the permalink is not 'shop'
1051
-
1052
- = 0.9 =
1053
- * First release
1054
-
1055
- == Upgrade Notice ==
1056
-
1057
- = 2.0 =
1058
- More variation fixes and compatibility with WooCommerce 2.x
1059
-
1060
- = 1.5 =
1061
- Variation translation works a lot better now. This version runs best with WooCommerce 1.6.6.
1062
-
1063
- = 1.4 =
1064
- This version runs with WooCommerce 1.6.5.x and 1.7.x. Recommeded WPML version is 2.6.2 and above.
1065
-
1066
- = 1.3 =
1067
- Fixed compatibility between WooCommerce 1.5.8 and WPML 2.5.2
1068
-
1069
- = 1.2 =
1070
- Added a few improvements and fixed bugs.
1071
-
1072
- = 1.1 =
1073
- Fixed a few bugs. Added multi-currency mode.
1074
-
1075
- = 1.0 =
1076
- Recommended update! Fixed a few bugs;
1077
-
1078
- = 0.9 =
1079
- * First release
5
  License: GPLv2
6
  Requires at least: 4.7
7
  Tested up to: 5.3
8
+ Stable tag: 4.7.5
9
  Requires PHP: 5.6
10
 
11
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
66
  * MySQL version 5.6 or later
67
 
68
  * WooCommerce 3.3.0 or later
69
+ * WPML Multilingual CMS 4.3.5 or later
70
+ * WPML String Translation 3.0.5 or later
71
+ * WPML Translation Management 2.9.1 or later
72
 
73
  = WordPress automatic installation =
74
  In your WordPress dashboard, go to the Plugins section and click 'Add new'.
137
 
138
  == Changelog ==
139
 
140
+ = 4.7.5 =
141
+ * Skip Currency Switcher caching for NginxCache.
142
+ * Improve performance on plugin page.
143
+ * Fixed missing products on shop page in second language for some themes when slug is identical to default language.
144
+ * Fixed wrong strings localization on some WooCommerce ajax actions.
145
+ * Fixed Cash on delivery "Payment method instructions" not translated in the customer order emails.
146
+ * Fixed RTL styling on WCML Status Tab.
147
+ * Fixed notice for Product-Addon and specific field settings.
148
+ * Composite products fixed a wrong displayed discounted price.
149
+ * Fixed not pre-selected custom attributes for variable Bundle product.
150
+ * Fixed missed images for product translation created via REST API.
151
+ * Added new setting option for synchronizing not translated media on translated product front page.
152
+ * Fixed not duplicated variation description while duplicating variable product to another language.
153
+ * Fixed not matched variation on translated variable product page when "Translatable - use translation if available or fallback to default language" mode enabled for products and global attribute terms are translated.
154
+ * Fixed overlapping columns on WooCommerce Order Statuses table.
155
+ * WooCommerce Bookings compatibility - fixed availability count duplication while updating original product and bookings were made in the second language.
156
+ * wcml_client_currency hook not applied in some cases
157
+ * Fixed variation product title modifying after switching language on cart page in specific situations.
158
+ * Fixed mixed strings language on variable product admin edit page in not admin language.
159
+ * Fixed performance when a large number of shipping methods are defined.
160
+ * Long query to get currencies removed from WCML to optimise performance.
161
+ * Fixed cart total shipping converted twice when enabled custom settings for gateways and use not default currency as a currency for gateway.
162
+ * Fixed converted product price when using custom gateway settings for second currency.
163
+ * Fixed notice while importing xliff translations with custom attributes in some specific cases.
164
 
165
  = 4.7.0 =
166
  * Replaced some Twig templates with pure PHP templates as the first step towards the removal of Twig dependencies.
167
+ * added comp. class to cover price update when products are edited with WOOBE plugin
168
  * Added compatibility class for WooCommerce order status Manager plugin
 
 
 
 
169
  * Fixed an issue where the strings for the default payment methods were not properly translated on the Checkout page.
 
 
170
  * Fixed an issue with the cache flush during language switching.
171
  * Fixed in the original ticket.
172
  * Fixed an issue where the gateway strings would always register in English instead of the site's default language.
173
+ * Fixed PHP Notice for WC Variations Swatches And Photos compatibility.
174
+ * WooCommerce Bookings compatibility : Fixed notice when trying to cancel booking.
 
 
 
 
175
  * Fixed an issue where the total price on the Composite product page was not rounded.
176
  * Fixed an issue causing wrong rewrite rules after saving the settings and visiting a page in a language other than the default.
177
  * Fixed an issue with incorrect price converting for the Product add-ons.
178
+ * Fixed an issue with the WooCommerce Subscriptions availability in the secondary language after purchasing the subscription in the original language.
179
  * Fixed an issue with the currency reverting to the default one during checkout.
180
  * Fixed removed meta from original product not synchronized to translation.
181
  * Fixed an issue where the BACS gateway instructions were not translated when re-sending the customer notification email from the admin.
182
  * Fixed an issue with missing language information for attribute terms that happened after changing the attribute slug.
183
  * Removed the Twig Composer dependency as it now relies on Twig from the WPML core plugin.
184
+ * Fixed an issue where customers would not receive notifications in the correct language.
185
  * Fixed an issue where the Products shortcode was not working in the secondary language.
186
+ * Fixed error while sending WooCoomerce Bookings email for bookings which didn't have orders assigned.
187
+ * Updated compatibility class for WC Checkout Addons
188
  * Fixed the images that were wrongly inserted in the translation job when attachments are not translatable.
189
  * Significantly improved the site performance on when updating the page, post, or a WooCommerce product page in the admin.
190
  * Added the "wp_" prefix to all cookies so that hosting and caching layers can properly handle them.
191
+ * Fixed a JavaScript error on the Store URLs tab.
192
+ * Fixed an issue where the "Fix translated variations relationships" troubleshooting option was removing translated variations.
193
+ * Fixed an issue where product names were not translated in the admin emails.
194
+ * Fixed an issue with the price filter widget not showing results in a secondary language.
195
+ * Fixed an issue where the shipping classes in secondary languages were not calculated during checkout.
196
  * Display larger images when hovering thumbnails in the WooCommerce Multilingual Products admin page.
197
  * Added the "wcml_new_order_admin_email_language" filter to allow setting the language of emails sent to admins for new or updated orders.
198
 
291
  * Fix small issue in product stock sync
292
  * Refund and restock - not working properly when refunding the variation in second language
293
  * WooCommerce Product Bundles -> original overwrites translation (visible when using title/description override)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
res/css/admin.css CHANGED
@@ -1 +1 @@
1
- .wcml-menu-warn{display:inline-block;color:#d54e21;line-height:15px;margin:1px 0 0 2px;z-index:26}a.wcml-external-link{padding-right:15px}a.wcml-external-link:after{content:"\f504";display:inline-block;width:15px;margin-right:-15px;font-size:14px;line-height:18px;font-family:dashicons;text-decoration:none;font-weight:normal;font-style:normal;vertical-align:top;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.wcml-pointer-inner .wcml-information-paragraph{padding-right:30px}.wcml-pointer-inner .wp-pointer-buttons{padding:0}.wcml-pointer-inner.wp-pointer-bottom .wp-pointer-arrow{left:auto;right:50px}.wcml-message-icon.wcml-table-cell,.wcml-message-content.wcml-table-cell{height:100px}.wcml-pointer-link{position:relative;text-decoration:none;padding:10px}.wcml-cart-dialog button{text-transform:capitalize}div[data-selector="woocommerce_table_rate_title"] a,div[data-selector="wpbody-content .woocommerce h2"] a{padding:10px 0 0 0}#shipping_rates .shipping_label .wcml-pointer-link{padding:0}.otgs-ico-ok:before{content:"\63"}.wcml-wrap .mouse-hovered{display: none; width: auto; max-width: 350px; height:auto; max-height:250px; position: absolute; z-index:10; border:solid 4px #999; background: #fff;}
1
+ .wcml-menu-warn{display:inline-block;color:#d54e21;line-height:15px;margin:1px 0 0 2px;z-index:26}a.wcml-external-link{padding-right:15px}a.wcml-external-link:after{content:"\f504";display:inline-block;width:15px;margin-right:-15px;font-size:14px;line-height:18px;font-family:dashicons;text-decoration:none;font-weight:normal;font-style:normal;vertical-align:top;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.wcml-pointer-inner .wcml-information-paragraph{padding-right:30px}.wcml-pointer-inner .wp-pointer-buttons{padding:0}.wcml-pointer-inner.wp-pointer-bottom .wp-pointer-arrow{left:auto;right:50px}.wcml-message-icon.wcml-table-cell,.wcml-message-content.wcml-table-cell{height:100px}.wcml-pointer-link{position:relative;text-decoration:none;padding:10px}.wcml-cart-dialog button{text-transform:capitalize}div[data-selector="woocommerce_table_rate_title"] a,div[data-selector="wpbody-content .woocommerce h2"] a{padding:10px 0 0 0}#shipping_rates .shipping_label .wcml-pointer-link{padding:0}.otgs-ico-ok:before{content:"\63"}.wcml-wrap .mouse-hovered{display:none;width:auto;max-width:350px;height:auto;max-height:250px;position:absolute;z-index:10;border:solid 4px #999;background:#fff}.wp-list-table.fixed .column-icl_translations{width:12%}
res/css/management.css CHANGED
@@ -1 +1 @@
1
- .wcml-wrap{border:1px solid #CCCCCC;padding:15px;background-color:#ffffff}.wcml-wrap:before,.wcml-wrap:after{content:" ";display:table}.wcml-wrap:after{clear:both}.dis_base{opacity:0.5}.display-block{display:block}.wcml-wrap{margin-bottom:20px}.wcml-wrap .wpml-tabs{margin-top:0}.wcml-wrap .otgs-ico-yes,.wcml-wrap .otgs-ico-ok{color:#51a351}.wcml-wrap .otgs-ico-no,.wcml-wrap .otgs-ico-warning,.wcml-wrap .otgs-ico-delete{color:#9d261d}.wcml-wrap .otgs-ico-edit{color:#3a87ad}.wcml-wrap .otgs-ico-in-progress{color:#ffb800}@media (max-width: 1199px){.wcml-wrap .tablenav.top{height:auto}.wcml-wrap .tablenav.top.wcml-product-translation-filtering .alignright,.wcml-wrap .tablenav.top.wcml-product-translation-filtering .alignleft{float:none;margin-bottom:5px}}[class*="otgs-ico"]:before{font-size:16px}.wcml-tabs:before,.wcml-tabs:after{content:" ";display:table}.wcml-tabs:after{clear:both}.wcml-tabs .nav-tab [class*="otgs-ico"]:before{font-size:18px}.wcml-tabs .nav-tab-active{background:#fff;border-bottom:none}.wcml-section{clear:both;padding:0 0 15px 0;margin:0 0 15px 0;border-bottom:1px solid #ededed}.wcml-section:after{content:'';display:table;clear:both}.wcml-section:last-of-type{border:none;margin:0}@media (max-width: 480px){.wcml-section .button{max-width:100%;white-space:normal;line-height:1.3;padding-top:7px;padding-bottom:8px;height:auto}}.explanation-text{color:#999}h4+.explanation-text{margin-top:-1.1em;margin-bottom:1.33em}.wcml-section-content .wcml-section-content-inner:not(:last-child){margin:0 0 20px 0;padding:0 0 10px 0;border-bottom:1px solid #ededed}.wcml-section-header h3{font-weight:normal;font-size:1.4em;margin-top:0.7em}.wcml-section-header h3 .wcml-tip:before{vertical-align:top}@media (min-width: 1200px){.wcml-section-header{width:310px;float:left}.wcml-section-content{float:left;width:600px;max-width:100%;margin-left:30px}.wcml-section-content-wide{width:calc(100% - 360px)}}.wcml_products{margin:20px 0;position:relative}.button-wrap,.widefat td .button-wrap{text-align:right;margin:10px 0}.currency_action_update{display:inline-block}.wcml-co-dialog.hidden{display:none}.wcml-co-dialog .wpml-form-row label,.wcml-co-dialog .wpml-form-row input,.wcml-co-dialog .wpml-form-row select{margin:3px 15px}.wcml-co-dialog .wpml-form-row label{width:215px;text-align:start}.wcml-co-dialog .wpml-form-row input,.wcml-co-dialog .wpml-form-row select{width:145px}.wcml-co-dialog .currency_code label{width:100px;vertical-align:top}.wcml-co-dialog .currency_code select{width:auto;max-width:calc(100% - 165px)}.wcml-co-dialog .wcml-co-exchange-rate label{width:100px;vertical-align:top}.wcml-co-dialog .wcml-co-exchange-rate input{margin:0 !important;width:75px}.wcml-co-dialog .wcml-co-exchange-rate .wcml-co-set-rate{display:inline-block;padding:4px 15px 7px 15px;max-width:265px}.wcml-co-dialog .wcml-co-exchange-rate small{display:block;margin-top:5px}.wcml-co-dialog .wcml-co-help-link{margin-top:7px}.wcml-co-dialog .wcml-co-preview label{width:120px;vertical-align:middle}.wcml-co-dialog .wcml-co-preview .wcml-co-preview-value{display:inline-block;padding:7px 15px;border:1px solid #555;font-size:1.4em;font-weight:bold;vertical-align:middle;margin:15px 0}.wcml-co-dialog .label-header{margin:20px 15px 7px 15px;display:block}.wcml-co-dialog .wcml-gateways-switcher{margin:7px 15px 30px}.wcml-co-dialog .wcml-gateways-switcher .otgs-toggle-group{display:inline-flex;-webkit-margin-end:15px;margin-inline-end:15px}.wcml-co-dialog .wcml-gateways{margin-bottom:30px}.wcml-co-dialog .wcml-gateways .wpml-form-row label{width:130px}.wcml-co-dialog .wcml-gateways .wpml-form-row input,.wcml-co-dialog .wcml-gateways .wpml-form-row select{width:auto}.wcml-co-dialog .wcml-gateways .wpml-form-row input+.wcml-tip,.wcml-co-dialog .wcml-gateways .wpml-form-row select+.wcml-tip{-webkit-margin-start:-12px;margin-inline-start:-12px}.wcml-co-dialog .wcml-gateways .explanation-text{display:block;margin:0 15px}table.widefat.currency_table{float:left;width:255px;border-right:none}@media (max-width: 782px){table.widefat.currency_table{width:120px}}table.widefat.currency_table td.wcml-col-currency,table.widefat.currency_table td.wcml-col-rate{padding-top:7px;padding-bottom:0;vertical-align:top}table.widefat.currency_table td.wcml-col-currency .truncate{max-width:100px;display:block}table.widefat.currency_table td.wcml-col-currency small{display:block}table.widefat.currency_table td.wcml-col-edit a{position:relative;top:-3px}table.widefat.currency_table td.wcml-col-rate{font-size:.85em;-webkit-padding-start:3px;padding-inline-start:3px}table.widefat.currency_table td.wcml-col-rate .truncate{max-width:75px;display:block}@media (max-width: 782px){table.widefat.currency_table .wcml-col-rate{display:none}}table.widefat.currency_settings_table{float:left;width:80px;border-left:none;clear:none}table.widefat.currency_settings_table td.wcml-col-delete,table.widefat.currency_settings_table td.wcml-col-edit{vertical-align:middle;text-align:center}table.widefat.currency_settings_table td.wcml-col-delete:first-child,table.widefat.currency_settings_table td.wcml-col-edit:first-child{border-left:1px solid #e5e5e5}.currency_value .wcml-error,.wcml-error{font-size:10px;color:#f00;display:inline-block}.trbl_variables_products{padding:10px;border:1px solid #8cceea;background-color:#eff8fc;border-radius:5px}.trbl_variables_products label span{font-weight:bold}.wcml_trbl_warning{padding:10px;margin-bottom:10px;border:1px solid #f00;background-color:#ffb7b7;border-radius:5px 5px}#wcml_sync_variations{background-color:#21759b;background-image:linear-gradient(to bottom, #2a95c5, #21759b);border-color:#21759b;border-bottom-color:#1e6a8d;box-shadow:inset 0 1px 0 rgba(120,200,230,0.5);color:#fff;text-decoration:none;text-shadow:0 1px 0 rgba(0,0,0,0.1)}.wcml_duplicate_product_notice td{border-bottom:none !important}.wcml_product_status_text,.prod_parent_text{font-style:italic;color:#9A9A9A}.wcml_no_found_text{text-align:center}.currency_languages{position:relative;text-align:center}.currency_languages:first-child{border-left:1px solid #e5e5e5}.currency_languages ul{margin:0;text-align:center}.currency_languages ul li{margin:0;display:none}.currency_languages ul li.on{display:inline-block}.currencies-table-content{display:inline-block;min-width:291px}@media (min-width: 1200px){.currencies-table-content{min-width:600px}}.currencies-table-content::after{display:table;clear:both;content:''}table.widefat.currency_lang_table{border-left:none;border-right:none}table.widefat.currency_lang_table thead .currency-lang-flags{height:23px}table.widefat.currency_lang_table thead tr{height:45px}table.widefat.currency_lang_table thead td{border-bottom:0;text-align:center;padding:3px 10px 1px 0;font-size:1em}table.widefat.currency_lang_table thead th{padding-top:0;padding-bottom:0;text-align:center}.currency_wrap{width:100%;max-width:calc(100% - 255px - 80px);min-width:70px;float:left;margin-bottom:10px;position:relative}.currency_wrap::after{content:'';position:absolute;top:1px;bottom:1px;right:0;width:15px;background:linear-gradient(to right, transparent, #fff)}@media (max-width: 782px){.currency_wrap{max-width:calc(100% - 121px - 80px)}}.currency_inner{overflow-x:auto;overflow-y:visible}.currency_table,.currency_lang_table,.currency_settings_table{clear:none}.currency_table thead tr,.currency_lang_table thead tr,.currency_settings_table thead tr{height:68px}.currency_table tr,.currency_lang_table tr,.currency_settings_table tr{height:50px}@media (max-width: 782px){.currency_table .default_currency,.currency_lang_table .default_currency,.currency_settings_table .default_currency{height:55px}}.currency_lang_table th{text-align:center}.currency_lang_table td{vertical-align:middle}.currency_lang_table.widefat td{padding-right:0;padding-left:0}@media (max-width: 782px){#wpbody .currency_lang_table select{font-size:10px}.currency_lang_table [class*='otgs-ico']::before{font-size:27px}}.default_currency select{font-size:9px;height:24px;margin:0;margin-right:2px;padding:2px 0}.default_currency td{border-top:1px solid #e5e5e5}.default_currency .inf_message{font-size:10px;font-style:italic;color:#9A9A9A}#wcml_currencies_order{display:block;overflow:hidden;width:100%}#wcml_currencies_order li{float:left;margin:2px 4px 2px 0;padding:2px 8px;border:1px solid #DFDFDF;border-radius:2px;background:linear-gradient(to top, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;cursor:move}.wcml_currencies_order_ajx_resp{font-weight:500;margin:0 5px;padding:1px 4px 2px;border-radius:3px;white-space:nowrap;color:#46b450;background-color:rgba(92,255,102,0.15)}.wcml-cs-list{font-size:inherit;width:100%;border-collapse:collapse;border:lightgrey 1px solid;vertical-align:middle}.wcml-cs-list thead tr{border:lightgrey 1px solid}.wcml-cs-list th,.wcml-cs-list td{text-align:center;padding:5px}.wcml-cs-list .wcml-cs-cell-preview{text-align:start}.wcml-cs-list .wcml-cs-actions{width:60px}.wcml-cs-list .wcml-cs-actions a{display:inline-block;width:20px;cursor:pointer}@media (max-width: 480px){.wcml-cs-list{display:block}.wcml-cs-list thead{display:none}.wcml-cs-list tbody,.wcml-cs-list tr:not(.wcml-cs-empty-row),.wcml-cs-list td{display:block !important;box-sizing:border-box}.wcml-cs-list tr::after{display:table;content:'';clear:both}.wcml-cs-list tr+tr{margin-top:30px}.wcml-cs-list .wcml-cs-cell-preview{width:100%}.wcml-cs-list .wcml-cs-widget-name,.wcml-cs-list .wcml-cs-actions{width:50%;float:left}.wcml-cs-list .wcml-cs-widget-name{text-align:start}.wcml-cs-list .wcml-cs-actions{text-align:end}}.wcml-currency-preview-wrapper{background-color:#fff;padding:15px 10px 10px;border:1px solid #ccc;width:100%;min-width:150px;min-height:120px;box-sizing:border-box;position:relative;display:flex !important;align-items:center;justify-content:center}.wcml-currency-preview-wrapper .wcml-currency-preview-label{position:absolute;top:5px;left:10px;z-index:101;display:inline-block;padding:2px;background:rgba(255,255,255,0.9)}.wcml-currency-preview-wrapper .spinner{position:absolute;bottom:5px;right:0;z-index:101}.wcml-cs-dialog .wcml-currency-switcher-options-form input{max-width:100%}@media (min-width: 1000px){.wcml-cs-dialog .wcml-currency-switcher-options-form{display:flex;flex-wrap:wrap;align-items:flex-start}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-switcher-options{width:60%;order:1;box-sizing:border-box}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-switcher-options>h4:first-child{margin-top:0}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper{width:40%;box-sizing:border-box;order:2}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper>div{display:block}}@media (max-width: 999px){.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper{margin:-17px -15px 30px -15px;width:calc(100% + 2 * 15px);border-left:0;border-right:0;z-index:10}}.wcml-cs-panel-colors table{width:100%;max-width:600px;font-size:inherit}.wcml-cs-panel-colors table th{text-align:start}.wcml-cs-panel-colors table td{vertical-align:top}.wcml-cs-panel-colors .wp-color-result,.wcml-cs-panel-colors .wp-color-result.button{padding-left:50px;position:relative}@media screen and (max-width: 782px){.wcml-cs-panel-colors .wp-color-result,.wcml-cs-panel-colors .wp-color-result.button{height:22px}}.wcml-cs-panel-colors .wp-color-result:after,.wcml-cs-panel-colors .wp-color-result.button:after{background:transparent;border-radius:0;border-left:0;padding:0;right:0;left:0;position:absolute;content:''}.wcml-cs-panel-colors .wp-color-result.wp-picker-open:after,.wcml-cs-panel-colors .wp-color-result.button.wp-picker-open:after{content:''}.wcml-cs-panel-colors .wp-color-result:not(.wp-picker-open):after,.wcml-cs-panel-colors .wp-color-result.button:not(.wp-picker-open):after{font-family:otgs-icons;content:'\69';color:#333;text-shadow:1px 1px 2px rgba(255,255,255,0.4);font-size:16px;min-width:0}.wcml-cs-panel-colors .wp-color-result.button .wp-color-result-text{display:none !important}.wcml-cs-panel-colors .wp-color-result.button:after{top:-2px}.wcml-cs-panel-colors .wp-picker-container input[type="text"].wp-color-picker{display:inline !important;margin-right:6px}.wcml_product_name{line-height:20px}.wcml_prod_filters{float:left}.wcml_miss_lang p:first-child{float:left}#display_custom_prices_select{display:inline-block;width:100%}.edit_slug_input,.edit_slug_hide_link{display:none}.wcml-tip{cursor:help;color:#555}.wcml-products a{cursor:pointer}@media (max-width: 782px){.column-product_cat,.column-product_tag,.column-product_type{display:none}}.wcml-link-troubleshooting{margin-top:7px}.wcml-status-list li{padding-left:25px;margin-bottom:30px}.wcml-status-list li ul li{margin-bottom:3.5px}.wcml-status-list.wcml-tax-translation-list li{margin-bottom:5px;line-height:26px}.wcml-status-list.wcml-plugins-status-list li{margin-bottom:10px}.wcml-status-list [class*="otgs-ico"]:not(.otgs-ico-help){margin-left:-25px;margin-right:5px;vertical-align:baseline}.wcml-status-list .button-secondary{vertical-align:middle}.wcml-status-list small{display:block}.wcml-lang-list{margin:7px 0}.wcml-lang-list .wpml-title-flag{margin-left:-25px;margin-right:5px}.wcml-dismiss-warning{position:relative;float:right;padding:0;text-decoration:none;outline:none}.wcml-dismiss-warning:active{outline:none}.wcml-notice{background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);margin:5px 0 15px;padding:1px 12px;position:relative}.wcml-notice p{margin:.5em 0;padding:2px}.otgs-is-dismissible{position:relative;padding-right:38px}.otgs-is-dismissible .notice-dismiss{text-decoration:none}.otgs-is-dismissible p [class*="button-"]{margin:-5px 5px}.wcml_tt_spinner{margin-right:15px;display:none}.wcml-product-attributes-selector{text-align:center;margin-bottom:25px}@media (max-width: 1280px){.wcml-product-attributes-selector{margin-left:.2em}}.wcml-product-attributes-selector select{min-width:200px}.wcml-product-custom-taxonomies-selector{text-align:center;margin-bottom:25px}.wcml_attributes_wrap #wpml_tt_taxonomy_translation_wrap>label,.wcml_custom_taxonomies_wrap #wpml_tt_taxonomy_translation_wrap>label{display:none}
1
+ .wcml-wrap{border:1px solid #CCCCCC;padding:15px;background-color:#ffffff}.wcml-wrap:before,.wcml-wrap:after{content:" ";display:table}.wcml-wrap:after{clear:both}.dis_base{opacity:0.5}.display-block{display:block}.wcml-wrap{margin-bottom:20px}.wcml-wrap .wpml-tabs{margin-top:0}.wcml-wrap .otgs-ico-yes,.wcml-wrap .otgs-ico-ok{color:#51a351}.wcml-wrap .otgs-ico-no,.wcml-wrap .otgs-ico-warning,.wcml-wrap .otgs-ico-delete{color:#9d261d}.wcml-wrap .otgs-ico-edit{color:#3a87ad}.wcml-wrap .otgs-ico-in-progress{color:#ffb800}@media (max-width: 1199px){.wcml-wrap .tablenav.top{height:auto}.wcml-wrap .tablenav.top.wcml-product-translation-filtering .alignright,.wcml-wrap .tablenav.top.wcml-product-translation-filtering .alignleft{float:none;margin-bottom:5px}}[class*="otgs-ico"]:before{font-size:16px}.wcml-tabs:before,.wcml-tabs:after{content:" ";display:table}.wcml-tabs:after{clear:both}.wcml-tabs .nav-tab [class*="otgs-ico"]:before{font-size:18px}.wcml-tabs .nav-tab-active{background:#fff;border-bottom:none}.wcml-section{clear:both;padding:0 0 15px 0;margin:0 0 15px 0;border-bottom:1px solid #ededed}.wcml-section:after{content:'';display:table;clear:both}.wcml-section:last-of-type{border:none;margin:0}@media (max-width: 480px){.wcml-section .button{max-width:100%;white-space:normal;line-height:1.3;padding-top:7px;padding-bottom:8px;height:auto}}.explanation-text{color:#999}h4+.explanation-text{margin-top:-1.1em;margin-bottom:1.33em}.wcml-section-content .wcml-section-content-inner:not(:last-child){margin:0 0 20px 0;padding:0 0 10px 0;border-bottom:1px solid #ededed}.wcml-section-header h3{font-weight:normal;font-size:1.4em;margin-top:0.7em}.wcml-section-header h3 .wcml-tip:before{vertical-align:top}@media (min-width: 1200px){.wcml-section-header{width:310px;float:left}.rtl .wcml-section-header{float:right}.wcml-section-content{float:left;width:600px;max-width:100%;margin-left:30px}.rtl .wcml-section-content{float:right}.wcml-section-content-wide{width:calc(100% - 360px)}}.wcml_products{margin:20px 0;position:relative}.button-wrap,.widefat td .button-wrap{text-align:right;margin:10px 0}.currency_action_update{display:inline-block}.wcml-co-dialog.hidden{display:none}.wcml-co-dialog .wpml-form-row label,.wcml-co-dialog .wpml-form-row input,.wcml-co-dialog .wpml-form-row select{margin:3px 15px}.wcml-co-dialog .wpml-form-row label{width:215px;text-align:start}.wcml-co-dialog .wpml-form-row input,.wcml-co-dialog .wpml-form-row select{width:145px}.wcml-co-dialog .currency_code label{width:100px;vertical-align:top}.wcml-co-dialog .currency_code select{width:auto;max-width:calc(100% - 165px)}.wcml-co-dialog .wcml-co-exchange-rate label{width:100px;vertical-align:top}.wcml-co-dialog .wcml-co-exchange-rate input{margin:0 !important;width:75px}.wcml-co-dialog .wcml-co-exchange-rate .wcml-co-set-rate{display:inline-block;padding:4px 15px 7px 15px;max-width:265px}.wcml-co-dialog .wcml-co-exchange-rate small{display:block;margin-top:5px}.wcml-co-dialog .wcml-co-help-link{margin-top:7px}.wcml-co-dialog .wcml-co-preview label{width:120px;vertical-align:middle}.wcml-co-dialog .wcml-co-preview .wcml-co-preview-value{display:inline-block;padding:7px 15px;border:1px solid #555;font-size:1.4em;font-weight:bold;vertical-align:middle;margin:15px 0}.wcml-co-dialog .label-header{margin:20px 15px 7px 15px;display:block}.wcml-co-dialog .wcml-gateways-switcher{margin:7px 15px 30px}.wcml-co-dialog .wcml-gateways-switcher .otgs-toggle-group{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-margin-end:15px;margin-inline-end:15px}.wcml-co-dialog .wcml-gateways{margin-bottom:30px}.wcml-co-dialog .wcml-gateways .wpml-form-row label{width:130px}.wcml-co-dialog .wcml-gateways .wpml-form-row input,.wcml-co-dialog .wcml-gateways .wpml-form-row select{width:auto}.wcml-co-dialog .wcml-gateways .wpml-form-row input+.wcml-tip,.wcml-co-dialog .wcml-gateways .wpml-form-row select+.wcml-tip{-webkit-margin-start:-12px;margin-inline-start:-12px}.wcml-co-dialog .wcml-gateways .explanation-text{display:block;margin:0 15px}table.widefat.currency_table{float:left;width:255px;border-right:none}@media (max-width: 782px){table.widefat.currency_table{width:120px}}table.widefat.currency_table td.wcml-col-currency,table.widefat.currency_table td.wcml-col-rate{padding-top:7px;padding-bottom:0;vertical-align:top}table.widefat.currency_table td.wcml-col-currency .truncate{max-width:100px;display:block}table.widefat.currency_table td.wcml-col-currency small{display:block}table.widefat.currency_table td.wcml-col-edit a{position:relative;top:-3px}table.widefat.currency_table td.wcml-col-rate{font-size:.85em;-webkit-padding-start:3px;padding-inline-start:3px}table.widefat.currency_table td.wcml-col-rate .truncate{max-width:75px;display:block}@media (max-width: 782px){table.widefat.currency_table .wcml-col-rate{display:none}}table.widefat.currency_settings_table{float:left;width:80px;border-left:none;clear:none}table.widefat.currency_settings_table td.wcml-col-delete,table.widefat.currency_settings_table td.wcml-col-edit{vertical-align:middle;text-align:center}table.widefat.currency_settings_table td.wcml-col-delete:first-child,table.widefat.currency_settings_table td.wcml-col-edit:first-child{border-left:1px solid #e5e5e5}.currency_value .wcml-error,.wcml-error{font-size:10px;color:#f00;display:inline-block}.trbl_variables_products{padding:10px;border:1px solid #8cceea;background-color:#eff8fc;border-radius:5px}.trbl_variables_products label span{font-weight:bold}.wcml_trbl_warning{padding:10px;margin-bottom:10px;border:1px solid #f00;background-color:#ffb7b7;border-radius:5px 5px}#wcml_sync_variations{background-color:#21759b;background-image:-webkit-gradient(linear, left top, left bottom, from(#2a95c5), to(#21759b));background-image:linear-gradient(to bottom, #2a95c5, #21759b);border-color:#21759b;border-bottom-color:#1e6a8d;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,0.5);box-shadow:inset 0 1px 0 rgba(120,200,230,0.5);color:#fff;text-decoration:none;text-shadow:0 1px 0 rgba(0,0,0,0.1)}.wcml_duplicate_product_notice td{border-bottom:none !important}.wcml_product_status_text,.prod_parent_text{font-style:italic;color:#9A9A9A}.wcml_no_found_text{text-align:center}.currency_languages{position:relative;text-align:center}.currency_languages:first-child{border-left:1px solid #e5e5e5}.currency_languages ul{margin:0;text-align:center}.currency_languages ul li{margin:0;display:none}.currency_languages ul li.on{display:inline-block}.currencies-table-content{display:inline-block;min-width:291px}@media (min-width: 1200px){.currencies-table-content{min-width:600px}}.currencies-table-content::after{display:table;clear:both;content:''}table.widefat.currency_lang_table{border-left:none;border-right:none}table.widefat.currency_lang_table thead .currency-lang-flags{height:23px}table.widefat.currency_lang_table thead tr{height:45px}table.widefat.currency_lang_table thead td{border-bottom:0;text-align:center;padding:3px 10px 1px 0;font-size:1em}table.widefat.currency_lang_table thead th{padding-top:0;padding-bottom:0;text-align:center}.currency_wrap{width:100%;max-width:calc(100% - 255px - 80px);min-width:70px;float:left;margin-bottom:10px;position:relative}.currency_wrap::after{content:'';position:absolute;top:1px;bottom:1px;right:0;width:15px;background:-webkit-gradient(linear, left top, right top, from(transparent), to(#fff));background:linear-gradient(to right, transparent, #fff)}@media (max-width: 782px){.currency_wrap{max-width:calc(100% - 121px - 80px)}}.currency_inner{overflow-x:auto;overflow-y:visible}.currency_table,.currency_lang_table,.currency_settings_table{clear:none}.currency_table thead tr,.currency_lang_table thead tr,.currency_settings_table thead tr{height:68px}.currency_table tr,.currency_lang_table tr,.currency_settings_table tr{height:50px}@media (max-width: 782px){.currency_table .default_currency,.currency_lang_table .default_currency,.currency_settings_table .default_currency{height:55px}}.currency_lang_table th{text-align:center}.currency_lang_table td{vertical-align:middle}.currency_lang_table.widefat td{padding-right:0;padding-left:0}@media (max-width: 782px){#wpbody .currency_lang_table select{font-size:10px}.currency_lang_table [class*='otgs-ico']::before{font-size:27px}}.default_currency select{font-size:9px;height:24px;margin:0;margin-right:2px;padding:2px 0}.default_currency td{border-top:1px solid #e5e5e5}.default_currency .inf_message{font-size:10px;font-style:italic;color:#9A9A9A}#wcml_currencies_order{display:block;overflow:hidden;width:100%}#wcml_currencies_order li{float:left;margin:2px 4px 2px 0;padding:2px 8px;border:1px solid #DFDFDF;border-radius:2px;background:-webkit-gradient(linear, left bottom, left top, from(#ECECEC), to(#F9F9F9)) repeat scroll 0 0 #F1F1F1;background:linear-gradient(to top, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;cursor:move}.wcml_currencies_order_ajx_resp{font-weight:500;margin:0 5px;padding:1px 4px 2px;border-radius:3px;white-space:nowrap;color:#46b450;background-color:rgba(92,255,102,0.15)}.wcml-cs-list{font-size:inherit;width:100%;border-collapse:collapse;border:lightgrey 1px solid;vertical-align:middle}.wcml-cs-list thead tr{border:lightgrey 1px solid}.wcml-cs-list th,.wcml-cs-list td{text-align:center;padding:5px}.wcml-cs-list .wcml-cs-cell-preview{text-align:start}.wcml-cs-list .wcml-cs-actions{width:60px}.wcml-cs-list .wcml-cs-actions a{display:inline-block;width:20px;cursor:pointer}@media (max-width: 480px){.wcml-cs-list{display:block}.wcml-cs-list thead{display:none}.wcml-cs-list tbody,.wcml-cs-list tr:not(.wcml-cs-empty-row),.wcml-cs-list td{display:block !important;-webkit-box-sizing:border-box;box-sizing:border-box}.wcml-cs-list tr::after{display:table;content:'';clear:both}.wcml-cs-list tr+tr{margin-top:30px}.wcml-cs-list .wcml-cs-cell-preview{width:100%}.wcml-cs-list .wcml-cs-widget-name,.wcml-cs-list .wcml-cs-actions{width:50%;float:left}.wcml-cs-list .wcml-cs-widget-name{text-align:start}.wcml-cs-list .wcml-cs-actions{text-align:end}}.wcml-currency-preview-wrapper{background-color:#fff;padding:15px 10px 10px;border:1px solid #ccc;width:100%;min-width:150px;min-height:120px;-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.wcml-currency-preview-wrapper .wcml-currency-preview-label{position:absolute;top:5px;left:10px;z-index:101;display:inline-block;padding:2px;background:rgba(255,255,255,0.9)}.wcml-currency-preview-wrapper .spinner{position:absolute;bottom:5px;right:0;z-index:101}.wcml-cs-dialog .wcml-currency-switcher-options-form input{max-width:100%}@media (min-width: 1000px){.wcml-cs-dialog .wcml-currency-switcher-options-form{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-switcher-options{width:60%;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1;-webkit-box-sizing:border-box;box-sizing:border-box}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-switcher-options>h4:first-child{margin-top:0}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper{width:40%;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper>div{display:block}}@media (max-width: 999px){.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper{margin:-17px -15px 30px -15px;width:calc(100% + 2 * 15px);border-left:0;border-right:0;z-index:10}}.wcml-cs-panel-colors table{width:100%;max-width:600px;font-size:inherit}.wcml-cs-panel-colors table th{text-align:start}.wcml-cs-panel-colors table td{vertical-align:top}.wcml-cs-panel-colors .wp-color-result,.wcml-cs-panel-colors .wp-color-result.button{padding-left:50px;position:relative}@media screen and (max-width: 782px){.wcml-cs-panel-colors .wp-color-result,.wcml-cs-panel-colors .wp-color-result.button{height:22px}}.wcml-cs-panel-colors .wp-color-result:after,.wcml-cs-panel-colors .wp-color-result.button:after{background:transparent;border-radius:0;border-left:0;padding:0;right:0;left:0;position:absolute;content:''}.wcml-cs-panel-colors .wp-color-result.wp-picker-open:after,.wcml-cs-panel-colors .wp-color-result.button.wp-picker-open:after{content:''}.wcml-cs-panel-colors .wp-color-result:not(.wp-picker-open):after,.wcml-cs-panel-colors .wp-color-result.button:not(.wp-picker-open):after{font-family:otgs-icons;content:'\69';color:#333;text-shadow:1px 1px 2px rgba(255,255,255,0.4);font-size:16px;min-width:0}.wcml-cs-panel-colors .wp-color-result.button .wp-color-result-text{display:none !important}.wcml-cs-panel-colors .wp-color-result.button:after{top:-2px}.wcml-cs-panel-colors .wp-picker-container input[type="text"].wp-color-picker{display:inline !important;margin-right:6px}.wcml_product_name{line-height:20px}.wcml_prod_filters{float:left}.wcml_miss_lang p:first-child{float:left}#display_custom_prices_select{display:inline-block;width:100%}.edit_slug_input,.edit_slug_hide_link{display:none}.wcml-tip{cursor:help;color:#555}.wcml-products a{cursor:pointer}@media (max-width: 782px){.column-product_cat,.column-product_tag,.column-product_type{display:none}}.wcml-link-troubleshooting{margin-top:7px}.wcml-status-list li{padding-left:25px;margin-bottom:30px}.wcml-status-list li ul li{margin-bottom:3.5px}.wcml-status-list.wcml-tax-translation-list li{margin-bottom:5px;line-height:26px}.wcml-status-list.wcml-plugins-status-list li{margin-bottom:10px}.wcml-status-list [class*="otgs-ico"]:not(.otgs-ico-help){margin-left:-25px;margin-right:5px;vertical-align:baseline}.rtl .wcml-status-list [class*="otgs-ico"]:not(.otgs-ico-help){margin-left:5px;margin-right:-25px}.wcml-status-list .button-secondary{vertical-align:middle}.wcml-status-list small{display:block}.wcml-lang-list{margin:7px 0}.wcml-lang-list .wpml-title-flag{margin-left:-25px;margin-right:5px}.rtl .wcml-lang-list .wpml-title-flag{margin-left:5px;margin-right:0}.wcml-dismiss-warning{position:relative;float:right;padding:0;text-decoration:none;outline:none}.wcml-dismiss-warning:active{outline:none}.wcml-notice{background:#fff;-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);margin:5px 0 15px;padding:1px 12px;position:relative}.wcml-notice p{margin:.5em 0;padding:2px}.otgs-is-dismissible{position:relative;padding-right:38px}.otgs-is-dismissible .notice-dismiss{text-decoration:none}.otgs-is-dismissible p [class*="button-"]{margin:-5px 5px}.wcml_tt_spinner{margin-right:15px;display:none}.wcml-product-attributes-selector{text-align:center;margin-bottom:25px}@media (max-width: 1280px){.wcml-product-attributes-selector{margin-left:.2em}}.wcml-product-attributes-selector select{min-width:200px}.wcml-product-custom-taxonomies-selector{text-align:center;margin-bottom:25px}.wcml_attributes_wrap #wpml_tt_taxonomy_translation_wrap>label,.wcml_custom_taxonomies_wrap #wpml_tt_taxonomy_translation_wrap>label{display:none}
templates/settings-ui.twig CHANGED
@@ -61,6 +61,29 @@
61
 
62
  </div>
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  <div class="wcml-section">
66
 
61
 
62
  </div>
63
 
64
+ <div class="wcml-section">
65
+
66
+ <div class="wcml-section-header">
67
+ <h3>
68
+ {{ form.media_synchronization.heading }}
69
+ <i class="otgs-ico-help wcml-tip" data-tip="{{ form.media_synchronization.tip }}"></i>
70
+ </h3>
71
+ </div>
72
+
73
+ <div class="wcml-section-content">
74
+
75
+ <ul>
76
+ <li>
77
+ <input type="checkbox" name="sync_media" value="1"
78
+ {% if form.media_synchronization.sync_media.value == 1 %} checked="checked"{% endif %} id="wcml_sync_media" />
79
+ <label for="wcml_sync_media">{{ form.media_synchronization.sync_media.label }}</label>
80
+ </li>
81
+ </ul>
82
+
83
+ </div>
84
+
85
+ </div>
86
+
87
 
88
  <div class="wcml-section">
89
 
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitaa29be73d32a70e36d5628c27c0b9239::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit5ac08f95a41ac99faca9cacc98fc9fc3::getLoader();
vendor/composer/autoload_classmap.php CHANGED
@@ -6,6 +6,9 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
 
 
9
  'WCML\\Media\\Wrapper\\Factory' => $baseDir . '/classes/media/Wrapper/Factory.php',
10
  'WCML\\Media\\Wrapper\\IMedia' => $baseDir . '/classes/media/Wrapper/IMedia.php',
11
  'WCML\\Media\\Wrapper\\NonTranslatable' => $baseDir . '/classes/media/Wrapper/NonTranslatable.php',
@@ -201,7 +204,7 @@ return array(
201
  'WCML_Woobe' => $baseDir . '/compatibility/class-wcml-woobe.php',
202
  'WCML_WpFastest_Cache' => $baseDir . '/compatibility/class-wcml-wpfastest-cache.php',
203
  'WCML_Wpb_Vc' => $baseDir . '/compatibility/class-wcml-wpb-vc.php',
204
- 'WCML_YIKES_Custom_Product_Tabs_Pro' => $baseDir . '/compatibility/class-wcml-yikes-custom-product-tabs-pro.php',
205
  'WCML_YITH_WCQV' => $baseDir . '/compatibility/class-wcml-yith-wcqv.php',
206
  'WCML_gravityforms' => $baseDir . '/compatibility/class-wcml-gravityforms.php',
207
  'WCML_wcExporter' => $baseDir . '/compatibility/class-wcml-wcexporter.php',
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'WCML\\Container\\Config' => $baseDir . '/classes/Container/Config.php',
10
+ 'WCML\\Email\\OrderItems\\Hooks' => $baseDir . '/classes/Email/OrderItems/Hooks.php',
11
+ 'WCML\\Email\\Settings\\Hooks' => $baseDir . '/classes/Email/Settings/Hooks.php',
12
  'WCML\\Media\\Wrapper\\Factory' => $baseDir . '/classes/media/Wrapper/Factory.php',
13
  'WCML\\Media\\Wrapper\\IMedia' => $baseDir . '/classes/media/Wrapper/IMedia.php',
14
  'WCML\\Media\\Wrapper\\NonTranslatable' => $baseDir . '/classes/media/Wrapper/NonTranslatable.php',
204
  'WCML_Woobe' => $baseDir . '/compatibility/class-wcml-woobe.php',
205
  'WCML_WpFastest_Cache' => $baseDir . '/compatibility/class-wcml-wpfastest-cache.php',
206
  'WCML_Wpb_Vc' => $baseDir . '/compatibility/class-wcml-wpb-vc.php',
207
+ 'WCML_YIKES_Custom_Product_Tabs' => $baseDir . '/compatibility/class-wcml-yikes-custom-product-tabs.php',
208
  'WCML_YITH_WCQV' => $baseDir . '/compatibility/class-wcml-yith-wcqv.php',
209
  'WCML_gravityforms' => $baseDir . '/compatibility/class-wcml-gravityforms.php',
210
  'WCML_wcExporter' => $baseDir . '/compatibility/class-wcml-wcexporter.php',
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitaa29be73d32a70e36d5628c27c0b9239
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInitaa29be73d32a70e36d5628c27c0b9239
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitaa29be73d32a70e36d5628c27c0b9239', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitaa29be73d32a70e36d5628c27c0b9239', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInitaa29be73d32a70e36d5628c27c0b9239
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequireaa29be73d32a70e36d5628c27c0b9239($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequireaa29be73d32a70e36d5628c27c0b9239($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit5ac08f95a41ac99faca9cacc98fc9fc3
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit5ac08f95a41ac99faca9cacc98fc9fc3', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit5ac08f95a41ac99faca9cacc98fc9fc3', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit5ac08f95a41ac99faca9cacc98fc9fc3::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit5ac08f95a41ac99faca9cacc98fc9fc3::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire5ac08f95a41ac99faca9cacc98fc9fc3($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequire5ac08f95a41ac99faca9cacc98fc9fc3($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239
8
  {
9
  public static $files = array (
10
  'b45b351e6b6f7487d819961fef2fda77' => __DIR__ . '/..' . '/jakeasmith/http_build_url/src/http_build_url.php',
@@ -25,6 +25,9 @@ class ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239
25
  );
26
 
27
  public static $classMap = array (
 
 
 
28
  'WCML\\Media\\Wrapper\\Factory' => __DIR__ . '/../..' . '/classes/media/Wrapper/Factory.php',
29
  'WCML\\Media\\Wrapper\\IMedia' => __DIR__ . '/../..' . '/classes/media/Wrapper/IMedia.php',
30
  'WCML\\Media\\Wrapper\\NonTranslatable' => __DIR__ . '/../..' . '/classes/media/Wrapper/NonTranslatable.php',
@@ -220,7 +223,7 @@ class ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239
220
  'WCML_Woobe' => __DIR__ . '/../..' . '/compatibility/class-wcml-woobe.php',
221
  'WCML_WpFastest_Cache' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpfastest-cache.php',
222
  'WCML_Wpb_Vc' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpb-vc.php',
223
- 'WCML_YIKES_Custom_Product_Tabs_Pro' => __DIR__ . '/../..' . '/compatibility/class-wcml-yikes-custom-product-tabs-pro.php',
224
  'WCML_YITH_WCQV' => __DIR__ . '/../..' . '/compatibility/class-wcml-yith-wcqv.php',
225
  'WCML_gravityforms' => __DIR__ . '/../..' . '/compatibility/class-wcml-gravityforms.php',
226
  'WCML_wcExporter' => __DIR__ . '/../..' . '/compatibility/class-wcml-wcexporter.php',
@@ -235,9 +238,9 @@ class ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239
235
  public static function getInitializer(ClassLoader $loader)
236
  {
237
  return \Closure::bind(function () use ($loader) {
238
- $loader->prefixLengthsPsr4 = ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239::$prefixLengthsPsr4;
239
- $loader->prefixDirsPsr4 = ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239::$prefixDirsPsr4;
240
- $loader->classMap = ComposerStaticInitaa29be73d32a70e36d5628c27c0b9239::$classMap;
241
 
242
  }, null, ClassLoader::class);
243
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit5ac08f95a41ac99faca9cacc98fc9fc3
8
  {
9
  public static $files = array (
10
  'b45b351e6b6f7487d819961fef2fda77' => __DIR__ . '/..' . '/jakeasmith/http_build_url/src/http_build_url.php',
25
  );
26
 
27
  public static $classMap = array (
28
+ 'WCML\\Container\\Config' => __DIR__ . '/../..' . '/classes/Container/Config.php',
29
+ 'WCML\\Email\\OrderItems\\Hooks' => __DIR__ . '/../..' . '/classes/Email/OrderItems/Hooks.php',
30
+ 'WCML\\Email\\Settings\\Hooks' => __DIR__ . '/../..' . '/classes/Email/Settings/Hooks.php',
31
  'WCML\\Media\\Wrapper\\Factory' => __DIR__ . '/../..' . '/classes/media/Wrapper/Factory.php',
32
  'WCML\\Media\\Wrapper\\IMedia' => __DIR__ . '/../..' . '/classes/media/Wrapper/IMedia.php',
33
  'WCML\\Media\\Wrapper\\NonTranslatable' => __DIR__ . '/../..' . '/classes/media/Wrapper/NonTranslatable.php',
223
  'WCML_Woobe' => __DIR__ . '/../..' . '/compatibility/class-wcml-woobe.php',
224
  'WCML_WpFastest_Cache' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpfastest-cache.php',
225
  'WCML_Wpb_Vc' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpb-vc.php',
226
+ 'WCML_YIKES_Custom_Product_Tabs' => __DIR__ . '/../..' . '/compatibility/class-wcml-yikes-custom-product-tabs.php',
227
  'WCML_YITH_WCQV' => __DIR__ . '/../..' . '/compatibility/class-wcml-yith-wcqv.php',
228
  'WCML_gravityforms' => __DIR__ . '/../..' . '/compatibility/class-wcml-gravityforms.php',
229
  'WCML_wcExporter' => __DIR__ . '/../..' . '/compatibility/class-wcml-wcexporter.php',
238
  public static function getInitializer(ClassLoader $loader)
239
  {
240
  return \Closure::bind(function () use ($loader) {
241
+ $loader->prefixLengthsPsr4 = ComposerStaticInit5ac08f95a41ac99faca9cacc98fc9fc3::$prefixLengthsPsr4;
242
+ $loader->prefixDirsPsr4 = ComposerStaticInit5ac08f95a41ac99faca9cacc98fc9fc3::$prefixDirsPsr4;
243
+ $loader->classMap = ComposerStaticInit5ac08f95a41ac99faca9cacc98fc9fc3::$classMap;
244
 
245
  }, null, ClassLoader::class);
246
  }
wpml-dependencies.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
- "sitepress-multilingual-cms": "4.3.0",
3
- "wpml-string-translation": "3.0.0",
4
- "wpml-translation-management": "2.9.0",
5
- "woocommerce-multilingual": "4.7.0"
6
  }
1
  {
2
+ "sitepress-multilingual-cms": "4.3.5",
3
+ "wpml-string-translation": "3.0.5",
4
+ "wpml-translation-management": "2.9.1",
5
+ "woocommerce-multilingual": "4.7.5"
6
  }
wpml-woocommerce.php CHANGED
@@ -8,7 +8,7 @@
8
  * Text Domain: woocommerce-multilingual
9
  * Requires at least: 4.7
10
  * Tested up to: 5.3
11
- * Version: 4.7.4
12
  * Plugin Slug: woocommerce-multilingual
13
  * WC requires at least: 3.3.0
14
  * WC tested up to: 3.8.0
@@ -33,7 +33,7 @@ if ( ! $wpml_php_version_check->is_ok() ) {
33
  return;
34
  }
35
 
36
- define( 'WCML_VERSION', '4.7.4' );
37
  define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
38
  define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
39
  define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
@@ -71,6 +71,8 @@ if ( WPML_Core_Version_Check::is_ok( WCML_PLUGIN_PATH . '/wpml-dependencies.json
71
  * Load WooCommerce Multilingual after WPML is loaded
72
  */
73
  function wcml_loader() {
 
 
74
  $xdomain_data = new WCML_xDomain_Data( new WPML_Cookie() );
75
  $xdomain_data->add_hooks();
76
 
@@ -78,6 +80,8 @@ function wcml_loader() {
78
  'WCML_Privacy_Content_Factory',
79
  'WCML_ATE_Activate_Synchronization',
80
  \WCML\RewriteRules\Hooks::class,
 
 
81
  );
82
 
83
  if (
8
  * Text Domain: woocommerce-multilingual
9
  * Requires at least: 4.7
10
  * Tested up to: 5.3
11
+ * Version: 4.7.5
12
  * Plugin Slug: woocommerce-multilingual
13
  * WC requires at least: 3.3.0
14
  * WC tested up to: 3.8.0
33
  return;
34
  }
35
 
36
+ define( 'WCML_VERSION', '4.7.5' );
37
  define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
38
  define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
39
  define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
71
  * Load WooCommerce Multilingual after WPML is loaded
72
  */
73
  function wcml_loader() {
74
+ \WPML\Container\share( \WCML\Container\Config::getSharedInstances() );
75
+
76
  $xdomain_data = new WCML_xDomain_Data( new WPML_Cookie() );
77
  $xdomain_data->add_hooks();
78
 
80
  'WCML_Privacy_Content_Factory',
81
  'WCML_ATE_Activate_Synchronization',
82
  \WCML\RewriteRules\Hooks::class,
83
+ \WCML\Email\Settings\Hooks::class,
84
+ \WCML\Email\OrderItems\Hooks::class,
85
  );
86
 
87
  if (