vue-i18n not use vuetify components strings - vue.js

i try to use vue-i18n to translate my application. I use also vuetify and the vue cli.
At the moment i have the languages englisch and german.
Here is my project structure and code.
main.js
import Vue from "vue";
import i18n from "./plugins/i18n";
import vuetify from "./plugins/vuetify";
Vue.config.productionTip = false;
new Vue({
vuetify,
i18n,
render: (h) => h(App),
}).$mount("#app");
plugins/i18n.js
import Vue from "vue";
import VueI18n from "vue-i18n";
import de from "#/locale/de";
import en from "#/locale/en";
Vue.use(VueI18n);
const messages = {
de: de,
en: en,
};
const i18n = new VueI18n({
locale: "de",
fallbackLocale: "en",
messages,
});
export default i18n;
locale/en.js
export default {
hello: "hello",
};
locale/de.js
export default {
hello: "Hallo",
$vuetify: {
dataIterator: {
rowsPerPageText: "Einträge pro Seite:",
pageText: "{0}-{1} von {2}",
},
}
};
plugins/vuetify.js
import Vue from "vue";
import Vuetify from "vuetify/lib/framework";
import i18n from "./i18n";
Vue.use(Vuetify);
export default new Vuetify({
lang: {
t: (key, ...params) => i18n.t(key, params),
},
});
All works fine with the hello translation, but the vuetify components not working as expected.
I would like to add a translation to german for few vuetify components in the future.
But at the moment a would like to use the original names from vuetify. And that is not working.
For example, the v-select component looks like:
And other components also not working.
What i do wrong?

You are missing default vuetify component locales. you should provide it by rewriting them in your locales or import it at the beginning of each locale file.
locale/en.js
import { en } from 'vuetify/lib/locale'
export default {
$vuetify: { ...en },
hello: "hello",
};
locale/de.js
import { de } from 'vuetify/lib/locale'
export default {
hello: "Hallo",
$vuetify: {
...de,
dataIterator: {
rowsPerPageText: "Einträge pro Seite:",
pageText: "{0}-{1} von {2}",
},
}
};

Related

How to dynamically change language for vue-google-maps

I use #fawmi/vue-google-maps for show google map in my Vue3 app. Also I use vue-i18n for i18n.
My main.js:
const { createApp } = require("vue");
import VueGoogleMaps from '#fawmi/vue-google-maps';
import * as VueI18n from 'vue-i18n';
import messages from './assets/messages';
import App from './App.vue';
const i18n = VueI18n.createI18n({
locale: 'ar',
fallbackLocale: 'en',
messages,
});
createApp(App)
.use(i18n)
.use(VueGoogleMaps, {
load: {
key: 'myprivatekey',
language: 'ar',
}
})
.mount("#app");
If I want to set language for map by default, it is no problem.
In other files I can set locale dynamically like this
this.$i18n.locale = 'es'
But how I can make it for map component?
Code like below is not working for me (obliviously, because $i18n is not defined here)
.use(i18n)
.use(VueGoogleMaps, {
load: {
key: 'myprivatekey',
language: this.$i18n.locale,
}
})

Use vuex state in Vuetify.js plugin

I'm getting very confused about calling a vuex state inside the Vuetify.js plugin.
My project is to translate a website based on the users preferred language. I've completely setup the translations with i18n. This project consists of 2 parts.
The translation based on JSON files (This is working just fine)
The translation of the Vuetify components based on the translations provided by Vuetify.
The 2nd point is where I get stuck.
According to the manual from Vuetify you need to import the needed language files inside the Vuetify.js plugin. This all works perfect.
But...I can only change it manually....
What I want to achieve is that the correct Vuetify language gets set based in the language set inside my vuex store.
Believe me, I've been search the internet for days and tried everything that I could find. But nothing seems to work. I can't seem to figure out how to call the vuex state inside the Vuetify.js plugin.
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
import nl from 'vuetify/es5/locale/nl'
import fr from 'vuetify/es5/locale/fr'
import en from 'vuetify/es5/locale/en'
Vue.component('my-component', {
methods: {
changeLocale() {
this.$vuetify.lang.current
},
},
})
export default new Vuetify({
lang: {
locales: { nl, en, fr },
current: "nl",
},
})
So the state of current should be based on the state in my vuex store.
Here is my vuex store
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import i18n, { selectedLocale } from './i18n'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
locale: selectedLocale
},
mutations: {
updateLocale(state, newLocale) {
state.locale = newLocale
}
},
actions: {
changeLocale({ commit }, newLocale) {
i18n.locale = newLocale
commit('updateLocale', newLocale)
}
},
plugins: [createPersistedState()]
})
Who can point me in the right direct on who to go about this?
When you change the locale in i18n you should also change it in Vuetify:
export default new Vuex.Store({
state: {
locale: selectedLocale
},
mutations: {
updateLocale(state, newLocale) {
state.locale = newLocale
}
},
actions: {
changeLocale({ commit }, { newLocale, currentVueComponent }) {
i18n.locale = newLocale
currentVueComponent.$vuetify.lang.current = newLocale // <--- the important code
commit('updateLocale', newLocale)
}
},
plugins: [createPersistedState()]
})

Get current locale in a child component

