Polylang - Version 2.3.6

Version Description

(2018-05-17) =

  • Pro: Fix post type archive slug not translated in ACF page link fields
  • WP 4.9.6: Translate the privacy policy page
  • WP 4.9.6: Add the translated user descriptions to exported personal data
  • Update Plugin updater to version 1.6.16
  • Fix conflict with the plugin View Admin As. Props Jory Hogeveen. #253
Download this release

Release Info

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

Code changes from version 2.3.5 to 2.3.6

include/filters.php CHANGED
@@ -43,6 +43,12 @@ class PLL_Filters {
43
  // Translate the site title in emails sent to users
44
  add_filter( 'password_change_email', array( $this, 'translate_user_email' ) );
45
  add_filter( 'email_change_email', array( $this, 'translate_user_email' ) );
 
 
 
 
 
 
46
  }
47
 
48
  /**
@@ -263,10 +269,78 @@ class PLL_Filters {
263
  * @param array $email
264
  * @return array
265
  */
266
- function translate_user_email( $email ) {
267
  $blog_name = wp_specialchars_decode( pll__( get_option( 'blogname' ) ), ENT_QUOTES );
268
  $email['subject'] = sprintf( $email['subject'], $blog_name );
269
  $email['message'] = str_replace( '###SITENAME###', $blog_name, $email['message'] );
270
  return $email;
271
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  }
43
  // Translate the site title in emails sent to users
44
  add_filter( 'password_change_email', array( $this, 'translate_user_email' ) );
45
  add_filter( 'email_change_email', array( $this, 'translate_user_email' ) );
46
+
47
+ // Translates the privacy policy page
48
+ add_filter( 'option_wp_page_for_privacy_policy', array( $this, 'translate_page_for_privacy_policy' ), 20 ); // Since WP 4.9.6
49
+
50
+ // Personal data exporter
51
+ add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'register_personal_data_exporter' ), 0 ); // Since WP 4.9.6
52
  }
53
 
54
  /**
269
  * @param array $email
270
  * @return array
271
  */
272
+ public function translate_user_email( $email ) {
273
  $blog_name = wp_specialchars_decode( pll__( get_option( 'blogname' ) ), ENT_QUOTES );
274
  $email['subject'] = sprintf( $email['subject'], $blog_name );
275
  $email['message'] = str_replace( '###SITENAME###', $blog_name, $email['message'] );
276
  return $email;
277
  }
278
+
279
+ /**
280
+ * Translates the privacy policy page, on both frontend and admin
281
+ *
282
+ * @since 2.3.6
283
+ *
284
+ * @param int $id Privacy policy page id
285
+ * @return int
286
+ */
287
+ public function translate_page_for_privacy_policy( $id ) {
288
+ return empty( $this->curlang ) ? $id : $this->model->post->get( $id, $this->curlang );
289
+ }
290
+
291
+ /**
292
+ * Register our personal data exporter
293
+ *
294
+ * @since 2.3.6
295
+ *
296
+ * @param array $exporters Personal data exporters
297
+ * @retun array
298
+ */
299
+ public function register_personal_data_exporter( $exporters ) {
300
+ $exporters[] = array(
301
+ 'exporter_friendly_name' => __( 'Translated user descriptions', 'polylang' ),
302
+ 'callback' => array( $this, 'user_data_exporter' ),
303
+ );
304
+ return $exporters;
305
+ }
306
+
307
+ /**
308
+ * Export translated user description as WP exports only the description in the default language
309
+ *
310
+ * @since 2.3.6
311
+ *
312
+ * @param string $email_address User email address
313
+ * @return array Personal data
314
+ */
315
+ public function user_data_exporter( $email_address ) {
316
+ $email_address = trim( $email_address );
317
+
318
+ $data_to_export = array();
319
+
320
+ if ( $user = get_user_by( 'email', $email_address ) ) {
321
+ foreach ( $this->model->get_languages_list() as $lang ) {
322
+ if ( $lang->slug !== $this->options['default_lang'] && $value = get_user_meta( $user->ID, 'description_' . $lang->slug, true ) ) {
323
+ $user_data_to_export[] = array(
324
+ /* translators: %s is a language native name */
325
+ 'name' => sprintf( __( 'User description - %s', 'polylang' ), $lang->name ),
326
+ 'value' => $value,
327
+ );
328
+ }
329
+ }
330
+
331
+ if ( ! empty( $user_data_to_export ) ) {
332
+ $data_to_export[] = array(
333
+ 'group_id' => 'user',
334
+ 'group_label' => __( 'User' ),
335
+ 'item_id' => "user-{$user->ID}",
336
+ 'data' => $user_data_to_export,
337
+ );
338
+ }
339
+ }
340
+
341
+ return array(
342
+ 'data' => $data_to_export,
343
+ 'done' => true,
344
+ );
345
+ }
346
  }
