Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vuejs3 I18n and composition API

I'm right now doing a frontend interface in vueJS, and i'm currently working with vuejs 3 and i18n. The implementation of i18n works quite fine the normal way but when I want to use it with the composition API starts the problems.

So what I did. My main.js looks like this:

const i18n = createI18n({
    messages: {
        en: en,
        fr: fr
    },
    fallbackLocale: 'en',
    locale: localStorage.Language || navigator.language.split('-')[0] || 'en',
})
const app = createApp(App)


app.use(router)
app.use(i18n)

app.mount('#app')

I saw in the documentation to use composition API I have to add legacy:false so I did it. Then my $t doesn't work anymore. I go firther in the documentation and arrive at the point I'm lost with. The documentation saiys to use this:

const app = Vue.createApp({
  setup() {
    const { t } = VueI18n.useI18n() // call `useI18n`, and spread `t` from  `useI18n` returning
    return { t } // return render context that included `t`
  }
})

My problem is that my createApp is already used like this:

const app = createApp(App)

which is the default implementation by Vuejs. I tried to modify it adding the setup after App, before, removing App nothing works and I think I do more and more stupid things.

Does anyone has an idea how to make i18n works with the composition API? The final objective is basically in a component switchLanguage made with composition API to have access to $i18n (to get some informations and manage my language switch)

Thanks in advance for the help you can provide.

like image 324
Tartempion34 Avatar asked Sep 05 '25 03:09

Tartempion34


1 Answers

You already instantiated i18n on your app, in main.js. That's the important bit.

The example presented in docs doesn't necessarily have to be done on the instance defined inside createApp. It works in any component, as long as you have instantiated i18n on main.(js|ts)

This will work in any component (wherever you need t):

import { useI18n } from "vue-i18n";

export default defineComponent({
  setup() {
    const { t } = useI18n();
    // you can now use t('some.text.to.be.translated')
    // t('some.text.to.be.pluralized', { n: 1 }, 1);

    return {
      // expose `t` to <template>:
      t, 
    }
  },
  // if you want it inside any method, computed or hook
  // in case you still use Options API
  computed() {
    someTranslatedText() {
      return useI18n().t('translate.me');
    }
  },
  methods: {
    methodNeedingTranslation() {
      const { t } = useI18n();
      // do stuff with `t`
    }
  }
})

Side note: All $tc (pluralization) functionality has been moved to t.

If you're upgrading an existing app and you don't want to go through templates and replace all instances of $t and $tc with t:

setup: () => ({ 
  $t: useI18n().t
  $tc: useI18n().t 
})

To make $t and $tc available in any component's <template>, without having to import + expose them in <script> (or <script setup>):

import App from './App.vue'
import { useI18n } from 'vue-i18n'

const app = createApp(App);
app.config.globalProperties.$t = useI18n().t
  • If you still need them in <script>, import from 'vue-i18n', as shown above.
  • $tc is no longer used in Vue3. If your templates are coming from Vue2, it would be best to replace all $tc's with $t. Or you could assign useI18n().t to both, if you don't want to touch the templates:
Object.assign(app.config.globalProperties, {
  $t: useI18n().t,
  $tc: useI18n().t
})
like image 87
tao Avatar answered Sep 08 '25 15:09

tao