Polylang - Version 0.9.6

Version Description

(2012-11-26) =

  • It is now possible to query the terms by language using the WordPress function 'get_terms'
  • Bug correction: search for empty string in default language displays posts in all languages when hiding the URL language information for default language
  • Bug correction: completely reworked the canonical redirection introduced in 0.9.5 which created more problems than it solved
  • Bug correction: ajax for media translations does not work
  • Started tests with WordPress 3.5 beta RC1
Download this release

Release Info

Developer Chouby
Plugin Icon 128x128 Polylang
Version 0.9.6
Comparing to
See all releases

Code changes from version 0.9.5 to 0.9.6

include/admin-filters.php CHANGED
@@ -67,7 +67,7 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
67
  add_action('wp_ajax_media_lang_choice', array(&$this,'media_lang_choice'));
68
 
69
  // adds actions related to languages when creating, saving or deleting media
70
- add_filter('attachment_fields_to_save', array(&$this, 'save_media'));
71
  add_action('delete_attachment', array(&$this, 'delete_post'));
72
  add_filter('wp_delete_file', array(&$this, 'wp_delete_file'));
73
 
@@ -217,7 +217,9 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
217
  }
218
 
219
  // filters the list of media by language when uploading from post
220
- if ($GLOBALS['pagenow'] == 'media-upload.php' && isset($_GET['post_id']) && $lang = $this->get_post_language($_GET['post_id']))
 
 
221
  $query->set('lang', $lang->slug);
222
 
223
  if (!isset($qvars['lang']) && $lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true))
@@ -229,9 +231,9 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
229
  return $query;
230
  }
231
 
232
- // adds the Language box in the 'Edit Post' and 'Edit Page' panels (as well as in custom post types panels)
233
  function add_meta_boxes($post_type) {
234
- if (in_array($post_type, $this->post_types))
235
  add_meta_box('ml_box', __('Languages','polylang'), array(&$this,'post_language'), $post_type, 'side', 'high');
236
 
237
  // replace tag metabox by our own
@@ -508,7 +510,7 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
508
  $this->save_translations('post', $post_id, $translations);
509
 
510
  // STOP synchronisation if unwanted
511
- if (!$this->options['sync'])
512
  return;
513
 
514
  // synchronise terms and metas in translations
@@ -541,7 +543,6 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
541
 
542
  // adds the language field and translations tables in the 'Edit Media' panel
543
  function attachment_fields_to_edit($fields, $post) {
544
- $screen = get_current_screen();
545
  $post_id = $post->ID;
546
  $lang = $this->get_post_language($post_id);
547
 
@@ -560,7 +561,8 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
560
  );
561
 
562
  // don't show translations except on edit media panel
563
- if ($screen->base == 'media') {
 
564
  if ($lang) {
565
  ob_start();
566
  include PLL_INC . '/media-translations.php';
@@ -626,8 +628,9 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
626
  }
627
 
628
  // called when a media is saved
629
- // the language is automatically saved by WP
630
- function save_media($post) {
 
631
  $this->delete_translation('post', $post['ID']);
632
 
633
  // save translations after checking the translated media is in the right language
@@ -666,6 +669,10 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
666
  return $clauses;
667
  }
668
 
 
 
 
 
669
  if (function_exists('get_current_screen'))
670
  $screen = get_current_screen(); // since WP 3.1, may not be available the first time(s) get_terms is called
671
 
@@ -836,7 +843,7 @@ class Polylang_Admin_Filters extends Polylang_Admin_Base {
836
  // synchronize translations of this term in all posts
837
 
838
  // STOP synchronisation if unwanted
839
- if (!$this->options['sync'])
840
  return;
841
 
842
  // get all posts associated to this term
67
  add_action('wp_ajax_media_lang_choice', array(&$this,'media_lang_choice'));
68
 
69
  // adds actions related to languages when creating, saving or deleting media
70
+ add_filter('attachment_fields_to_save', array(&$this, 'save_media'), 10, 2);
71
  add_action('delete_attachment', array(&$this, 'delete_post'));
72
  add_filter('wp_delete_file', array(&$this, 'wp_delete_file'));
73
 
217
  }
218
 
219
  // filters the list of media by language when uploading from post
220
+ if (($GLOBALS['pagenow'] == 'media-upload.php' || // WP < 3.5
221
+ ($GLOBALS['pagenow'] == 'admin-ajax.php' && isset($_REQUEST['action']) && $_REQUEST['action'] == 'query-attachments')) && // WP 3.5+
222
+ isset($_REQUEST['post_id']) && $lang = $this->get_post_language($_REQUEST['post_id']))
223
  $query->set('lang', $lang->slug);
224
 
225
  if (!isset($qvars['lang']) && $lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true))
231
  return $query;
232
  }
233
 
