WooCommerce Multilingual – run WooCommerce with WPML - Version 0.9

Version Description

  • First release

=

Download this release

Release Info

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

Version 0.9

Files changed (4) hide show
  1. readme.txt +57 -0
  2. screenshot-1.png +0 -0
  3. wpml-config.xml +43 -0
  4. wpml-woocommerce.php +396 -0
readme.txt ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === WooCommerce Multilingual - run WooCommerce with WPML ===
2
+ Contributors: dominykasgel, AmirHelzer
3
+ Donate link: http://wp-types.com
4
+ Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multilingual
5
+ Requires at least: 3.2.1
6
+ Tested up to: 3.3.1
7
+ Stable tag: 0.9
8
+
9
+ Allows running multilingual e-commerce sites using WooCommerce and WPML.
10
+
11
+ == Description ==
12
+
13
+ This 'glue' plugin makes it possible to run fully multilignual e-commerce sites using WooCommerce and WPML. It makes products and store pages translatable, lets visitors switch languages and order products in their language.
14
+
15
+ = Features =
16
+
17
+ * Makes languages persist through the checkout process
18
+ * Sends emails to clients and admins in their selected language
19
+ * Collapses all products to the default language for inventory tracking and shipping
20
+
21
+ = Documentation =
22
+
23
+ Please go to [WooCommerce Multilingual Doc](http://wpml.org/documentation/related-projects/woocommerce-multilingual/) page. You'll find instructions for translating the shop pages, the products and plugin strings.
24
+
25
+ = Downloads =
26
+
27
+ You will need:
28
+
29
+ * [WooCommerce](http://wordpress.org/extend/plugins/woocommerce/) version 1.4 and up - the actual e-commerce plugin (free)
30
+ * [WPML](http://wpml.org) version 2.4.2 and up - the multilingual WordPress plugin (costs $79)
31
+
32
+ == Installation ==
33
+
34
+ 1. Upload 'types' to the '/wp-content/plugins/' directory
35
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
36
+
37
+
38
+ == Frequently Asked Questions ==
39
+
40
+ = Does this work with other e-commerce plugins? =
41
+
42
+ No. This plugin is tailored for WooCommerce.
43
+
44
+ == Screenshots ==
45
+
46
+ 1. Translation controls for products
47
+
48
+ == Changelog ==
49
+
50
+ = 0.9 =
51
+ * First release
52
+
53
+ == Upgrade Notice ==
54
+
55
+ = 0.9 =
56
+ * First release
57
+
screenshot-1.png ADDED
Binary file
wpml-config.xml ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <wpml-config>
2
+ <custom-fields>
3
+ <custom-field action="copy">backorders</custom-field>
4
+ <custom-field action="copy">description</custom-field>
5
+ <custom-field action="copy">downloadable</custom-field>
6
+ <custom-field action="copy">featured</custom-field>
7
+ <custom-field action="copy">height</custom-field>
8
+ <custom-field action="copy">keywords</custom-field>
9
+ <custom-field action="copy">length</custom-field>
10
+ <custom-field action="copy">price</custom-field>
11
+ <custom-field action="copy">product_attributes</custom-field>
12
+ <custom-field action="copy">regular_price</custom-field>
13
+ <custom-field action="copy">sale_price</custom-field>
14
+ <custom-field action="copy">sale_price_dates_from</custom-field>
15
+ <custom-field action="copy">sale_price_dates_to</custom-field>
16
+ <custom-field action="copy">seo_description</custom-field>
17
+ <custom-field action="copy">seo_follow</custom-field>
18
+ <custom-field action="copy">seo_keywords</custom-field>
19
+ <custom-field action="copy">sku</custom-field>
20
+ <custom-field action="copy">stock</custom-field>
21
+ <custom-field action="copy">stock_status</custom-field>
22
+ <custom-field action="copy">manage_stock</custom-field>
23
+ <custom-field action="copy">tax_class</custom-field>
24
+ <custom-field action="copy">tax_status</custom-field>
25
+ <custom-field action="copy">title</custom-field>
26
+ <custom-field action="copy">virtual</custom-field>
27
+ <custom-field action="copy">visibility</custom-field>
28
+ <custom-field action="copy">weight</custom-field>
29
+ <custom-field action="copy">width</custom-field>
30
+ <custom-field action="copy">total_sales</custom-field>
31
+ </custom-fields>
32
+ <custom-types>
33
+ <custom-type translate="1">product</custom-type>
34
+ <custom-type translate="1">product_variation</custom-type>
35
+ <custom-type translate="0">shop_order</custom-type>
36
+ </custom-types>
37
+ <taxonomies>
38
+ <taxonomy translate="1">product_cat</taxonomy>
39
+ <taxonomy translate="1">product_type</taxonomy>
40
+ <taxonomy translate="1">shop_order_status</taxonomy>
41
+ <taxonomy translate="1">link_category</taxonomy>
42
+ </taxonomies>
43
+ </wpml-config>
wpml-woocommerce.php ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: WooCommerce Multilingual
4
+ Plugin URI: http://wpml.org/documentation/related-projects/woocommerce-multilingual/
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: 0.9
9
+ */
10
+ add_action('plugins_loaded', 'wpml_woocommerce_init', 2);
11
+
12
+ function wpml_woocommerce_init(){
13
+ if(!defined('ICL_SITEPRESS_VERSION') || ICL_PLUGIN_INACTIVE){
14
+ if(!function_exists('is_multisite') || !is_multisite()) {
15
+ add_action('admin_notices', 'wpml_no_wpml_warning');
16
+ }
17
+ return false;
18
+ } else if(version_compare(ICL_SITEPRESS_VERSION, '2.0.5', '<')){
19
+ add_action('admin_notices', 'wpml_old_wpml_warning');
20
+ return false;
21
+ } else if(!class_exists('woocommerce')){
22
+ add_action('admin_notices', 'wpml_no_woocommerce');
23
+ return false;
24
+ }
25
+
26
+ add_filter('woocommerce_get_checkout_url', 'wpml_get_checkout_url');
27
+ add_filter('woocommerce_get_cart_page_id', 'wpml_get_cart_url');
28
+ add_filter('woocommerce_get_remove_url', 'wpml_get_remove_url');
29
+ add_filter('woocommerce_get_myaccount_page_id', 'wpml_get_myaccount_page_id');
30
+ add_filter('woocommerce_get_edit_address_page_id', 'wpml_get_edit_address_page_id');
31
+ add_filter('woocommerce_get_view_order_page_id', 'wpml_get_view_order_page_id');
32
+ add_filter('woocommerce_get_change_password_page_id', 'wpml_get_change_password_page_id');
33
+ add_filter('woocommerce_get_thanks_page_id', 'wpml_get_thanks_page_id');
34
+ add_filter('woocommerce_get_shop_page_id', 'wpml_shop_page_id');
35
+ add_filter('woocommerce_get_pay_page_id', 'wpml_pay_page_id');
36
+ add_filter('woocommerce_get_checkout_payment_url', 'wpml_get_checkout_payment_url');
37
+ add_filter('woocommerce_get_cancel_order_url', 'wpml_get_cancel_order_url');
38
+ add_filter('woocommerce_get_return_url', 'wpml_get_return_url');
39
+ add_filter('woocommerce_in_cart_product_title', 'wpml_in_cart_product_title', 13, 2);
40
+ add_filter('woocommerce_in_cart_product_id', 'wpml_in_cart_product_id', 11, 2);
41
+ add_filter('woocommerce_params', 'wpml_params');
42
+ add_filter('woocommerce_redirect', 'wpml_redirect');
43
+ add_filter('wp_head', 'wpml_redirect_to_store');
44
+
45
+ add_action("updated_post_meta", 'wpml_updated_post_meta_hook', 10, 4);
46
+ add_action('woocommerce_email_header', 'wpml_email_header', 0);
47
+ add_action('woocommerce_email_footer', 'wpml_email_footer', 0);
48
+ add_action('woocommerce_new_order', 'wpml_order_language');
49
+ }
50
+
51
+ /**
52
+ * Adds admin notice.
53
+ */
54
+ function wpml_no_wpml_warning(){
55
+ ?>
56
+ <div class="message error"><p><?php printf(__('WooCommerce Multilingual is enabled but not effective. It requires <a href="%s">WPML</a> in order to work.', 'plugin woocommerce'),
57
+ 'http://wpml.org/'); ?></p></div>
58
+ <?php
59
+ }
60
+
61
+ /**
62
+ * Adds admin notice.
63
+ */
64
+ function wpml_old_wpml_warning(){
65
+ ?>
66
+ <div class="message error"><p><?php printf(__('WooCommerce Multilingual is enabled but not effective. It is not compatible with <a href="%s">WPML</a> versions prior 2.0.5.', 'plugin woocommerce'),
67
+ 'http://wpml.org/'); ?></p></div>
68
+ <?php
69
+ }
70
+
71
+ /**
72
+ * Adds admin notice.
73
+ */
74
+ function wpml_no_woocommerce(){
75
+ ?>
76
+ <div class="message error"><p><?php printf(__('WooCommerce Multilingual is enabled but not effective. It requires <a href="%s">WooCommerce</a> in order to work.', 'plugin woocommerce'),
77
+ 'http://www.woothemes.com/woocommerce/'); ?></p></div>
78
+ <?php
79
+ }
80
+
81
+ /**
82
+ * Filters WooCommerce product link in cart.
83
+ *
84
+ * @param type $url
85
+ * @param type $product_id
86
+ * @return type
87
+ */
88
+ function wpml_add_to_cart_product_id($url, $product_id) {
89
+ return get_permalink(icl_object_id($product_id, 'product', true));
90
+ }
91
+
92
+ /**
93
+ * Adjusts WooCommerce product ID to be added in cart (original product ID).
94
+ *
95
+ * @param type $product_id
96
+ * @return type
97
+ */
98
+ function wpml_in_cart_product_id($product_id) {
99
+ return icl_object_id($product_id, 'product', true);
100
+ }
101
+
102
+ /**
103
+ * Synchronizes post meta 'stock' and 'stock_status' betweeen translated posts.
104
+ *
105
+ * @global type $sitepress
106
+ * @param type $meta_id
107
+ * @param type $object_id
108
+ * @param type $meta_key
109
+ * @param type $_meta_value
110
+ */
111
+ function wpml_updated_post_meta_hook($meta_id, $object_id, $meta_key, $_meta_value) {
112
+ global $sitepress;
113
+ $update_meta_keys = array('stock', 'stock_status');
114
+
115
+ if (in_array($meta_key, $update_meta_keys)) {
116
+ $translations = $sitepress->get_element_translations($object_id, 'product');
117
+
118
+ foreach($translations as $t){
119
+ if(!$t->original){
120
+ if($meta_key == 'stock'){
121
+ update_post_meta($t->translation_id, 'stock', $_meta_value);
122
+ } else if($meta_key = 'stock_status'){
123
+ update_post_meta($t->translation_id, 'stock_status', $_meta_value);
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Filters WooCommerce navigation menu translated shop page link (redirect to store).
132
+ *
133
+ * @global type $post
134
+ * @global type $sitepress
135
+ */
136
+ function wpml_redirect_to_store(){
137
+ global $post, $sitepress;
138
+
139
+ $shop_page_id = get_option('woocommerce_shop_page_id');
140
+ $translated_shop_page_id = icl_object_id($shop_page_id, 'page', false);
141
+
142
+ if(is_page($translated_shop_page_id)){
143
+ wp_safe_redirect($sitepress->convert_url(get_option('home') . '/?post_type=product'));
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Filters WooCommerce cancel order (payment gateway).
149
+ *
150
+ * @global type $sitepress
151
+ * @param type $link
152
+ * @return type
153
+ */
154
+ function wpml_get_cancel_order_url($link){
155
+ global $sitepress;
156
+ return $sitepress->convert_url($link);
157
+ }
158
+
159
+ /**
160
+ * Filters WooCommerce return URL after payment (payment gateway e.g. PayPal).
161
+ *
162
+ * @global type $sitepress
163
+ * @param type $link
164
+ * @return type
165
+ */
166
+ function wpml_get_return_url($link){
167
+ global $sitepress;
168
+ return $sitepress->convert_url($link);
169
+ }
170
+
171
+ /**
172
+ * Filters WooCommerce redirect location.
173
+ *
174
+ * @global type $sitepress
175
+ * @param type $link
176
+ * @return type
177
+ */
178
+ function wpml_redirect($link){
179
+ global $sitepress;
180
+ return $sitepress->convert_url($link);
181
+ }
182
+
183
+ /**
184
+ * Filters WooCommerce shop link.
185
+ *
186
+ * @global type $sitepress
187
+ * @param type $link
188
+ * @return type
189
+ */
190
+ function wpml_shop_page_id($link){
191
+ global $sitepress;
192
+
193
+ if($sitepress->get_current_language() !== $sitepress->get_default_language()){
194
+ $shop_page_id = icl_object_id(get_option('woocommerce_shop_page_id'), 'page', true);
195
+ } else {
196
+ $shop_page_id = $sitepress->convert_url(get_option('home') . '/?post_type=product');
197
+ }
198
+
199
+ return $shop_page_id;
200
+ }
201
+
202
+ /**
203
+ * Filters WooCommerce thanks link.
204
+ */
205
+ function wpml_get_thanks_page_id(){
206
+ return icl_object_id(get_option('woocommerce_thanks_page_id'), 'page', true);
207
+ }
208
+
209
+ /**
210
+ * Filters WooCommerce payment link for unpaid - pending orders.
211
+ *
212
+ * @global type $sitepress
213
+ * @param type $link
214
+ * @return type
215
+ */
216
+ function wpml_get_checkout_payment_url($link){
217
+ global $sitepress;
218
+ return $sitepress->convert_url($link);
219
+ }
220
+
221
+ /**
222
+ * Filters WooCommerce my account link.
223
+ */
224
+ function wpml_get_myaccount_page_id(){
225
+ return icl_object_id(get_option('woocommerce_myaccount_page_id'), 'page', true);
226
+ }
227
+
228
+ /**
229
+ * Filters WooCommerce my account edit address link.
230
+ */
231
+ function wpml_get_edit_address_page_id(){
232
+ return icl_object_id(get_option('woocommerce_edit_address_page_id'), 'page', true);
233
+ }
234
+
235
+ /**
236
+ * Filters WooCommerce view order link.
237
+ */
238
+ function wpml_get_view_order_page_id(){
239
+ return icl_object_id(get_option('woocommerce_view_order_page_id'), 'page', true);
240
+ }
241
+
242
+ /**
243
+ * Filters WooCommerce my account change password link.
244
+ */
245
+ function wpml_get_change_password_page_id(){
246
+ return icl_object_id(get_option('woocommerce_change_password_page_id'), 'page', true);
247
+ }
248
+
249
+ /**
250
+ * Filters WooCommerce pay page id
251
+ * @return type
252
+ */
253
+ function wpml_pay_page_id(){
254
+ $is_cart_page = icl_object_id(get_option('woocommerce_cart_page_id'), 'page', true);
255
+
256
+ if(is_page($is_cart_page)){
257
+ return true;
258
+ } else {
259
+ return icl_object_id(get_option('woocommerce_pay_page_id'), 'page', true);
260
+ }
261
+ }
262
+
263
+ /**
264
+ * Filters WooCommerce checkout link.
265
+ *
266
+ * @global type $sitepress
267
+ * @param type $link
268
+ * @return type
269
+ */
270
+ function wpml_get_checkout_url($link){
271
+ global $sitepress;
272
+ return $sitepress->convert_url($link);
273
+ }
274
+
275
+ /**
276
+ * Filters WooCommerce cart link.
277
+ *
278
+ * @return type
279
+ */
280
+ function wpml_get_cart_url($link) {
281
+ return icl_object_id(get_option('woocommerce_cart_page_id'), 'page', true);
282
+ }
283
+
284
+ /**
285
+ * Filters WooCommerce product remove link.
286
+ *
287
+ * @global type $sitepress
288
+ * @param type $link
289
+ * @return type
290
+ */
291
+ function wpml_get_remove_url($link){
292
+ global $sitepress;
293
+ return $sitepress->convert_url($link);
294
+ }
295
+
296
+ /**
297
+ * Filters WooCommerce js params
298
+ *
299
+ * @global type $sitepress
300
+ * @global type $post
301
+ * @param type $value
302
+ * @return type
303
+ */
304
+ function wpml_params($value){
305
+ global $sitepress, $post;
306
+
307
+ if(!isset($post->ID)){
308
+ $post->ID = null;
309
+ }
310
+
311
+ if($sitepress->get_current_language() !== $sitepress->get_default_language()){
312
+ $value['checkout_url'] = admin_url('admin-ajax.php?action=woocommerce-checkout&lang=' . ICL_LANGUAGE_CODE);
313
+ $value['ajax_url'] = admin_url('admin-ajax.php?lang=' . ICL_LANGUAGE_CODE);
314
+ }
315
+
316
+ $checkout_page_id = get_option('woocommerce_checkout_page_id');
317
+ $pay_page_id = get_option('woocommerce_pay_page_id');
318
+ $cart_page_id = get_option('woocommerce_cart_page_id');
319
+
320
+ $translated_checkout_page_id = icl_object_id($checkout_page_id, 'page', false);
321
+ $translated_pay_page_id = icl_object_id($pay_page_id, 'page', false);
322
+ $translated_cart_page_id = icl_object_id($cart_page_id, 'page', false);
323
+
324
+ if($translated_cart_page_id == $post->ID){
325
+ $value['is_cart'] = 1;
326
+ } else if($translated_checkout_page_id == $post->ID || $checkout_page_id == $post->ID){
327
+ $value['is_checkout'] = 1;
328
+ $_SESSION['wpml_globalcart_language'] = $sitepress->get_current_language();
329
+ } else if($translated_pay_page_id == $post->ID){
330
+ $value['is_pay_page'] = 1;
331
+ }
332
+
333
+ return $value;
334
+ }
335
+
336
+ /**
337
+ * Adds language to order post type.
338
+ *
339
+ * Language was stored in the session created on checkout page.
340
+ * See params().
341
+ *
342
+ * @param type $order_id
343
+ */
344
+ function wpml_order_language($order_id) {
345
+ if(!get_post_meta($order_id, 'wpml_language')){
346
+ $language = isset($_SESSION['wpml_globalcart_language']) ? $_SESSION['wpml_globalcart_language'] : ICL_LANGUAGE_CODE;
347
+ update_post_meta($order_id, 'wpml_language', $language);
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Translates WooCommerce emails.
353
+ *
354
+ * @global type $sitepress
355
+ * @global type $order_id
356
+ * @return type
357
+ */
358
+ function wpml_email_header() {
359
+ global $sitepress, $order_id, $email_heading;
360
+
361
+ $order_lang = get_post_custom_values('wpml_language', $order_id);
362
+ $order_lang = trim($order_lang[0]);
363
+
364
+ $sitepress->switch_lang($order_lang, true);
365
+ }
366
+
367
+ /**
368
+ * After email translation switch language to default.
369
+ *
370
+ * @global type $sitepress
371
+ * @return type
372
+ */
373
+ function wpml_email_footer() {
374
+ global $sitepress;
375
+
376
+ $sitepress->switch_lang();
377
+ }
378
+
379
+ /**
380
+ * After email translation switch language to default.
381
+ *
382
+ * @param type $title
383
+ * @param $_product
384
+ * @return type
385
+ */
386
+ function wpml_in_cart_product_title($title, $_product){
387
+ $product_id = icl_object_id($_product->id, 'product', false, ICL_LANGUAGE_CODE);
388
+
389
+ if($product_id){
390
+ $title = get_the_title($product_id);
391
+ }
392
+
393
+ return $title;
394
+ }
395
+
396
+ ?>