My Vue app is quite large, built with Vuetify, and I recently integrated vue-i18n into it. The json translation files are set up correctly, and the $t() calls work fine in my components and other .js files. However, I'm struggling to change the locale dynamically so that all translated fields display the correct language. When I update the locale in new VueI18n({}) definition and save the file, everything works as expected.
In my scenario, the language choices are displayed as items on a menu:
<v-icon color="primary" dark slot="activator">
person
</v-icon>
<v-list dark class="primary">
<v-list-tile>
<v-list-tile-title>{{ getUser.userId }}</v-list-tile-title>
</v-list-tile>
<v-divider />
<v-list-tile @click="passDialog = !passDialog">
<v-list-tile-title>Password</v-list-tile-title>
</v-list-tile>
<v-list-tile @click="logoutClick">
<v-list-tile-title>Logout</v-list-tile-title>
</v-list-tile>
<v-list-tile>
<v-list-tile-title @click="setLocale('en')">English</v-list-tile-title>
</v-list-tile>
<v-list-tile>
<v-list-tile-title @click="setLocale('es')">Spanish</v-list-tile-title>
</v-list-tile>
</v-list>
and the click handler triggers a method passing the selected locale:
setLocale(locale) {
this.$root.$i18n.locale = locale;
},
The VueI18n is initialized as follows:
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
function loadLocaleMessages() {
const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i);
const messages = {};
locales.keys().forEach((key) => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i);
if (matched && matched.length > 1) {
const locale = matched[1];
messages[locale] = locales(key);
}
});
return messages;
}
export default new VueI18n({
locale: 'en',
localeDir: 'locales',
fallbackLocale: 'en',
messages: loadLocaleMessages(),
});
I've tried different approaches like using this.$i18n.locale = locale; or i18n.locale = locale; after importing i18n from '@/i18n'; in the component. However, none of them seem to update all field names that have translations. It feels like a re-render of the translated values is needed once the language changes.
What am I missing to ensure all translated values update when changing languages?
UPDATE: Upon revisiting my setup based on feedback, I realized a crucial part I missed. Each field has multiple Vuetify attributes extracted to a separate fields.js file. Here's an example of field definitions:
...
userId: {
label: i18n.t('users.generalInfo.userId'),
...
}
...
It's these fields that aren't updating with language changes. Binding the label directly in the component does update the label value accordingly:
<v-text-field
v-bind="fields.userId"
v-model="userModel.userId"
:disabled="!canSave"
:label="$t('users.generalInfo.userId')"
/>
Seems like the issue lies within the bound file, even though it includes i18n.js where the locale is set.
UPDATE 2: It appears others have faced similar challenges (view GitHub issue).