We could try to filter the <strike>`WPLANG` option</strike> *locale* [(see e.g. this approach from the related list here on the right](http://wordpress.stackexchange.com/questions/53326/change-admin-language-based-on-user-in-single-site) by @brasofilo, that's based on [this one](http://wordpress.stackexchange.com/a/52436/26350) by @toscho ): /** * Override locale settings for the current (non-admin) user */ is_admin() && add_filter( 'locale', function( $locale ) { // Modify locale for non-admins (we don't want to override this on the settings pages) if( ! current_user_can( 'manage_options' ) ) { // Get admin language for the current user $lang = get_user_meta( get_current_user_id(), 'wpse_lang', true ); // Use 'en_US' as default $locale = ! empty( $lang ) ? sanitize_text_field( $lang ) : 'en_US'; } return $locale; } ); where we check if the current user has the `wpse_lang` user meta key set, with values like `is_IS`, `da_DK`, ... Then we could add the language selection for each user, on the user settings page. There we could use the [`wp_dropdown_languages()`][1] function, with the [`get_available_languages()`][2] function, to display the select-box for available languages. Here's an [example](http://wordpress.stackexchange.com/a/6711/26350) by @sanchothefat on how we can add custom user settings. We can display the user language selection with: /** * Display available language dropdown */ function wpse_user_language( $user ) { // Only display for non-admins, but allow admins to edit for other users if( current_user_can( 'manage_options' ) && $user->ID == get_current_user_id() ) return; // Get the current 'wp_lang' settings $lang = get_user_meta( $user->ID, 'wpse_lang', true ); ?> <table class="form-table"> <tr id="wpse-lang-selection"> <th scope="row"> <label for="wpse_lang"> <?php _e( 'WPSE' ); ?> - <?php _e( 'Site Language' ); ?> </label> </th> <td><?php wp_dropdown_languages( [ 'id' => 'wpse_lang', 'name' => 'wpse_lang', 'languages' => get_available_languages(), 'translations' => [], 'selected' => $lang, 'show_available_translations' => false, ] ); ?></td> </tr> </table> <?php } add_action( 'show_user_profile', 'wpse_user_language' ); add_action( 'edit_user_profile', 'wpse_user_language' ); Note that here we re-use the *Site Language* string, because it's translated. The update part is: /** * Update the 'wp_lang' user settings */ function wpse_user_language_save( $user_id ) { if( current_user_can( 'edit_user', $user_id ) && isset( $_POST['wpse_lang'] ) ) return update_user_meta( $user_id, 'wpse_lang', $_POST['wpse_lang'] ); return false; } add_action( 'personal_options_update', 'wpse_user_language_save' ); add_action( 'edit_user_profile_update', 'wpse_user_language_save' ); Here's an example output: [![wpse_lang selection][3]][3] Hopefully you can adjust this to your needs. It would be a good idea to wrap this in a class, where we could initialize it with a custom setup and re-use things for better performance. We might also consider removing the `is_admin()` check to apply this also on the front-end, but then we might need an extra `is_user_logged_in()` check. [1]: https://codex.wordpress.org/Function_Reference/wp_dropdown_languages [2]: https://developer.wordpress.org/reference/functions/get_available_languages/ [3]: https://i.sstatic.net/Gczck.jpg