kazupon / vue-i18n

:globe_with_meridians: Internationalization plugin for Vue.js
https://kazupon.github.io/vue-i18n/
MIT License
7.28k stars 861 forks source link

How do I change the language after configuration? #2

Closed thelinuxlich closed 8 years ago

kazupon commented 9 years ago

sorry, this plugin cannot change the language after the configuration.

kazupon commented 9 years ago

@thelinuxlich Hi I released vue-i18n new version. You can change language the below code.

<p>{{ $t('message.hello', 'en') }}</p>

Please try it !!

thelinuxlich commented 9 years ago

I tested it and it is useful but I think that it would be better to somehow set lang parameter as observable and change globally based on it

kazupon commented 9 years ago

I add Vue.config.lang configuration.

thelinuxlich commented 9 years ago

This doesn't solve the issue unless Vue.config.lang is reactive

kazupon commented 9 years ago

Sorry, I didn't understand your request.

I think that it would be better to somehow set lang parameter as observable and change globally based on it

You need reactive lang params, don't you ?

thelinuxlich commented 9 years ago

yeah, I believe it's a common case for the user switching the language during interaction

kazupon commented 9 years ago

OK. I'll try out. :)

nkovacs commented 9 years ago

How about this: http://jsfiddle.net/nkovacs/1zh3agxr/?

See also https://github.com/yyx990803/vue/issues/1114

ChrisRM commented 9 years ago

Any news on this one?

SystemZ commented 9 years ago

I'm interested in easy switching languages by user too.

martinlindhe commented 9 years ago

+1 i tried making a language switcher widget, but it don't seem to update the translations after Vue.config.lang has been changed

seemsindie commented 8 years ago

+1

tasarsu commented 8 years ago

+1

flaird commented 8 years ago

+1 @martinlindhe Did you get it to work?

flaird commented 8 years ago

@kazupon This package https://github.com/Haixing-Hu/vue-i18n has support for this through jQuery AJAX calls(from what I can tell). Perhaps you can use some of it's logic to solve this issue. Just a thought!

martinlindhe commented 8 years ago

@sagaio: nope, i'm currently working around it by doing a page reload when language was changed.

location.reload();

works, but ain't pretty!

rtfleg commented 8 years ago

+1

stephanedemotte commented 8 years ago

+1

ghost commented 8 years ago

+1

martinlindhe commented 8 years ago

Was thinking of this issue again today and came up with this solution. It involves using a new tag and I'm not sure i gonna do this on my current vue project, but maybe for the next one.

First, we have someplace in our ui to change language.

to change language you do something like this

select(code) {
    Vue.config.lang = code;
    this.$broadcast('language');
}

to put translations in our templates, we now do <t t="user.new"></t>

and finally a T.vue component:

<template>
    <span>
        {{ translated }}
    </span>
</template>

<script>
export default {
    props: {
        t: '',
    },
    data() {
        return {
            translated: '',
        };
    },
    ready() {
        this.translated = this.$t(this.t);
        this.$on('language', function() {
            this.translated = this.$t(this.t);
        });
    },
};
</script>

Now your language changes are reactive.

MattyRad commented 8 years ago

+1

seemsindie commented 8 years ago

@kazupon I would like to add this feature myself, but i can't afford it right now...but i would like to know do you plan to support this or should i switch to what @sagaio said?

kazupon commented 8 years ago

@seemsindie I'll plan to support in vue-i18n v3. but the release of vue-i18n v3 is undecided.

seemsindie commented 8 years ago

@kazupon Ok thanks, all i needed to hear :)

kvdmolen commented 8 years ago

+1

A global runtime this.$setLang() method preferred

ealves-pt commented 8 years ago

+1 count me in if you need an hand for the next release

ealves-pt commented 8 years ago

Also, for those using vuex I'm using the following workaround at the moment:

modules/i18n/mutation-types.js

export const SET_LANGUAGE = 'SET_LANGUAGE'

modules/i18n/index.js

import {
 SET_LANGUAGE
} from './mutation-types'

const state = {
 lang: 'en',
 locales: [ 'en', 'fi' ]
}

const mutations = {
 [SET_LANGUAGE] (state, lang) {
  if (state.locales.indexOf(lang) !== -1) {
   state.lang = lang
  }
 }
}

export default {
 state,
 mutations
}

store.js

import i18n from './modules/i18n'
// ... import other stuff

Vue.use(Vuex)

const store = new Vuex.Store({
 modules: {
  i18n
 }
})

export default store

main.js

import Vue from 'vue'
import store from './store'

Vue.filter('translate', function (value, arg) {
 return this.$t(value, this.$store.state.i18n.lang, arg)
})

and then just use it like this

<span>{{ 'message' | translate }}</span>

where

en.json

{
 "message": "English message"
}

fi.json

{
 "message": "Finnish message"
}

If you change the language like this:

vm.$store.dispatch('SET_LANGUAGE', 'fi')

