How to use $t from vue-i18n inside Vuex action

I need to call $t() inside Vuex action or mutation but I can not access it…

this.app.$t() does not work.

Thanks

you can just import the class instance of VueI18n that you created:

// you probably do something like this somehwere:
const i18n =  new VueI18n({
  locale: 'ja', // set locale
  messages, // set locale messages
})

// export that constant, and import it into your store:

// store.js
import { i18n } from './i18n.js' 

// and use it in your actions:
someAction: ({ commit }, payload) => {
  i18n.t() / works just like `$t()` in components.
}

https://kazupon.github.io/vue-i18n/en/api.html#methods

12 Likes

Thanks @LinusBorg. Comming from your answer I have found even better way, without needing to call include again…

this.app.i18n.t('MSG.API.MSG_FIELD_UPDATE')

I am using Nuxt.js.

4 Likes

thank you so much . you are the only hero who solved my question .

1 Like

I try your guide but not working

// store.js
import { i18n } from '../../translate/index.js'

const data = {
  title: i18n.t('sales-today')
}

// error
Cannot read property 't' of undefined at Module...

Hi, I know this is a while ago, but I would like to ask a question related to your first answer in this post @LinusBorg

A problem that I am having is dynamic changing. So I can now access the t() function in my vuex store, but when I change the locale with my VUEX store, it doesn’t update. Here is my store index.js file:

import Vue from 'vue';
import Vuex from 'vuex';

// MODULES
import auth from '@/_common/store/auth.module';
import language from '@/_common/store/language.module';
import layout from '@/_common/store/layout.module';

import i18n from '@/_common/plugins/i18n';
import LanguageService from '@/_common/services/language.service';

// LOCALES
import en from '../locales/en/index';
import de from '../locales/de/index';

Vue.use(Vuex);

// Initialise the translations
const messages = {
  en,
  de,
};
LanguageService.addMessageToLocale('en', messages.en);
LanguageService.addMessageToLocale('de', messages.de);

console.log(`root.sidebarItems.welcome =  ${i18n.t('root.sidebarItems.welcome')}`);

export default new Vuex.Store({
  modules: {
    auth,
    language,
    layout,
  },
  state: {
    sidebar: {
      items: [
        {
          icon: 'apps',
          title: i18n.t('root.sidebarItems.welcome'),  <---- Problem
          to: '/',
        },
      ],
    },
    toolbar: {
      title: 'HUB',
    },
  },
  mutations: {

  },
  actions: {

  },
});

The title is correctly selected when my app is loaded for the first time, but when the locale is changed, the title field here doesn’t update. Any advice?

Best regards,
Evert

You should probably keep the translation path as state, as well as the current locale, and then use a getter to dynamically create the translated statewhenever the locale changes.

getters: {
  translatedItems: (state, getters, rootState) => {
    const locale = rootState.locale // or wherever you keep it  
    return state.items.map(item => ({
      ...item,
      title: i18nt.t(item.title)  
    })
  }
}

or do it just in the components anyway.

Translating state like that is not really the use case for such a library, which is more concerned with translating the UI, not the content.

1 Like

@LinusBorg that is true, thank you for the advice. Instead, I simply leave the translations to happen in the component, and only use the path to the translation. By that, I mean something like this,

state: {
  sidebar: {
    items: [
      {
        title: 'root.sidebar.welcome',
        ...
      }
    ]
  }
}

Has anyone been able to make this work inside state.js? No format seems to work there for me.

I have a menu that I would like to store in vuex (rather than in the top level component). This menu has titles that are translated using vue-i18n. Inside the component, everything works great, but when I move my menu to my vuex store (inside state.js), my app refuses to load and I get errors that are all similar to:

state.js?6b3c:16 Uncaught TypeError: src_boot_i18n__WEBPACK_IMPORTED_MODULE_0__.default.t is not a function

my state.js file looks like this (and variations of it):

// state.js
import i18n from 'src/boot/i18n'
export default {
  storeVersion: '1',
  version: {
    version: 0,
    date: 0,
    PWA: 0
  },
  menu: [
    {
      active: 'dashboard',
      main: [
        {
          id: 'dashboard',
          parent: null,
          title: this.$i18n.t('dashboard'),
          subtitle: this.$i18n.t('dashboardSub'),
          url: '/dashboard'
        }, // etc, etc

I have tried replacing translatable strings like this.$i18n.t('dashboard') with:

i18n.t('dashboard')
$i18n.t('dashboard')
app.i18n.t('dashboard')
i18n.$t('dashboard')
$i18n.$t('dashboard')
app.i18n.$t('dashboard')
i18n.tc('dashboard')
$i18n.tc('dashboard')
app.i18n.tc('dashboard')

and so on, but I keep getting variations on the error above telling me that t (or tc, or whatever) is not a function. Any idea if this is even possible to do? vue-i18n is installed and working flawlessly in all of my components, I just wanted to move this one global menu item to the store, but it seems I am missing something fundamental. Any advice appreciated. Thanks!

thank you, works like a charm

This works perfect.

I have a better way…

just at the mounted of the home.vue or some other main file of your app do that:

  methods: {
        translateMe(val){
            return this.$t(val)
        }

then in the same file:

mounted() {
        this.$store.state.$t = this.translateMe;
    }

then you can do in your vuex file:

this.state.$t('someWord'))

explanation:
this.$store.state.$t = this.translateMe;
so it sends the function with it’s context like (bind) iguess because vue methods are arrow functions.

hope it will help someone