From 4a88d550545034c760bcae7adf992814a3ed6879 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 3 Oct 2016 07:04:29 +0000 Subject: [PATCH] I18N: Introduce a user-specific language setting. By enabling the user to select their preferred locale when editing the profile, we allow for greater personalization of the WordPress admin and therefore a better user experience. The back end will be displayed in the user's individual locale while the locale used on the front end equals the one set for the whole site. If the user didn't specify a locale, the site's locale will be used as a fallback. The new `locale` property of the `WP_User` class can be used to retrieve the user's locale setting. Props ocean90, ipm-frommen, swissspidy. Fixes #29783. Built from https://develop.svn.wordpress.org/trunk@38705 git-svn-id: http://core.svn.wordpress.org/trunk@38648 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/admin-header.php | 2 +- .../class-wp-plugin-install-list-table.php | 2 +- wp-admin/includes/class-wp-press-this.php | 2 +- wp-admin/includes/credits.php | 2 +- wp-admin/includes/dashboard.php | 2 +- wp-admin/includes/import.php | 4 +-- wp-admin/includes/plugin-install.php | 2 +- wp-admin/includes/template.php | 2 +- wp-admin/includes/theme.php | 2 +- wp-admin/includes/user.php | 10 ++++++ wp-admin/options.php | 16 ++++++---- wp-admin/plugin-editor.php | 2 +- wp-admin/theme-editor.php | 2 +- wp-admin/user-edit.php | 32 +++++++++++++++++++ wp-includes/class-wp-editor.php | 4 +-- wp-includes/class-wp-theme.php | 2 +- wp-includes/class-wp-user.php | 1 + wp-includes/l10n.php | 21 ++++++++++-- wp-includes/user.php | 6 +++- wp-includes/version.php | 2 +- 20 files changed, 93 insertions(+), 25 deletions(-) diff --git a/wp-admin/admin-header.php b/wp-admin/admin-header.php index 9ec3999ac8..b5bbec0e98 100644 --- a/wp-admin/admin-header.php +++ b/wp-admin/admin-header.php @@ -156,7 +156,7 @@ if ( $current_screen->taxonomy ) $admin_body_class .= ' branch-' . str_replace( array( '.', ',' ), '-', floatval( get_bloginfo( 'version' ) ) ); $admin_body_class .= ' version-' . str_replace( '.', '-', preg_replace( '/^([.0-9]+).*/', '$1', get_bloginfo( 'version' ) ) ); $admin_body_class .= ' admin-color-' . sanitize_html_class( get_user_option( 'admin_color' ), 'fresh' ); -$admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) ); +$admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_user_locale() ) ) ); if ( wp_is_mobile() ) $admin_body_class .= ' mobile'; diff --git a/wp-admin/includes/class-wp-plugin-install-list-table.php b/wp-admin/includes/class-wp-plugin-install-list-table.php index 475c95e8af..c4bdaf9a15 100644 --- a/wp-admin/includes/class-wp-plugin-install-list-table.php +++ b/wp-admin/includes/class-wp-plugin-install-list-table.php @@ -134,7 +134,7 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { 'active_installs' => true ), // Send the locale and installed plugin slugs to the API so it can provide context-sensitive results. - 'locale' => get_locale(), + 'locale' => get_user_locale(), 'installed_plugins' => $this->get_installed_plugin_slugs(), ); diff --git a/wp-admin/includes/class-wp-press-this.php b/wp-admin/includes/class-wp-press-this.php index 3ff242bed8..e275b16e5b 100644 --- a/wp-admin/includes/class-wp-press-this.php +++ b/wp-admin/includes/class-wp-press-this.php @@ -1312,7 +1312,7 @@ class WP_Press_This { $admin_body_class .= ' branch-' . str_replace( array( '.', ',' ), '-', floatval( $wp_version ) ); $admin_body_class .= ' version-' . str_replace( '.', '-', preg_replace( '/^([.0-9]+).*/', '$1', $wp_version ) ); $admin_body_class .= ' admin-color-' . sanitize_html_class( get_user_option( 'admin_color' ), 'fresh' ); - $admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) ); + $admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_user_locale() ) ) ); /** This filter is documented in wp-admin/admin-header.php */ $admin_body_classes = apply_filters( 'admin_body_class', '' ); diff --git a/wp-admin/includes/credits.php b/wp-admin/includes/credits.php index 6634724c84..005858c384 100644 --- a/wp-admin/includes/credits.php +++ b/wp-admin/includes/credits.php @@ -16,7 +16,7 @@ */ function wp_credits() { $wp_version = get_bloginfo( 'version' ); - $locale = get_locale(); + $locale = get_user_locale(); $results = get_site_transient( 'wordpress_credits_' . $locale ); diff --git a/wp-admin/includes/dashboard.php b/wp-admin/includes/dashboard.php index 659e0600d8..a338f4c48d 100644 --- a/wp-admin/includes/dashboard.php +++ b/wp-admin/includes/dashboard.php @@ -1353,7 +1353,7 @@ function wp_dashboard_browser_nag() { $notice .= "

