We could try to filter the locale (see e.g. this approach from the related list here on the right by @brasofilo, that’s based on this one by @toscho ):WPLANG
option
/**
* 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()
function, with the get_available_languages()
function, to display the select-box for available languages.
Here’s an example 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:
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.