Polylang - Version 2.0.4

Version Description

(2016-09-06) =

  • Add Gujarati to the predefined languages list
  • Fix conflict with Page Builder. Other parts of the conflict are fixed in Page Builder 2.4.14
  • Fix plugins translations incorrectly loaded in WP 4.6
  • Fix error 404 on paged urls when using a non standard port
Download this release

Release Info

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

Code changes from version 2.0.3 to 2.0.4

frontend/frontend-filters-links.php CHANGED
@@ -1,18 +1,18 @@
1
  <?php
2
 
3
  /**
4
- * manages links filters on frontend
5
  *
6
  * @since 1.8
7
  */
8
  class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
9
  public $curlang;
10
- public $cache; // our internal non persistent cache object
11
 
12
  /**
13
- * constructor
14
- * adds filters once the language is defined
15
- * low priority on links filters to come after any other modification
16
  *
17
  * @since 1.8
18
  *
@@ -24,37 +24,37 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
24
  $this->curlang = &$polylang->curlang;
25
  $this->cache = new PLL_Cache();
26
 
27
- // rewrites author and date links to filter them by language
28
  foreach ( array( 'feed_link', 'author_link', 'search_link', 'year_link', 'month_link', 'day_link' ) as $filter ) {
29
  add_filter( $filter, array( $this, 'archive_link' ), 20 );
30
  }
31
 
32
- // rewrites post types archives links to filter them by language
33
  add_filter( 'post_type_archive_link', array( $this, 'post_type_archive_link' ), 20, 2 );
34
 
35
- // meta in the html head section
36
  add_action( 'wp_head', array( $this, 'wp_head' ) );
37
 
38
- // modifies the home url
39
  if ( ! defined( 'PLL_FILTER_HOME_URL' ) || PLL_FILTER_HOME_URL ) {
40
  add_filter( 'home_url', array( $this, 'home_url' ), 10, 2 );
41
  }
42
 
43
  if ( $this->options['force_lang'] > 1 ) {
44
- // rewrites next and previous post links when not automatically done by WordPress
45
  add_filter( 'get_pagenum_link', array( $this, 'archive_link' ), 20 );
46
 
47
- // rewrites ajax url
48
  add_filter( 'admin_url', array( $this, 'admin_url' ), 10, 2 );
49
  }
50
 
51
- // redirects to canonical url before WordPress redirect_canonical
52
  // but after Nextgen Gallery which hacks $_SERVER['REQUEST_URI'] !!! and restores it in 'template_redirect' with priority 1
53
  add_action( 'template_redirect', array( $this, 'check_canonical_url' ), 4 );
54
  }
55
 
56
  /**
57
- * modifies the author and date links to add the language parameter ( as well as feed link )
58
  *
59
  * @since 0.4
60
  *
@@ -66,7 +66,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
66
  }
67
 
68
  /**
69
- * modifies the post type archive links to add the language parameter
70
  * only if the post type is translated
71
  *
72
  * @since 1.7.6
@@ -80,8 +80,8 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
80
  }
81
 
82
  /**
83
- * modifies post & page links
84
- * caches the result
85
  *
86
  * @since 0.7
87
  *
@@ -99,8 +99,8 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
99
  }
100
 
101
  /**
102
- * modifies page links
103
- * caches the result
104
  *
105
  * @since 1.7
106
  *
@@ -118,8 +118,8 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
118
  }
119
 
120
  /**
121
- * modifies attachment links
122
- * caches the result
123
  *
124
  * @since 1.6.2
125
  *
@@ -137,8 +137,8 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
137
  }
138
 
139
  /**
140
- * modifies custom posts links
141
- * caches the result
142
  *
143
  * @since 1.6
144
  *
@@ -156,8 +156,8 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
156
  }
157
 
158
  /**
159
- * modifies filtered taxonomies ( post format like ) and translated taxonomies links
160
- * caches the result
161
  *
162
  * @since 0.7
163
  *
@@ -185,7 +185,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
185
  }
186
 
187
  /**
188
- * outputs references to translated pages ( if exists ) in the html head section
189
  *
190
  * @since 0.1
191
  */
@@ -197,10 +197,10 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
197
  }
198
  }
199
 
