Search code examples
typescriptvue.jsvuetify.jsvue-i18nvue-class-components

How to use vue-i18n with Vue class components?


The following code:

import Vue from 'vue'
import Component from 'vue-class-component'

@Component
export default class SomeComponent extends Vue {
  public someText = this.$t('some.key')
}

Throws an error:

[Vue warn]: Error in data(): "TypeError: i18n is undefined"

I made sure to initialize Vue with Vue.use(VueI18n) and new Vue({ /* ... */, i18n }). The i18n object is initialized this way:

new VueI18n({
  locale: DEFAULT_LOCALE, // imported
  fallbackLocale: 'en',
  messages // imported
})

Translations work perfectly fine as long as they are not immediately called, for example in templates or in component methods.

This vue-i18n issue seems to imply that there is an initialization problem.
I could work around this by using methods and only translating in templates, but there is a specific instance out of my control in which such immediate calls happen: Vuetify input rules.

someRule = [(v) => !!v || this.$t('field.must_not_be_empty')]

These rules are executed immediately, even with lazy-validation on Vuetify forms.

I have identified two possible solutions:

  1. Circumventing the Vuetify rules system and allowing to simply return a string to be translated within the template itself;
  2. Solving the $t immediate availability issue.

Sadly I have not been able to accomplish any of these.

Is there any way to solve this problem?


Solution

  • The issue lied in the use of this.
    Basically, Vue needs a very specific execution context that is not the same as what is normally accessible in the root context of a fresh class.

    The solution ends up being very simple: Use a getter.

    import Vue from 'vue'
    import Component from 'vue-class-component'
    
    @Component
    export default class SomeComponent extends Vue {
      public get someText () { return this.$t('some.key') }
    }