Search code examples
vue.jsinternationalizationpersistence

How to stop i18n from reverting to default locale on page reload on Vue?


I'm using i18n to translate my app on Vue. I've created a component name LocaleChanger to allow the user to change the app language. I'm using it in two different places: in the login page and the dashboard page.

The default locale language is Spanish. I'm in the login page and I change the language to English and log in and push to dashboard. The language remains English. But if I reload the page the language changes to Spanish. How can I stop this from happening?

This is my component

<template>
  <v-menu offset-y>
      <template v-slot:activator="{ on }">
        <v-btn class="transparent" rounded outlined v-on="on">
          <v-icon class="pr-3">mdi-web</v-icon> 
           {{  $store.getters.getAppLanguage }}
          <v-icon class="pl-3">mdi-menu-down</v-icon> 
        </v-btn>
      </template>

      <v-list>
        <v-list-item-group>
          <v-list-item
            v-for="(item, i) in items"
            :key="i"
            @click="setLanguage(item)"
          >
            <v-list-item-content class="text-center">
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-menu>
</template>

<script>
export default {
  name: 'LocaleChanger',
  data () {
    return {
      selectedLanguage: this.$store.getters.getAppLanguage,
      items: [
        {
          text: 'ES',
        },
        {
          text: 'EN',
        },
      ],
    }
  },
  methods: {
    // Set local i18n language acording to the language user has selected 
    setLanguage (item) {
      if (item.text == 'ES') {
        i18n.locale = 'es'
        this.$store.commit('setAppLanguage', 'ES')
      } else if (item.text == 'EN') {
        i18n.locale = 'en'
        this.$store.commit('setAppLanguage', 'EN')     
      }
    },
  },
}
</script>

And this i18n.js

Vue.use(VueI18n)

const messages = {
  en: {
    ...require('@/locales/en.json'),
    $vuetify: en,
  },
  es: {
    ...require('@/locales/es.json'),
    $vuetify: es,
  },
}

export default new VueI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || 'es',
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
  messages,
})


Solution

  • You could use localstorage to persist the information.

    In your store try to get appLanguage from the localStorage.

    export default new Vuex.Store({
      state: {
        appLanguage: localStorage.getItem("appLanguage") || process.env.VUE_APP_I18N_LOCALE || 'es'
      },
      getters: {
        getAppLanguage: (state) => state.appLanguage
      },
      mutations: {
        setAppLanguage(state, language) {
          state.appLanguage = language;
          localStorage.setItem("appLanguage", language); // Whenever we change the appLanguage we save it to the localStorage
        }
      }
    })
    

    And then initialize localStorage with the value from your store.

    import store  from "./store.js";
    
    export default new VueI18n({
      locale: store.getters.getAppLanguage,
      messages,
    })
    

    https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage