can't access i18n translation inside vuex state.js file
-
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!
-
What does your boot file look like ?
Scott
-
Here is my boot file:
import VueI18n from 'vue-i18n' import messages from 'src/i18n' let i18n export default ({ app, Vue }) => { Vue.use(VueI18n) // Set i18n instance on app app.i18n = new VueI18n({ locale: 'en-gb', fallbackLocale: 'en-gb', silentFallbackWarn: true, silentTranslationWarn: true, // enableInSFC: true, messages }) i18n = app.i18n } export { i18n }
-
Sorry, but I’m not certain what is wrong. It should work.
Scott
-
Thanks for taking a look anyway, I appreciate it.
-
Interestingly, (and although it does not throw an error) when I
console.log(i18n)
I getundefined
-
And if I try to use
const i18n = require('src/boot/i18n')
instead of import,console.log(i18n)
gives me:Module {__esModule: true, Symbol(Symbol.toStringTag): "Module", default: ƒ} default: ƒ (_ref) arguments: [Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.invokeGetter (<anonymous>:1:142)] caller: [Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.invokeGetter (<anonymous>:1:142)] length: 1 name: "" prototype: constructor: ƒ (_ref) __proto__: Object __proto__: ƒ () [[FunctionLocation]]: i18n.js?8847:6 [[Scopes]]: Scopes[3] i18n: (...) Symbol(Symbol.toStringTag): "Module" __esModule: true get i18n: ƒ () __proto__: Object
-
Aren’t the boot files supposed to be loaded before anything else? It feels like i18n is not being loaded in time and that is why it comes back undefined?
-
@ssuess your import seems to be wrong, should be with curly braces
import { i18n } from 'src/boot/i18n'
. -
This post is deleted! -
@metalsadman Thanks, I already tried it both ways, made no difference alas.
-
I think the problem is that the store is initialized before boot files, which is quite logical since boot files can access the store.
So, a solution may be to defer translations. You may use a getter for that, with a map on your menu array that will replace fields by their translation.
-
Hmm you arr using
this
in your state. Remove thatt as well. -
@metalsadman definitely not that, see above for all the variations I have tried.
-
@tof06 this sounds logical to me, do you have any example code you could point me to? Where exactly would this code go? in the state.js file or somewhere else?
-
I imported i18n in vuex modules where I need it this way:
import { i18n } from 'src/boot/i18n'
and then accessed i18n translations in my vuex actions this way:
let myMessage = i18n.t('messages.myMessage')
Works like magic.
-
You should import
i18n
as likeimport {i18n} from '../boot/i18n'
because
i18n
is not default exported.