Vue-i18n: Cannot read property '_t' of undefined. Vue-i18t injection with @vue/test-utils mount()

Created on 22 Dec 2019  路  4Comments  路  Source: kazupon/vue-i18n

vue & vue-i18n version

2.6.10, 8.15.1

Reproduction Link

Unfortunately I don't know how to reproduce unit testing with jsfiddle. It would be very helpfull if you provide base template for unit testing like you did http://jsfiddle.net/r8qnsfb1/

Steps to reproduce

jest test.spec.js

What is Expected?

test success

What is actually happening?

TypeError: Cannot read property '_t' of undefined

Description

hello!
I got this error inside unit test. I found very similar Issue in https://github.com/kazupon/vue-i18n/issues/276 except we don't use Vue.extends() and $mount() syntax in our code and tests. We try inject vue-i18n using regular @vue/test-utils mount() function and get this error.

// test.spec.js
import Vue from "vue";

import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
const vueI18n= new VueI18n()
import {mount} from '@vue/test-utils'

import Demo from '../../../src/components/Demo'

it('vue-i18n test', async () => {
    const wrapper = mount(Demo, {  // try to inject vue-i18n
        vueI18n,
    })    // mount({ vueI18n,   ...Demo}) not works too

})

As you can see we use mount(component, options) . And get error

TypeError: Cannot read property '_t' of undefined



  at Proxy.Vue.$t (node_modules/vue-i18n/dist/vue-i18n.common.js:179:17)
  at Proxy.render (src/components/Demo.vue:17:154)
  at VueComponent.Vue._render (node_modules/vue/dist/vue.runtime.common.dev.js:3532:22)
  at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4048:21)
  at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4459:25)
  at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4448:12)
  at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4055:3)
  at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8386:10)
  at init (node_modules/vue/dist/vue.runtime.common.dev.js:3112:13)
  at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:5952:9)
  at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5899:9)
  at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6449:7)
  at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3927:19)
  at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4048:10)
  at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4459:25)
  at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4448:12)
  at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4055:3)
  at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8386:10)
  at mount (node_modules/@vue/test-utils/dist/vue-test-utils.js:8649:21)
  at Object.<anonymous> (tests/unit/components/VueI18n.spec.js:11:21)
<template>
    <div>
        {{ $t('profile.lastName') }}
    </div>
</template>
<script>
    export default {

    }
</script>

Most helpful comment

Looks like my resolution is to change const $t = this.$i18n.t; to const $t = this.$i18n.t.bind(this.$i18n);.

All 4 comments

Hi there! Try using the correct key name just as you would when adding vue-i18n to your app:

   import Vue from "vue";

   import VueI18n from 'vue-i18n'
   Vue.use(VueI18n)
-  const vueI18n= new VueI18n()
+  const i18n = new VueI18n()
   import {mount} from '@vue/test-utils'

   import Demo from '../../../src/components/Demo'

   it('vue-i18n test', async () => {
       const wrapper = mount(Demo, {  // try to inject vue-i18n
-          vueI18n,
+          i18n,
       })    // mount({ vueI18n,   ...Demo}) not works too

   })

That should do the trick.

Thanks

I'm getting this error in a pure-JS single-file-component with code akin to that below. After getting the error with $t = this.$i18n.t, I tried importing i18n directly. Still got the error.

Component that is throwing the error:

export default {
  render(vnode) {
    const $t = this.$i18n.t; // or require(...).i18n.t
    return vnode(
      require('another/component'), 
      {
        props: {
          columns: [
            { key: 'name', label: $t('fields.name') }, 
            { 
              key: 'role', label: $t('fields.role.title'),
              formatter: (value, key, item) => $t("fields.role.values." + value)
            }, 
            { key: 'actions', label: $t('Actions') }
          ]
        },
      }
    );
  }
}

My base i18n configuration:

import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
const i18n = new VueI18n({
    locale: require('./util/language').default,
    fallbackLocale: 'en',
    messages: {
        "en": require('./i18n/en.json'),
    },
    silentTranslationWarn: true
});

Looks like my resolution is to change const $t = this.$i18n.t; to const $t = this.$i18n.t.bind(this.$i18n);.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

blak3r picture blak3r  路  4Comments

cslee picture cslee  路  5Comments

zhangruinian picture zhangruinian  路  4Comments

forddyce picture forddyce  路  5Comments

tvld picture tvld  路  4Comments