Polylang - Version 2.2.4

Version Description

(2017-10-26) =

  • Pro: Fix unknown language not redirected to default when using multiple domains
  • Pro: Fix empty 'lang' query var not deactivating the language query filter
  • Pro: Fix conflict with The Events Calendar and Visual Composer when used together
  • Add new filter pll_hide_archive_translation_url #174
  • Add support for undocumented and deprecated WPML functions wpml_object_id_filter and icl_get_current_language
  • Fix 'orderby' and 'order' in wpml_active_languages. Needs WP 4.7+
  • Fix icl_get_languages not returning all languages when skip_missing
Download this release

Release Info

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

Code changes from version 2.2.3 to 2.2.4

frontend/frontend-auto-translate.php CHANGED
@@ -152,16 +152,30 @@ class PLL_Frontend_Auto_Translate {
152
  }
153
  }
154
 
155
- // name, pagename can only take one slug
156
- foreach ( array( 'name', 'pagename' ) as $key ) {
157
- if ( ! empty( $qv[ $key ] ) ) {
 
 
 
 
 
 
 
 
158
  // no function to get post by name except get_posts itself
159
- $post_type = empty( $qv['post_type'] ) ? 'post' : $qv['post_type'];
160
- $id = $wpdb->get_var( $wpdb->prepare( "SELECT ID from $wpdb->posts WHERE post_type=%s AND post_name=%s", $post_type, $qv[ $key ] ) );
161
- $qv[ $key ] = ( $id && ( $tr_id = $this->get_post( $id ) ) && $tr = get_post( $tr_id ) ) ? $tr->post_name : $qv[ $key ];
162
  }
163
  }
164
 
 
 
 
 
 
 
165
  // array of post ids
166
  // post_parent__in & post_parent__not_in since WP 3.6