I don't manage to get the locale parameter from vue-i18n in my child component.
I've installed vue-i18n in cli ui. The translation with $t("message") is working but I have error when i try to access to i18n.locale
my enter point (main.js)
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import i18n from './i18n'
new Vue({
router,
i18n,
render: h => h(App)
}).$mount('#app')
my child component
<template>
<div>{{ $t("message") }}</div>
</template>
<script>
import {HTTP} from '#/http-common'
export default
{
name : 'c1',
methods:{
selectMap()
{
console.log(i18n.locale);//=> doesn't work
}
}
</script>
i18n.js
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: process.env.VUE_APP_I18N_LOCALE || 'en',
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
messages: loadLocaleMessages()
})
Try this.$i18n.locale, or just $i18n.locale if inside the <template>.
For Composition API this is my solution:
<script setup>
import { useI18n } from "vue-i18n";
const i18nLocale = useI18n();
console.log(i18nLocale.locale.value); // "en"
</script>

Vuejs - How to call the mounted function of main.js from another Js file

This is the code I have given in commonValidation.js.
commonValidation.js:
this.$validator.localize('en', {
messages: {
required: (field) => '* ' + field + ' is required'
},
attributes: {
email: 'Email'
}
})
I want to call the above file in main.js inside the mounted function
like below. But it's not working. If I given those validation(from commonValidation.js) inside the mounted()(in main.js) method it's working.
main.js:
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import App from './App'
import router from './router'
import VeeValidate from 'vee-validate';
import commonValidation from './commonValidation'
Vue.use(VeeValidate);
Vue.use(BootstrapVue);
new Vue({
el: '#app',
router,
template: '<App/>',
components: {
App
},
mounted()
{
commonValidation
}
})
Please help me to call the commonValidation.Js inside the mounted() in main.js . Thanks in advance.
This is my complete commonValidation.js
export default {
mounted() {
this.$validator.localize('en', {
messages: {
required: (field) => '* ' + field + ' is required'
},
attributes: {
email: 'Email'
}
})
}
}
You are exporting an object in commonValidation.js file.
An object cannot be invoked like a function.
I think your intent is to use a mixin. A mixin is nothing but an object that contains reusable component options as its properties.
So just register the mixin on the root component in your main.js file:
//main.js
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import App from './App'
import router from './router'
import VeeValidate from 'vee-validate';
import commonValidation from './commonValidation'
Vue.use(VeeValidate);
Vue.use(BootstrapVue);
new Vue({
el: '#app',
router,
template: '<App/>',
components: {
App
},
mixins : [commonValidation]
}

Vue-i18n - Cannot read property 'config' of undefined

First of all I show you what works (in App.js)
import router from './routes.js';
import VueI18n from 'vue-i18n';
const messages = {
en: {
message: {
hello: 'hello world'
}
}
}
// Create VueI18n instance with options
const i18n = new VueI18n({
locale: 'en', // set locale
messages, // set locale messages
})
const app = new Vue({
el: '#app',
router,
i18n
});
But if I want to separate the code in lang.js
import VueI18n from 'vue-i18n';
const messages = {
en: {
message: {
hello: 'hello world'
}
}
}
export default new VueI18n({
locale: 'en', // set locale
messages, // set locale messages
});
So that I can write in App.js
import router from './routes.js';
import i18n from './lang.js';
const app = new Vue({
el: '#app',
router,
i18n
});
But somehow this doesn't work even though routes.js is built exact the same.
My bootstrap.js looks like that, if it is important to know.
import Vue from 'vue';
window.Vue = Vue;
import VueRouter from 'vue-router';
import VueI18n from 'vue-i18n';
Vue.use(VueRouter);
Vue.use(VueI18n);
I'm sorry for the long code, but somehow the mistake lies in import i18n from './lang.js';
I get the message: Uncaught TypeError: Cannot read property 'config' of undefined
In your main file where you create the app instance add the i18n as option instead of Vue.use(Vuei18n) like this:
new Vue({
el: '#app',
i18n, // < --- HERE
store,
router,
template: '<App/>',
components: { App }
})
Put it just after el;
And this should be your lang:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import en from './en'
import fr from './fr'
import ro from './ro'
Vue.use(VueI18n)
export default new VueI18n({
locale: 'en',
fallbackLocale: 'en',
messages: {
en, fr, ro
}
})
Just to add a detail, you MUST construct the new VueI18n after using Vue.use(VueI18n)
Vue.use(VueI18n);
// must be called after vue.use
const i18n = new VueI18n({
locale: "en",
fallbackLocale: "en",
messages: {
en
}
});
new Vue({
el: "#app",
i18n,
render: (h) => h(App),
});
The idea of code separation can be implemented this way
/* i18n.ts */
import VueI18n from "vue-i18n";
import en from "./locales/en.json";
// Export as an arrow function
export default () =>
new VueI18n({
locale: process.env.VUE_APP_I18N_LOCALE || "en",
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
messages: { en }
});
/* plugins.ts */
import Vue from "vue";
// Plugins
import VueI18n from "vue-i18n";
import i18n from "./i18n";
Vue.use(VueI18n);
export default {
i18n: i18n()
};
And finally, the main.ts
/* main.ts */
import Vue from "vue";
import plugins from "./core/plugins";
import App from "./App.vue";
new Vue({
...plugins,
render: (h) => h(App)
}).$mount("#app");
The trick is using arrow functions when exporting i18n settings. It's worth mentioning that this problem does not occur with some other Vue plugins.