You should remember the chosen language for a user, if they had selected one previously, I store this in the database, in a user_preference
table.
Then you need to intercept the request, it can be done in the application configuration file, using the on beforeRequest
property.
If you don't have stored a preference for the current user, or the user is a guest, use the browser language to set the application language.
Configuration file
use app\models\User;
...
'on beforeRequest' => function ($event) {
$user_lang = '';
if (!Yii::$app->user->isGuest) {
// Check if you have stored a language preference for the user
$user_lang = User::findIdentity(Yii::$app->user->id)->getUserPreference('lang');
}
if (!empty($user_lang)) {
// If you have a stored preference for the user, use it
Yii::$app->language = $user_lang;
} else {
// If you don't have a preference, use the browser language
// Get the browser language from the headers
$browser_lang = Yii::$app->request->headers->get('accept-language');
// Alternatively get the headers from the event
// $event->sender->request->headers->get('accept-language')
// Calculate the language you want to provide based on the browser language
$language_code = LanguageHelper::calculatei18nCode($browser_lang);
Yii::$app->language = $language_code;
}
},
...
If you wanted to keep your configuration file clean, you could use filters instead to intercept the request.
Your LanguageHelper::calculatei18nCode($browser_lang)
method would try to find a match for the browser language in the available languages, if it didn't find one it could return the closest match, or the default application language.
LanguageHelper
public static function calculatei18nCode ($browser_lang) {
// For example, if you are offering one translation file for french
if (stripos($browser_lang, 'fr')) {
return 'fr';
}
...
return 'en';
}