vue-i18n-next: TypeError: _ctx.$t is not a function when using $t in child component

vue & vue-i18n version

  • vue: 3.0.0
  • vue-i18n: 9.0.0-rc.7

Reproduction Link

https://github.com/boussadjra/vue3-tailwind2

Steps to reproduce

I added a file named i18n.ts next to main.ts which contains the following snippet :

import { createI18n } from "vue-i18n";

const i18n = createI18n({
  legacy: false,
  locale: "ja",
  messages: {
    en: {
      message: {
        language: "English",
        greeting: "Hello !"
      }
    },
    ar: {
      message: {
        language: "العربية",
        greeting: "السلام عليكم"
      }
    },
    es: {
      message: {
        language: "Español",
        greeting: "Hola !"
      }
    }
  }
});
export default i18n;

then I imported the file inside main.ts and use it :

...
import i18n from './i18n'
let root = app.use(i18n).use(store).use(router).mount('#app')

then I added the following snippet to home.vue :

<h2>{{ $t("message.greeting", {}, { locale: "en" }) }}</h2>

What is Expected?

Render the message Hello !

What is actually happening?

but this is giving the following error :

Uncaught (in promise) TypeError: _ctx.$t is not a function at Proxy.render (Home.vue?bb51:2)

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 3
  • Comments: 30

Most upvoted comments

Hi, I think this may be similar to my issue, I found out that to have the global $t injected like on previous version I neet to pass globalInjection: true, in the createI18n() function options.

So your i18n.ts may look like this:

import { createI18n } from "vue-i18n";

const i18n = createI18n({
  legacy: false,
  locale: "ja",
  globalInjection: true,
  messages: {
    en: {
      message: {
        language: "English",
        greeting: "Hello !"
      }
    },
    ar: {
      message: {
        language: "العربية",
        greeting: "السلام عليكم"
      }
    },
    es: {
      message: {
        language: "Español",
        greeting: "Hola !"
      }
    }
  }
});
export default i18n;

Hi, I have a similar problem when I try to unit test my component : “vue-i18n”: “^9.2.2”, “vite”: “^3.2.4”, “vitest”: “^0.25.3”,

main.ts :

const i18n = createI18n({
  locale: 'fr',
  globalInjection: true,
  legacy: false,
  messages: {
    fr
  }
})

const app = createApp(App)

app.use(i18n)

It’s working on my dev environment but not when I try to test with :

components/__tests__/Header.spec.ts > Header > renders properly
TypeError: _ctx.$t is not a function

Vue3 and vue-i18n-next sample, it could works as bellow:

<template>
  <q-page class="flex flex-center">
    <img alt="Quasar logo" src="/imgs/logo.svg" />
    <div>{{ t("success") }}</div>
  </q-page>
</template>

<script>
import { defineComponent } from "vue";
import { useI18n } from "vue-i18n";

export default defineComponent({
  name: "PageIndex",
  setup() {
    const { t } = useI18n();
    return {
      t,
    };
  },
});
</script>
  • import useI18n:
import { useI18n } from "vue-i18n";
  • define function in setup():
const { t } = useI18n();
  • using t in the template:
<div>{{ t("success") }}</div>

@boussadjra I’m glad it worked. This may be useful in the future. I found out that $t is not available everywhere (like inside other .ts files) but if you add this function to the i18n file you can import it and use it to translate strings:

// file: i18n.ts
/**
 * it's ugly but we can use this to translate strings inside js code
 * @param key
 */
export const translate = (key: string) => {
    if (!key) {
        return '';
    }
    return i18n.global.t(key);
};
// another .ts file
import { translate } from 'path to i18n file'
...
console.log(translate('message.languge'))

Spent 6 hours today until I arrived here for this magic “globalInjection: true,” Thanks!

@brainafesoh sorry but I don’t know the plugin enough to find whats wrong. The only thing comming to my mind if you have problems with $t is: have you tried to add globalInjection: true, to the createI18n({ locale: "fr", // set locale fallbackLocale: "en", // set fallback locale }); block?

There is no solution yet, isn’t it?

@danielpetrica @jbiddulph having similar issue but with a different spin) Setup is vue2 codebase + vite + @vue/compat + vue3 with compatibility set to 2, and boostrap-vue On initial render of the page all good $t(‘some.translation’) works, but for components that are rendered conditionally using v-if TypeError: _ctx.$t is not a function

Hi, I think this may be similar to my issue, I found out that to have the global $t injected like on previous version I neet to pass globalInjection: true, in the createI18n() function options.

So your i18n.ts may look like this:

import { createI18n } from "vue-i18n";

const i18n = createI18n({
  legacy: false,
  locale: "ja",
  globalInjection: true,
  messages: {
    en: {
      message: {
        language: "English",
        greeting: "Hello !"
      }
    },
    ar: {
      message: {
        language: "العربية",
        greeting: "السلام عليكم"
      }
    },
    es: {
      message: {
        language: "Español",
        greeting: "Hola !"
      }
    }
  }
});
export default i18n;

Thanks very much,it works.

Hi, I think this may be similar to my issue, I found out that to have the global $t injected like on previous version I neet to pass globalInjection: true, in the createI18n() function options.

So your i18n.ts may look like this:

import { createI18n } from "vue-i18n";

const i18n = createI18n({
  legacy: false,
  locale: "ja",
  globalInjection: true,
  messages: {
    en: {
      message: {
        language: "English",
        greeting: "Hello !"
      }
    },
    ar: {
      message: {
        language: "العربية",
        greeting: "السلام عليكم"
      }
    },
    es: {
      message: {
        language: "Español",
        greeting: "Hola !"
      }
    }
  }
});
export default i18n;

I had same Issue Your solution works perfectly 😃 thanks BRO !

@danielpetrica Thank you very much. You saved my life.

Hi ! I have same issue but with $tc. I pass globalInjection to true, $t is available but not $tc.

Hi @gwen1230 from what i can see the plurarization has been integrated in t()when using composition api https://vue-i18n.intlify.dev/guide/advanced/composition.html#pluralization

Yes I saw that and it works with composition API. But with global injection, $t is like the old $t, and $tc doesn’t seem to exist.

Hi ! I have same issue but with $tc. I pass globalInjection to true, $t is available but not $tc.

@danielpetrica Wow it works like charm, thank you very very much