200
- // ouptputs the section only if there are translations ( $urls always contains self link )
201
- // don't output anything on paged archives: see https://wordpress.org/support/topic/hreflang-on-page2
202
  if ( ! empty( $urls ) && count( $urls ) > 1 && ! is_paged() ) {
203
- // prepare the list of languages to remove the country code
204
  foreach ( array_keys( $urls ) as $locale ) {
205
  $split = explode( '-', $locale );
206
  $languages[ $locale ] = reset( $split );
@@ -209,12 +209,12 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
209
  $count = array_count_values( $languages );
210
 
211
  foreach ( $urls as $locale => $url ) {
212
- $lang = $count[ $languages[ $locale ] ] > 1 ? $locale : $languages[ $locale ]; // output the country code only when necessary
213
  printf( '<link rel="alternate" href="%s" hreflang="%s" />'."\n", esc_url( $url ), esc_attr( $lang ) );
214
  }
215
 
216
- // adds the site root url when the default language code is not hidden
217
- // see https://wordpress.org/support/topic/implementation-of-hreflangx-default
218
  if ( is_front_page() && ! $this->options['hide_default'] && $this->options['force_lang'] < 3 ) {
219
  printf( '<link rel="alternate" href="%s" hreflang="x-default" />'."\n", esc_url( home_url( '/' ) ) );
220
  }
@@ -222,7 +222,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
222
  }
223
 
224
  /**
225
- * filters the home url to get the right language
226
  *
227
  * @since 0.4
228
  *
@@ -235,12 +235,12 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
235
  return $url;
236
  }
237
 
238
- static $white_list, $black_list; // avoid evaluating this at each function call
239
 
240
- // we *want* to filter the home url in these cases
241
  if ( empty( $white_list ) ) {
242
- // on Windows get_theme_root() mixes / and \
243
- // we want only \ for the comparison with debug_backtrace
244
  $theme_root = get_theme_root();
245
  $theme_root = ( false === strpos( $theme_root, '\\' ) ) ? $theme_root : str_replace( '/', '\\', $theme_root );
246
 
@@ -262,7 +262,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
262
  ) );
263
  }
264
 
265
- // we don't want to filter the home url in these cases
266
  if ( empty( $black_list ) ) {
267
 
268
  /**
@@ -276,7 +276,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
276
  * @param array $args
277
  */
278
  $black_list = apply_filters( 'pll_home_url_black_list', array(
279
- array( 'file' => 'searchform.php' ), // since WP 3.6 searchform.php is passed through get_search_form
280
  array( 'function' => 'get_search_form' ),
281
  ) );
282
  }
@@ -285,7 +285,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
285
  unset( $traces[0], $traces[1] ); // We don't need the last 2 calls: this function + call_user_func_array (or apply_filters on PHP7+)
286
 
