diff --git a/src/wp-admin/includes/user.php b/src/wp-admin/includes/user.php index 6bf826bb2a..e5f84fa316 100644 --- a/src/wp-admin/includes/user.php +++ b/src/wp-admin/includes/user.php @@ -98,11 +98,13 @@ function edit_user( $user_id = 0 ) { if ( isset( $_POST['locale'] ) ) { $locale = sanitize_text_field( $_POST['locale'] ); - if ( ! in_array( $locale, get_available_languages(), true ) ) { + if ( 'site-default' === $locale ) { $locale = ''; + } elseif ( ! in_array( $locale, get_available_languages(), true ) ) { + $locale = 'en_US'; } - $user->locale = ( '' === $locale ) ? 'en_US' : $locale; + $user->locale = $locale; } } diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index a85de3b241..f1dc417e68 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -284,9 +284,9 @@ if ( $languages ) : ?> $user_locale = $profileuser->locale; if ( 'en_US' === $user_locale ) { - $user_locale = false; - } elseif ( ! in_array( $user_locale, $languages, true ) ) { - $user_locale = get_locale(); + $user_locale = ''; + } elseif ( '' === $user_locale || ! in_array( $user_locale, $languages, true ) ) { + $user_locale = 'site-default'; } wp_dropdown_languages( array( @@ -294,7 +294,8 @@ if ( $languages ) : ?> 'id' => 'locale', 'selected' => $user_locale, 'languages' => $languages, - 'show_available_translations' => false + 'show_available_translations' => false, + 'show_site_locale_default' => true ) ); ?> diff --git a/src/wp-includes/l10n.php b/src/wp-includes/l10n.php index 4ae7e2d278..39346c4d0d 100644 --- a/src/wp-includes/l10n.php +++ b/src/wp-includes/l10n.php @@ -1048,6 +1048,7 @@ function wp_get_pomo_file_data( $po_file ) { * * @since 4.0.0 * @since 4.3.0 Introduced the `echo` argument. + * @since 4.7.0 Introduced the `show_site_locale_default` argument. * * @see get_available_languages() * @see wp_get_available_translations() @@ -1065,6 +1066,7 @@ function wp_get_pomo_file_data( $po_file ) { * @type bool|int $echo Whether to echo the generated markup. Accepts 0, 1, or their * boolean equivalents. Default 1. * @type bool $show_available_translations Whether to show available translations. Default true. + * @type bool $show_site_locale_default Whether to show an option to fall back to the site's locale. Default false. * } * @return string HTML content */ @@ -1078,8 +1080,14 @@ function wp_dropdown_languages( $args = array() ) { 'selected' => '', 'echo' => 1, 'show_available_translations' => true, + 'show_site_locale_default' => false, ) ); + // English (United States) uses an empty string for the value attribute. + if ( 'en_US' === $args['selected'] ) { + $args['selected'] = ''; + } + $translations = $args['translations']; if ( empty( $translations ) ) { require_once( ABSPATH . 'wp-admin/includes/translation-install.php' ); @@ -1122,7 +1130,20 @@ function wp_dropdown_languages( $args = array() ) { if ( $translations_available ) { $structure[] = ''; } - $structure[] = ''; + + if ( $args['show_site_locale_default'] ) { + $structure[] = sprintf( + '', + selected( 'site-default', $args['selected'], false ), + _x( 'Site Default', 'default site language' ) + ); + } + + $structure[] = sprintf( + '', + selected( '', $args['selected'], false ) + ); + foreach ( $languages as $language ) { $structure[] = sprintf( '', diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php index 9fece46997..08fc183167 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php @@ -1074,7 +1074,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller { 'locale' => array( 'description' => __( 'Locale for the resource.' ), 'type' => 'string', - 'enum' => array_merge( array( 'en_US' ), get_available_languages() ), + 'enum' => array_merge( array( '', 'en_US' ), get_available_languages() ), 'context' => array( 'edit' ), ), 'nickname' => array( diff --git a/tests/phpunit/tests/l10n.php b/tests/phpunit/tests/l10n.php index 39065c9b74..4df34d16fa 100644 --- a/tests/phpunit/tests/l10n.php +++ b/tests/phpunit/tests/l10n.php @@ -99,6 +99,50 @@ class Tests_L10n extends WP_UnitTestCase { $this->assertContains( '', $actual ); } + /** + * @ticket 38632 + */ + function test_wp_dropdown_languages_site_default() { + $args = array( + 'id' => 'foo', + 'name' => 'bar', + 'languages' => array( 'de_DE' ), + 'translations' => $this->wp_dropdown_languages_filter(), + 'selected' => 'de_DE', + 'echo' => false, + 'show_site_locale_default' => true, + ); + $actual = wp_dropdown_languages( $args ); + + $this->assertContains( 'id="foo"', $actual ); + $this->assertContains( 'name="bar"', $actual ); + $this->assertContains( '', $actual ); + $this->assertContains( '', $actual ); + $this->assertContains( '', $actual ); + $this->assertContains( '', $actual ); + } + + /** + * @ticket 38632 + */ + function test_wp_dropdown_languages_en_US_selected() { + $args = array( + 'id' => 'foo', + 'name' => 'bar', + 'languages' => array( 'de_DE' ), + 'translations' => $this->wp_dropdown_languages_filter(), + 'selected' => 'en_US', + 'echo' => false, + ); + $actual = wp_dropdown_languages( $args ); + + $this->assertContains( 'id="foo"', $actual ); + $this->assertContains( 'name="bar"', $actual ); + $this->assertContains( '', $actual ); + $this->assertContains( '', $actual ); + $this->assertContains( '', $actual ); + } + /** * We don't want to call the API when testing. * diff --git a/tests/phpunit/tests/rest-api/rest-users-controller.php b/tests/phpunit/tests/rest-api/rest-users-controller.php index 09e11a6693..08a1597fa2 100644 --- a/tests/phpunit/tests/rest-api/rest-users-controller.php +++ b/tests/phpunit/tests/rest-api/rest-users-controller.php @@ -879,6 +879,25 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { $this->assertEquals( 'en_US', $user->locale ); } + /** + * @ticket 38632 + */ + public function test_update_item_empty_locale() { + $user_id = $this->factory->user->create( array( 'user_login' => 'test_json_user', 'user_email' => 'testjson@example.com', 'locale' => 'de_DE' ) ); + $this->allow_user_to_manage_multisite(); + wp_set_current_user( self::$user ); + + $request = new WP_REST_Request( 'PUT', '/wp/v2/users/' . $user_id ); + $request->set_param( 'locale', '' ); + $response = $this->server->dispatch( $request ); + $this->check_add_edit_user_response( $response, true ); + + $data = $response->get_data(); + $this->assertEquals( get_locale(), $data['locale'] ); + $user = get_userdata( $user_id ); + $this->assertEquals( '', $user->locale ); + } + public function test_update_item_username_attempt() { $user1 = $this->factory->user->create( array( 'user_login' => 'test_json_user', 'user_email' => 'testjson@example.com' ) ); $user2 = $this->factory->user->create( array( 'user_login' => 'test_json_user2', 'user_email' => 'testjson2@example.com' ) );