Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set locale dynamically at runtime #253

Closed
Francisc opened this issue Nov 15, 2017 · 13 comments
Closed

Set locale dynamically at runtime #253

Francisc opened this issue Nov 15, 2017 · 13 comments

Comments

@Francisc
Copy link

Francisc commented Nov 15, 2017

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});
@tvld
Copy link

tvld commented Dec 20, 2017

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:

  <locale-switcher :locales="['en', 'nl']" :show-full="true" ></locale-switcher>

@BenoitRanque
Copy link

BenoitRanque commented Mar 11, 2018

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

@ABleas
Copy link

ABleas commented Apr 13, 2018

@BenoitRanque that solution is very nice, thanks!

@marouim
Copy link

marouim commented Apr 28, 2018

@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.

@ghost
Copy link

ghost commented May 2, 2018

@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?

@ghost
Copy link

ghost commented May 2, 2018

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.

@kazupon kazupon reopened this Jun 14, 2018
@jgradzki
Copy link

+1

1 similar comment
@pggalaviz
Copy link

+1

@Jserrano12
Copy link

+1

@olvenmage
Copy link

Place it in a store?

@dmouroutis
Copy link

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()
})

@ghost
Copy link

ghost commented Dec 11, 2018

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.

@Ahmed7fathi
Copy link

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 require refreshing the page any other good one ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests