Vue-i18n: How to switch language through UI with lazy loading

Created on 8 Apr 2021  路  4Comments  路  Source: kazupon/vue-i18n

Module versions:

  • vue: 2.x
  • vue-i18n: 8.x

I already have the lazy loading with external lang files working.

/resources/lang/locals/en.js

export default {
      username_or_email: 'Username or Email',
      password: 'Password'
}

/resources/lang/locals/es.js

export default {
      username_or_email: 'Usuario o Email',
      password: 'Contrase帽a'
}

/resources/lang/index.js
```import Vue from 'vue'
import VueI18n from 'vue-i18n'
import es from '@/resources/lang/locals/es'
import axios from 'axios'

console.log('init')

Vue.use(VueI18n)

export const i18n = new VueI18n({
locale: 'es', // set locale
fallbackLocale: 'en',
messages: { es: es } // set locale messages
})

const loadedLanguages = ['es'] // our default language that is preloaded

function setI18nLanguage (lang) {
console.log('setI18nLanguage')
i18n.locale = lang
axios.defaults.headers.common['Accept-Language'] = lang
document.querySelector('html').setAttribute('lang', lang)
return lang
}

export function loadLanguageAsync (lang) {
console.log('loadLanguageAsync')
// If the same language
if (i18n.locale === lang) {
return Promise.resolve(setI18nLanguage(lang))
}

// If the language was already loaded
if (loadedLanguages.includes(lang)) {
    return Promise.resolve(setI18nLanguage(lang))
}

// If the language hasn't been loaded yet
return import('@/resources/lang/locals/' + lang + '.js').then(
    messages => {
        i18n.setLocaleMessage(lang, messages.default)
        loadedLanguages.push(lang)
        return setI18nLanguage(lang)
    }
)

}

/main.js

import { i18n } from '@/resources/lang/index'
..........
..........
new Vue({
router,
i18n,
render: h => h(App)
}).$mount('#app')

Assuming that my app contains a dropdown to switch the language, how should I handle language switching from any child component? I'm not able to reach the `loadLanguageAsync()`

I've tried by passing the function to vue instance like this, but no luck so far
/main.js

import { i18n, loadLanguageAsync } from '@/resources/lang/index'
..........
..........
new Vue({
router,
i18n,
loadLanguageAsync,
render: h => h(App)
}).$mount('#app')

Then in my child component 

methods: {
switchLang (lang) { loadLanguageAsync(lang) }
}
`` In addition I've triedthis.$i18n.locale = 'es'getting[vue-i18n] Cannot translate the value of keypath`.
Any advice will be appreciated

Review Needed

Most helpful comment

Thank you Lucas! I finally made a small component for language switching and your code works like a charm.
For those who want to have loadLanguageAsync globally, you can import and set the Vue.prototype in your main.js

import { loadLanguageAsync } from '@/resources/lang/index'
..............................
Vue.prototype.loadLanguageAsync = loadLanguageAsync

Then you can simply call the function in any component by doing

this.loadLanguageAsync('es')

Case closed!

All 4 comments

Hello Luciano, how are you doing?

But this file /resources/lang/index.js have with a export default i18n ?
Do you need pass messages params with messages.default in i18n.setLocaleMessage(lang, messages.default)
And import direct loadLanguageAsync in your component child import { loadLanguageAsync } from '@/resources/lang/index'

Follow a docs recomendation Lazy Loading

Best regards

Hello Luciano, how are you doing?

But this file /resources/lang/index.js have with a export default i18n ?
Do you need pass messages params with messages.default in i18n.setLocaleMessage(lang, messages.default)
And import direct loadLanguageAsync in your component child import { loadLanguageAsync } from '@/resources/lang/index'

Follow a docs recomendation Lazy Loading

Best regards

Hi Lucas, sorry about that, I've pasted the wrong code. Now it's updated
I'm still not able to understand how to reach the loadLanguageAsync function from my components

Nice work Luciano, do you need import loadLanguageAsync in your component

Try it

import { loadLanguageAsync } from '@/resources/lang/index'

// omitted

methods: {
   switchLang (lang) { loadLanguageAsync(lang) }
}

Thank you Lucas! I finally made a small component for language switching and your code works like a charm.
For those who want to have loadLanguageAsync globally, you can import and set the Vue.prototype in your main.js

import { loadLanguageAsync } from '@/resources/lang/index'
..............................
Vue.prototype.loadLanguageAsync = loadLanguageAsync

Then you can simply call the function in any component by doing

this.loadLanguageAsync('es')

Case closed!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Brotzka picture Brotzka  路  4Comments

karol-f picture karol-f  路  3Comments

koslo picture koslo  路  5Comments

sergot picture sergot  路  5Comments

nogic1008 picture nogic1008  路  5Comments