167
  foreach ( array( 'post__in', 'post__not_in', 'post_parent__in', 'post_parent__not_in' ) as $key ) {
@@ -194,7 +208,7 @@ class PLL_Frontend_Auto_Translate {
194
  * @return array modified $args
195
  */
196
  public function get_terms_args( $args, $taxonomies ) {
197
- if ( ! empty( $args['include'] ) && $this->model->is_translated_taxonomy( $taxonomies ) ) {
198
  foreach ( wp_parse_id_list( $args['include'] ) as $id ) {
199
  $arr[] = ( $tr = $this->get_term( $id ) ) ? $tr : $id;
200
  }
152
  }
153
  }
154
 
155
+ // name, can only take one slug
156
+ if ( ! empty( $qv['name'] ) ) {
157
+ if ( empty( $qv['post_type'] ) ) {
158
+ $post_types = array( 'post' );
159
+ } elseif ( 'any' === $qv['post_type'] ) {
160
+ $post_types = get_post_types( array('exclude_from_search' => false) ); // May return a empty array
161
+ } else {
162
+ $post_types = (array) $qv['post_type'];
163
+ }
164
+
165
+ if ( ! empty( $post_types ) ) {
166
  // no function to get post by name except get_posts itself
167
+ $where = "{$wpdb->posts}.post_type IN ('" . implode( "', '", esc_sql( $post_types ) ) . "')";
168
+ $id = $wpdb->get_var( $wpdb->prepare( "SELECT ID from {$wpdb->posts} WHERE {$where} AND post_name=%s", $qv['name'] ) );
169
+ $qv['name'] = ( $id && ( $tr_id = $this->get_post( $id ) ) && $tr = get_post( $tr_id ) ) ? $tr->post_name : $qv['name'];
170
  }
171
  }
172
 
173
+ // pagename, the page id is already available in queried_object_id
174
+ if ( ! empty( $qv['pagename'] ) && ! empty( $query->queried_object_id ) && $tr_id = $this->get_post( $query->queried_object_id ) ) {
175
+ $query->queried_object_id = $tr_id;
176
+ $qv['pagename'] = get_page_uri( $tr_id );
177
+ }
178
+
179
  // array of post ids
180
  // post_parent__in & post_parent__not_in since WP 3.6
181
  foreach ( array( 'post__in', 'post__not_in', 'post_parent__in', 'post_parent__not_in' ) as $key ) {
208
  * @return array modified $args
209
  */
210
  public function get_terms_args( $args, $taxonomies ) {
211
+ if ( ! empty( $args['include'] ) && ( empty( $taxonomies ) || $this->model->is_translated_taxonomy( $taxonomies ) ) ) {
212
  foreach ( wp_parse_id_list( $args['include'] ) as $id ) {
213
  $arr[] = ( $tr = $this->get_term( $id ) ) ? $tr : $id;
214
  }
frontend/frontend-filters.php CHANGED
@@ -42,9 +42,7 @@ class PLL_Frontend_Filters extends PLL_Filters {
42
  add_filter( 'sidebars_widgets', array( $this, 'sidebars_widgets' ) );
43
 
44
  if ( $this->options['media_support'] ) {
45
- foreach ( array( 'audio', 'image', 'video' ) as $media ) {
46
- add_filter( "widget_media_{$media}_instance", array( $this, 'widget_media_instance' ), 1 ); // Since WP 4.8
47
- }
48
  }
49
 
50
  // Strings translation ( must be applied before WordPress applies its default formatting filters )
42
  add_filter( 'sidebars_widgets', array( $this, 'sidebars_widgets' ) );
43
 
44
  if ( $this->options['media_support'] ) {
45
+ add_filter( 'widget_media_image_instance', array( $this, 'widget_media_instance' ), 1 ); // Since WP 4.8
 
 
46
  }
47
 
48
  // Strings translation ( must be applied before WordPress applies its default formatting filters )
frontend/frontend-links.php CHANGED
@@ -1,16 +1,16 @@
1
  <?php
2
 
3
  /**
4
- * manages links filters and url of translations on frontend
5
  *
6
  * @since 1.2
7
  */
8
  class PLL_Frontend_Links extends PLL_Links {
9
  public $curlang;
10
- public $cache; // our internal non persistent cache object
11
 
12
  /**
13
- * constructor
14
  *
15
  * @since 1.2
16
  *
@@ -25,7 +25,7 @@ class PLL_Frontend_Links extends PLL_Links {
25
  }
26
 
27
  /**
28
- * returns the url of the translation ( if exists ) of the current page
29
  *
30
  * @since 0.1
31
  *
@@ -39,8 +39,8 @@ class PLL_Frontend_Links extends PLL_Links {
39
  return $translation_url;
40
  }
41
 
42
- // make sure that we have the queried object
43
- // see https://wordpress.org/support/topic/patch-for-fixing-a-notice
44
  $queried_object_id = $wp_query->get_queried_object_id();
45
 
46
  /**
@@ -49,20 +49,20 @@ class PLL_Frontend_Links extends PLL_Links {
49
  *
50
  * @since 1.8
51
  *
52
- * @param string $url empty or the url of the translation of teh current page
53
- * @param object $language language of the translation
54
- * @param int $queried_object_id queried object id
55
  */
56
  if ( ! $url = apply_filters( 'pll_pre_translation_url', '', $language, $queried_object_id ) ) {
57
  $qv = $wp_query->query_vars;
58
  $hide = $this->options['default_lang'] == $language->slug && $this->options['hide_default'];
59
 
60
- // post and attachment
61
  if ( is_single() && ( $this->options['media_support'] || ! is_attachment() ) && ( $id = $this->model->post->get( $queried_object_id, $language ) ) && $this->current_user_can_read( $id ) ) {
62
  $url = get_permalink( $id );
63
  }
64
 
65
- // page
66
  elseif ( is_page() && ( $id = $this->model->post->get( $queried_object_id, $language ) ) && $this->current_user_can_read( $id ) ) {
67
  $url = get_page_link( $id );
68
  }
@@ -70,17 +70,17 @@ class PLL_Frontend_Links extends PLL_Links {
70
  elseif ( is_search() ) {
71
  $url = $this->get_archive_url( $language );
72
 
73
- // special case for search filtered by translated taxonomies: taxonomy terms are translated in the translation url
74
  if ( ! empty( $wp_query->tax_query->queries ) ) {
75
  foreach ( $wp_query->tax_query->queries as $tax_query ) {
76
  if ( ! empty( $tax_query['taxonomy'] ) && $this->model->is_translated_taxonomy( $tax_query['taxonomy'] ) ) {
77
 
78
  $tax = get_taxonomy( $tax_query['taxonomy'] );
79
- $terms = get_terms( $tax->name, array( 'fields' => 'id=>slug' ) ); // filtered by current language
80
 
81
  foreach ( $tax_query['terms'] as $slug ) {
82
- $term_id = array_search( $slug, $terms ); // what is the term_id corresponding to taxonomy term?
83
- if ( $term_id && $term_id = $this->model->term->get_translation( $term_id, $language ) ) { // get the translated term_id
84
  $term = get_term( $term_id, $tax->name );
85
  $url = str_replace( $slug, $term->slug, $url );
86
  }
@@ -90,42 +90,64 @@ class PLL_Frontend_Links extends PLL_Links {
90
  }
91
  }
92
 
93
- // translated taxonomy
94
- // take care that is_tax() is false for categories and tags
95
  elseif ( ( is_category() || is_tag() || is_tax() ) && ( $term = get_queried_object() ) && $this->model->is_translated_taxonomy( $term->taxonomy ) ) {
96
  $lang = $this->model->term->get_language( $term->term_id );
97
 
98
  if ( ! $lang || $language->slug == $lang->slug ) {
99
- $url = wpcom_vip_get_term_link( $term, $term->taxonomy ); // self link
100
  }
101
 
102
  elseif ( $tr_id = $this->model->term->get_translation( $term->term_id, $language ) ) {
103
- $tr_term = get_term( $tr_id, $term->taxonomy );
104
- // check if translated term ( or children ) have posts
105
- if ( $tr_term && ( $tr_term->count || ( is_taxonomy_hierarchical( $term->taxonomy ) && array_sum( wp_list_pluck( get_terms( $term->taxonomy, array( 'child_of' => $tr_term->term_id, 'lang' => $language->slug ) ), 'count' ) ) ) ) ) {
106
- $url = wpcom_vip_get_term_link( $tr_term, $term->taxonomy );
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
108
  }
109
  }
110
 
111
- // post type archive
112
  elseif ( is_post_type_archive() ) {
113
- if ( $this->model->is_translated_post_type( $qv['post_type'] ) && $this->model->count_posts( $language, array( 'post_type' => $qv['post_type'] ) ) ) {
114
- $url = $this->get_archive_url( $language );
 
 
 
 
 
 
115
  }
116
  }
117
 
 
118
  elseif ( is_archive() ) {
119
  $keys = array( 'post_type', 'm', 'year', 'monthnum', 'day', 'author', 'author_name' );
120
  $keys = array_merge( $keys, $this->model->get_filtered_taxonomies_query_vars() );
 
 
121
 
122
- // check if there are existing translations before creating the url
123
- if ( $this->model->count_posts( $language, array_intersect_key( $qv, array_flip( $keys ) ) ) ) {
124
  $url = $this->get_archive_url( $language );
125
  }
126
  }
127
 
128
- // front page when it is the list of posts
129
  elseif ( is_front_page() ) {
130
  $url = $this->get_home_url( $language );
131
  }
@@ -136,8 +158,8 @@ class PLL_Frontend_Links extends PLL_Links {
136
  *
137
  * @since 1.1.2
138
  *
139
- * @param null|string $url the translation url, null if none was found
140
- * @param string $language the language code of the translation
141
  */
142
  $translation_url = apply_filters( 'pll_translation_url', ( isset( $url ) && ! is_wp_error( $url ) ? $url : null ), $language->slug );
143
  $this->cache->set( 'translation_url:' . $language->slug, $translation_url );
@@ -145,7 +167,7 @@ class PLL_Frontend_Links extends PLL_Links {
145
  }
146
 
147
  /**
148
- * get the translation of the current archive url
149
  * used also for search
150
  *
151
  * @since 1.2
@@ -163,14 +185,14 @@ class PLL_Frontend_Links extends PLL_Links {
163
  *
164
  * @since 1.6
165
  *
166
- * @param string $url url of the archive
167
- * @param object $language language of the archive
168
  */
169
  return apply_filters( 'pll_get_archive_url', $url, $language );
170
  }
171
 
172
  /**
173
- * returns the home url in the right language
174
  *
175
  * @since 0.1
176
  *
1
  <?php
2
 
3
  /**
4
+ * Manages links filters and url of translations on frontend
5
  *
6
  * @since 1.2
7
  */
8
  class PLL_Frontend_Links extends PLL_Links {
9
  public $curlang;
10
+ public $cache; // Our internal non persistent cache object
11
 
12
  /**
13
+ * Constructor
14
  *
15
  * @since 1.2
16
  *
25
  }
26
 
27
  /**
28
+ * Returns the url of the translation ( if exists ) of the current page
29
  *
30
  * @since 0.1
31
  *
39
  return $translation_url;
40
  }
41
 
42
+ // Make sure that we have the queried object
43
+ // See https://wordpress.org/support/topic/patch-for-fixing-a-notice
44
  $queried_object_id = $wp_query->get_queried_object_id();
45
 
46
  /**
49
  *
50
  * @since 1.8
51
  *
52
+ * @param string $url Empty or the url of the translation of teh current page
53
+ * @param object $language Language of the translation
54
+ * @param int $queried_object_id Queried object id
55
  */
56
  if ( ! $url = apply_filters( 'pll_pre_translation_url', '', $language, $queried_object_id ) ) {
57
  $qv = $wp_query->query_vars;
58
  $hide = $this->options['default_lang'] == $language->slug && $this->options['hide_default'];
59
 
60
+ // Post and attachment
61
  if ( is_single() && ( $this->options['media_support'] || ! is_attachment() ) && ( $id = $this->model->post->get( $queried_object_id, $language ) ) && $this->current_user_can_read( $id ) ) {
62
  $url = get_permalink( $id );
63
  }
64
 
65
+ // Page
66
  elseif ( is_page() && ( $id = $this->model->post->get( $queried_object_id, $language ) ) && $this->current_user_can_read( $id ) ) {
67
  $url = get_page_link( $id );
68
  }
70
  elseif ( is_search() ) {
71
  $url = $this->get_archive_url( $language );
72
 
73
+ // Special case for search filtered by translated taxonomies: taxonomy terms are translated in the translation url
74
  if ( ! empty( $wp_query->tax_query->queries ) ) {
75
  foreach ( $wp_query->tax_query->queries as $tax_query ) {
76
  if ( ! empty( $tax_query['taxonomy'] ) && $this->model->is_translated_taxonomy( $tax_query['taxonomy'] ) ) {
77
 
78
  $tax = get_taxonomy( $tax_query['taxonomy'] );
79
+ $terms = get_terms( $tax->name, array( 'fields' => 'id=>slug' ) ); // Filtered by current language
80
 
81
  foreach ( $tax_query['terms'] as $slug ) {
82
+ $term_id = array_search( $slug, $terms ); // What is the term_id corresponding to taxonomy term?
83
+ if ( $term_id && $term_id = $this->model->term->get_translation( $term_id, $language ) ) { // Get the translated term_id
84
  $term = get_term( $term_id, $tax->name );
85
  $url = str_replace( $slug, $term->slug, $url );
86
  }
90
  }
91
  }
92
 
93
+ // Translated taxonomy
94
+ // Take care that is_tax() is false for categories and tags
95
  elseif ( ( is_category() || is_tag() || is_tax() ) && ( $term = get_queried_object() ) && $this->model->is_translated_taxonomy( $term->taxonomy ) ) {
96
  $lang = $this->model->term->get_language( $term->term_id );
97
 
98
  if ( ! $lang || $language->slug == $lang->slug ) {
99
+ $url = wpcom_vip_get_term_link( $term, $term->taxonomy ); // Self link
100
  }
101
 
102
  elseif ( $tr_id = $this->model->term->get_translation( $term->term_id, $language ) ) {
103
+ if ( $tr_term = get_term( $tr_id, $term->taxonomy ) ) {
104
+ // Check if translated term ( or children ) have posts
105
+ $count = $tr_term->count || ( is_taxonomy_hierarchical( $term->taxonomy ) && array_sum( wp_list_pluck( get_terms( $term->taxonomy, array( 'child_of' => $tr_term->term_id, 'lang' => $language->slug ) ), 'count' ) ) );
106
+
107
+ /**
108
+ * Filter whether to hide an archive translation url
109
+ *
110
+ * @since 2.2.4
111
+ *
112
+ * @param bool $hide True to hide the translation url.
113
+ * defaults to true when the translated archive is empty, false otherwise.
114
+ * @param string $lang The language code of the translation
115
+ * @param array $args Arguments used to evaluated the number of posts in the archive
116
+ */
117
+ if ( ! apply_filters( 'pll_hide_archive_translation_url', ! $count , $language->slug, array( 'taxonomy' => $term->taxonomy ) ) ) {
118
+ $url = wpcom_vip_get_term_link( $tr_term, $term->taxonomy );
119
+ }
120
  }
121
  }
122
  }
123
 
124
+ // Post type archive
125
  elseif ( is_post_type_archive() ) {
126
+ if ( $this->model->is_translated_post_type( $qv['post_type'] ) ) {
127
+ $args = array( 'post_type' => $qv['post_type'] );
128
+ $count = $this->model->count_posts( $language, $args );
129
+
130
+ /** This filter is documented in frontend/frontend-links.php */
131
+ if ( ! apply_filters( 'pll_hide_archive_translation_url', ! $count , $language->slug, $args ) ) {
132
+ $url = $this->get_archive_url( $language );
133
+ }
134
  }
135
  }
136
 
137
+ // Other archives
138
  elseif ( is_archive() ) {
139
  $keys = array( 'post_type', 'm', 'year', 'monthnum', 'day', 'author', 'author_name' );
140
  $keys = array_merge( $keys, $this->model->get_filtered_taxonomies_query_vars() );
141
+ $args = array_intersect_key( $qv, array_flip( $keys ) );
142
+ $count = $this->model->count_posts( $language, $args );
143
 
144
+ /** This filter is documented in frontend/frontend-links.php */
145
+ if ( ! apply_filters( 'pll_hide_archive_translation_url', ! $count , $language->slug, $args ) ) {
146
  $url = $this->get_archive_url( $language );
147
  }
148
  }
149
 
150
+ // Front page when it is the list of posts
151
  elseif ( is_front_page() ) {
152
  $url = $this->get_home_url( $language );
153
  }
158
  *
159
  * @since 1.1.2
160
  *
161
+ * @param null|string $url The translation url, null if none was found
162
+ * @param string $language The language code of the translation
163
  */
164
  $translation_url = apply_filters( 'pll_translation_url', ( isset( $url ) && ! is_wp_error( $url ) ? $url : null ), $language->slug );
165
  $this->cache->set( 'translation_url:' . $language->slug, $translation_url );
167
  }
168
 
169
  /**
170
+ * Get the translation of the current archive url
171
  * used also for search
172
  *
173
  * @since 1.2
185
  *
186
  * @since 1.6
187
  *
188
+ * @param string $url Url of the archive
189
+ * @param object $language Language of the archive
190
  */
191
  return apply_filters( 'pll_get_archive_url', $url, $language );
192
  }
193
 
194
  /**
195
+ * Returns the home url in the right language
196
  *
197
  * @since 0.1
198
  *
frontend/frontend.php CHANGED
@@ -81,6 +81,11 @@ class PLL_Frontend extends PLL_Base {
81
  $this->filters_links = new PLL_Frontend_Filters_Links( $this );
82
  $this->filters = new PLL_Frontend_Filters( $this );
83
  $this->filters_search = new PLL_Frontend_Filters_Search( $this );
 
 
 
 
 
84
  }
85
 
86
  /**
81
  $this->filters_links = new PLL_Frontend_Filters_Links( $this );
82
  $this->filters = new PLL_Frontend_Filters( $this );
83
  $this->filters_search = new PLL_Frontend_Filters_Search( $this );
84
+
85
+ // Auto translate for Ajax
86
+ if ( ( ! defined( 'PLL_AUTO_TRANSLATE' ) || PLL_AUTO_TRANSLATE ) && wp_doing_ajax() ) {
87
+ $this->auto_translate();
88
+ }
89
  }
90
 
91
  /**
include/api.php CHANGED
@@ -193,7 +193,7 @@ function pll_esc_attr_e( $string ) {
193
  * @return string the string translation in the requested language
194
  */
195
  function pll_translate_string( $string, $lang ) {
196
- if ( pll_current_language() == $lang ) {
197
  return pll__( $string );
198
  }
199
 
193
  * @return string the string translation in the requested language
194
  */
195
  function pll_translate_string( $string, $lang ) {
196
+ if ( PLL() instanceof PLL_Frontend && pll_current_language() == $lang ) {
197
  return pll__( $string );
198
  }
199
 
include/model.php CHANGED
@@ -242,7 +242,7 @@ class PLL_Model {
242
  */
243
  public function is_translated_post_type( $post_type ) {
244
  $post_types = $this->get_translated_post_types( false );
245
- return ( is_array( $post_type ) && array_intersect( $post_type, $post_types ) || in_array( $post_type, $post_types ) );
246
  }
247
 
248
  /**
242
  */
243
  public function is_translated_post_type( $post_type ) {
244
  $post_types = $this->get_translated_post_types( false );
245
+ return ( is_array( $post_type ) && array_intersect( $post_type, $post_types ) || in_array( $post_type, $post_types ) || 'any' === $post_type && ! empty( $post_types ) );
246
  }
247
 
248
  /**
include/query.php CHANGED
@@ -53,14 +53,16 @@ class PLL_Query {
53
  * @return bool
54
  */
55
  protected function have_translated_taxonomy( $tax_queries ) {
56
- foreach ( $tax_queries as $tax_query ) {
57
- if ( isset( $tax_query['taxonomy'] ) && $this->model->is_translated_taxonomy( $tax_query['taxonomy'] ) && ! ( isset( $tax_query['operator'] ) && 'NOT IN' === $tax_query['operator'] ) ) {
58
- return true;
59
- }
 
60
 
61
- // Nested queries
62
- elseif ( is_array( $tax_query ) && $this->have_translated_taxonomy( $tax_query ) ) {
63
- return true;
 
64
  }
65
  }
66
 
@@ -132,7 +134,7 @@ class PLL_Query {
132
  }
133
  }
134
 
135
- if ( ! empty( $qvars['tax_query'] ) && is_array( $qvars['tax_query'] ) && $this->have_translated_taxonomy( $qvars['tax_query'] ) ) {
136
  return;
137
  }
138
 
@@ -154,7 +156,7 @@ class PLL_Query {
154
  }
155
  } else {
156
  // Do not filter untranslatable post types such as nav_menu_item
157
- if ( isset( $qvars['post_type'] ) && ! $this->model->is_translated_post_type( $qvars['post_type'] ) ) {
158
  unset( $qvars['lang'] );
159
  }
160
 
53
  * @return bool
54
  */
55
  protected function have_translated_taxonomy( $tax_queries ) {
56
+ if ( is_array( $tax_queries ) ) {
57
+ foreach ( $tax_queries as $tax_query ) {
58
+ if ( isset( $tax_query['taxonomy'] ) && $this->model->is_translated_taxonomy( $tax_query['taxonomy'] ) && ! ( isset( $tax_query['operator'] ) && 'NOT IN' === $tax_query['operator'] ) ) {
59
+ return true;
60
+ }
61
 
62
+ // Nested queries
63
+ elseif ( is_array( $tax_query ) && $this->have_translated_taxonomy( $tax_query ) ) {
64
+ return true;
65
+ }
66
  }
67
  }
68
 
134
  }
135
  }
136
 
137
+ if ( ! empty( $qvars['tax_query'] ) && $this->have_translated_taxonomy( $qvars['tax_query'] ) ) {
138
  return;
139
  }
140
 
156
  }
157
  } else {
158
  // Do not filter untranslatable post types such as nav_menu_item
159
+ if ( isset( $qvars['post_type'] ) && ! $this->model->is_translated_post_type( $qvars['post_type'] ) && ( empty( $qvars['tax_query'] ) || ! $this->have_translated_taxonomy( $qvars['tax_query'] ) ) ) {
160
  unset( $qvars['lang'] );
161
  }
162
 
modules/plugins/plugins-compat.php CHANGED
@@ -560,10 +560,14 @@ class PLL_Plugins_Compat {
560
  *
561
  * @since 1.8
562
  *
563
- * @param array $taxonomies
564
  * @return array
565
  */
566
  function duplicate_post_taxonomies_blacklist( $taxonomies ) {
 
 
 
 
567
  $taxonomies[] = 'post_translations';
568
  return $taxonomies;
569
  }
560
  *
561
  * @since 1.8
562
  *
563
+ * @param array|string $taxonomies
564
  * @return array
565
  */
566
  function duplicate_post_taxonomies_blacklist( $taxonomies ) {
567
+ if ( empty( $taxonomies ) ) {
568
+ $taxonomies = array(); // As we get an empty string when there is no taxonomy
569
+ }
570
+
571
  $taxonomies[] = 'post_translations';
572
  return $taxonomies;
573
  }
modules/wpml/wpml-legacy-api.php CHANGED
@@ -26,15 +26,15 @@ if ( ! function_exists( 'icl_get_languages' ) ) {
26
  *
27
  * list of paramaters accepted in $args
28
  *
29
- * skip_missing => wether to skip missing translation or not, 0 or 1, defaults to 0
30
  * orderby => 'id', 'code', 'name', defaults to 'id'
31
  * order => 'ASC' or 'DESC', defaults to 'ASC'
32
  * link_empty_to => link to use when the translation is missing {$lang} is replaced by the language code
33
  *
34
- * list of parameters returned per language:
35
  *
36
  * id => the language id
37
- * active => wether this is the active language or no, 0 or 1
38
  * native_name => the language name
39
  * missing => wether the translation is missing or not, 0 or 1
40
  * translated_name => empty, does not exist in Polylang
@@ -54,7 +54,15 @@ if ( ! function_exists( 'icl_get_languages' ) ) {
54
 
55
  $arr = array();
56
 
57
- foreach ( PLL()->model->get_languages_list( array( 'hide_empty' => true, 'orderby' => $orderby, 'order' => $order ) ) as $lang ) {
 
 
 
 
 
 
 
 
58
  // We can find a translation only on frontend
59
  if ( method_exists( PLL()->links, 'get_translation_url' ) ) {
60
  $url = PLL()->links->get_translation_url( $lang );
@@ -167,6 +175,23 @@ if ( ! function_exists( 'icl_object_id' ) ) {
167
  }
168
  }
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  if ( ! function_exists( 'wpml_get_language_information' ) ) {
171
  /**
172
  * Undocumented function used by the theme Maya
@@ -330,3 +355,16 @@ if ( ! function_exists( 'wpml_get_default_language' ) ) {
330
  return pll_default_language();
331
  }
332
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  *
27
  * list of paramaters accepted in $args
28
  *
29
+ * skip_missing => whether to skip missing translation or not, 0 or 1, defaults to 0
30
  * orderby => 'id', 'code', 'name', defaults to 'id'
31
  * order => 'ASC' or 'DESC', defaults to 'ASC'
32
  * link_empty_to => link to use when the translation is missing {$lang} is replaced by the language code
33
  *
34
+ * List of parameters returned per language:
35
  *
36
  * id => the language id
37
+ * active => whether this is the active language or no, 0 or 1
38
  * native_name => the language name
39
  * missing => wether the translation is missing or not, 0 or 1
40
  * translated_name => empty, does not exist in Polylang
54
 
55
  $arr = array();
56
 
57
+ // NB: When 'skip_missing' is false, WPML returns all languages even if there is no content
58
+ $languages = PLL()->model->get_languages_list( array( 'hide_empty' => $args['skip_missing'] ) );
59
+
60
+ // FIXME: Backward compatibility with WP < 4.7
61
+ if ( function_exists( 'wp_list_sort' ) ) {
62
+ $languages = wp_list_sort( $languages, $orderby, $order ); // Since WP 4.7
63
+ }
64
+
65
+ foreach ( $languages as $lang ) {
66
  // We can find a translation only on frontend
67
  if ( method_exists( PLL()->links, 'get_translation_url' ) ) {
68
  $url = PLL()->links->get_translation_url( $lang );
175
  }
176
  }
177
 
178
+ if ( ! function_exists( 'wpml_object_id_filter' ) ) {
179
+ /**
180
+ * Undocumented alias of `icl_object_id` introduced in WPML 3.2, used by Yith WooCommerce compare
181
+ *
182
+ * @since 2.2.4
183
+ *
184
+ * @param int $id object id
185
+ * @param string $type optional, post type or taxonomy name of the object, defaults to 'post'
186
+ * @param bool $return_original_if_missing optional, true if Polylang should return the original id if the translation is missing, defaults to false
187
+ * @param string $lang optional, language code, defaults to current language
188
+ * @return int|null the object id of the translation, null if the translation is missing and $return_original_if_missing set to false
189
+ */
190
+ function wpml_object_id_filter( $id, $type = 'post', $return_original_if_missing = false, $lang = null ) {
191
+ return icl_object_id( $id, $type, $return_original_if_missing, $lang );
192
+ }
193
+ }
194
+
195
  if ( ! function_exists( 'wpml_get_language_information' ) ) {
196
  /**
197
  * Undocumented function used by the theme Maya
355
  return pll_default_language();
356
  }
357
  }
358
+
359
+ if ( ! function_exists( 'icl_get_current_language' ) ) {
360
+ /**
361
+ * Undocumented function used by Ultimate Member
362
+ *
363
+ * @since 2.2.4
364
+ *
365
+ * @return string Current language code
366
+ */
367
+ function icl_get_current_language() {
368
+ return pll_current_language();
369
+ }
370
+ }
polylang.php CHANGED
@@ -3,7 +3,7 @@
3
  /**
4
  Plugin Name: Polylang
5
  Plugin URI: https://polylang.pro
6
- Version: 2.2.3
7
  Author: Frédéric Demarle
8
  Author uri: https://polylang.pro
9
  Description: Adds multilingual capability to WordPress
@@ -35,7 +35,7 @@ if ( ! defined( 'ABSPATH' ) ) {
35
  exit; // don't access directly
36
  };
37
 
38
- define( 'POLYLANG_VERSION', '2.2.3' );
39
  define( 'PLL_MIN_WP_VERSION', '4.4' );
40
 
41
  define( 'POLYLANG_FILE', __FILE__ ); // this file
3
  /**
4
  Plugin Name: Polylang
5
  Plugin URI: https://polylang.pro
6
+ Version: 2.2.4
7
  Author: Frédéric Demarle
8
  Author uri: https://polylang.pro
9
  Description: Adds multilingual capability to WordPress
35
  exit; // don't access directly
36
  };
37
 
38
+ define( 'POLYLANG_VERSION', '2.2.4' );
39
  define( 'PLL_MIN_WP_VERSION', '4.4' );
40
 
41
  define( 'POLYLANG_FILE', __FILE__ ); // this file
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: Chouby
3
  Donate link: https://polylang.pro
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
5
  Requires at least: 4.4
6
- Tested up to: 4.8
7
- Stable tag: 2.2.3
8
  License: GPLv2 or later
9
 
10
  Making WordPress multilingual
@@ -76,6 +76,24 @@ Don't hesitate to [give your feedback](http://wordpress.org/support/view/plugin-
76
 
77
  == Changelog ==
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  = 2.2.3 (2017-09-24) =
80
 
81
  * Fix editor removed on pages (introduced in 2.2.2)
3
  Donate link: https://polylang.pro
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
5
  Requires at least: 4.4
6
+ Tested up to: 4.9
7
+ Stable tag: 2.2.4
8
  License: GPLv2 or later
9
 
10
  Making WordPress multilingual
76
 
77
  == Changelog ==
78
 
79
+ = 2.2.4 (2017-10-26) =
80
+
81
+ * Pro: Fix unknown language not redirected to default when using multiple domains
82
+ * Pro: Fix empty 'lang' query var not deactivating the language query filter
83
+ * Pro: Fix conflict with The Events Calendar and Visual Composer when used together
84
+ * Add new filter `pll_hide_archive_translation_url` #174
85
+ * Add support for undocumented and deprecated WPML functions `wpml_object_id_filter` and `icl_get_current_language`
86
+ * Fix 'orderby' and 'order' in `wpml_active_languages`. Needs WP 4.7+
87
+ * Fix `icl_get_languages` not returning all languages when skip_missing = 0. Props Loïc Blascos
88
+ * Fix `pll_translate_string` not working on admin #178
89
+ * Fix PHP Warning in widget video in WP 4.9
90
+ * Fix query using 'any' post type not filtered per language (introduced in 2.2)
91
+ * Fix untranslatable string in About metabox. Props Farhad Sakhaei
92
+ * Fix error with PHP 7.1 and Duplicate Post. Props Enea Scerba
93
+ * Fix query auto translation not active in ajax requests on frontend
94
+ * Fix query auto translation for 'postname' and 'pagename'
95
+ * Fix terms query auto translation not working for 'include' when no taxonomy is provided (WP 4.5+)
96
+
97
  = 2.2.3 (2017-09-24) =
98
 
99
  * Fix editor removed on pages (introduced in 2.2.2)
settings/view-about.php CHANGED
@@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) {
20
  echo ' ';
21
  printf(
22
  /* translators: %s are html tags */
23
- esc_html__( 'Support and extra features are available to %sPolylang Pro%s users.' ),
24
  '<a href="https://polylang.pro">',
25
  '</a>'
26
  );
20
  echo ' ';
21
  printf(
22
  /* translators: %s are html tags */
23
+ esc_html__( 'Support and extra features are available to %sPolylang Pro%s users.', 'polylang' ),
24
  '<a href="https://polylang.pro">',
25
  '</a>'
26
  );