Preferred Languages - Version 1.3.0

Version Description

  • New: Users can now choose English (United States) again as a preferred locale.
  • New: Users with the right capabilities can now install languages in their user profile as well.
Download this release

Release Info

Developer swissspidy
Plugin Icon Preferred Languages
Version 1.3.0
Comparing to
See all releases

Code changes from version 1.2.0 to 1.3.0

CHANGELOG.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Changelog
2
+
3
+ ## 1.3.0
4
+
5
+ * New: Users can now choose English (United States) again as a preferred locale.
6
+ * New: Users with the right capabilities can now install languages in their user profile as well.
7
+
8
+ ## 1.2.0
9
+
10
+ * Fixed: Other English locales can now be added again.
11
+ * Fixed: Prevented some errors when adding all available locales.
12
+
13
+ ## 1.1.0
14
+
15
+ * New: Support for just-in-time loading of translations.
16
+ * New: Keyboard shortcut for making inactive locales active.
17
+ * Fixed: Responsive design improvements.
18
+ * Fixed: Worked around a few edge cases with the various controls.
19
+ * Fixed: Added missing text domains.
20
+
21
+ ## 1.0.1
22
+
23
+ * Fixed: Fixed a bug that prevented saving changes.
24
+
25
+ ## 1.0.0
26
+
27
+ * Initial release.
inc/default-filters.php CHANGED
@@ -1,24 +1,26 @@
1
  <?php
 
 
 
 
 
2
 
3
  add_action( 'plugins_loaded', 'preferred_languages_init_registry' );
4
 
5
  add_filter( 'gettext', 'preferred_languages_filter_gettext', 10, 3 );
6
 
7
  add_action( 'init', 'preferred_languages_register_setting' );
8
- add_action( 'init', 'preferred_languages_register_meta' );
9
  add_action( 'init', 'preferred_languages_register_scripts' );
10
 
11
  add_action( 'admin_init', 'preferred_languages_settings_field' );
12
 
13
- add_action( 'personal_options', 'preferred_languages_personal_options' );
14
- add_action( 'personal_options_update', 'preferred_languages_update_user_option' );
15
  add_action( 'edit_user_profile_update', 'preferred_languages_update_user_option' );
16
 
17
- add_filter( 'update_option_preferred_languages', 'preferred_languages_download_language_packs', 10, 2 );
18
- add_filter( 'get_user_metadata', 'preferred_languages_filter_user_locale', 10, 3 );
19
- add_filter( 'locale', 'preferred_languages_filter_locale' );
20
- add_filter( 'load_textdomain_mofile', 'preferred_languages_load_textdomain_mofile', 10 );
21
-
22
-
23
-
24
-
1
  <?php
2
+ /**
3
+ * Adds all plugin actions and filters.
4
+ *
5
+ * @package PreferredLanguages
6
+ */
7
 
8
  add_action( 'plugins_loaded', 'preferred_languages_init_registry' );
9
 
10
  add_filter( 'gettext', 'preferred_languages_filter_gettext', 10, 3 );
11
 
12
  add_action( 'init', 'preferred_languages_register_setting' );
13
+ add_action( 'init', 'preferred_languages_register_meta' );
14
  add_action( 'init', 'preferred_languages_register_scripts' );
15
 
16
  add_action( 'admin_init', 'preferred_languages_settings_field' );
17
 
18
+ add_action( 'personal_options', 'preferred_languages_personal_options' );
19
+ add_action( 'personal_options_update', 'preferred_languages_update_user_option' );
20
  add_action( 'edit_user_profile_update', 'preferred_languages_update_user_option' );
21
 
22
+ add_filter( 'update_option_preferred_languages', 'preferred_languages_update_option', 10, 2 );
23
+ add_filter( 'update_user_meta', 'preferred_languages_update_user_meta', 10, 4 );
24
+ add_filter( 'get_user_metadata', 'preferred_languages_filter_user_locale', 10, 3 );
25
+ add_filter( 'locale', 'preferred_languages_filter_locale' );
26
+ add_filter( 'load_textdomain_mofile', 'preferred_languages_load_textdomain_mofile', 10 );
 
 
 
inc/functions.php CHANGED
@@ -1,4 +1,9 @@
1
  <?php
 
 
 
 
 
2
 
3
  /**
4
  * Registers the option for the preferred languages.
@@ -25,13 +30,15 @@ function preferred_languages_register_setting() {
25
  * @since 1.0.0
26
  */
27
  function preferred_languages_register_meta() {
28
- register_meta( 'user', 'preferred_languages', array(
29
- 'type' => 'string',
30
- 'description' => 'List of preferred languages',
31
- 'single' => true,
32
- 'sanitize_callback' => 'preferred_languages_sanitize_list',
33
- 'show_in_rest' => true,
34
- ) );
 
 
35
  }
36
 
37
  /**
@@ -47,11 +54,50 @@ function preferred_languages_update_user_option( $user_id ) {
47
  }
48
  }
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  /**
51
  * Returns the list of preferred languages.
52
  *
53
  * If in the admin area, this returns the data for the current user.
54
- * Else the site settings are used.
55
  *
56
  * @since 1.0.0
57
  *
@@ -61,17 +107,69 @@ function preferred_languages_get_list() {
61
  $preferred_languages = array();
62
 
63
  if ( is_admin() ) {
64
- $preferred_languages = get_user_meta( get_current_user_id(), 'preferred_languages', true );
65
- $preferred_languages = array_filter( explode( ',', $preferred_languages ) );
 
 
 
66
  }
67
 
68
  // Fall back to site setting.
69
- if ( empty( $preferred_languages ) ) {
70
- $preferred_languages = get_option( 'preferred_languages', '' );
71
- $preferred_languages = array_filter( explode( ',', $preferred_languages ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
 
74
- return $preferred_languages;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  }
76
 
77
  /**
@@ -79,24 +177,17 @@ function preferred_languages_get_list() {
79
  *
80
  * @since 1.0.0
81
  *
82
- * @param string $old_value The old option value.
83
- * @param string $value The new option value.
84
  */
