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.
Related
When using vue-i18n, I need to add this to every single component:
setup() {
const { t, locale } = useI18n();
return { t, locale };
}
Is there any way to preload the t function to all my components?
You can load and switch languages as below.
in 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
}
const locale = localStorage.getItem('language') || 'tr'
export default new VueI18n({
locale: locale,
fallbackLocale: locale,
messages: loadLocaleMessages()
})
in main.js
import i18n from './i18n'
new Vue({
el: "#app",
router,
store,
i18n,
render: h => h(App),
})
createI18n() creates a Vue plugin that makes vue-i18n available globally for all components:
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { createI18n } from 'vue-i18n'
const i18n = createI18n(/*...*/)
createApp(App).use(i18n).mount('#app')
t is then available in the template as $t, and locale is $i18n.locale.
demo
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}",
},
}
};
I want to translate my whole component with i18n and I don't know how to use $t() in this use case. I have data like this
[
{"prizeCount":"300","prizeSum":"2442000","gameStartAt":"2018-01-08 13:00:00.000000"},
{"prizeCount":"288","prizeSum":"2530000","gameStartAt":"2018-01-09 12:00:00.000000"}
]
I pass this data to :items="mydata" for table and I want to translate title of my fields for example I want to translate prizeCount to another language.
I am using vue-bootstrap.
What is the best solution for this?
main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import i18n from './i18n'
Vue.config.productionTip = false
Vue.use(BootstrapVue)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: {
App
},
i18n,
template: '<App/>'
})
You can add it like this:
new Vue({
el: '#app',
router,
components: {
App
},
i18n,
t: i18n.t,
template: '<App/>'
})
Than in your component you can use $t or this.$t in your methods.
For get keys from your object you can do like this:
data: [
{"prizeCount":"300","prizeSum":"2442000","gameStartAt":"2018-01-08 13:00:00"},
{"prizeCount":"288","prizeSum":"2530000","gameStartAt":"2018-01-09 12:00:00"}
]
data.forEach( obj => {
let keys = Object.keys(obj)
// ['prizeCount', 'prizeSum', 'gameStartAt']
newData = []
newObj = {}
keys.forEach( key => {
let val = obj[key]
let trans = this.$t(key)
newObj[trans] = val
})
newData.push(newObj)
})
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>
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]
}