Yii2下拉框切换语言问题:仅生效一次,刷新后恢复英文
Hey there! Let's break down why your language dropdown only works once and resets to English after a refresh. The root problem is that you're not persisting the user's language selection—right now, you send the choice to the server, but there's no code to save that preference (like in a session or cookie), so the app defaults back to English every time the page reloads.
Here's how to fix it step by step:
1. Update the View to Reflect Saved Language
First, make sure the dropdown loads with the user's saved language pre-selected instead of always defaulting to English. Modify your select element like this:
<select class="form-control user_language"> <option value="en" <?= Yii::$app->language === 'en' ? 'selected' : '' ?>>English</option> <option value="nl" <?= Yii::$app->language === 'nl' ? 'selected' : '' ?>>Norwegian</option> </select>
This checks the current application language (which we'll set based on saved preferences) and marks the correct option as selected.
2. Enhance the JavaScript to Handle Initialization & AJAX
Update your JS to initialize the dropdown on page load and ensure the AJAX request properly communicates with the backend to save the language:
<script> $(document).ready(function() { // Set dropdown to saved language when page loads const savedLanguage = '<?= Yii::$app->language ?>'; $('.user_language').val(savedLanguage); // Handle language change event $(".user_language").change(function(){ const selectedLang = this.value; $.ajax({ url: '<?= Yii::$app->request->baseUrl . '/site/set-language' ?>', // Replace with your actual controller route method: 'POST', data: { language: selectedLang }, success: function() { // Reload the page to apply the new language immediately window.location.reload(); }, error: function() { alert('Oops, something went wrong while changing the language.'); } }); }); }); </script>
3. Add Backend Logic to Save Language Preference
You need a controller action to receive the language choice, validate it, and save it (we'll use both session and cookie for persistence). Add this to your SiteController (or relevant controller):
public function actionSetLanguage() { if (Yii::$app->request->isPost) { $language = Yii::$app->request->post('language'); // Only allow supported languages to prevent invalid inputs $allowedLanguages = ['en', 'nl']; if (in_array($language, $allowedLanguages)) { // Save to session for temporary persistence (until user closes browser) Yii::$app->session->set('language', $language); // Optional: Save to cookie for long-term persistence (30 days) $languageCookie = new \yii\web\Cookie([ 'name' => 'user_language', 'value' => $language, 'expire' => time() + (3600 * 24 * 30), // 30 days from now 'httpOnly' => true, ]); Yii::$app->response->cookies->add($languageCookie); // Update the app's current language immediately Yii::$app->language = $language; } return $this->asJson(['success' => true]); } return $this->asJson(['success' => false]); }
4. Load Saved Language on App Bootstrap
To make sure the app uses the saved language on every request, update your config/web.php (or relevant config file) to check for the session/cookie and set the language early:
return [ // ... other configs 'language' => function() { // Check session first, then cookie, default to 'en' if (Yii::$app->session->has('language')) { return Yii::$app->session->get('language'); } elseif (Yii::$app->request->cookies->has('user_language')) { return Yii::$app->request->cookies->getValue('user_language'); } return 'en'; }, // ... ];
Why This Works:
- Persistence: We save the language choice in both session (temporary) and cookie (long-term) so it stays even after page refreshes or browser restarts.
- Initialization: The dropdown loads with the saved language instead of always defaulting to English.
- Validation: We only allow supported languages to avoid invalid inputs.
- Immediate Application: Reloading the page after AJAX success ensures all content updates to the selected language right away.
内容的提问来源于stack exchange,提问作者Yasin Patel

