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