install/plugin-updater.php CHANGED
@@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
10
  * Modified version with 'polylang' text domain and comments for translators
11
  *
12
  * @author Easy Digital Downloads
13
- * @version 1.6.15
14
  */
15
  class PLL_Plugin_Updater {
16
 
@@ -47,6 +47,15 @@ class PLL_Plugin_Updater {
47
 
48
  $edd_plugin_data[ $this->slug ] = $this->api_data;
49
 
 
 
 
 
 
 
 
 
 
50
  // Set up hooks.
51
  $this->init();
52
 
@@ -115,7 +124,7 @@ class PLL_Plugin_Updater {
115
 
116
  }
117
 
118
- $_transient_data->last_checked = current_time( 'timestamp' );
119
  $_transient_data->checked[ $this->name ] = $this->version;
120
 
121
  }
@@ -174,7 +183,7 @@ class PLL_Plugin_Updater {
174
 
175
  }
176
 
177
- $update_cache->last_checked = current_time( 'timestamp' );
178
  $update_cache->checked[ $this->name ] = $this->version;
179
 
180
  set_site_transient( 'update_plugins', $update_cache );
@@ -202,7 +211,7 @@ class PLL_Plugin_Updater {
202
  if ( empty( $version_info->download_link ) ) {
203
  printf(
204
  /* translators: %1$s plugin name, %3$s plugin version, %2$s is link start tag, %4$s is link end tag. */
205
- esc_html__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'polylang' ),
206
  esc_html( $version_info->name ),
207
  '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
208
  esc_html( $version_info->new_version ),
@@ -211,7 +220,7 @@ class PLL_Plugin_Updater {
211
  } else {
212
  printf(
213
  /* translators: %1$s plugin name, %3$s plugin version, %2$s and %5$s are link start tags, %4$s and %6$s are link end tags. */
214
- esc_html__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'polylang' ),
215
  esc_html( $version_info->name ),
216
  '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
217
  esc_html( $version_info->new_version ),
@@ -460,7 +469,7 @@ class PLL_Plugin_Updater {
460
 
461
  $cache = get_option( $cache_key );
462
 
463
- if( empty( $cache['timeout'] ) || current_time( 'timestamp' ) > $cache['timeout'] ) {
464
  return false; // Cache is expired
465
  }
466
 
@@ -475,7 +484,7 @@ class PLL_Plugin_Updater {
475
  }
476
 
477
  $data = array(
478
- 'timeout' => strtotime( '+3 hours', current_time( 'timestamp' ) ),
479
  'value' => json_encode( $value )
480
  );
481
 
10
  * Modified version with 'polylang' text domain and comments for translators
11
  *
12
  * @author Easy Digital Downloads
13
+ * @version 1.6.16
14
  */
15
  class PLL_Plugin_Updater {
16
 
47
 
48
  $edd_plugin_data[ $this->slug ] = $this->api_data;
49
 
50
+ /**
51
+ * Fires after the $edd_plugin_data is setup.
52
+ *
53
+ * @since x.x.x
54
+ *
55
+ * @param array $edd_plugin_data Array of EDD SL plugin data.
56
+ */
57
+ do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
58
+
59
  // Set up hooks.
60
  $this->init();
61
 
124
 
125
  }
126
 
127
+ $_transient_data->last_checked = time();
128
  $_transient_data->checked[ $this->name ] = $this->version;
129
 
130
  }
183
 
184
  }
185
 
186
+ $update_cache->last_checked = time();
187
  $update_cache->checked[ $this->name ] = $this->version;
188
 
189
  set_site_transient( 'update_plugins', $update_cache );
211
  if ( empty( $version_info->download_link ) ) {
212
  printf(
213
  /* translators: %1$s plugin name, %3$s plugin version, %2$s is link start tag, %4$s is link end tag. */
214
+ __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'polylang' ),
215
  esc_html( $version_info->name ),
216
  '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
217
  esc_html( $version_info->new_version ),
220
  } else {
221
  printf(
222
  /* translators: %1$s plugin name, %3$s plugin version, %2$s and %5$s are link start tags, %4$s and %6$s are link end tags. */
223
+ __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'polylang' ),
224
  esc_html( $version_info->name ),
225
  '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
226
  esc_html( $version_info->new_version ),
469
 
470
  $cache = get_option( $cache_key );
471
 
472
+ if( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
473
  return false; // Cache is expired
474
  }
475
 
484
  }
485
 
486
  $data = array(
487
+ 'timeout' => strtotime( '+3 hours', time() ),
488
  'value' => json_encode( $value )
489
  );
490
 
js/admin.js CHANGED
@@ -57,7 +57,7 @@ jQuery( document ).ready(function( $ ) {
57
  // fills the fields based on the language dropdown list choice
58
  $( '#lang_list' ).change(function() {
59
  var value = $( this ).val().split( ':' );
60
- var selected = $( "select option:selected" ).text().split( ' - ' );
61
  $( '#lang_slug' ).val( value[0] );
62
  $( '#lang_locale' ).val( value[1] );
63
  $( 'input[name="rtl"]' ).val( [value[2]] );
57
  // fills the fields based on the language dropdown list choice
58
  $( '#lang_list' ).change(function() {
59
  var value = $( this ).val().split( ':' );
60
+ var selected = $( "option:selected", this ).text().split( ' - ' );
61
  $( '#lang_slug' ).val( value[0] );
62
  $( '#lang_locale' ).val( value[1] );
63
  $( 'input[name="rtl"]' ).val( [value[2]] );
js/admin.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(e){function t(){var t=e(this).val();if(t){var n=e(this).iconselectmenu("widget").children(":last"),i=e('<img class="ui-icon" >').appendTo(n);i.attr("src",pll_flag_base_url+t+".png")}}var n;e("table.languages").on({focusin:function(){clearTimeout(n),focusedRowActions=e(this).find(".row-actions"),e(".row-actions").not(this).removeClass("visible"),focusedRowActions.addClass("visible")},focusout:function(){n=setTimeout(function(){focusedRowActions.removeClass("visible")},30)}},"tr"),e.widget("custom.iconselectmenu",e.ui.selectmenu,{_renderItem:function(t,n){var i=e("<li>",{text:n.label});return n.value&&e("<img>",{src:pll_flag_base_url+n.value+".png","class":"ui-icon"}).appendTo(i),i.appendTo(t)}}),e("#flag_list").iconselectmenu({create:t,select:t}),e("#lang_list").change(function(){var n=e(this).val().split(":"),i=e("select option:selected").text().split(" - ");e("#lang_slug").val(n[0]),e("#lang_locale").val(n[1]),e('input[name="rtl"]').val([n[2]]),e("#lang_name").val(i[0]),e('#flag_list option[value="'+n[3]+'"]').attr("selected","selected"),e("#flag_list").iconselectmenu("destroy").iconselectmenu({create:t,select:t})}),e(".translation input").keypress(function(t){13===t.keyCode&&(t.preventDefault(),e("#submit").click())}),e("#the-list").on("click",".configure>a",function(){return e(".pll-configure").hide().prev().show(),e(this).closest("tr").hide().next().show(),!1}),e("#the-list").on("click",".cancel",function(){e(this).closest("tr").hide().prev().show()}),e("#the-list").on("click",".save",function(){var t=e(this).closest("tr"),n=t.attr("id").split("-"),i={action:"pll_save_options",pll_ajax_settings:!0,module:n[n.length-1],_pll_nonce:e("#_pll_nonce").val()};i=t.find(":input").serialize()+"&"+e.param(i),e.post(ajaxurl,i,function(n){var i=wpAjax.parseAjaxResponse(n,"ajax-response");e.each(i.responses,function(){switch(this.what){case"license-update":e("#pll-license-"+this.data).replaceWith(this.supplemental.html);break;case"success":t.hide().prev().show();case"error":e(".settings-error").remove(),e("h1").after(this.data),e(".notice.is-dismissible").each(function(){var t=e(this),n=e('<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>'),i=commonL10n.dismiss||"";n.find(".screen-reader-text").text(i),t.append(n),n.on("click.wp-dismiss-notice",function(n){n.preventDefault(),t.fadeTo(100,0,function(){e(this).slideUp(100,function(){e(this).remove()})})})})}})})}),e(".pll-configure").keypress(function(t){13===t.keyCode&&(t.preventDefault(),e(this).find(".save").click()),27===t.keyCode&&(t.preventDefault(),e(this).find(".cancel").click())}),e("input[name='force_lang']").change(function(){function t(e,t){t?e.show():e.hide()}var n=e(this).val();t(e("#pll-domains-table"),3==n),t(e("#pll-hide-default"),3>n),t(e("#pll-rewrite"),2>n),t(e("#pll-redirect-lang"),2>n)}),e(".pll-deactivate-license").on("click",function(){var t={action:"pll_deactivate_license",pll_ajax_settings:!0,id:e(this).attr("id"),_pll_nonce:e("#_pll_nonce").val()};e.post(ajaxurl,t,function(t){e("#pll-license-"+t.id).replaceWith(t.html)})})});
1
+ jQuery(document).ready(function(e){function t(){var t=e(this).val();if(t){var n=e(this).iconselectmenu("widget").children(":last"),i=e('<img class="ui-icon" >').appendTo(n);i.attr("src",pll_flag_base_url+t+".png")}}var n;e("table.languages").on({focusin:function(){clearTimeout(n),focusedRowActions=e(this).find(".row-actions"),e(".row-actions").not(this).removeClass("visible"),focusedRowActions.addClass("visible")},focusout:function(){n=setTimeout(function(){focusedRowActions.removeClass("visible")},30)}},"tr"),e.widget("custom.iconselectmenu",e.ui.selectmenu,{_renderItem:function(t,n){var i=e("<li>",{text:n.label});return n.value&&e("<img>",{src:pll_flag_base_url+n.value+".png","class":"ui-icon"}).appendTo(i),i.appendTo(t)}}),e("#flag_list").iconselectmenu({create:t,select:t}),e("#lang_list").change(function(){var n=e(this).val().split(":"),i=e("option:selected",this).text().split(" - ");e("#lang_slug").val(n[0]),e("#lang_locale").val(n[1]),e('input[name="rtl"]').val([n[2]]),e("#lang_name").val(i[0]),e('#flag_list option[value="'+n[3]+'"]').attr("selected","selected"),e("#flag_list").iconselectmenu("destroy").iconselectmenu({create:t,select:t})}),e(".translation input").keypress(function(t){13===t.keyCode&&(t.preventDefault(),e("#submit").click())}),e("#the-list").on("click",".configure>a",function(){return e(".pll-configure").hide().prev().show(),e(this).closest("tr").hide().next().show(),!1}),e("#the-list").on("click",".cancel",function(){e(this).closest("tr").hide().prev().show()}),e("#the-list").on("click",".save",function(){var t=e(this).closest("tr"),n=t.attr("id").split("-"),i={action:"pll_save_options",pll_ajax_settings:!0,module:n[n.length-1],_pll_nonce:e("#_pll_nonce").val()};i=t.find(":input").serialize()+"&"+e.param(i),e.post(ajaxurl,i,function(n){var i=wpAjax.parseAjaxResponse(n,"ajax-response");e.each(i.responses,function(){switch(this.what){case"license-update":e("#pll-license-"+this.data).replaceWith(this.supplemental.html);break;case"success":t.hide().prev().show();case"error":e(".settings-error").remove(),e("h1").after(this.data),e(".notice.is-dismissible").each(function(){var t=e(this),n=e('<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>'),i=commonL10n.dismiss||"";n.find(".screen-reader-text").text(i),t.append(n),n.on("click.wp-dismiss-notice",function(n){n.preventDefault(),t.fadeTo(100,0,function(){e(this).slideUp(100,function(){e(this).remove()})})})})}})})}),e(".pll-configure").keypress(function(t){13===t.keyCode&&(t.preventDefault(),e(this).find(".save").click()),27===t.keyCode&&(t.preventDefault(),e(this).find(".cancel").click())}),e("input[name='force_lang']").change(function(){function t(e,t){t?e.show():e.hide()}var n=e(this).val();t(e("#pll-domains-table"),3==n),t(e("#pll-hide-default"),3>n),t(e("#pll-rewrite"),2>n),t(e("#pll-redirect-lang"),2>n)}),e(".pll-deactivate-license").on("click",function(){var t={action:"pll_deactivate_license",pll_ajax_settings:!0,id:e(this).attr("id"),_pll_nonce:e("#_pll_nonce").val()};e.post(ajaxurl,t,function(t){e("#pll-license-"+t.id).replaceWith(t.html)})})});
polylang.php CHANGED
@@ -3,7 +3,7 @@
3
  /**
4
  Plugin Name: Polylang
5
  Plugin URI: https://polylang.pro
6
- Version: 2.3.5
7
  Author: Frédéric Demarle
8
  Author uri: https://polylang.pro
9
  Description: Adds multilingual capability to WordPress
@@ -53,7 +53,7 @@ if ( defined( 'POLYLANG_BASENAME' ) ) {
53
  }
54
  } else {
55
  // Go on loading the plugin
56
- define( 'POLYLANG_VERSION', '2.3.5' );
57
  define( 'PLL_MIN_WP_VERSION', '4.4' );
58
 
59
  define( 'POLYLANG_FILE', __FILE__ ); // this file
3
  /**
4
  Plugin Name: Polylang
5
  Plugin URI: https://polylang.pro
6
+ Version: 2.3.6
7
  Author: Frédéric Demarle
8
  Author uri: https://polylang.pro
9
  Description: Adds multilingual capability to WordPress
53
  }
54
  } else {
55
  // Go on loading the plugin
56
+ define( 'POLYLANG_VERSION', '2.3.6' );
57
  define( 'PLL_MIN_WP_VERSION', '4.4' );
58
 
59
  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.4
6
  Tested up to: 4.9
7
- Stable tag: 2.3.5
8
  License: GPLv2 or later
9
 
10
  Making WordPress multilingual
@@ -76,6 +76,14 @@ Don't hesitate to [give your feedback](http://wordpress.org/support/view/plugin-
76
 
77
  == Changelog ==
78
 
 
 
 
 
 
 
 
 
79
  = 2.3.5 (2018-05-08) =
80
 
81
  * Pro: Fix translated CPT slugs when one CPT name is a substring of another one. Props Steve Reimer.
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.3.6
8
  License: GPLv2 or later
9
 
10
  Making WordPress multilingual
76
 
77
  == Changelog ==
78
 
79
+ = 2.3.6 (2018-05-17) =
80
+
81
+ * Pro: Fix post type archive slug not translated in ACF page link fields
82
+ * WP 4.9.6: Translate the privacy policy page
83
+ * WP 4.9.6: Add the translated user descriptions to exported personal data
84
+ * Update Plugin updater to version 1.6.16
85
+ * Fix conflict with the plugin View Admin As. Props Jory Hogeveen. #253
86
+
87
  = 2.3.5 (2018-05-08) =
88
 
89
  * Pro: Fix translated CPT slugs when one CPT name is a substring of another one. Props Steve Reimer.