everything will work like a charm.

NOTE: In my case I opt-out for create a filter, and it might not work perfectly, but gives an idea on how to get this to work.

kucherenkovova commented 8 years ago

+1

francoisromain commented 8 years ago

Hello @kazupon Do you have an example on how to change the Vue.config.lang from within a component?

thanks

pawlox commented 8 years ago

+1 for some example

kazupon commented 8 years ago

You can use the Component locale and $t method with lang params.

pawlox commented 8 years ago

Oh, thanks, but as a matter of fact I was looking for some example to switch language dynamically in my app - should I just change global config option like Vue.config.lang = 'ja' or Is threre any special method like 'setLanguage' ?

kazupon commented 8 years ago

hmm, I cannot see the your use-case ... I think you can resolve with component that was wrapped vuex like state management (e.g. the above @ealves-pt comment.

francoisromain commented 8 years ago

@kazupon The use case is if a user navigates a websites in one language, then he clicks a button to switch to another language. Now the global vue.config.lang has to be the new language. How would you handle that switcher-button-component?

pawlox commented 8 years ago

Exactly :)

kazupon commented 8 years ago

In this use-case, I think you can handle data changing with watch in the component.

the below example of implementation:

const navigation = {
  template: `<nav>
    <select v-model="lang">
      <option selected value="en">EN</option>
      <option> value="ja">JA</option>
    </select>
  </nav>`,
  data () {
    return { lang: 'en' }
  },
  watch: {
    lang (val) {
      Vue.config.lang = val
    }
  }
}
francoisromain commented 8 years ago

Ok thank you. At the moment, Vue is only imported in the main file, not in the components. So I have to import 'Vue' inside my component for this?

pespantelis commented 8 years ago

@francoisromain you could use the $lang property:

new Vue({
  // ...
  methods: {
    change () {
      let current = this.$lang.lang

      if (current === 'en') {
        this.$lang.lang = 'el'
      } else {
        this.$lang.lang = 'en'
      }
    }
  }
})

https://jsfiddle.net/pespantelis/4xcuLtur/

francoisromain commented 8 years ago

@pespantelis sweet!

francoisromain commented 8 years ago

@pespantelis Oh but $lang is undefined in the module scope…

pespantelis commented 8 years ago

@francoisromain Ohh you are right!

However, I have another approach to achieve this in the module scope.

You could add Vue instance methods by attaching them to Vue.prototype.

Vue.prototype.$locale = {
  change (lang) {
    Vue.config.lang = lang
  },
  current () {
    return Vue.config.lang
  }
}

Vue.component('my-component', {
  template: '...',
  methods: {
    change () {
      let current = this.$locale.current()

      if (current === 'en') {
        this.$locale.change('el') 
      } else {
        this.$locale.change('en') 
      }
    }
  }
})

https://jsfiddle.net/pespantelis/4xcuLtur/1/

francoisromain commented 8 years ago

@pespantelis thanks a lot : )

I solved it a different way, as I use vue-router:

in the main js file:

router.beforeEach((to, from, next) => {
    Vue.config.lang = to.params.lang;
    next();
});

and the lang-select component:

<template>
    <div class="lang-select">
        <button @click="change('en')">en</button>
        <button @click="change('de')">de</button>
        <button @click="change('fr')">fr</button>
    </div>
</template>

<script>
    export default {
        methods: {
            change (lang) {
                const route = Object.assign({}, this.$route);
                route.params.lang = lang;
                this.$router.push(route);
            }
        }
    };
</script>

What do you think about this solution?

TheBroox commented 7 years ago

@pespantelis' altering of the prototype is by far the most elegant solution. Really feels like it should be baked in.

ssc-hrep3 commented 7 years ago

With Vue i18n 6.0, you need to adapt the locale property of VueI18n to change the language. I solved it like this:

Vue.use(VueI18n);

const i18n = new VueI18n({
    locale: 'en',
    fallbackLocale: 'en',
    messages: { [...] }
});

Vue.prototype.$locale = {
    change (language) {
        i18n.locale = language;
    },
    current () {
        return i18n.locale;
    }
};

new Vue({
    el: '#app',
    i18n,
    [...]
});
kazupon commented 7 years ago

You can set the locale via $i18n property of Vue instance. :) https://kazupon.github.io/vue-i18n/en/api.html#injected-properties

nickkuijpers commented 7 years ago

Ha, @kazupon, your response fixed it. Been trying for 3 hours but we only had do to this haha;

The value en can be dynamic.

this.$i18n.locale = 'en' 

If it does not work, make sure you can console log the right instance.

pedrocatre commented 7 years ago

thanks for the information @nickkuijpers, worked great.

roelvan commented 7 years ago

@nickkuijpers and @TheBroox the documentation says this property is readonly. That is a typo I guess?

nickkuijpers commented 7 years ago

@roelvan i think so because in my end it works. Have u tried it?