Vue-i18n: Set locale dynamically at runtime

Created on 15 Nov 2017  路  12Comments  路  Source: kazupon/vue-i18n

Hello,

It unclear to me from the docs if using setLocaleMessage() is how you get dynamic locales at runtime to work. There are many articles about how to do that at build time, but none that I could see about runtime changes.

To give an example, here is what I mean in the form of a timeline:

  1. App loads, reads locale requirement.
  2. Makes AJAX call to fetch the appropriate JSON file (e.g. en.json).
  3. Calls setLocaleMessage() as shown below:
const i18n = new VueI18n({...});
...
i18n.setLocaleMessage('en', {...pathsHere});
...
//Later on:
//After another AJAX call to fetch fr.json:
i18n.setLocaleMessage('fr', {...pathsHere});

Most helpful comment

There should be some easy way to change the global language/locale at run-time / dynamically and it should be documented very well and at a central point because this IMHO is an essential feature of this type of library.

All 12 comments

This works for me locale_switcher.vue:

<template>
  <div class="locale-switcher">
    <!-- {{ initLocale() }} -->
    <b-nav-item-dropdown :dropup="dropup" :text="dropdownLbl" right>
      <b-dropdown-item
        class="locale-link"
        v-for="locale in locales"
        :key="locale.id"
        @click="setLocale(locale)"
        :class="{ 'is-current': locale === activeLocale }"
        href="#">
        {{ getLanguageString(locale) }}
      </b-dropdown-item>
    </b-nav-item-dropdown>
  </div>
</template>

<script>

  import Vue from 'vue'
  // Restore locale from cookie, if it was set
  import VueCookie from 'vue-cookie'
  Vue.use(VueCookie)

  const localeStrings = {
    en: "English",
    nl: "Nederlands",
    ru: "Russian",
    ua: "Ukrainian",
    fr: "Fran莽ais",
    de: "Deutsch"
  }

  Vue.config.lang = VueCookie.get('locale') || 'en'
  console.log("Locale from cookie = " + Vue.config.lang + ": language = " + localeStrings[Vue.config.lang])

  export default {
    props: {
      locales: {
        type: Array,
        default: ['en']
      },
      showFull: Boolean,
      dropup: Boolean,
      locLabel: {
        type: String,
        default: ''
      }
    },
    data: function () {
      return {
        activeLocale: Vue.config.lang
      }
    },
    computed: {
      dropdownLbl: function () {
        return this.locLabel ? this.locLabel : this.activeLocale
      }
    },
    methods: {
      setLocale: function (locale) {
        Vue.config.lang = locale
        this.activeLocale = locale
        this.$cookie.set('locale', locale)
        this.$i18n.locale = Vue.config.lang
        console.log("New locale = " + Vue.config.lang + ": language = " + localeStrings[Vue.config.lang])
      },
      getLanguageString: function (locale) {
        return this.showFull ? localeStrings[locale] : locale
      }
    }
  }
</script>

And as component:
```html

````

Here is my solution:

  app.i18n = new VueI18n({
    locale: 'es',
    fallbackLocale: 'es',
    messages
  })

  Object.defineProperty(Vue.prototype, '$locale', {
    get: function () {
      return app.i18n.locale
    },
    set: function (locale) {
      app.i18n.locale = locale
    }
  })

  // this part happens later

 new Vue(app)

Usage:

this.$locale // root Vuei18n locale

this.$locale = 'en' // set root Vuei18n locale

Edit: this works too:

this.$root.i18n.locale // root Vuei18n locale

this.$root.i18n.locale  = 'en' // set root Vuei18n locale

@BenoitRanque that solution is very nice, thanks!

@BenoitRanque So easy compared to other solutions I've seen ! Thanks a lot.
just a quick one.. this.$root.i18n.locale didn't work... this works this.$locale.

@kazupon Why do you think this issue is solved?

Personally, I could work this issue around like this:

// change global locale like this in any component:
this.$root.$i18n.locale = 'newLocale';
// then, use the global locale like this in any (other or the same) component:
this.$t(
    somePath, // example: 'hello {name}'
    this.$root.$i18n.locale,
    namedFormattingParametersObject, // optional. example: { name: 'kazupon' }
);

IMHO you can find the best (but still bad) documentation regarding this here: https://kazupon.github.io/vue-i18n/en/migrations.html#instance-properties @kazupon Do I see correctly that $i18n isn't documented anywhere else than there?

There should be some easy way to change the global language/locale at run-time / dynamically and it should be documented very well and at a central point because this IMHO is an essential feature of this type of library.

+1

+1

+1

Place it in a store?

I don't like to use this.$root in general so my solution since I'm using vuex was this:

On i18n.js I use a dynamic locale value from a state getter with a fallback as well.

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import store from '@/store.js'

Vue.use(VueI18n)

export default new VueI18n({
  locale: store.getters.getLangKey || 'en',
  messages: loadLocaleMessages()
})

This works perfectly for me. You just have to access to the i18n object directly and change its params there.

this.$root._i18n._vm.locale

Also, @DMouroutis, how could you manage to get the value from the store dinamically? Using vuex was my first option and I implemented it as you did, but can't manage to retreive the data after mutating them.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sergot picture sergot  路  5Comments

koslo picture koslo  路  5Comments

lucianobosco picture lucianobosco  路  4Comments

zhangruinian picture zhangruinian  路  4Comments

cslee picture cslee  路  5Comments