85
- function preferred_languages_download_language_packs( $old_value, $value ) {
86
- if ( is_multisite() && ! is_super_admin() ) {
87
- return;
88
  }
89
 
90
  // Handle translation install.
91
  require_once ABSPATH . 'wp-admin/includes/translation-install.php';
92
 
93
- if ( ! wp_can_install_language_pack() ) {
94
- return;
95
- }
96
-
97
- $locales = $value;
98
- $locales = explode( ',', $locales );
99
-
100
  $installed_languages = array();
101
 
102
  foreach ( $locales as $locale ) {
@@ -106,16 +197,7 @@ function preferred_languages_download_language_packs( $old_value, $value ) {
106
  }
107
  }
108
 
109
- remove_filter( 'update_option_preferred_languages', 'preferred_languages_download_language_packs' );
110
-
111
- // Only store actually installed languages in option.
112
- update_option( 'preferred_languages', implode( ',', $installed_languages ) );
113
-
114
- add_filter( 'update_option_preferred_languages', 'preferred_languages_download_language_packs', 10, 2 );
115
-
116
- // Reload translations after save.
117
- $preferred_languages_list = preferred_languages_get_list();
118
- load_default_textdomain( reset( $preferred_languages_list ) );
119
  }
120
 
121
  /**
@@ -169,8 +251,7 @@ function preferred_languages_filter_user_locale( $value, $object_id, $meta_key )
169
  return $value;
170
  }
171
 
172
- $preferred_languages = get_user_meta( $object_id, 'preferred_languages', true );
173
- $preferred_languages = array_filter( explode( ',', $preferred_languages ) );
174
 
175
  if ( ! empty( $preferred_languages ) ) {
176
  return reset( $preferred_languages );
@@ -228,7 +309,7 @@ function preferred_languages_register_scripts() {
228
  'jquery-ui-sortable',
229
  'wp-a11y',
230
  ),
231
- '20171011',
232
  true
233
  );
234
 
@@ -251,7 +332,7 @@ function preferred_languages_register_scripts() {
251
  'preferred-languages',
252
  plugin_dir_url( dirname( __FILE__ ) ) . 'css/preferred-languages' . $rtl_suffix . '.css',
253
  array(),
254
- '20171010',
255
  'screen'
256
  );
257
  }
@@ -269,7 +350,7 @@ function preferred_languages_settings_field() {
269
  'general',
270
  'default',
271
  array(
272
- 'selected' => array_filter( explode( ',', get_option( 'preferred_languages', '' ) ) ),
273
  )
274
  );
275
  }
@@ -284,7 +365,7 @@ function preferred_languages_settings_field() {
284
  function preferred_languages_personal_options( $user ) {
285
  $languages = get_available_languages();
286
 
287
- if ( ! $languages ) {
288
  return;
289
  }
290
  ?>
@@ -294,11 +375,14 @@ function preferred_languages_personal_options( $user ) {
294
  </th>
295
  <td>
296
  <?php
297
- preferred_languages_display_form( array(
298
- 'selected' => array_filter( explode( ',', get_user_option( 'preferred_languages', $user->ID ) ) ),
299
- 'show_available_translations' => false,
300
- 'show_option_site_default' => true,
301
- ) );
 
 
 
302
  ?>
303
  </td>
304
  </tr>
@@ -315,11 +399,14 @@ function preferred_languages_personal_options( $user ) {
315
  function preferred_languages_display_form( $args = array() ) {
316
  wp_enqueue_script( 'preferred-languages' );
317
 
318
- $args = wp_parse_args( $args, array(
319
- 'selected' => array(),
320
- 'show_available_translations' => true,
321
- 'show_option_site_default' => false,
322
- ) );
 
 
 
323
 
324
  require_once ABSPATH . 'wp-admin/includes/translation-install.php';
325
  $translations = wp_get_available_translations();
@@ -328,7 +415,7 @@ function preferred_languages_display_form( $args = array() ) {
328
 
329
  $preferred_languages = array();
330
 
331
- foreach ( $args['selected'] as $locale ) {
332
  if ( isset( $translations[ $locale ] ) ) {
333
  $translation = $translations[ $locale ];
334
 
@@ -343,19 +430,26 @@ function preferred_languages_display_form( $args = array() ) {
343
  'native_name' => $locale,
344
  'lang' => '',
345
  );
 
 
 
 
 
 
346
  }
347
  }
 
348
  ?>
349
  <div class="preferred-languages">
350
  <input type="hidden" name="preferred_languages" value="<?php echo esc_attr( implode( ',', $args['selected'] ) ); ?>"/>
351
  <p><?php _e( 'Choose languages for displaying WordPress in, in order of preference.', 'preferred-languages' ); ?></p>
352
  <div class="active-locales">
353
  <?php
 
 
 
354
  if ( true === $args['show_option_site_default'] ) {
355
  $screen_reader_text = __( 'No languages selected. Falling back to Site Default.', 'preferred-languages' );
356
- } else {
357
- /* translators: %s: English (United States) */
358
- $screen_reader_text = sprintf( __( 'No languages selected. Falling back to %s.', 'preferred-languages' ), 'English (United States)' );
359
  }
360
  ?>
361
  <div class="<?php echo ! empty( $preferred_languages ) ? 'hidden' : ''; ?>" id="active-locales-empty-message" data-a11y-message="<?php echo esc_attr( $screen_reader_text ); ?>">