234
+ // adds the Language box in the 'Edit Post' and 'Edit Page' panels (as well as in custom post types panels) but not in the 'Edit media' panel
235
  function add_meta_boxes($post_type) {
236
+ if (in_array($post_type, array_diff($this->post_types, array('attachment'))))
237
  add_meta_box('ml_box', __('Languages','polylang'), array(&$this,'post_language'), $post_type, 'side', 'high');
238
 
239
  // replace tag metabox by our own
510
  $this->save_translations('post', $post_id, $translations);
511
 
512
  // STOP synchronisation if unwanted
513
+ if (!isset($this->options['sync']) || !$this->options['sync'])
514
  return;
515
 
516
  // synchronise terms and metas in translations
543
 
544
  // adds the language field and translations tables in the 'Edit Media' panel
545
  function attachment_fields_to_edit($fields, $post) {
 
546
  $post_id = $post->ID;
547
  $lang = $this->get_post_language($post_id);
548
 
561
  );
562
 
563
  // don't show translations except on edit media panel
564
+ // media.php for WP < 3.5 and post.php for WP 3.5+
565
+ if (in_array($GLOBALS['pagenow'], array('media.php', 'post.php'))) {
566
  if ($lang) {
567
  ob_start();
568
  include PLL_INC . '/media-translations.php';
628
  }
629
 
630
  // called when a media is saved
631
+ function save_media($post, $attachment) {
632
+ $this->set_post_language($post['ID'], $attachment['language']); // FIXME the language is no more automatically saved by WP since WP 3.5 (just a bug?)
633
+
634
  $this->delete_translation('post', $post['ID']);
635
 
636
  // save translations after checking the translated media is in the right language
669
  return $clauses;
670
  }
671
 
672
+ // if get_terms is queried with a 'lang' parameter
673
+ if (isset($args['lang']) && $args['lang'])
674
+ return $this->_terms_clauses($clauses, $args['lang']);
675
+
676
  if (function_exists('get_current_screen'))
677
  $screen = get_current_screen(); // since WP 3.1, may not be available the first time(s) get_terms is called
678
 
843
  // synchronize translations of this term in all posts
844
 
845
  // STOP synchronisation if unwanted
846
+ if (!isset($this->options['sync']) || !$this->options['sync'])
847
  return;
848
 
849
  // get all posts associated to this term
include/api.php CHANGED
@@ -3,13 +3,13 @@
3
  // template tag: displays the language switcher
4
  function pll_the_languages($args = '') {
5
  global $polylang;
6
- return isset($polylang) ? $polylang->the_languages($args) : '';
7
  }
8
 
9
  // returns the current language
10
  function pll_current_language($args = 'slug') {
11
  global $polylang;
12
- return isset($polylang) ? $polylang->current_language($args) : false;
13
  }
14
 
15
  // among the post and its translations, returns the id of the post which is in the language represented by $slug
@@ -27,7 +27,7 @@ function pll_get_term($term_id, $slug = false) {
27
  // returns the home url in the right language
28
  function pll_home_url() {
29
  global $polylang;
30
- return isset($polylang) ? $polylang->get_home_url() : home_url('/');
31
  }
32
 
33
  // register strings for translation in the "strings translation" panel
3
  // template tag: displays the language switcher
4
  function pll_the_languages($args = '') {
5
  global $polylang;
6
+ return class_exists('Polylang_Core') && $polylang instanceof Polylang_Core ? $polylang->the_languages($args) : '';
7
  }
8
 
9
  // returns the current language
10
  function pll_current_language($args = 'slug') {
11
  global $polylang;
12
+ return class_exists('Polylang_Core') && $polylang instanceof Polylang_Core ? $polylang->current_language($args) : false;
13
  }
14
 
15
  // among the post and its translations, returns the id of the post which is in the language represented by $slug
27
  // returns the home url in the right language
28
  function pll_home_url() {
29
  global $polylang;
30
+ return class_exists('Polylang_Core') && $polylang instanceof Polylang_Core ? $polylang->get_home_url() : home_url('/');
31
  }
32
 
33
  // register strings for translation in the "strings translation" panel
include/base.php CHANGED
@@ -260,8 +260,21 @@ abstract class Polylang_Base {
260
  function _terms_clauses($clauses, $lang) {
261
  global $wpdb;
262
  if (isset($lang) && $lang) {
263
- $clauses['join'] .= $wpdb->prepare(" LEFT JOIN $wpdb->termmeta AS pll_tm ON t.term_id = pll_tm.term_id");
264
- $clauses['where'] .= $wpdb->prepare(" AND pll_tm.meta_key = '_language' AND pll_tm.meta_value IN ($lang->term_id)");
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  }
266
  return $clauses;
267
  }
260
  function _terms_clauses($clauses, $lang) {
261
  global $wpdb;
262
  if (isset($lang) && $lang) {
263
+ // the query is coming from Polylang and the $lang is an object
264
+ if (is_object($lang))
265
+ $languages = esc_sql($lang->term_id);
266
+
267
+ // the query is coming from outside with 'lang' parameter and $lang is a comma separated list of slugs (or an array of slugs)
268
+ else {
269
+ $languages = is_array($lang) ? $lang : explode(',', $lang);
270
+ $languages = "'" . implode("','", array_map( 'sanitize_title_for_query', $languages)) . "'";
271
+ $languages = $wpdb->get_col("SELECT $wpdb->term_taxonomy.term_id FROM $wpdb->term_taxonomy
272
+ INNER JOIN $wpdb->terms USING (term_id) WHERE taxonomy = 'language' AND $wpdb->terms.slug IN ($languages)"); // get ids from slugs
273
+ $languages = esc_sql(implode(',', $languages));
274
+ }
275
+
276
+ $clauses['join'] .= " LEFT JOIN $wpdb->termmeta AS pll_tm ON t.term_id = pll_tm.term_id";
277
+ $clauses['where'] .= " AND pll_tm.meta_key = '_language' AND pll_tm.meta_value IN ($languages)";
278
  }
279
  return $clauses;
280
  }
include/core.php CHANGED
@@ -75,10 +75,6 @@ class Polylang_Core extends Polylang_base {
75
  // prevents redirection of the homepage
76
  add_filter('redirect_canonical', array(&$this, 'stop_redirect_canonical'), 10, 2);
77
 
78
- // redirects incoming links to the proper URL when adding the language code to all urls
79
- if ($this->options['force_lang'] && get_option('permalink_structure') && PLL_LANG_EARLY)
80
- add_action('template_redirect', array(&$this, 'redirect_canonical'), 20); // after Wordpress redirect_canonical
81
-
82
  // adds javascript at the end of the document
83
  if (!$GLOBALS['wp_rewrite']->using_permalinks() && PLL_SEARCH_FORM_JS)
84
  add_action('wp_footer', array(&$this, 'wp_print_footer_scripts'));
@@ -256,8 +252,10 @@ class Polylang_Core extends Polylang_base {
256
  $this->curlang = $this->get_language($matches[1]);
257
  elseif (false === strpos($_SERVER['SCRIPT_NAME'], 'index.php')) // wp-login, wp-signup, wp-activate
258
  $this->curlang = $this->get_preferred_language();
259
- else
260
  $this->curlang = $this->get_language($this->options['default_lang']);
 
 
261
 
262
  $GLOBALS['l10n']['pll_string'] = $this->mo_import($this->curlang);
263
  do_action('pll_language_defined');
@@ -332,8 +330,7 @@ class Polylang_Core extends Polylang_base {
332
 
333
  // reinitializes wp_locale for weekdays and months, as well as for text direction
334
  unset($GLOBALS['wp_locale']);
335
- $GLOBALS['wp_locale'] = new WP_Locale();
336
- $GLOBALS['wp_locale']->text_direction = get_metadata('term', $this->curlang->term_id, '_rtl', true) ? 'rtl' : 'ltr';
337
 
338
  // translate labels of post types and taxonomies
339
  foreach ($GLOBALS['wp_taxonomies'] as $tax)
@@ -369,8 +366,7 @@ class Polylang_Core extends Polylang_base {
369
  // we are already on the right page
370
  if ($this->options['default_lang'] == $this->curlang->slug && $this->options['hide_default']) {
371
  if ($this->page_on_front && $link_id = $this->get_post($this->page_on_front, $this->curlang))
372
- $query ? $query->set('page_id', $link_id) : set_query_var('page_id', $link_id);
373
- else
374
  $query ? $query->set('lang', $this->curlang->slug) : set_query_var('lang', $this->curlang->slug);
375
  }
376
  // redirect to the home page in the right language
@@ -498,7 +494,10 @@ class Polylang_Core extends Polylang_base {
498
  $query->set('lang', $this->curlang->slug);
499
  }
500
 
501
- // to avoid conflict beetwen taxonomies
 
 
 
502
  if (isset($query->tax_query->queries))
503
  foreach ($query->tax_query->queries as $tax)
504
  if (in_array($tax['taxonomy'], $this->taxonomies))
@@ -526,8 +525,8 @@ class Polylang_Core extends Polylang_base {
526
  return $clauses;
527
  }
528
 
529
- // adds our clauses to filter by current language
530
- return $this->_terms_clauses($clauses, $this->curlang);
531
  }
532
 
533
  // meta in the html head section
@@ -560,39 +559,30 @@ class Polylang_Core extends Polylang_base {
560
 
561
  // prevents redirection of the homepage when using page on front
562
  function stop_redirect_canonical($redirect_url, $requested_url) {
563
- return $requested_url == home_url('/') || strpos($requested_url, $this->page_link('', get_option('page_on_front'))) !== false ? false : $redirect_url;
 
 
564
  }
565
 
566
  // redirects incoming links to the proper URL when adding the language code to all urls
567
- function redirect_canonical($requested_url = false, $do_redirect = true) {
568
- if (!$requested_url)
569
- $requested_url = (is_ssl() ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
570
-
571
  if (is_single() || is_page()) {
572
  global $post;
573
  if (isset($post->ID) && in_array($post->post_type, $this->post_types))
574
- $redirect_url = get_permalink((int)$post->ID);
575
  }
576
  elseif (is_category() || is_tag() || is_tax()) {
577
  $obj = $GLOBALS['wp_query']->get_queried_object();
578
  if (in_array($obj->taxonomy, $this->taxonomies))
579
- $redirect_url = get_term_link((int)$obj->term_id, $obj->taxonomy);
580
  }
581
-
582
- if (!isset($redirect_url) || is_wp_error($redirect_url) || $redirect_url == $requested_url)
583
- return false;
584
-
585
- if ($do_redirect) {
586
- // protect against chained redirects
587
- if (!$this->redirect_canonical($redirect_url, false) ) {
588
- wp_redirect($redirect_url, 301);
589
- exit;
590
- }
591
- else
592
- return false;
593
  }
594
-
595
- return $redirect_url;
596
  }
597
 
598
  // adds some javascript workaround knowing it's not perfect...
@@ -673,14 +663,13 @@ class Polylang_Core extends Polylang_base {
673
  // modifies the sql request for wp_get_archives an get_adjacent_post to filter by the current language
674
  function posts_join($sql) {
675
  global $wpdb;
676
- return $sql . $wpdb->prepare(" INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id = ID");
677
  }
678
 
679
  // modifies the sql request for wp_get_archives and get_adjacent_post to filter by the current language
680
  function posts_where($sql) {
681
  global $wpdb;
682
- $id = $this->curlang->term_taxonomy_id;
683
- return $sql . $wpdb->prepare(" AND pll_tr.term_taxonomy_id IN ($id)");
684
  }
685
 
686
  // modifies the author and date links to add the language parameter (as well as feed link)
@@ -770,7 +759,7 @@ class Polylang_Core extends Polylang_base {
770
  elseif (is_home() || is_tax('language') )
771
  $url = $this->get_home_url($language);
772
 
773
- return $this->translation_url[$language->slug] = (isset($url) ? $url : null);
774
  }
775
 
776
  // filters the nav menus according to the current language when called from get_nav_menu_locations()
@@ -859,7 +848,10 @@ class Polylang_Core extends Polylang_base {
859
  if (!$is_search && $this->page_on_front && $id = $this->get_post($this->page_on_front, $language))
860
  return $this->home_urls[$language->slug][$is_search] = $this->page_link('', $id);
861
 
862
- return $this->home_urls[$language->slug][$is_search] = trailingslashit(get_term_link($language, 'language'));
 
 
 
863
  }
864
 
865
  // displays (or returns) the language switcher
75
  // prevents redirection of the homepage
76
  add_filter('redirect_canonical', array(&$this, 'stop_redirect_canonical'), 10, 2);
77
 
 
 
 
 
78
  // adds javascript at the end of the document
79
  if (!$GLOBALS['wp_rewrite']->using_permalinks() && PLL_SEARCH_FORM_JS)
80
  add_action('wp_footer', array(&$this, 'wp_print_footer_scripts'));
252
  $this->curlang = $this->get_language($matches[1]);
253
  elseif (false === strpos($_SERVER['SCRIPT_NAME'], 'index.php')) // wp-login, wp-signup, wp-activate
254
  $this->curlang = $this->get_preferred_language();
255
+ else {
256
  $this->curlang = $this->get_language($this->options['default_lang']);
257
+ add_action('wp', array(&$this, 'check_language_code_in_url')); // before Wordpress redirect_canonical
258
+ }
259
 
260
  $GLOBALS['l10n']['pll_string'] = $this->mo_import($this->curlang);
261
  do_action('pll_language_defined');
330
 
331
  // reinitializes wp_locale for weekdays and months, as well as for text direction
332
  unset($GLOBALS['wp_locale']);
333
+ $GLOBALS['wp_locale'] = new WP_Locale(); $GLOBALS['wp_locale']->text_direction = get_metadata('term', $this->curlang->term_id, '_rtl', true) ? 'rtl' : 'ltr';
 
334
 
335
  // translate labels of post types and taxonomies
336
  foreach ($GLOBALS['wp_taxonomies'] as $tax)
366
  // we are already on the right page
367
  if ($this->options['default_lang'] == $this->curlang->slug && $this->options['hide_default']) {
368
  if ($this->page_on_front && $link_id = $this->get_post($this->page_on_front, $this->curlang))
369
+ $query ? $query->set('page_id', $link_id) : set_query_var('page_id', $link_id); else
 
370
  $query ? $query->set('lang', $this->curlang->slug) : set_query_var('lang', $this->curlang->slug);
371
  }
372
  // redirect to the home page in the right language
494
  $query->set('lang', $this->curlang->slug);
495
  }
496
 
497
+ // sets the language for an empty string search when hiding the code for default language
498
+ // http://wordpress.org/support/topic/search-for-empty-string-in-default-language
499
+ if (!$this->curlang && !get_query_var('lang') && $this->options['hide_default'] && isset($query->query['s']) && !$query->query['s'])
500
+ $query->set('lang', $this->options['default_lang']); // to avoid conflict beetwen taxonomies
501
  if (isset($query->tax_query->queries))
502
  foreach ($query->tax_query->queries as $tax)
503
  if (in_array($tax['taxonomy'], $this->taxonomies))
525
  return $clauses;
526
  }
527
 
528
+ // adds our clauses to filter by language
529
+ return $this->_terms_clauses($clauses, isset($args['lang']) && $args['lang'] ? $args['lang'] : $this->curlang);
530
  }
531
 
532
  // meta in the html head section
559
 
560
  // prevents redirection of the homepage when using page on front
561
  function stop_redirect_canonical($redirect_url, $requested_url) {
562
+ $home_url = home_url('/');
563
+ $page_link = $this->page_link('', get_option('page_on_front'));
564
+ return $requested_url == $home_url || ($page_link != $home_url && strpos($requested_url, $page_link ) !== false) ? false : $redirect_url;
565
  }
566
 
567
  // redirects incoming links to the proper URL when adding the language code to all urls
568
+ function check_language_code_in_url() {
 
 
 
569
  if (is_single() || is_page()) {
570
  global $post;
571
  if (isset($post->ID) && in_array($post->post_type, $this->post_types))
572
+ $language = $this->get_post_language((int)$post->ID);
573
  }
574
  elseif (is_category() || is_tag() || is_tax()) {
575
  $obj = $GLOBALS['wp_query']->get_queried_object();
576
  if (in_array($obj->taxonomy, $this->taxonomies))
577
+ $language = $this->get_term_language((int)$obj->term_id);
578
  }
579
+ // the language is not correctly set so let's redirect to the correct url for this object
580
+ if (isset($language) && $language->slug != $this->curlang->slug) {
581
+ $requested_url = (is_ssl() ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
582
+ $redirect_url = $this->add_language_to_link($requested_url, $language);
583
+ wp_redirect($redirect_url, 301);
584
+ exit;
 
 
 
 
 
 
585
  }
 
 
586
  }
587
 
588
  // adds some javascript workaround knowing it's not perfect...
663
  // modifies the sql request for wp_get_archives an get_adjacent_post to filter by the current language
664
  function posts_join($sql) {
665
  global $wpdb;
666
+ return $sql . " INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id = ID";
667
  }
668
 
669
  // modifies the sql request for wp_get_archives and get_adjacent_post to filter by the current language
670
  function posts_where($sql) {
671
  global $wpdb;
672
+ return $sql . $wpdb->prepare(" AND pll_tr.term_taxonomy_id IN (%s)", $this->curlang->term_taxonomy_id);
 
673
  }
674
 
675
  // modifies the author and date links to add the language parameter (as well as feed link)
759
  elseif (is_home() || is_tax('language') )
760
  $url = $this->get_home_url($language);
761
 
762
+ return $this->translation_url[$language->slug] = (isset($url) && !is_wp_error($url) ? $url : null);
763
  }
764
 
765
  // filters the nav menus according to the current language when called from get_nav_menu_locations()
848
  if (!$is_search && $this->page_on_front && $id = $this->get_post($this->page_on_front, $language))
849
  return $this->home_urls[$language->slug][$is_search] = $this->page_link('', $id);
850
 
851
+ $link = get_term_link($language, 'language');
852
+ // add a trailing slash as done by WP on homepage (otherwise could break the search form when the permalink structure does not include one)
853
+ // only for pretty permalinks
854
+ return $this->home_urls[$language->slug][$is_search] = $GLOBALS['wp_rewrite']->using_permalinks() ? trailingslashit($link) : $link;
855
  }
856
 
857
  // displays (or returns) the language switcher
include/languages.php CHANGED
@@ -32,7 +32,7 @@ $languages = array(
32
  array('fy', 'fy', 'Frysk'),
33
  array('gd', 'gd', 'Gàidhlig'),
34
  array('gl', 'gl_ES', 'Galego'),
35
- array('he', 'he_IL', 'עברית', 'rtl'),
36
  array('hi', 'hi_IN', 'हिन्दी'),
37
  array('hr', 'hr', 'Hrvatski'),
38
  array('hu', 'hu_HU', 'Magyar'),
32
  array('fy', 'fy', 'Frysk'),
33
  array('gd', 'gd', 'Gàidhlig'),
34
  array('gl', 'gl_ES', 'Galego'),
35
+ array('he', 'he_IL', 'עברית', 'rtl'),
36
  array('hi', 'hi_IN', 'हिन्दी'),
37
  array('hr', 'hr', 'Hrvatski'),
38
  array('hu', 'hu_HU', 'Magyar'),
js/post.js CHANGED
@@ -266,4 +266,28 @@ jQuery(document).ready(function($) {
266
  $('#post_lang_choice option:selected').removeAttr('selected');
267
  $('#post_lang_choice option[value="'+lang+'"]').attr('selected', 'selected');
268
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  });
266
  $('#post_lang_choice option:selected').removeAttr('selected');
267
  $('#post_lang_choice option[value="'+lang+'"]').attr('selected', 'selected');
268
  });
269
+
270
+ // ajax for changing the media's language
271
+ $('.media_lang_choice').change( function() {
272
+ var data = {
273
+ action: 'media_lang_choice',
274
+ lang: $(this).attr('value'),
275
+ post_id: $(this).attr('name')
276
+ }
277
+
278
+ $.post(ajaxurl, data , function(response) {
279
+ var res = wpAjax.parseAjaxResponse(response, 'ajax-response');
280
+ $.each(res.responses, function() {
281
+ switch (this.what) {
282
+ case 'translations': // translations fields
283
+ $('.translations').html(this.data); // WP < 3.5
284
+ $('.compat-field-translations').html(this.data); // WP 3.5+
285
+ break;
286
+ default:
287
+ break;
288
+ }
289
+ });
290
+ });
291
+ });
292
+
293
  });
js/post.min.js CHANGED
@@ -1 +1 @@
1
- var pll_tagBox;(function(a){pll_tagBox={clean:function(b){return b.replace(/\s*,\s*/g,",").replace(/,+/g,",").replace(/[,\s]+$/,"").replace(/^[,\s]+/,"")},parseTags:function(e){var h=e.id,b=h.split("-check-num-")[1],d=a(e).closest(".tagsdiv"),g=d.find(".the-tags"),c=g.val().split(","),f=[];delete c[b];a.each(c,function(i,j){j=a.trim(j);if(j){f.push(j)}});g.val(this.clean(f.join(",")));this.quickClicks(d);return false},quickClicks:function(d){var g=a(".the-tags",d),e=a(".tagchecklist",d),f=a(d).attr("id"),b,c;if(!g.length){return}c=g.attr("disabled");b=g.val().split(",");e.empty();a.each(b,function(i,k){var j,h;k=a.trim(k);if(!k){return}j=a("<span />").text(k);if(!c){h=a('<a id="'+f+"-check-num-"+i+'" class="ntdelbutton">X</a>');h.click(function(){pll_tagBox.parseTags(this)});j.prepend("&nbsp;").prepend(h)}e.append(j)})},flushTags:function(e,b,g){b=b||false;var i,c=a(".the-tags",e),h=a("input.newtag",e),d;i=b?a(b).text():h.val();tagsval=c.val();d=tagsval?tagsval+","+i:i;d=this.clean(d);d=array_unique_noempty(d.split(",")).join(",");c.val(d);this.quickClicks(e);if(!b){h.val("")}if("undefined"==typeof(g)){h.focus()}return false},get:function(e,b){var c=e.substr(e.indexOf("-")+1);var d={action:"get-tagcloud",lang:a("#post_lang_choice").attr("value"),tax:c};a.post(ajaxurl,d,function(g,f){if(0==g||"success"!=f){g=wpAjax.broken}g=a('<p id="tagcloud-'+c+'" class="the-tagcloud">'+g+"</p>");a("a",g).click(function(){pll_tagBox.flushTags(a(this).closest(".inside").children(".tagsdiv"),this);return false});if(b==1){a("#"+e).after(g)}else{v=a(".the-tagcloud").css("display");a(".the-tagcloud").replaceWith(g);a(".the-tagcloud").css("display",v)}})},suggest:function(){ajaxtag=a("div.ajaxtag");a("input.newtag",ajaxtag).unbind().blur(function(){if(this.value==""){a(this).parent().siblings(".taghint").css("visibility","")}}).focus(function(){a(this).parent().siblings(".taghint").css("visibility","hidden")}).keyup(function(b){if(13==b.which){pll_tagBox.flushTags(a(this).closest(".tagsdiv"));return false}}).keypress(function(b){if(13==b.which){b.preventDefault();return false}}).each(function(){var c=a("#post_lang_choice").attr("value");var b=a(this).closest("div.tagsdiv").attr("id");a(this).suggest(ajaxurl+"?action=polylang-ajax-tag-search&lang="+c+"&tax="+b,{delay:500,minchars:2,multiple:true,multipleSep:","})})},init:function(){var b=this,c=a("div.ajaxtag");a(".tagsdiv").each(function(){pll_tagBox.quickClicks(this)});a("input.tagadd",c).click(function(){b.flushTags(a(this).closest(".tagsdiv"))});a("div.taghint",c).click(function(){a(this).css("visibility","hidden").parent().siblings(".newtag").focus()});pll_tagBox.suggest();a("#post").submit(function(){a("div.tagsdiv").each(function(){pll_tagBox.flushTags(this,false,1)})});a("a.tagcloud-link").click(function(){pll_tagBox.get(a(this).attr("id"),1);a(this).unbind().click(function(){a(this).siblings(".the-tagcloud").toggle();return false});return false})}}})(jQuery);jQuery(document).ready(function(b){var a=new Array();b(".categorydiv").each(function(){var e=b(this).attr("id"),d,c;d=e.split("-");d.shift();c=d.join("-");a.push(c);b("#"+c+"-add-submit").before(b("<input />").attr("type","hidden").attr("id",c+"-lang").attr("name","term_lang_choice").attr("value",b("#post_lang_choice").attr("value")))});b("#post_lang_choice").change(function(){var c={action:"post_lang_choice",lang:b(this).attr("value"),taxonomies:a,post_id:b("#post_ID").attr("value")};b.post(ajaxurl,c,function(d){var e=wpAjax.parseAjaxResponse(d,"ajax-response");b.each(e.responses,function(){switch(this.what){case"translations":b("#post-translations").html(this.data);break;case"taxonomy":var f=this.data;b("#"+f+"checklist").html(this.supplemental.all);b("#"+f+"checklist-pop").html(this.supplemental.populars);b("#new"+f+"_parent").replaceWith(this.supplemental.dropdown);b("#"+f+"-lang").val(b("#post_lang_choice").attr("value"));break;case"pages":b("#parent_id").replaceWith(this.data);break;default:break}});b(".tagcloud-link").each(function(){var f=b(this).attr("id");pll_tagBox.get(f,0)});pll_tagBox.suggest()})});if(b("#pll-tagsdiv-post_tag").length){pll_tagBox.init()}else{b("#side-sortables, #normal-sortables, #advanced-sortables").children("div.postbox").each(function(){if(this.id.indexOf("pll-tagsdiv-")===0){pll_tagBox.init();return false}})}jQuery("a.editinline").live("click",function(){inlineEditPost.revert();var c=inlineEditPost.getId(this);var d=b("input[name='lang_"+c+"']").attr("value");b("#post_lang_choice option:selected").removeAttr("selected");b('#post_lang_choice option[value="'+d+'"]').attr("selected","selected")})});
1
+ var pll_tagBox;(function(a){pll_tagBox={clean:function(b){return b.replace(/\s*,\s*/g,",").replace(/,+/g,",").replace(/[,\s]+$/,"").replace(/^[,\s]+/,"")},parseTags:function(e){var h=e.id,b=h.split("-check-num-")[1],d=a(e).closest(".tagsdiv"),g=d.find(".the-tags"),c=g.val().split(","),f=[];delete c[b];a.each(c,function(i,j){j=a.trim(j);if(j){f.push(j)}});g.val(this.clean(f.join(",")));this.quickClicks(d);return false},quickClicks:function(d){var g=a(".the-tags",d),e=a(".tagchecklist",d),f=a(d).attr("id"),b,c;if(!g.length){return}c=g.attr("disabled");b=g.val().split(",");e.empty();a.each(b,function(i,k){var j,h;k=a.trim(k);if(!k){return}j=a("<span />").text(k);if(!c){h=a('<a id="'+f+"-check-num-"+i+'" class="ntdelbutton">X</a>');h.click(function(){pll_tagBox.parseTags(this)});j.prepend("&nbsp;").prepend(h)}e.append(j)})},flushTags:function(e,b,g){b=b||false;var i,c=a(".the-tags",e),h=a("input.newtag",e),d;i=b?a(b).text():h.val();tagsval=c.val();d=tagsval?tagsval+","+i:i;d=this.clean(d);d=array_unique_noempty(d.split(",")).join(",");c.val(d);this.quickClicks(e);if(!b){h.val("")}if("undefined"==typeof(g)){h.focus()}return false},get:function(e,b){var c=e.substr(e.indexOf("-")+1);var d={action:"get-tagcloud",lang:a("#post_lang_choice").attr("value"),tax:c};a.post(ajaxurl,d,function(g,f){if(0==g||"success"!=f){g=wpAjax.broken}g=a('<p id="tagcloud-'+c+'" class="the-tagcloud">'+g+"</p>");a("a",g).click(function(){pll_tagBox.flushTags(a(this).closest(".inside").children(".tagsdiv"),this);return false});if(b==1){a("#"+e).after(g)}else{v=a(".the-tagcloud").css("display");a(".the-tagcloud").replaceWith(g);a(".the-tagcloud").css("display",v)}})},suggest:function(){ajaxtag=a("div.ajaxtag");a("input.newtag",ajaxtag).unbind().blur(function(){if(this.value==""){a(this).parent().siblings(".taghint").css("visibility","")}}).focus(function(){a(this).parent().siblings(".taghint").css("visibility","hidden")}).keyup(function(b){if(13==b.which){pll_tagBox.flushTags(a(this).closest(".tagsdiv"));return false}}).keypress(function(b){if(13==b.which){b.preventDefault();return false}}).each(function(){var c=a("#post_lang_choice").attr("value");var b=a(this).closest("div.tagsdiv").attr("id");a(this).suggest(ajaxurl+"?action=polylang-ajax-tag-search&lang="+c+"&tax="+b,{delay:500,minchars:2,multiple:true,multipleSep:","})})},init:function(){var b=this,c=a("div.ajaxtag");a(".tagsdiv").each(function(){pll_tagBox.quickClicks(this)});a("input.tagadd",c).click(function(){b.flushTags(a(this).closest(".tagsdiv"))});a("div.taghint",c).click(function(){a(this).css("visibility","hidden").parent().siblings(".newtag").focus()});pll_tagBox.suggest();a("#post").submit(function(){a("div.tagsdiv").each(function(){pll_tagBox.flushTags(this,false,1)})});a("a.tagcloud-link").click(function(){pll_tagBox.get(a(this).attr("id"),1);a(this).unbind().click(function(){a(this).siblings(".the-tagcloud").toggle();return false});return false})}}})(jQuery);jQuery(document).ready(function(b){var a=new Array();b(".categorydiv").each(function(){var e=b(this).attr("id"),d,c;d=e.split("-");d.shift();c=d.join("-");a.push(c);b("#"+c+"-add-submit").before(b("<input />").attr("type","hidden").attr("id",c+"-lang").attr("name","term_lang_choice").attr("value",b("#post_lang_choice").attr("value")))});b("#post_lang_choice").change(function(){var c={action:"post_lang_choice",lang:b(this).attr("value"),taxonomies:a,post_id:b("#post_ID").attr("value")};b.post(ajaxurl,c,function(d){var e=wpAjax.parseAjaxResponse(d,"ajax-response");b.each(e.responses,function(){switch(this.what){case"translations":b("#post-translations").html(this.data);break;case"taxonomy":var f=this.data;b("#"+f+"checklist").html(this.supplemental.all);b("#"+f+"checklist-pop").html(this.supplemental.populars);b("#new"+f+"_parent").replaceWith(this.supplemental.dropdown);b("#"+f+"-lang").val(b("#post_lang_choice").attr("value"));break;case"pages":b("#parent_id").replaceWith(this.data);break;default:break}});b(".tagcloud-link").each(function(){var f=b(this).attr("id");pll_tagBox.get(f,0)});pll_tagBox.suggest()})});if(b("#pll-tagsdiv-post_tag").length){pll_tagBox.init()}else{b("#side-sortables, #normal-sortables, #advanced-sortables").children("div.postbox").each(function(){if(this.id.indexOf("pll-tagsdiv-")===0){pll_tagBox.init();return false}})}jQuery("a.editinline").live("click",function(){inlineEditPost.revert();var c=inlineEditPost.getId(this);var d=b("input[name='lang_"+c+"']").attr("value");b("#post_lang_choice option:selected").removeAttr("selected");b('#post_lang_choice option[value="'+d+'"]').attr("selected","selected")});b(".media_lang_choice").change(function(){var c={action:"media_lang_choice",lang:b(this).attr("value"),post_id:b(this).attr("name")};b.post(ajaxurl,c,function(d){var e=wpAjax.parseAjaxResponse(d,"ajax-response");b.each(e.responses,function(){switch(this.what){case"translations":b(".translations").html(this.data);b(".compat-field-translations").html(this.data);break;default:break}})})})});
polylang.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Polylang
4
  Plugin URI: http://wordpress.org/extend/plugins/polylang/
5
- Version: 0.9.5
6
  Author: F. Demarle
7
  Description: Adds multilingual capability to Wordpress
8
  Text Domain: polylang
@@ -26,7 +26,7 @@ Domain Path: /languages
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
29
- define('POLYLANG_VERSION', '0.9.5');
30
  define('PLL_MIN_WP_VERSION', '3.1');
31
 
32
  define('POLYLANG_DIR', dirname(__FILE__)); // our directory
@@ -119,7 +119,7 @@ class Polylang extends Polylang_Base {
119
 
120
  // check if it is a network activation - if so, run the activation function for each blog
121
  if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
122
- foreach ($wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs")) as $blog_id) {
123
  switch_to_blog($blog_id);
124
  $this->_activate();
125
  }
@@ -180,7 +180,7 @@ class Polylang extends Polylang_Base {
180
 
181
  // check if it is a network deactivation - if so, run the deactivation function for each blog
182
  if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
183
- foreach ($wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs")) as $blog_id) {
184
  switch_to_blog($blog_id);
185
  $this->_deactivate();
186
  }
@@ -298,10 +298,8 @@ class Polylang extends Polylang_Base {
298
  if (version_compare($options['version'], '0.8.8', '<'))
299
  flush_rewrite_rules(); // rewrite rules have been modified in 0.8.8
300
 
301
- if (version_compare($options['version'], '0.9', '<')) {
302
- if (defined('PLL_SYNC'))
303
- $options['sync'] = PLL_SYNC ? 1 : 0; // the option replaces PLL_SYNC in 0.9
304
- }
305
 
306
  $options['version'] = POLYLANG_VERSION;
307
  update_option('polylang', $options);
2
  /*
3
  Plugin Name: Polylang
4
  Plugin URI: http://wordpress.org/extend/plugins/polylang/
5
+ Version: 0.9.6
6
  Author: F. Demarle
7
  Description: Adds multilingual capability to Wordpress
8
  Text Domain: polylang
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
29
+ define('POLYLANG_VERSION', '0.9.6');
30
  define('PLL_MIN_WP_VERSION', '3.1');
31
 
32
  define('POLYLANG_DIR', dirname(__FILE__)); // our directory
119
 
120
  // check if it is a network activation - if so, run the activation function for each blog
121
  if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
122
+ foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
123
  switch_to_blog($blog_id);
124
  $this->_activate();
125
  }
180
 
181
  // check if it is a network deactivation - if so, run the deactivation function for each blog
182
  if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
183
+ foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
184
  switch_to_blog($blog_id);
185
  $this->_deactivate();
186
  }
298
  if (version_compare($options['version'], '0.8.8', '<'))
299
  flush_rewrite_rules(); // rewrite rules have been modified in 0.8.8
300
 
301
+ if (version_compare($options['version'], '0.9', '<'))
302
+ $options['sync'] = defined('PLL_SYNC') && !PLL_SYNC ? 0 : 1; // the option replaces PLL_SYNC in 0.9
 
 
303
 
304
  $options['version'] = POLYLANG_VERSION;
305
  update_option('polylang', $options);
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, i18n, international, l10n, localization
5
  Requires at least: 3.1
6
  Tested up to: 3.4.2
7
- Stable tag: 0.9.5
8
  License: GPLv2 or later
9
 
10
  Polylang adds multilingual content management support to WordPress.
@@ -93,6 +93,14 @@ Every suggestions are welcome.
93
 
94
  == Changelog ==
95
 
 
 
 
 
 
 
 
 
96
  = 0.9.5 (2012-11-13) =
97
 
98
  * The user can now choose the number of languages and strings translations to display
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, i18n, international, l10n, localization
5
  Requires at least: 3.1
6
  Tested up to: 3.4.2
7
+ Stable tag: 0.9.6
8
  License: GPLv2 or later
9
 
10
  Polylang adds multilingual content management support to WordPress.
93
 
94
  == Changelog ==
95
 
96
+ = 0.9.6 (2012-11-26) =
97
+
98
+ * It is now possible to query the terms by language using the WordPress function 'get_terms'
99
+ * Bug correction: search for empty string in default language displays posts in all languages when hiding the URL language information for default language
100
+ * Bug correction: completely reworked the canonical redirection introduced in 0.9.5 which created more problems than it solved
101
+ * Bug correction: ajax for media translations does not work
102
+ * Started tests with WordPress 3.5 beta RC1
103
+
104
  = 0.9.5 (2012-11-13) =
105
 
106
  * The user can now choose the number of languages and strings translations to display
uninstall.php CHANGED
@@ -7,7 +7,7 @@ class Polylang_Uninstall {
7
 
8
  // check if it is a multisite uninstall - if so, run the uninstall function for each blog id
9
  if (is_multisite()) {
10
- foreach ($wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs")) as $blog_id) {
11
  switch_to_blog($blog_id);
12
  $this->uninstall();
13
  }
@@ -57,7 +57,7 @@ class Polylang_Uninstall {
57
  $table = $wpdb->termmeta;
58
  $count = $wpdb->get_var("SELECT COUNT(*) FROM $table;");
59
  if (!$count) {
60
- $wpdb->query($wpdb->prepare("DROP TABLE $table;"));
61
  unset($wpdb->termmeta);
62
  }
63
 
7
 
8
  // check if it is a multisite uninstall - if so, run the uninstall function for each blog id
9
  if (is_multisite()) {
10
+ foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
11
  switch_to_blog($blog_id);
12
  $this->uninstall();
13
  }
57
  $table = $wpdb->termmeta;
58
  $count = $wpdb->get_var("SELECT COUNT(*) FROM $table;");
59
  if (!$count) {
60
+ $wpdb->query("DROP TABLE $table;");
61
  unset($wpdb->termmeta);
62
  }
63