Vue.js project using Vue I18n has got the following error: "TypeError: i18n is undefined"
Asked Answered
K

2

1

I'm trying to add internationalization on my Vue.js project using Vue I18n.

I'm using the documentation (i.e. http://kazupon.github.io/vue-i18n/guide/sfc.html#basic-usage), but I've got the following error message:

[Vue warn]: Error in render: "TypeError: i18n is undefined"

found in

---> <MainNavBar> at src/components/MainNavBar.vue
       <VApp>
         <App> at src/App.vue
           <Root> vue.runtime.esm.js:619 

TypeError: "i18n is undefined"
    $t vue-i18n.esm.js:167
    render MainNavBar.vue:33
    VueJS 42
    <anonymous> main.js:18
    js app.js:6991
    __webpack_require__ app.js:724
    fn app.js:101
    0 app.js:7304
    __webpack_require__ app.js:724
    <anonymous> app.js:791
    <anonymous> app.js:1 vue.runtime.esm.js:1887
    VueJS 45
    <anonymous> main.js:18
    js app.js:6991
    __webpack_require__ app.js:724
    fn app.js:101
    0 app.js:7304
    __webpack_require__ app.js:724
    <anonymous> app.js:791
    <anonymous> app.js:1

I don't understand why i18n is "undefined", because I've installed it through NPM as it is shown in documentation.

Could someone help me?

I've already tried to look for a solution on the internet, but without success.

In order to help in this question, I send below the code that I use.

Thank you in advance.

MainNavBar.vue

<i18n>
{
  "en": {
    "home": "Home"
  },
  "pt": {
    "home": "Início"
  }
}
</i18n>

<template>
  ...
  <li class="nav-item">
    <router-link class="nav-link" to='/home'>
      <i class="fa fa-home"></i> {{ $t('home') }}
    </router-link>
  </li>
  ...
</template>

<script>
export default {
  data () {
    return {
      locale: 'en'
    }
  },
  watch: {
    locale (val) {
      this.$i18n.locale = val
    }
  }
}
</script>

main.js

import 'vuetify/dist/vuetify.min.css'

import Vue from 'vue'
import Vuetify from 'vuetify'
import VueI18n from 'vue-i18n'

import App from './App.vue'
import router from './router'
import store from './store'

Vue.use(Vuetify)
Vue.use(VueI18n)

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

vue.config.js

const merge = require('deepmerge')

module.exports = {
  chainWebpack: config => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options =>
        merge(options, {
          loaders: {
            i18n: '@kazupon/vue-i18n-loader'
          }
        })
      )
  }
}

package.json

{
  "name": "executive_frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "test:e2e": "vue-cli-service test:e2e",
    "test:unit": "vue-cli-service test:unit"
  },
  "dependencies": {
    "axios": "^0.18.0",
    "bootstrap": "^4.3.1",
    "jquery": "^3.3.1",
    "material-design-icons-iconfont": "^4.0.5",
    "ol": "^5.3.1",
    "popper.js": "^1.14.7",
    "vue": "^2.6.7",
    "vue-i18n": "^8.10.0",
    "vue-router": "^3.0.1",
    "vuetify": "^1.5.6",
    "vuex": "^3.0.1"
  },
  "devDependencies": {
    "@kazupon/vue-i18n-loader": "^0.3.0",
    "@vue/cli-plugin-babel": "^3.4.0",
    "@vue/cli-plugin-e2e-nightwatch": "^3.4.0",
    "@vue/cli-plugin-eslint": "^3.4.0",
    "@vue/cli-plugin-unit-jest": "^3.4.0",
    "@vue/cli-service": "^3.4.0",
    "@vue/eslint-config-standard": "^4.0.0",
    "@vue/test-utils": "^1.0.0-beta.20",
    "babel-core": "7.0.0-bridge.0",
    "babel-eslint": "^10.0.1",
    "babel-jest": "^23.6.0",
    "deepmerge": "^3.2.0",
    "eslint": "^5.8.0",
    "eslint-plugin-vue": "^5.0.0",
    "node-sass": "^4.11.0",
    "sass-loader": "^7.1.0",
    "vue-template-compiler": "^2.5.21"
  }
}
Keister answered 1/4, 2019 at 13:36 Comment(2)
github.com/kazupon/vue-i18n/blob/dev/examples/sfc/src/main.js. I guessed you should add i18n in new Vue().Lazar
Yes, I believe that you are right, however I would like to separate the "messages" inside the component as it is shown in the documentation. In your code the "messages" is inside the i18n. Thank you so much.Keister
R
3

You should pass an i18n instance to the Vue constructor.

This is the instance

const i18n = new VueI18n({
    locale: "en", // set default locale
    messages: {
        en: { // object with messages },
        fr: { // another locale messages }
    },
})

and pass it here

new Vue({
    i18n,
    router,
    ...
})
Roane answered 22/1, 2020 at 11:19 Comment(1)
console.log(i18n ${this.$i18n}) // print undefinedApraxia
R
0

Watchers has no context. You should use method instead:

<template>
  <select @change="update">
    <option value="en">English</option>
    <option value="es">Español</option>
    <option value="ru">Русский</option>
  </select>
</template>

<script>
export default {
  methods: {
    update(e) {
      this.i18n.locale = e.target.value
    }
  }
}
</script>
Ruffian answered 21/1, 2023 at 18:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.