Kyll
Kyll

Reputation: 7139

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?

Upvotes: 6

Views: 5382

Answers (2)

Paul
Paul

Reputation: 1264

Your solution with placing the error message in a getter didn't work for me in the context of Vuetify input rules, I get this: Error in beforeMount hook: "TypeError: Cannot read property '_t' of undefined"

I managed to get it working in 2 possible ways:

  1. Use a getter, but for the whole rules array:
get someRules() {
    return [
        (v) => !!v || this.$t('field.must_not_be_empty')
    ];
}
  1. Place the rules in the @Component decorator:
@Component({
    data() {
        return {
            someRules: [
                (v) => !!v || this.$t('field.must_not_be_empty')
            ]
        };
    }
})
export default class SomeComponent extends Vue {
...
}

Upvotes: 0

Kyll
Kyll

Reputation: 7139

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') }
}

Upvotes: 5

Related Questions