{$msg}

"; $browsehappy = 'http://browsehappy.com/'; - $locale = get_locale(); + $locale = get_user_locale(); if ( 'en_US' !== $locale ) $browsehappy = add_query_arg( 'locale', $locale, $browsehappy ); diff --git a/wp-admin/includes/import.php b/wp-admin/includes/import.php index 4f0b78536f..0d534422c2 100644 --- a/wp-admin/includes/import.php +++ b/wp-admin/includes/import.php @@ -125,13 +125,13 @@ function wp_import_handle_upload() { function wp_get_popular_importers() { include( ABSPATH . WPINC . '/version.php' ); // include an unmodified $wp_version - $locale = get_locale(); + $locale = get_user_locale(); $cache_key = 'popular_importers_' . md5( $locale . $wp_version ); $popular_importers = get_site_transient( $cache_key ); if ( ! $popular_importers ) { $url = add_query_arg( array( - 'locale' => get_locale(), + 'locale' => get_user_locale(), 'version' => $wp_version, ), 'http://api.wordpress.org/core/importers/1.1/' ); $options = array( 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url() ); diff --git a/wp-admin/includes/plugin-install.php b/wp-admin/includes/plugin-install.php index 10568b0158..b569d7679d 100644 --- a/wp-admin/includes/plugin-install.php +++ b/wp-admin/includes/plugin-install.php @@ -109,7 +109,7 @@ function plugins_api( $action, $args = array() ) { } if ( ! isset( $args->locale ) ) { - $args->locale = get_locale(); + $args->locale = get_user_locale(); } /** diff --git a/wp-admin/includes/template.php b/wp-admin/includes/template.php index f9f463b62f..d6fcab06ee 100644 --- a/wp-admin/includes/template.php +++ b/wp-admin/includes/template.php @@ -1622,7 +1622,7 @@ do_action( "admin_head-$hook_suffix" ); /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_head' ); -$admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) ); +$admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_user_locale() ) ) ); if ( is_rtl() ) $admin_body_class .= ' rtl'; diff --git a/wp-admin/includes/theme.php b/wp-admin/includes/theme.php index 95aaec1618..b5fc98042d 100644 --- a/wp-admin/includes/theme.php +++ b/wp-admin/includes/theme.php @@ -412,7 +412,7 @@ function themes_api( $action, $args = array() ) { } if ( ! isset( $args->locale ) ) { - $args->locale = get_locale(); + $args->locale = get_user_locale(); } /** diff --git a/wp-admin/includes/user.php b/wp-admin/includes/user.php index fc46dd3ad2..6bf826bb2a 100644 --- a/wp-admin/includes/user.php +++ b/wp-admin/includes/user.php @@ -94,6 +94,16 @@ function edit_user( $user_id = 0 ) { $user->rich_editing = isset( $_POST['rich_editing'] ) && 'false' == $_POST['rich_editing'] ? 'false' : 'true'; $user->admin_color = isset( $_POST['admin_color'] ) ? sanitize_text_field( $_POST['admin_color'] ) : 'fresh'; $user->show_admin_bar_front = isset( $_POST['admin_bar_front'] ) ? 'true' : 'false'; + $user->locale = ''; + + if ( isset( $_POST['locale'] ) ) { + $locale = sanitize_text_field( $_POST['locale'] ); + if ( ! in_array( $locale, get_available_languages(), true ) ) { + $locale = ''; + } + + $user->locale = ( '' === $locale ) ? 'en_US' : $locale; + } } $user->comment_shortcuts = isset( $_POST['comment_shortcuts'] ) && 'true' == $_POST['comment_shortcuts'] ? 'true' : ''; diff --git a/wp-admin/options.php b/wp-admin/options.php index f319d5208e..93c69bc1e4 100644 --- a/wp-admin/options.php +++ b/wp-admin/options.php @@ -209,19 +209,23 @@ if ( 'update' == $action ) { $value = null; if ( isset( $_POST[ $option ] ) ) { $value = $_POST[ $option ]; - if ( ! is_array( $value ) ) + if ( ! is_array( $value ) ) { $value = trim( $value ); + } $value = wp_unslash( $value ); } update_option( $option, $value ); } // Switch translation in case WPLANG was changed. - $language = get_option( 'WPLANG' ); - if ( $language ) { - load_default_textdomain( $language ); - } else { - unload_textdomain( 'default' ); + $language = get_option( 'WPLANG' ); + $user_language = get_user_locale(); + if ( $language === $user_language ) { + if ( $language ) { + load_default_textdomain( $language ); + } else { + unload_textdomain( 'default' ); + } } } diff --git a/wp-admin/plugin-editor.php b/wp-admin/plugin-editor.php index a5dd63dba1..f9bdc80f8f 100644 --- a/wp-admin/plugin-editor.php +++ b/wp-admin/plugin-editor.php @@ -260,7 +260,7 @@ foreach ( $plugin_files as $plugin_file ) : -
+
diff --git a/wp-admin/theme-editor.php b/wp-admin/theme-editor.php index cd9f8392f1..145ff5a94d 100644 --- a/wp-admin/theme-editor.php +++ b/wp-admin/theme-editor.php @@ -263,7 +263,7 @@ else : ?>
- +
diff --git a/wp-admin/user-edit.php b/wp-admin/user-edit.php index b97cdddd95..0e183e71d7 100644 --- a/wp-admin/user-edit.php +++ b/wp-admin/user-edit.php @@ -269,6 +269,38 @@ if ( !( IS_PROFILE_PAGE && !$user_can_edit ) ) : ?> + + + + + + + + ID ); + + if ( 'en_US' === $user_locale ) { // en_US + $user_locale = false; + } elseif ( ! in_array( $user_locale, $languages, true ) ) { + $user_locale = get_locale(); + } + + wp_dropdown_languages( array( + 'name' => 'locale', + 'id' => 'locale', + 'selected' => $user_locale, + 'languages' => $languages, + 'show_available_translations' => false + ) ); + ?> + + + + locale; + return ( '' === $locale ) ? get_locale() : $locale; +} + /** * Retrieve the translation of $text. * @@ -633,7 +650,7 @@ function unload_textdomain( $domain ) { */ function load_default_textdomain( $locale = null ) { if ( null === $locale ) { - $locale = get_locale(); + $locale = is_admin() ? get_user_locale() : get_locale(); } // Unload previously loaded strings so we can switch translations. @@ -1148,4 +1165,4 @@ function is_rtl() { return false; } return $wp_locale->is_rtl(); -} \ No newline at end of file +} diff --git a/wp-includes/user.php b/wp-includes/user.php index fc40b478b9..a83e57e099 100644 --- a/wp-includes/user.php +++ b/wp-includes/user.php @@ -1358,6 +1358,7 @@ function validate_username( $username ) { * @since 2.0.0 * @since 3.6.0 The `aim`, `jabber`, and `yim` fields were removed as default user contact * methods for new installs. See wp_get_user_contact_methods(). + * @since 4.7.0 The user's locale can be passed to `$userdata`. * * @global wpdb $wpdb WordPress database abstraction object. * @@ -1392,6 +1393,7 @@ function validate_username( $username ) { * @type string|bool $show_admin_bar_front Whether to display the Admin Bar for the user on the * site's front end. Default true. * @type string $role User's role. + * @type string $locale User's locale. Default empty. * } * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not * be created. @@ -1606,6 +1608,8 @@ function wp_insert_user( $userdata ) { $meta['show_admin_bar_front'] = empty( $userdata['show_admin_bar_front'] ) ? 'true' : $userdata['show_admin_bar_front']; + $meta['locale'] = isset( $userdata['locale'] ) ? $userdata['locale'] : ''; + $user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $user_nicename, $user_login)); if ( $user_nicename_check ) { @@ -1965,7 +1969,7 @@ function wp_create_user($username, $password, $email = '') { * @return array List of user keys to be populated in wp_update_user(). */ function _get_additional_user_keys( $user ) { - $keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front' ); + $keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front', 'locale' ); return array_merge( $keys, array_keys( wp_get_user_contact_methods( $user ) ) ); } diff --git a/wp-includes/version.php b/wp-includes/version.php index c7ef279cbb..3215b9abab 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.7-alpha-38704'; +$wp_version = '4.7-alpha-38705'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.