@@ -380,7 +474,7 @@ function preferred_languages_display_form( $args = array() ) {
380
  <?php foreach ( $preferred_languages as $language ) : ?>
381
  <li
382
  role="option"
383
- aria-selected="<?php echo (string) ( get_locale() === $language['language'] ); ?>"
384
  id="<?php echo esc_attr( $language['language'] ); ?>"
385
  class="active-locale">
386
  <?php echo esc_html( $language['native_name'] ); ?>
@@ -422,15 +516,17 @@ function preferred_languages_display_form( $args = array() ) {
422
  </div>
423
  <div class="inactive-locales">
424
  <label class="screen-reader-text" for="preferred-languages-inactive-locales"><?php _e( 'Inactive Locales', 'preferred-languages' ); ?></label>
425
- <div class="inactive-locales-list">
426
  <?php
427
- wp_dropdown_languages( array(
428
- 'id' => 'preferred-languages-inactive-locales',
429
- 'name' => 'preferred-languages-inactive-locales',
430
- 'languages' => $languages,
431
- 'translations' => $translations,
432
- 'show_available_translations' => $args['show_available_translations'],
433
- ) );
 
 
434
  ?>
435
  </div>
436
  <div class="inactive-locales-controls">
@@ -496,7 +592,8 @@ function preferred_languages_filter_gettext( $translation, $text, $domain ) {
496
 
497
  if ( load_textdomain( $domain, $mofile ) ) {
498
  $translations = get_translations_for_domain( $domain );
499
- $translation = $translations->translate( $text );
 
500
 
501
  break;
502
  }
1
  <?php
2
+ /**
3
+ * Plugin functions.
4
+ *
5
+ * @package PreferredLanguages
6
+ */
7
 
8
  /**
9
  * Registers the option for the preferred languages.
30
  * @since 1.0.0
31
  */
32
  function preferred_languages_register_meta() {
33
+ register_meta(
34
+ 'user', 'preferred_languages', array(
35
+ 'type' => 'string',
36
+ 'description' => 'List of preferred languages',
37
+ 'single' => true,
38
+ 'sanitize_callback' => 'preferred_languages_sanitize_list',
39
+ 'show_in_rest' => true,
40
+ )
41
+ );
42
  }
43
 
44
  /**
54
  }
55
  }
56
 
57
+ /**
58
+ * Returns the list of preferred languages of a user.
59
+ *
60
+ * @since 1.3.0
61
+ *
62
+ * @param int|WP_User $user_id User's ID or a WP_User object. Defaults to current user.
63
+ * @return array|false Preferred languages or false if user does not exists.
64
+ */
65
+ function preferred_languages_get_user_list( $user_id = 0 ) {
66
+ $user = false;
67
+
68
+ if ( 0 === $user_id && function_exists( 'wp_get_current_user' ) ) {
69
+ $user = wp_get_current_user();
70
+ } elseif ( $user_id instanceof WP_User ) {
71
+ $user = $user_id;
72
+ } elseif ( $user_id && is_numeric( $user_id ) ) {
73
+ $user = get_user_by( 'id', $user_id );
74
+ }
75
+
76
+ if ( ! $user ) {
77
+ return false;
78
+ }
79
+
80
+ $preferred_languages = get_user_meta( $user->ID, 'preferred_languages', true );
81
+ return array_filter( explode( ',', $preferred_languages ) );
82
+ }
83
+
84
+ /**
85
+ * Returns the list of preferred languages of the current site.
86
+ *
87
+ * @since 1.3.0
88
+ *
89
+ * @return array|false Preferred languages.
90
+ */
91
+ function preferred_languages_get_site_list() {
92
+ $preferred_languages = get_option( 'preferred_languages', '' );
93
+ return array_filter( explode( ',', $preferred_languages ) );
94
+ }
95
+
96
  /**
97
  * Returns the list of preferred languages.
98
  *
99
  * If in the admin area, this returns the data for the current user.
100
+ * Otherwise the site settings are used.
101
  *
102
  * @since 1.0.0
103
  *
107
  $preferred_languages = array();
108
 
109
  if ( is_admin() ) {
110
+ $preferred_languages = preferred_languages_get_user_list( get_current_user_id() );
111
+ }
112
+
113
+ if ( ! empty( $preferred_languages ) ) {
114
+ return $preferred_languages;
115
  }
116
 
117
  // Fall back to site setting.
118
+ return preferred_languages_get_site_list();
119
+ }
120
+
121
+ /**
122
+ * Downloads language pack when updating user meta.
123
+ *
124
+ * @since 1.3.0
125
+ *
126
+ * @param int $meta_id ID of the metadata entry to update.
127
+ * @param int $object_id Object ID.
128
+ * @param string $meta_key Meta key.
129
+ * @param mixed $meta_value Meta value.
130
+ */
131
+ function preferred_languages_update_user_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
132
+ if ( 'preferred_languages' !== $meta_key ) {
133
+ return;
134
  }
135
 
136
+ remove_filter( 'update_user_meta', 'preferred_languages_update_user_meta' );
137
+
138
+ $locales = array_filter( explode( ',', $meta_value ) );
139
+ $installed_languages = preferred_languages_download_language_packs( $locales );
140
+
141
+ // Only store actually installed languages in option.
142
+ update_user_meta( $object_id, 'preferred_languages', implode( ',', $installed_languages ) );
143
+
144
+ add_filter( 'update_user_meta', 'preferred_languages_update_user_meta', 10, 4 );
145
+
146
+ // Reload translations after save.
147
+ $preferred_languages_list = preferred_languages_get_list();
148
+ load_default_textdomain( reset( $preferred_languages_list ) );
149
+ }
150
+
151
+ /**
152
+ * Downloads language packs upon updating the site option.
153
+ *
154
+ * @since 1.3.0
155
+ *
156
+ * @param string $old_value The old option value.
157
+ * @param string $value The new option value.
158
+ */
159
+ function preferred_languages_update_option( $old_value, $value ) {
160
+ remove_filter( 'update_option_preferred_languages', 'preferred_languages_update_option' );
161
+
162
+ $locales = array_filter( explode( ',', $value ) );
163
+ $installed_languages = preferred_languages_download_language_packs( $locales );
164
+
165
+ // Only store actually installed languages in option.
166
+ update_option( 'preferred_languages', implode( ',', $installed_languages ) );
167
+
168
+ add_filter( 'update_option_preferred_languages', 'preferred_languages_update_option', 10, 2 );
169
+
170
+ // Reload translations after save.
171
+ $preferred_languages_list = preferred_languages_get_list();
172
+ load_default_textdomain( reset( $preferred_languages_list ) );
173
  }
174
 
175
  /**
177
  *
178
  * @since 1.0.0
179
  *
180
+ * @param array $locales The language packs to install.
181
+ * @return array|false The installed language packs or false on failure.
182
  */
183
+ function preferred_languages_download_language_packs( $locales ) {
184
+ if ( ! current_user_can( 'install_languages' ) ) {
185
+ return false;
186
  }
187
 
188
  // Handle translation install.
189
  require_once ABSPATH . 'wp-admin/includes/translation-install.php';
190
 
 
 
 
 
 
 
 
191
  $installed_languages = array();
192
 
193
  foreach ( $locales as $locale ) {
197
  }
198
  }
199
 
200
+ return $installed_languages;
 
 
 
 
 
 
 
 
 
201
  }
202
 
203
  /**
251
  return $value;
252
  }
253
 
254
+ $preferred_languages = preferred_languages_get_user_list( $object_id );
 
255
 
256
  if ( ! empty( $preferred_languages ) ) {
257
  return reset( $preferred_languages );
309
  'jquery-ui-sortable',
310
  'wp-a11y',
311
  ),
312
+ '20180708',
313
  true
314
  );
315
 
332
  'preferred-languages',
333
  plugin_dir_url( dirname( __FILE__ ) ) . 'css/preferred-languages' . $rtl_suffix . '.css',
334
  array(),
335
+ '20180708',
336
  'screen'
337
  );
338
  }
350
  'general',
351
  'default',
352
  array(
353
+ 'selected' => preferred_languages_get_site_list(),
354
  )
355
  );
356
  }
365
  function preferred_languages_personal_options( $user ) {
366
  $languages = get_available_languages();
367
 
368
+ if ( ! $languages && ! current_user_can( 'install_languages' ) ) {
369
  return;
370
  }
371
  ?>
375
  </th>
376
  <td>
377
  <?php
378
+ preferred_languages_display_form(
379
+ array(
380
+ 'selected' => preferred_languages_get_user_list( $user ),
381
+ 'show_available_translations' => current_user_can( 'install_languages' ),
382
+ 'show_option_site_default' => true,
383
+ 'show_option_en_US' => true,
384
+ )
385
+ );
386
  ?>
387
  </td>
388
  </tr>
399
  function preferred_languages_display_form( $args = array() ) {
400
  wp_enqueue_script( 'preferred-languages' );
401
 
402
+ $args = wp_parse_args(
403
+ $args, array(
404
+ 'selected' => array(),
405
+ 'show_available_translations' => current_user_can( 'install_languages' ),
406
+ 'show_option_site_default' => false,
407
+ 'show_option_en_US' => false,
408
+ )
409
+ );
410
 
411
  require_once ABSPATH . 'wp-admin/includes/translation-install.php';
412
  $translations = wp_get_available_translations();
415
 
416
  $preferred_languages = array();
417
 
418
+ foreach ( (array) $args['selected'] as $locale ) {
419
  if ( isset( $translations[ $locale ] ) ) {
420
  $translation = $translations[ $locale ];
421
 
430
  'native_name' => $locale,
431
  'lang' => '',
432
  );
433
+ } else {
434
+ $preferred_languages[] = array(
435
+ 'language' => $locale,
436
+ 'native_name' => 'English (United States)',
437
+ 'lang' => 'en',
438
+ );
439
  }
440
  }
441
+
442
  ?>
443
  <div class="preferred-languages">
444
  <input type="hidden" name="preferred_languages" value="<?php echo esc_attr( implode( ',', $args['selected'] ) ); ?>"/>
445
  <p><?php _e( 'Choose languages for displaying WordPress in, in order of preference.', 'preferred-languages' ); ?></p>
446
  <div class="active-locales">
447
  <?php
448
+ /* translators: %s: English (United States) */
449
+ $screen_reader_text = sprintf( __( 'No languages selected. Falling back to %s.', 'preferred-languages' ), 'English (United States)' );
450
+
451
  if ( true === $args['show_option_site_default'] ) {
452
  $screen_reader_text = __( 'No languages selected. Falling back to Site Default.', 'preferred-languages' );
 
 
 
453
  }
454
  ?>
455
  <div class="<?php echo ! empty( $preferred_languages ) ? 'hidden' : ''; ?>" id="active-locales-empty-message" data-a11y-message="<?php echo esc_attr( $screen_reader_text ); ?>">
474
  <?php foreach ( $preferred_languages as $language ) : ?>
475
  <li
476
  role="option"
477
+ aria-selected="<?php echo get_locale() === $language['language'] ? 'true' : 'false'; ?>"
478
  id="<?php echo esc_attr( $language['language'] ); ?>"
479
  class="active-locale">
480
  <?php echo esc_html( $language['native_name'] ); ?>
516
  </div>
517
  <div class="inactive-locales">
518
  <label class="screen-reader-text" for="preferred-languages-inactive-locales"><?php _e( 'Inactive Locales', 'preferred-languages' ); ?></label>
519
+ <div class="inactive-locales-list" data-show-en_US="<?php echo $args['show_option_en_US'] ? 'true' : 'false'; ?>">
520
  <?php
521
+ wp_dropdown_languages(
522
+ array(
523
+ 'id' => 'preferred-languages-inactive-locales',
524
+ 'name' => 'preferred-languages-inactive-locales',
525
+ 'languages' => $languages,
526
+ 'translations' => $translations,
527
+ 'show_available_translations' => $args['show_available_translations'],
528
+ )
529
+ );
530
  ?>
531
  </div>
532
  <div class="inactive-locales-controls">
592
 
593
  if ( load_textdomain( $domain, $mofile ) ) {
594
  $translations = get_translations_for_domain( $domain );
595
+ // phpcs:ignore WordPress.WP.I18n
596
+ $translation = $translations->translate( $text );
597
 
598
  break;
599
  }
js/preferred-languages.js CHANGED
@@ -4,7 +4,8 @@
4
  var $activeLocales = $('.active-locales-list');
5
  var $activeLocalesControls = $('.active-locales-controls');
6
  var $emptyMessage = $('#active-locales-empty-message');
7
- var $inactiveLocales = $('.inactive-locales-list select');
 
8
  var $inactiveLocalesControls = $('.inactive-locales-controls');
9
  var $selectedLocale = $activeLocales.find('li[aria-selected="true"]');
10
  var $inputField = $('input[name="preferred_languages"]');
@@ -19,8 +20,8 @@
19
  function changeButtonState(activeLocale) {
20
  var activeLocalesList = $activeLocales.find('.active-locale');
21
 
22
- $activeLocalesControls.find('.locales-move-up').attr('disabled', $activeLocales.hasClass('empty-list') || activeLocalesList.first().is(activeLocale));
23
- $activeLocalesControls.find('.locales-move-down').attr('disabled', $activeLocales.hasClass('empty-list') || activeLocalesList.last().is(activeLocale));
24
  $activeLocalesControls.find('.locales-remove').attr('disabled', $activeLocales.hasClass('empty-list') || !$selectedLocale.length);
25
  $inactiveLocalesControls.find('.locales-add').attr('disabled', 'disabled' === $inactiveLocales.attr('disabled'));
26
  }
@@ -34,14 +35,21 @@
34
  */
35
  function toggleLocale($locale) {
36
  var selected = $locale.attr('aria-selected');
37
- var newState = '' === selected ? true : !!selected;
38
 
39
  // It's already the current locale, so nothing to do here.
40
- if (true === selected) {
 
 
 
 
 
41
  return;
42
  }
43
 
44
- $selectedLocale.attr('aria-selected', false);
 
 
45
 
46
  $locale.attr('aria-selected', newState);
47
 
@@ -174,7 +182,8 @@
174
  * @param {jQuery} option The locale element.
175
  */
176
  function makeLocaleActive(option) {
177
- var $newLocale = $('<li/>', { text: option.text(), 'role': 'option', 'aria-selected': false, 'id': option.val(), 'class': 'active-locale' });
 
178
  var $successor = void 0;
179
 
180
  // 1. Hide from dropdown.
@@ -200,7 +209,7 @@
200
  $inactiveLocalesControls.val($successor.val());
201
 
202
  // It's already in the list of active locales, stop here.
203
- if ($activeLocales.find('#' + option.val()).length) {
204
  return;
205
  }
206
 
@@ -231,7 +240,7 @@
231
  $('#WPLANG').parent().parent().remove();
232
 
233
  // Remove en_US as an option from the dropdown.
234
- $inactiveLocales.find('[lang="en"][value=""]').remove();
235
 
236
  // Change initial button state.
237
  changeButtonState($selectedLocale);
@@ -239,6 +248,8 @@
239
  // Initially hide already active locales from dropdown.
240
  if ($inputField.val().length) {
241
  $.each($inputField.val().split(','), function (index, value) {
 
 
242
  var $option = $inactiveLocales.find('[value="' + value + '"]');
243
 
244
  // 2. Hide from dropdown.
4
  var $activeLocales = $('.active-locales-list');
5
  var $activeLocalesControls = $('.active-locales-controls');
6
  var $emptyMessage = $('#active-locales-empty-message');
7
+ var $inactiveLocalesWrap = $('.inactive-locales-list');
8
+ var $inactiveLocales = $inactiveLocalesWrap.find('select');
9
  var $inactiveLocalesControls = $('.inactive-locales-controls');
10
  var $selectedLocale = $activeLocales.find('li[aria-selected="true"]');
11
  var $inputField = $('input[name="preferred_languages"]');
20
  function changeButtonState(activeLocale) {
21
  var activeLocalesList = $activeLocales.find('.active-locale');
22
 
23
+ $activeLocalesControls.find('.locales-move-up').attr('disabled', $activeLocales.hasClass('empty-list') || activeLocalesList.first().is(activeLocale) || !$selectedLocale.length);
24
+ $activeLocalesControls.find('.locales-move-down').attr('disabled', $activeLocales.hasClass('empty-list') || activeLocalesList.last().is(activeLocale) || !$selectedLocale.length);
25
  $activeLocalesControls.find('.locales-remove').attr('disabled', $activeLocales.hasClass('empty-list') || !$selectedLocale.length);
26
  $inactiveLocalesControls.find('.locales-add').attr('disabled', 'disabled' === $inactiveLocales.attr('disabled'));
27
  }
35
  */
36
  function toggleLocale($locale) {
37
  var selected = $locale.attr('aria-selected');
38
+ var newState = 'true' !== selected;
39
 
40
  // It's already the current locale, so nothing to do here.
41
+ if ('true' === selected) {
42
+ $locale.attr('aria-selected', false);
43
+ $selectedLocale = [];
44
+
45
+ changeButtonState($locale);
46
+
47
  return;
48
  }
49
 
50
+ if ($selectedLocale.length) {
51
+ $selectedLocale.attr('aria-selected', false);
52
+ }
53
 
54
  $locale.attr('aria-selected', newState);
55
 
182
  * @param {jQuery} option The locale element.
183
  */
184
  function makeLocaleActive(option) {
185
+ var locale = option.val() || 'en_US';
186
+ var $newLocale = $('<li/>', { text: option.text(), 'role': 'option', 'aria-selected': false, 'id': locale, 'class': 'active-locale' });
187
  var $successor = void 0;
188
 
189
  // 1. Hide from dropdown.
209
  $inactiveLocalesControls.val($successor.val());
210
 
211
  // It's already in the list of active locales, stop here.
212
+ if ($activeLocales.find('#' + locale).length) {
213
  return;
214
  }
215
 
240
  $('#WPLANG').parent().parent().remove();
241
 
242
  // Remove en_US as an option from the dropdown.
243
+ $inactiveLocalesWrap.filter('[data-show-en_US="false"]').find('[lang="en"][value=""]').remove();
244
 
245
  // Change initial button state.
246
  changeButtonState($selectedLocale);
248
  // Initially hide already active locales from dropdown.
249
  if ($inputField.val().length) {
250
  $.each($inputField.val().split(','), function (index, value) {
251
+ value = 'en_US' === value ? '' : value;
252
+
253
  var $option = $inactiveLocales.find('[value="' + value + '"]');
254
 
255
  // 2. Hide from dropdown.
js/preferred-languages.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";(function(wp,settings,$){var $activeLocales=$(".active-locales-list");var $activeLocalesControls=$(".active-locales-controls");var $emptyMessage=$("#active-locales-empty-message");var $inactiveLocales=$(".inactive-locales-list select");var $inactiveLocalesControls=$(".inactive-locales-controls");var $selectedLocale=$activeLocales.find('li[aria-selected="true"]');var $inputField=$('input[name="preferred_languages"]');function changeButtonState(activeLocale){var activeLocalesList=$activeLocales.find(".active-locale");$activeLocalesControls.find(".locales-move-up").attr("disabled",$activeLocales.hasClass("empty-list")||activeLocalesList.first().is(activeLocale));$activeLocalesControls.find(".locales-move-down").attr("disabled",$activeLocales.hasClass("empty-list")||activeLocalesList.last().is(activeLocale));$activeLocalesControls.find(".locales-remove").attr("disabled",$activeLocales.hasClass("empty-list")||!$selectedLocale.length);$inactiveLocalesControls.find(".locales-add").attr("disabled","disabled"===$inactiveLocales.attr("disabled"))}function toggleLocale($locale){var selected=$locale.attr("aria-selected");var newState=""===selected?true:!!selected;if(true===selected){return}$selectedLocale.attr("aria-selected",false);$locale.attr("aria-selected",newState);if(true===newState){$selectedLocale=$locale;$activeLocales.attr("aria-activedescendant",$selectedLocale.attr("id"))}changeButtonState($locale)}function updateHiddenInput(){var locales=[];$activeLocales.children(".active-locale").each(function(index,el){locales.push($(el).attr("id"))});$inputField.val(locales.join(","))}function moveLocaleUp(){$selectedLocale.insertBefore($selectedLocale.prev());updateHiddenInput();changeButtonState($selectedLocale);wp.a11y.speak(settings.l10n.movedUp)}function moveLocaleDown(){$selectedLocale.insertAfter($selectedLocale.next());updateHiddenInput();changeButtonState($selectedLocale);wp.a11y.speak(settings.l10n.movedDown)}function toggleEmptyListMessage(){if($activeLocales.hasClass("empty-list")){$activeLocales.removeClass("empty-list");$emptyMessage.addClass("hidden")}else{$activeLocales.addClass("empty-list");$activeLocales.attr("aria-activedescendant","");$emptyMessage.removeClass("hidden");wp.a11y.speak($emptyMessage.data("a11y-message"))}}function makeLocaleInactive(){var locale=$selectedLocale.attr("id");var $successor=void 0;$successor=$selectedLocale.prevAll(":first");if(0===$successor.length){$successor=$selectedLocale.nextAll(":first")}$selectedLocale.remove();if($successor.length){toggleLocale($successor)}else{toggleEmptyListMessage()}$inactiveLocales.find('option[value="'+locale+'"]').removeClass("hidden");$inactiveLocales.attr("disabled",false);updateHiddenInput();changeButtonState($selectedLocale);wp.a11y.speak(settings.l10n.localeRemoved)}function makeLocaleActive(option){var $newLocale=$("<li/>",{text:option.text(),role:"option","aria-selected":false,id:option.val(),class:"active-locale"});var $successor=void 0;option.removeAttr("selected").addClass("hidden");$successor=option.prevAll(":not(.hidden):first");if(!$successor.length){$successor=option.nextAll(":not(.hidden):first")}if(!$successor.length){$successor=$inactiveLocales.find("option:not(.hidden):first")}if(!$successor.length){$inactiveLocales.attr("disabled",true)}$successor.attr("selected",true);$inactiveLocalesControls.val($successor.val());if($activeLocales.find("#"+option.val()).length){return}if($activeLocales.hasClass("empty-list")){toggleEmptyListMessage()}$activeLocales.append($newLocale);toggleLocale($newLocale);$activeLocales.animate({scrollTop:$newLocale.offset().top-$activeLocales.offset().top+$activeLocales.scrollTop()});updateHiddenInput();wp.a11y.speak(settings.l10n.localeAdded)}$(".user-language-wrap").remove();$("#WPLANG").parent().parent().remove();$inactiveLocales.find('[lang="en"][value=""]').remove();changeButtonState($selectedLocale);if($inputField.val().length){$.each($inputField.val().split(","),function(index,value){var $option=$inactiveLocales.find('[value="'+value+'"]');$option.removeAttr("selected").addClass("hidden")});var $firstInactiveLocale=$inactiveLocales.find("option:not(.hidden):first");$firstInactiveLocale.attr("selected",true);$inactiveLocalesControls.val($firstInactiveLocale.val())}$activeLocales.sortable({axis:"y",cursor:"move",items:":not(#active-locales-list-empty-message)"});$activeLocales.on("keydown",function(e){if(38===e.which){if(e.altKey){moveLocaleUp()}else{$selectedLocale.prev().length&&toggleLocale($selectedLocale.prev())}e.preventDefault()}if(40===e.which){if(e.altKey){moveLocaleDown()}else{$selectedLocale.next().length&&toggleLocale($selectedLocale.next())}e.preventDefault()}if(8===e.which){makeLocaleInactive();e.preventDefault()}});$inactiveLocales.on("keydown",function(e){if(65===e.which){if(e.altKey){makeLocaleActive($inactiveLocales.find("option:selected"))}e.preventDefault()}});$inactiveLocalesControls.find(".locales-add").on("click",function(){makeLocaleActive($inactiveLocales.find("option:selected"))});$activeLocales.on("click",".active-locale",function(e){toggleLocale($(e.currentTarget))});$activeLocalesControls.find(".locales-move-up").on("click",moveLocaleUp);$activeLocalesControls.find(".locales-move-down").on("click",moveLocaleDown);$activeLocalesControls.find(".locales-remove").on("click",makeLocaleInactive)})(wp,preferredLanguages,jQuery);
1
+ "use strict";(function(wp,settings,$){var $activeLocales=$(".active-locales-list");var $activeLocalesControls=$(".active-locales-controls");var $emptyMessage=$("#active-locales-empty-message");var $inactiveLocalesWrap=$(".inactive-locales-list");var $inactiveLocales=$inactiveLocalesWrap.find("select");var $inactiveLocalesControls=$(".inactive-locales-controls");var $selectedLocale=$activeLocales.find('li[aria-selected="true"]');var $inputField=$('input[name="preferred_languages"]');function changeButtonState(activeLocale){var activeLocalesList=$activeLocales.find(".active-locale");$activeLocalesControls.find(".locales-move-up").attr("disabled",$activeLocales.hasClass("empty-list")||activeLocalesList.first().is(activeLocale)||!$selectedLocale.length);$activeLocalesControls.find(".locales-move-down").attr("disabled",$activeLocales.hasClass("empty-list")||activeLocalesList.last().is(activeLocale)||!$selectedLocale.length);$activeLocalesControls.find(".locales-remove").attr("disabled",$activeLocales.hasClass("empty-list")||!$selectedLocale.length);$inactiveLocalesControls.find(".locales-add").attr("disabled","disabled"===$inactiveLocales.attr("disabled"))}function toggleLocale($locale){var selected=$locale.attr("aria-selected");var newState="true"!==selected;if("true"===selected){$locale.attr("aria-selected",false);$selectedLocale=[];changeButtonState($locale);return}if($selectedLocale.length){$selectedLocale.attr("aria-selected",false)}$locale.attr("aria-selected",newState);if(true===newState){$selectedLocale=$locale;$activeLocales.attr("aria-activedescendant",$selectedLocale.attr("id"))}changeButtonState($locale)}function updateHiddenInput(){var locales=[];$activeLocales.children(".active-locale").each(function(index,el){locales.push($(el).attr("id"))});$inputField.val(locales.join(","))}function moveLocaleUp(){$selectedLocale.insertBefore($selectedLocale.prev());updateHiddenInput();changeButtonState($selectedLocale);wp.a11y.speak(settings.l10n.movedUp)}function moveLocaleDown(){$selectedLocale.insertAfter($selectedLocale.next());updateHiddenInput();changeButtonState($selectedLocale);wp.a11y.speak(settings.l10n.movedDown)}function toggleEmptyListMessage(){if($activeLocales.hasClass("empty-list")){$activeLocales.removeClass("empty-list");$emptyMessage.addClass("hidden")}else{$activeLocales.addClass("empty-list");$activeLocales.attr("aria-activedescendant","");$emptyMessage.removeClass("hidden");wp.a11y.speak($emptyMessage.data("a11y-message"))}}function makeLocaleInactive(){var locale=$selectedLocale.attr("id");var $successor=void 0;$successor=$selectedLocale.prevAll(":first");if(0===$successor.length){$successor=$selectedLocale.nextAll(":first")}$selectedLocale.remove();if($successor.length){toggleLocale($successor)}else{toggleEmptyListMessage()}$inactiveLocales.find('option[value="'+locale+'"]').removeClass("hidden");$inactiveLocales.attr("disabled",false);updateHiddenInput();changeButtonState($selectedLocale);wp.a11y.speak(settings.l10n.localeRemoved)}function makeLocaleActive(option){var locale=option.val()||"en_US";var $newLocale=$("<li/>",{text:option.text(),role:"option","aria-selected":false,id:locale,class:"active-locale"});var $successor=void 0;option.removeAttr("selected").addClass("hidden");$successor=option.prevAll(":not(.hidden):first");if(!$successor.length){$successor=option.nextAll(":not(.hidden):first")}if(!$successor.length){$successor=$inactiveLocales.find("option:not(.hidden):first")}if(!$successor.length){$inactiveLocales.attr("disabled",true)}$successor.attr("selected",true);$inactiveLocalesControls.val($successor.val());if($activeLocales.find("#"+locale).length){return}if($activeLocales.hasClass("empty-list")){toggleEmptyListMessage()}$activeLocales.append($newLocale);toggleLocale($newLocale);$activeLocales.animate({scrollTop:$newLocale.offset().top-$activeLocales.offset().top+$activeLocales.scrollTop()});updateHiddenInput();wp.a11y.speak(settings.l10n.localeAdded)}$(".user-language-wrap").remove();$("#WPLANG").parent().parent().remove();$inactiveLocalesWrap.filter('[data-show-en_US="false"]').find('[lang="en"][value=""]').remove();changeButtonState($selectedLocale);if($inputField.val().length){$.each($inputField.val().split(","),function(index,value){value="en_US"===value?"":value;var $option=$inactiveLocales.find('[value="'+value+'"]');$option.removeAttr("selected").addClass("hidden")});var $firstInactiveLocale=$inactiveLocales.find("option:not(.hidden):first");$firstInactiveLocale.attr("selected",true);$inactiveLocalesControls.val($firstInactiveLocale.val())}$activeLocales.sortable({axis:"y",cursor:"move",items:":not(#active-locales-list-empty-message)"});$activeLocales.on("keydown",function(e){if(38===e.which){if(e.altKey){moveLocaleUp()}else{$selectedLocale.prev().length&&toggleLocale($selectedLocale.prev())}e.preventDefault()}if(40===e.which){if(e.altKey){moveLocaleDown()}else{$selectedLocale.next().length&&toggleLocale($selectedLocale.next())}e.preventDefault()}if(8===e.which){makeLocaleInactive();e.preventDefault()}});$inactiveLocales.on("keydown",function(e){if(65===e.which){if(e.altKey){makeLocaleActive($inactiveLocales.find("option:selected"))}e.preventDefault()}});$inactiveLocalesControls.find(".locales-add").on("click",function(){makeLocaleActive($inactiveLocales.find("option:selected"))});$activeLocales.on("click",".active-locale",function(e){toggleLocale($(e.currentTarget))});$activeLocalesControls.find(".locales-move-up").on("click",moveLocaleUp);$activeLocalesControls.find(".locales-move-down").on("click",moveLocaleDown);$activeLocalesControls.find(".locales-remove").on("click",makeLocaleInactive)})(wp,preferredLanguages,jQuery);
preferred-languages.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Preferred Languages
4
  * Plugin URI: https://github.com/swissspidy/preferred-languages/
5
  * Description: Choose languages for displaying WordPress in, in order of preference.
6
- * Version: 1.2.0
7
  * Author: Pascal Birchler
8
  * Author URI: https://pascalbirchler.com
9
  * License: GPL-2.0+
@@ -26,10 +26,21 @@
26
  * You should have received a copy of the GNU General Public License
27
  * along with this program; if not, write to the Free Software
28
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
 
29
  */
30
 
 
 
 
31
  require_once( dirname( __FILE__ ) . '/inc/class-preferred-languages-textdomain-registry.php' );
32
- require_once( dirname( __FILE__ ) . '/inc/functions.php' );
33
- require_once( dirname( __FILE__ ) . '/inc/default-filters.php' );
34
 
 
 
 
 
35
 
 
 
 
 
3
  * Plugin Name: Preferred Languages
4
  * Plugin URI: https://github.com/swissspidy/preferred-languages/
5
  * Description: Choose languages for displaying WordPress in, in order of preference.
6
+ * Version: 1.3.0
7
  * Author: Pascal Birchler
8
  * Author URI: https://pascalbirchler.com
9
  * License: GPL-2.0+
26
  * You should have received a copy of the GNU General Public License
27
  * along with this program; if not, write to the Free Software
28
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29
+ *
30
+ * @package PreferredLanguages
31
  */
32
 
33
+ /**
34
+ * Text domain registry class.
35
+ */
36
  require_once( dirname( __FILE__ ) . '/inc/class-preferred-languages-textdomain-registry.php' );
 
 
37
 
38
+ /**
39
+ * Plugin functions.
40
+ */
41
+ require_once( dirname( __FILE__ ) . '/inc/functions.php' );
42
 
43
+ /**
44
+ * Adds all plugin actions and filters.
45
+ */
46
+ require_once( dirname( __FILE__ ) . '/inc/default-filters.php' );
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Preferred Languages ===
2
  Contributors: swissspidy
3
  Tags: internationalization, i18n, localization, l10n, language, locale, translation
4
- Requires at least: 4.7
5
  Tested up to: 4.9
6
  Requires PHP: 5.2
7
- Stable tag: 1.2.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -31,6 +31,11 @@ If you want to get involved, check out [open issues](https://github.com/swissspi
31
 
32
  == Changelog ==
33
 
 
 
 
 
 
34
  = 1.2.0 =
35
 
36
  * Fixed: Other English locales can now be added again.
@@ -54,6 +59,10 @@ If you want to get involved, check out [open issues](https://github.com/swissspi
54
 
55
  == Upgrade Notice ==
56
 
 
 
 
 
57
  = 1.2.0 =
58
 
59
  This release fixes various bugs when adding and removing multiple languages.
1
  === Preferred Languages ===
2
  Contributors: swissspidy
3
  Tags: internationalization, i18n, localization, l10n, language, locale, translation
4
+ Requires at least: 4.9
5
  Tested up to: 4.9
6
  Requires PHP: 5.2
7
+ Stable tag: 1.3.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
31
 
32
  == Changelog ==
33
 
34
+ = 1.3.0 =
35
+
36
+ * New: Users can now choose English (United States) again as a preferred locale.
37
+ * New: Users with the right capabilities can now install languages in their user profile as well.
38
+
39
  = 1.2.0 =
40
 
41
  * Fixed: Other English locales can now be added again.
59
 
60
  == Upgrade Notice ==
61
 
62
+ = 1.3.0 =
63
+
64
+ Users can now install new languages from their user profile. Also, English (US) can be chosen as a preferred user language.
65
+
66
  = 1.2.0 =
67
 
68
  This release fixes various bugs when adding and removing multiple languages.
uninstall.php CHANGED
@@ -1,6 +1,13 @@
1
  <?php
 
 
 
 
 
 
 
2
 
3
  defined( 'WP_UNINSTALL_PLUGIN' ) or die;
4
 
5
  delete_option( 'preferred_languages' );
6
- delete_metadata( 'user', null, 'preferred_languages', '', true );
1
  <?php
2
+ /**
3
+ * Plugin uninstall routine.
4
+ *
5
+ * Removes all options and meta data added by the plugin.
6
+ *
7
+ * @package PreferredLanguages
8
+ */
9
 
10
  defined( 'WP_UNINSTALL_PLUGIN' ) or die;
11
 
12
  delete_option( 'preferred_languages' );
13
+ delete_metadata( 'user', null, 'preferred_languages', '', true );