287
  foreach ( $traces as $trace ) {
288
- // black list first
289
  foreach ( $black_list as $v ) {
290
  if ( ( isset( $trace['file'], $v['file'] ) && false !== strpos( $trace['file'], $v['file'] ) ) || ( isset( $trace['function'], $v['function'] ) && $trace['function'] == $v['function'] ) ) {
291
  return $url;
@@ -304,7 +304,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
304
  }
305
 
306
  /**
307
- * rewrites ajax url when using domains or subdomains
308
  *
309
  * @since 1.5
310
  *
@@ -317,7 +317,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
317
  }
318
 
319
  /**
320
- * if the language code is not in agreement with the language of the content
321
  * redirects incoming links to the proper URL to avoid duplicate content
322
  *
323
  * @since 0.9.6
@@ -329,17 +329,17 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
329
  public function check_canonical_url( $requested_url = '', $do_redirect = true ) {
330
  global $wp_query, $post, $is_IIS;
331
 
332
- // don't redirect in same cases as WP
333
  if ( is_trackback() || is_search() || is_admin() || is_preview() || is_robots() || ( $is_IIS && ! iis7_supports_permalinks() ) ) {
334
  return;
335
  }
336
 
337
- // don't redirect mysite.com/?attachment_id= to mysite.com/en/?attachment_id=
338
  if ( 1 == $this->options['force_lang'] && is_attachment() && isset( $_GET['attachment_id'] ) ) {
339
  return;
340
  }
341
 
342
- // if the default language code is not hidden and the static front page url contains the page name
343
  // the customizer lands here and the code below would redirect to the list of posts
344
  if ( isset( $_POST['wp_customize'], $_POST['customized'] ) ) {
345
  return;
@@ -368,8 +368,8 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
368
  }
369
 
370
  elseif ( is_404() && ! empty( $wp_query->query['page_id'] ) && $id = get_query_var( 'page_id' ) ) {
371
- // special case for page shortlinks when using subdomains or multiple domains
372
- // needed because redirect_canonical doesn't accept to change the domain name
373
  $language = $this->model->post->get_language( (int) $id );
374
  }
375
 
@@ -377,13 +377,15 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
377
  $language = $this->curlang;
378
  $redirect_url = $requested_url;
379
  } else {
380
- // first get the canonical url evaluated by WP
381
- $redirect_url = ( ! $redirect_url = redirect_canonical( $requested_url, false ) ) ? $requested_url : $redirect_url;
 
 
382
 
383
- // then get the right language code in url
384
  $redirect_url = $this->options['force_lang'] ?
385
  $this->links_model->switch_language_in_link( $redirect_url, $language ) :
386
- $this->links_model->remove_language_from_link( $redirect_url ); // works only for default permalinks
387
  }
388
 
389
  /**
@@ -396,7 +398,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
396
  */
397
  $redirect_url = apply_filters( 'pll_check_canonical_url', $redirect_url, $language );
398
 
399
- // the language is not correctly set so let's redirect to the correct url for this object
400
  if ( $do_redirect && $redirect_url && $requested_url != $redirect_url ) {
401
  wp_redirect( $redirect_url, 301 );
402
  exit;
1
  <?php
2
 
3
  /**
4
+ * Manages links filters on frontend
5
  *
6
  * @since 1.8
7
  */
8
  class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
9
  public $curlang;
10
+ public $cache; // Our internal non persistent cache object
11
 
12
  /**
13
+ * Constructor
14
+ * Adds filters once the language is defined
15
+ * Low priority on links filters to come after any other modification
16
  *
17
  * @since 1.8
18
  *
24
  $this->curlang = &$polylang->curlang;
25
  $this->cache = new PLL_Cache();
26
 
27
+ // Rewrites author and date links to filter them by language
28
  foreach ( array( 'feed_link', 'author_link', 'search_link', 'year_link', 'month_link', 'day_link' ) as $filter ) {
29
  add_filter( $filter, array( $this, 'archive_link' ), 20 );
30
  }
31
 
32
+ // Rewrites post types archives links to filter them by language
33
  add_filter( 'post_type_archive_link', array( $this, 'post_type_archive_link' ), 20, 2 );
34
 
35
+ // Meta in the html head section
36
  add_action( 'wp_head', array( $this, 'wp_head' ) );
37
 
38
+ // Modifies the home url
39
  if ( ! defined( 'PLL_FILTER_HOME_URL' ) || PLL_FILTER_HOME_URL ) {
40
  add_filter( 'home_url', array( $this, 'home_url' ), 10, 2 );
41
  }
42
 
43
  if ( $this->options['force_lang'] > 1 ) {
44
+ // Rewrites next and previous post links when not automatically done by WordPress
45
  add_filter( 'get_pagenum_link', array( $this, 'archive_link' ), 20 );
46
 
47
+ // Rewrites ajax url
48
  add_filter( 'admin_url', array( $this, 'admin_url' ), 10, 2 );
49
  }
50
 
51
+ // Redirects to canonical url before WordPress redirect_canonical
52
  // but after Nextgen Gallery which hacks $_SERVER['REQUEST_URI'] !!! and restores it in 'template_redirect' with priority 1
53
  add_action( 'template_redirect', array( $this, 'check_canonical_url' ), 4 );
54
  }
55
 
56
  /**
57
+ * Modifies the author and date links to add the language parameter ( as well as feed link )
58
  *
59
  * @since 0.4
60
  *
66
  }
67
 
68
  /**
69
+ * Modifies the post type archive links to add the language parameter
70
  * only if the post type is translated
71
  *
72
  * @since 1.7.6
80
  }
81
 
82
  /**
83
+ * Modifies post & page links
84
+ * and caches the result
85
  *
86
  * @since 0.7
87
  *
99
  }
100
 
101
  /**
102
+ * Modifies page links
103
+ * and caches the result
104
  *
105
  * @since 1.7
106
  *
118
  }
119
 
120
  /**
121
+ * Modifies attachment links
122
+ * and caches the result
123
  *
124
  * @since 1.6.2
125
  *
137
  }
138
 
139
  /**
140
+ * Modifies custom posts links
141
+ * and caches the result
142
  *
143
  * @since 1.6
144
  *
156
  }
157
 
158
  /**
159
+ * Modifies filtered taxonomies ( post format like ) and translated taxonomies links
160
+ * and caches the result
161
  *
162
  * @since 0.7
163
  *
185
  }
186
 
187
  /**
188
+ * Outputs references to translated pages ( if exists ) in the html head section
189
  *
190
  * @since 0.1
191
  */
197
  }
198
  }
199
 
200
+ // Ouptputs the section only if there are translations ( $urls always contains self link )
201
+ // Don't output anything on paged archives: see https://wordpress.org/support/topic/hreflang-on-page2
202
  if ( ! empty( $urls ) && count( $urls ) > 1 && ! is_paged() ) {
203
+ // Prepare the list of languages to remove the country code
204
  foreach ( array_keys( $urls ) as $locale ) {
205
  $split = explode( '-', $locale );
206
  $languages[ $locale ] = reset( $split );
209
  $count = array_count_values( $languages );
210
 
211
  foreach ( $urls as $locale => $url ) {
212
+ $lang = $count[ $languages[ $locale ] ] > 1 ? $locale : $languages[ $locale ]; // Output the country code only when necessary
213
  printf( '<link rel="alternate" href="%s" hreflang="%s" />'."\n", esc_url( $url ), esc_attr( $lang ) );
214
  }
215
 
216
+ // Adds the site root url when the default language code is not hidden
217
+ // See https://wordpress.org/support/topic/implementation-of-hreflangx-default
218
  if ( is_front_page() && ! $this->options['hide_default'] && $this->options['force_lang'] < 3 ) {
219
  printf( '<link rel="alternate" href="%s" hreflang="x-default" />'."\n", esc_url( home_url( '/' ) ) );
220
  }
222
  }
223
 
224
  /**
225
+ * Filters the home url to get the right language
226
  *
227
  * @since 0.4
228
  *
235
  return $url;
236
  }
237
 
238
+ static $white_list, $black_list; // Avoid evaluating this at each function call
239
 
240
+ // We *want* to filter the home url in these cases
241
  if ( empty( $white_list ) ) {
242
+ // On Windows get_theme_root() mixes / and \
243
+ // We want only \ for the comparison with debug_backtrace
244
  $theme_root = get_theme_root();
245
  $theme_root = ( false === strpos( $theme_root, '\\' ) ) ? $theme_root : str_replace( '/', '\\', $theme_root );
246
 
262
  ) );
263
  }
264
 
265
+ // We don't want to filter the home url in these cases
266
  if ( empty( $black_list ) ) {
267
 
268
  /**
276
  * @param array $args
277
  */
278
  $black_list = apply_filters( 'pll_home_url_black_list', array(
279
+ array( 'file' => 'searchform.php' ), // Since WP 3.6 searchform.php is passed through get_search_form
280
  array( 'function' => 'get_search_form' ),
281
  ) );
282
  }
285
  unset( $traces[0], $traces[1] ); // We don't need the last 2 calls: this function + call_user_func_array (or apply_filters on PHP7+)
286
 
287
  foreach ( $traces as $trace ) {
288
+ // Black list first
289
  foreach ( $black_list as $v ) {
290
  if ( ( isset( $trace['file'], $v['file'] ) && false !== strpos( $trace['file'], $v['file'] ) ) || ( isset( $trace['function'], $v['function'] ) && $trace['function'] == $v['function'] ) ) {
291
  return $url;
304
  }
305
 
306
  /**
307
+ * Rewrites ajax url when using domains or subdomains
308
  *
309
  * @since 1.5
310
  *
317
  }
318
 
319
  /**
320
+ * If the language code is not in agreement with the language of the content
321
  * redirects incoming links to the proper URL to avoid duplicate content
322
  *
323
  * @since 0.9.6
329
  public function check_canonical_url( $requested_url = '', $do_redirect = true ) {
330
  global $wp_query, $post, $is_IIS;
331
 
332
+ // Don't redirect in same cases as WP
333
  if ( is_trackback() || is_search() || is_admin() || is_preview() || is_robots() || ( $is_IIS && ! iis7_supports_permalinks() ) ) {
334
  return;
335
  }
336
 
337
+ // Don't redirect mysite.com/?attachment_id= to mysite.com/en/?attachment_id=
338
  if ( 1 == $this->options['force_lang'] && is_attachment() && isset( $_GET['attachment_id'] ) ) {
339
  return;
340
  }
341
 
342
+ // If the default language code is not hidden and the static front page url contains the page name
343
  // the customizer lands here and the code below would redirect to the list of posts
344
  if ( isset( $_POST['wp_customize'], $_POST['customized'] ) ) {
345
  return;
368
  }
369
 
370
  elseif ( is_404() && ! empty( $wp_query->query['page_id'] ) && $id = get_query_var( 'page_id' ) ) {
371
+ // Special case for page shortlinks when using subdomains or multiple domains
372
+ // Needed because redirect_canonical doesn't accept to change the domain name
373
  $language = $this->model->post->get_language( (int) $id );
374
  }
375
 
377
  $language = $this->curlang;
378
  $redirect_url = $requested_url;
379
  } else {
380
+ // First get the canonical url evaluated by WP
381
+ // Workaround a WP bug wich removes the port for some urls and get it back at second call to redirect_canonical
382
+ $_redirect_url = ( ! $_redirect_url = redirect_canonical( $requested_url, false ) ) ? $requested_url : $_redirect_url;
383
+ $redirect_url = ( ! $redirect_url = redirect_canonical( $_redirect_url, false ) ) ? $_redirect_url : $redirect_url;
384
 
385
+ // Then get the right language code in url
386
  $redirect_url = $this->options['force_lang'] ?
387
  $this->links_model->switch_language_in_link( $redirect_url, $language ) :
388
+ $this->links_model->remove_language_from_link( $redirect_url ); // Works only for default permalinks
389
  }
390
 
391
  /**
398
  */
399
  $redirect_url = apply_filters( 'pll_check_canonical_url', $redirect_url, $language );
400
 
401
+ // The language is not correctly set so let's redirect to the correct url for this object
402
  if ( $do_redirect && $redirect_url && $requested_url != $redirect_url ) {
403
  wp_redirect( $redirect_url, 301 );
404
  exit;
include/base.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  /**
4
- * base class for both admin and frontend
5
  *
6
  * @since 1.2
7
  */
@@ -9,7 +9,7 @@ abstract class PLL_Base {
9
  public $links_model, $model, $options;
10
 
11
  /**
12
- * constructor
13
  *
14
  * @since 1.2
15
  *
@@ -20,32 +20,34 @@ abstract class PLL_Base {
20
  $this->model = &$links_model->model;
21
  $this->options = &$this->model->options;
22
 
 
 
23
  add_action( 'widgets_init', array( $this, 'widgets_init' ) );
24
 
25
- // user defined strings translations
26
  add_action( 'pll_language_defined', array( $this, 'load_strings_translations' ), 5 );
27
 
28
- // switch_to_blog
29
  add_action( 'switch_blog', array( $this, 'switch_blog' ), 10, 2 );
30
  }
31
 
32
  /**
33
- * registers our widgets
34
  *
35
  * @since 0.1
36
  */
37
  public function widgets_init() {
38
  register_widget( 'PLL_Widget_Languages' );
39
 
40
- // overwrites the calendar widget to filter posts by language
41
  if ( ! defined( 'PLL_WIDGET_CALENDAR' ) || PLL_WIDGET_CALENDAR ) {
42
  unregister_widget( 'WP_Widget_Calendar' );
43
  register_widget( 'PLL_Widget_Calendar' );
44
  }
45
 
46
- // backward compatibility with WP < 4.4
47
- // overwrites the recent posts and recent comments widget to use a language dependant cache key
48
- // useful only if using a cache plugin
49
  if ( version_compare( $GLOBALS['wp_version'], '4.4', '<' ) && defined( 'WP_CACHE' ) && WP_CACHE ) {
50
  if ( ! defined( 'PLL_WIDGET_RECENT_POSTS' ) || PLL_WIDGET_RECENT_POSTS ) {
51
  unregister_widget( 'WP_Widget_Recent_Posts' );
@@ -60,7 +62,7 @@ abstract class PLL_Base {
60
  }
61
 
62
  /**
63
- * loads user defined strings translations
64
  *
65
  * @since 1.2
66
  */
@@ -71,8 +73,8 @@ abstract class PLL_Base {
71
  }
72
 
73
  /**
74
- * resets some variables when switching blog
75
- * applies only if Polylang is active on the new blog
76
  *
77
  * @since 1.5.1
78
  *
@@ -85,7 +87,7 @@ abstract class PLL_Base {
85
  // 2nd test needed when Polylang is not networked activated
86
  // 3rd test needed when Polylang is networked activated and a new site is created
87
  if ( $new_blog != $old_blog && in_array( POLYLANG_BASENAME, $plugins ) && get_option( 'polylang' ) ) {
88
- $this->options = get_option( 'polylang' ); // needed for menus
89
  $this->links_model = $this->model->get_links_model();
90
  return true;
91
  }
@@ -93,21 +95,21 @@ abstract class PLL_Base {
93
  }
94
 
95
  /**
96
- * some backward compatibility with Polylang < 1.2
97
- * allows for example to call $polylang->get_languages_list() instead of $polylang->model->get_languages_list()
98
- * this works but should be slower than the direct call, thus an error is triggered in debug mode
99
  *
100
  * @since 1.2
101
  *
102
  * @param string $func function name
103
- * @param array $args function arguments
104
  */
105
  public function __call( $func, $args ) {
106
  foreach ( $this as $prop => &$obj ) {
107
  if ( is_object( $obj ) && method_exists( $obj, $func ) ) {
108
  if ( WP_DEBUG ) {
109
  $debug = debug_backtrace();
110
- $i = 1 + empty( $debug[1]['line'] ); // the file and line are in $debug[2] if the function was called using call_user_func
111
  trigger_error( sprintf(
112
  '%1$s was called incorrectly in %3$s on line %4$s: the call to $polylang->%1$s() has been deprecated in Polylang 1.2, use PLL()->%2$s->%1$s() instead.' . "\nError handler",
113
  $func, $prop, $debug[ $i ]['file'], $debug[ $i ]['line']
1
  <?php
2
 
3
  /**
4
+ * Base class for both admin and frontend
5
  *
6
  * @since 1.2
7
  */
9
  public $links_model, $model, $options;
10
 
11
  /**
12
+ * Constructor
13
  *
14
  * @since 1.2
15
  *
20
  $this->model = &$links_model->model;
21
  $this->options = &$this->model->options;
22
 
23
+ $GLOBALS['l10n_unloaded']['pll_string'] = true; // Short-circuit _load_textdomain_just_in_time() for 'pll_string' domain in WP 4.6+
24
+
25
  add_action( 'widgets_init', array( $this, 'widgets_init' ) );
26
 
27
+ // User defined strings translations
28
  add_action( 'pll_language_defined', array( $this, 'load_strings_translations' ), 5 );
29
 
30
+ // Switch_to_blog
31
  add_action( 'switch_blog', array( $this, 'switch_blog' ), 10, 2 );
32
  }
33
 
34
  /**
35
+ * Registers our widgets
36
  *
37
  * @since 0.1
38
  */
39
  public function widgets_init() {
40
  register_widget( 'PLL_Widget_Languages' );
41
 
42
+ // Overwrites the calendar widget to filter posts by language
43
  if ( ! defined( 'PLL_WIDGET_CALENDAR' ) || PLL_WIDGET_CALENDAR ) {
44
  unregister_widget( 'WP_Widget_Calendar' );
45
  register_widget( 'PLL_Widget_Calendar' );
46
  }
47
 
48
+ // Backward compatibility with WP < 4.4
49
+ // Overwrites the recent posts and recent comments widget to use a language dependant cache key
50
+ // Useful only if using a cache plugin
51
  if ( version_compare( $GLOBALS['wp_version'], '4.4', '<' ) && defined( 'WP_CACHE' ) && WP_CACHE ) {
52
  if ( ! defined( 'PLL_WIDGET_RECENT_POSTS' ) || PLL_WIDGET_RECENT_POSTS ) {
53
  unregister_widget( 'WP_Widget_Recent_Posts' );
62
  }
63
 
64
  /**
65
+ * Loads user defined strings translations
66
  *
67
  * @since 1.2
68
  */
73
  }
74
 
75
  /**
76
+ * Resets some variables when switching blog
77
+ * Applies only if Polylang is active on the new blog
78
  *
79
  * @since 1.5.1
80
  *
87
  // 2nd test needed when Polylang is not networked activated
88
  // 3rd test needed when Polylang is networked activated and a new site is created
89
  if ( $new_blog != $old_blog && in_array( POLYLANG_BASENAME, $plugins ) && get_option( 'polylang' ) ) {
90
+ $this->options = get_option( 'polylang' ); // Needed for menus
91
  $this->links_model = $this->model->get_links_model();
92
  return true;
93
  }
95
  }
96
 
97
  /**
98
+ * Some backward compatibility with Polylang < 1.2
99
+ * Allows for example to call $polylang->get_languages_list() instead of $polylang->model->get_languages_list()
100
+ * This works but should be slower than the direct call, thus an error is triggered in debug mode
101
  *
102
  * @since 1.2
103
  *
104
  * @param string $func function name
105
+ * @param array $args function arguments
106
  */
107
  public function __call( $func, $args ) {
108
  foreach ( $this as $prop => &$obj ) {
109
  if ( is_object( $obj ) && method_exists( $obj, $func ) ) {
110
  if ( WP_DEBUG ) {
111
  $debug = debug_backtrace();
112
+ $i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func
113
  trigger_error( sprintf(
114
  '%1$s was called incorrectly in %3$s on line %4$s: the call to $polylang->%1$s() has been deprecated in Polylang 1.2, use PLL()->%2$s->%1$s() instead.' . "\nError handler",
115
  $func, $prop, $debug[ $i ]['file'], $debug[ $i ]['line']
include/links-directory.php CHANGED
@@ -141,7 +141,8 @@ class PLL_Links_Directory extends PLL_Links_Permalinks {
141
  */
142
  public function prepare_rewrite_rules( $pre ) {
143
  // Don't modify the rules if there is no languages created yet
144
- if ( $this->model->get_languages_list() && ! has_filter( 'language_rewrite_rules', '__return_empty_array' ) ) {
 
145
  // Suppress the rules created by WordPress for our taxonomy
146
  add_filter( 'language_rewrite_rules', '__return_empty_array' );
147
 
141
  */
142
  public function prepare_rewrite_rules( $pre ) {
143
  // Don't modify the rules if there is no languages created yet
144
+ // Make sure to add filter only once and if all custom post types and taxonomies have been registered
145
+ if ( $this->model->get_languages_list() && did_action( 'wp_loaded' ) && ! has_filter( 'language_rewrite_rules', '__return_empty_array' ) ) {
146
  // Suppress the rules created by WordPress for our taxonomy
147
  add_filter( 'language_rewrite_rules', '__return_empty_array' );
148
 
include/olt-manager.php CHANGED
@@ -25,7 +25,7 @@ class PLL_OLT_Manager {
25
  $this->default_locale = get_locale();
26
 
27
  // Filters for text domain management
28
- add_filter( 'override_load_textdomain', array( $this, 'mofile' ), 10, 3 );
29
  add_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
30
  add_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
31
 
@@ -59,8 +59,8 @@ class PLL_OLT_Manager {
59
  * @since 0.1
60
  */
61
  public function load_textdomains() {
62
- // Our override_load_textdomain filter has done its job. let's remove it before calling load_textdomain
63
- remove_filter( 'override_load_textdomain', array( $this, 'mofile' ), 10, 3 );
64
  remove_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
65
  remove_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
66
  $new_locale = get_locale();
@@ -69,7 +69,7 @@ class PLL_OLT_Manager {
69
  // Now we can load all overriden text domains with the right language
70
  if ( ! empty( $this->list_textdomains ) ) {
71
  foreach ( $this->list_textdomains as $textdomain ) {
72
- // FIXME: Since WP 4.6, plugins translations are first loaded from wp-content/languages
73
  if ( ! load_textdomain( $textdomain['domain'], str_replace( "{$this->default_locale}.mo", "$new_locale.mo", $textdomain['mo'] ) ) ) {
74
  // Since WP 3.5 themes may store languages files in /wp-content/languages/themes
75
  if ( ! load_textdomain( $textdomain['domain'], WP_LANG_DIR . "/themes/{$textdomain['domain']}-$new_locale.mo" ) ) {
@@ -121,7 +121,8 @@ class PLL_OLT_Manager {
121
  }
122
 
123
  /**
124
- * Saves all text domains in a table for later usage
 
125
  *
126
  * @since 0.1
127
  *
@@ -131,11 +132,22 @@ class PLL_OLT_Manager {
131
  * @return bool
132
  */
133
  public function mofile( $bool, $domain, $mofile ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  $this->list_textdomains[ $domain ] = array( 'mo' => $mofile, 'domain' => $domain );
135
- // Prevents WP loading text domains as we will load them all later
136
- // FIXME backward compatibility with WP < 4.6. See #34213
137
- // true for WP < 4.6, false for WP 4.6+ as we need to keep memory of the location of the language file inside the plugin directory
138
- return version_compare( $GLOBALS['wp_version'], '4.6-alpha', '<' );
139
  }
140
 
141
  /**
25
  $this->default_locale = get_locale();
26
 
27
  // Filters for text domain management
28
+ add_filter( 'load_textdomain_mofile', array( $this, 'load_textdomain_mofile' ), 10, 2 );
29
  add_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
30
  add_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
31
 
59
  * @since 0.1
60
  */
61
  public function load_textdomains() {
62
+ // Our load_textdomain_mofile filter has done its job. let's remove it before calling load_textdomain
63
+ remove_filter( 'load_textdomain_mofile', array( $this, 'load_textdomain_mofile' ), 10, 2 );
64
  remove_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
65
  remove_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
66
  $new_locale = get_locale();
69
  // Now we can load all overriden text domains with the right language
70
  if ( ! empty( $this->list_textdomains ) ) {
71
  foreach ( $this->list_textdomains as $textdomain ) {
72
+ // Since WP 4.6, plugins translations are first loaded from wp-content/languages
73
  if ( ! load_textdomain( $textdomain['domain'], str_replace( "{$this->default_locale}.mo", "$new_locale.mo", $textdomain['mo'] ) ) ) {
74
  // Since WP 3.5 themes may store languages files in /wp-content/languages/themes
75
  if ( ! load_textdomain( $textdomain['domain'], WP_LANG_DIR . "/themes/{$textdomain['domain']}-$new_locale.mo" ) ) {
121
  }
122
 
123
  /**
124
+ * FIXME: Backward compatibility with Polylang for WooCommerce < 0.3.4
125
+ * To remove in Polylang 2.1
126
  *
127
  * @since 0.1
128
  *
132
  * @return bool
133
  */
134
  public function mofile( $bool, $domain, $mofile ) {
135
+ return $bool;
136
+ }
137
+
138
+ /**
139
+ * Saves all text domains in a table for later usage
140
+ * It replaces the 'override_load_textdomain' filter used since 0.1
141
+ *
142
+ * @since 2.0.4
143
+ *
144
+ * @param string $mofile translation file name
145
+ * @param string $domain text domain name
146
+ * @return bool
147
+ */
148
+ public function load_textdomain_mofile( $mofile, $domain ) {
149
  $this->list_textdomains[ $domain ] = array( 'mo' => $mofile, 'domain' => $domain );
150
+ return ''; // Hack to prevent WP loading text domains as we will load them all later
 
 
 
151
  }
152
 
153
  /**
polylang.php CHANGED
@@ -3,7 +3,7 @@
3
  /*
4
  Plugin Name: Polylang
5
  Plugin URI: https://polylang.pro
6
- Version: 2.0.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.0.3' );
39
  define( 'PLL_MIN_WP_VERSION', '4.0' );
40
 
41
  define( 'POLYLANG_FILE', __FILE__ ); // this file
3
  /*
4
  Plugin Name: Polylang
5
  Plugin URI: https://polylang.pro
6
+ Version: 2.0.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.0.4' );
39
  define( 'PLL_MIN_WP_VERSION', '4.0' );
40
 
41
  define( 'POLYLANG_FILE', __FILE__ ); // this file
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://polylang.pro
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
5
  Requires at least: 4.0
6
  Tested up to: 4.6
7
- Stable tag: 2.0.3
8
  License: GPLv2 or later
9
 
10
  Making WordPress multilingual
@@ -77,6 +77,13 @@ Don't hesitate to [give your feedback](http://wordpress.org/support/view/plugin-
77
 
78
  == Changelog ==
79
 
 
 
 
 
 
 
 
80
  = 2.0.3 (2016-08-16) =
81
 
82
  * Pro: Fix PHP notice when hiding the language code in url and the language is set from subdomains
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
5
  Requires at least: 4.0
6
  Tested up to: 4.6
7
+ Stable tag: 2.0.4
8
  License: GPLv2 or later
9
 
10
  Making WordPress multilingual
77
 
78
  == Changelog ==
79
 
80
+ = 2.0.4 (2016-09-06) =
81
+
82
+ * Add Gujarati to the predefined languages list
83
+ * Fix conflict with Page Builder. Other parts of the conflict are fixed in Page Builder 2.4.14
84
+ * Fix plugins translations incorrectly loaded in WP 4.6
85
+ * Fix error 404 on paged urls when using a non standard port
86
+
87
  = 2.0.3 (2016-08-16) =
88
 
89
  * Pro: Fix PHP notice when hiding the language code in url and the language is set from subdomains
settings/languages.php CHANGED
@@ -61,6 +61,7 @@ $languages = array(
61
  'fy' => array( 'fy', 'fy', 'Frysk', 'ltr', 'nl' ),
62
  'gd' => array( 'gd', 'gd', 'Gàidhlig', 'ltr', 'scotland' ),
63
  'gl_ES' => array( 'gl', 'gl_ES', 'Galego', 'ltr', 'galicia' ),
 
64
  'haz' => array( 'haz', 'haz', 'هزاره گی', 'rtl', 'af' ),
65
  'he_IL' => array( 'he', 'he_IL', 'עברית', 'rtl', 'il' ),
66
  'hi_IN' => array( 'hi', 'hi_IN', 'हिन्दी', 'ltr', 'in' ),
61
  'fy' => array( 'fy', 'fy', 'Frysk', 'ltr', 'nl' ),
62
  'gd' => array( 'gd', 'gd', 'Gàidhlig', 'ltr', 'scotland' ),
63
  'gl_ES' => array( 'gl', 'gl_ES', 'Galego', 'ltr', 'galicia' ),
64
+ 'gu' => array( 'gu', 'gu', 'ગુજરાતી', 'ltr', 'in' ),
65
  'haz' => array( 'haz', 'haz', 'هزاره گی', 'rtl', 'af' ),
66
  'he_IL' => array( 'he', 'he_IL', 'עברית', 'rtl', 'il' ),
67
  'hi_IN' => array( 'hi', 'hi_IN', 'हिन्दी', 'ltr', 'in' ),