Closed pzuopin closed 7 years ago
this.$t('COMMON.LOGIN')
same here :( , @shipengyan as @pzuopin said, the requiment is to call $t helper in js files, it means not inside a Vue component
I have found a way but it's so fucking ugly, in my case as i want to create a handler for server responses i have a module that prints errors depending of the locale.
The only thing that i did was this when the app is mounted call my "provider"
let app = new Vue({
store,
i18n,
el: '#q-app',
router,
mounted() {
this.$nextTick(() => {
ResponseServiceProvider.handle(this)
})
},
render: h => h(require('./App'))
})
i said ugly because i had to pass whole context, which i think it's a bad practice but for the moment it saves me.
You can use the below APIs
t
method of VueI18n
this.$i18n.t('path', 'en', { foo: 'bar' })
See details: https://kazupon.github.io/vue-i18n/en/api.html
Vue.t
function
Vue.t('path', 'en', { foo: 'bar' })
See details: https://github.com/kazupon/vue-i18n/blob/5.x/gitbook/api.md
I tried to use to set metas on component:
metaInfo: {
title: this.$i18n.t('blog'),
},
But don't work, the page don't load with this
try metaInfo: { title: this.$i18n.t('message.blog'), },
Following the vue-meta documentation , it says: "Easy. Instead of defining metaInfo as an object, define it as a function and access this as usual"
This is an example working for me:
export default {
name: "Home",
metaInfo() {
return {
title: this.$i18n.t('home.seo.title'),
titleTemplate: '%s - ' + config.app_name,
htmlAttrs: {
lang: config.lang,
amp: undefined
}
}
}
}
@3ss0 I tried your method but still not working, the @verizecom method work like charm, seems a vue-meta stuff and not related with vue-i18n.
Sorry for the inconvenients and thanks to both for help me to solve it ^^
@verizecom Thank you for the solution. However, I didn't find a way to make it work with a Nuxt static generation. I used the @kazupon example with SSR.
export default {
head () {
return {
title: this.$i18n.t('title.main')
}
}
}
https://github.com/kazupon/vue-i18n/tree/dev/examples/ssr/nuxt
I found a 'elegant' solution
first you need a file lang.js like this
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import { ptBR } from './ptBR'
Vue.use(VueI18n)
// Create VueI18n instance with options
export const i18n = new VueI18n({
locale: 'pt-BR', // set locale
messages: {
'pt-BR': ptBR
}
})
then you need to import it inside your js file and use the tc ou t method in your js code
import { i18n } from './language/lang'
export default {
items: [
{
name: 'Home',
url: '/dashboard',
icon: 'icon-speedometer'
},
{
name: i18n.tc('general.constructions'),`
@anselmobattisti Looks like the preferred solution to me, since import order does not matter then and things are nicely separated, well done :+1:
@anselmobattisti Hey that is awesome!! I could easily follow your solution and get it done in a second! BTW I tried i18n.t first instead i18n.tc and it worked just fine. What's the difference between tc and t?
You can also simply use router.app.$t
// router.js
import VueRouter from 'vue-router'
Vue.use(VueRouter)
export const router = new VueRouter()
// non-template file
import { router } from './router'
router.app.$t('foo')
@anselmobattisti However, it cannot work when I use a language switch button to change the locale value in lang.js file, I mean, the data on the webpage cannot be internationalized automatically, only if I re-render the whole page(component). Can you give me some advice? Thanks!!!
@anselmobattisti - well done! Thanks a lot!
@WillieYang - I have the same problem, this solution isn't reactive.. Have you found a solution for this?? (the other solutions above don't take into account we have pure .js files which aren't related to vue, and therefor don't have import of vue/vue-router, etc... )
@ThinkerBell1 I haven't found the solution yet, and I am still trying to find a way to resolve it, but if it still cannot work ultimately, I would put all the data need to be internationalized into the corresponding component rather than into a single js file, it is the only way that I can think of now, sorry for not helping bro.
@WillieYang - thanx, that was also what i did at the end..
This work for me use to translate vue-chartjs to camboidia language by call: this.$i18n.t('label.months') in labels in vue-chartjs. look my picture here
methods: {
initLineChart(){
this.declaration_data = {
labels : this.$i18n.t('label.months'),
datasets: [
{
label : 'Electronics',
backgroundColor : '#e83e8c',
fillColor : 'rgba(210, 214, 222, .5)',
strokeColor : 'rgba(210, 214, 222, 1)',
pointColor : 'rgba(210, 214, 222, 1)',
pointStrokeColor : '#c1c7d1',
pointHighlightFill : '#fff',
pointHighlightStroke: 'rgba(220,220,220,1)',
data : [65, 59, 80, 81, 56, 55, 40, 50, 48, 67, 67, 45]
},
{
label : 'Digital Goods',
backgroundColor : '#28a745',
fillColor : 'rgba(60,141,188,0.9)',
strokeColor : 'rgba(60,141,188,0.8)',
pointColor : '#3b8bba',
pointStrokeColor : 'rgba(60,141,188,1)',
pointHighlightFill : '#fff',
pointHighlightStroke: 'rgba(60,141,188,1)',
data : [28, 48, 40, 19, 86, 27, 90, 40, 19, 86, 27, 90]
}
]
}
}
}
@WillieYang / @ThinkerBell1
My idea is to provide key of i18n in javascript file only, then using $t() inside vue file.
Something like this: Instead of: JS file:
name: i18n.tc('general.constructions')
Vue file:
{{name}}
You can use: JS file:
name: 'general.constructions'
Vue file:
{{$t(name)}}
Then it will be reactive
@WillieYang and @ThinkerBell1, i faced the same issue of reactivity. The work around i came up with was to change my js file into a function that returns the object following @anselmobattisti's solution. Then in my template, i bound the function to a computed property and used the computed property instead and the language button worked. Hope it helps someone facing the the same problem
@anselmobattisti answer works like a charm. And this is how I did based on his answer. I solved like this.
(If you coded i18n code in main.js (the main.js is entry point which is load Vue and App.vue then initialize application))
And t() method works in pure js. Hope it is helpful to someone!
@duykhanhrc Thanks for the tip! If it helps anyone else, I was trying to share input validation rules between vuetify components and ended up with something like the following:
Form.vue:
import { sensibleCharLength } from "~/shared/validationRules";
get nameRules() {
return this.buildValidationRules([sensibleCharLength]);
}
buildValidationRules(rules: Rule[]) {
return rules.map(this.generateRule);
}
generateRule(rule: Rule) {
return (value: string | number | boolean) =>
rule.passCondition(value) || this.$t(rule.failureMsgKey);
}
In validationRules.ts:
export const sensibleCharLength = {
passCondition: (value: string) => {
const MAX_LENGTH = 50;
return value.length < MAX_LENGTH;
},
failureMsgKey: 'validations.tooMany'
};
You have to import 'i18n' in your component. For example:
<script>
import i18n from '@/i18n'
{
...
data: () => {
return {
message: i18n.t('message'),
}
}
...
}
You have to import 'i18n' in your component. For example:
<script> import i18n from '@/i18n' { ... data: () => { return { message: i18n.t('message'), } } ... }
It works, but why directly call this.$i18n.t('xxx') not work?
@wilsonwu
Actually I don't know, maybe it was lazy loading.
elegant How to change language? I did this, but it not work.
let messages = { en: { ...enLocale, ...elementEnLocale }, zh: { ...zhLocale, ...elementZhLocale } }
const i18n = new VueI18n({ locale: "en", // set locale messages messages })
export function changeLanguage(lang) { try { i18n.locale = lang } catch (e) { console.log("Error while change language to <{}> : {error}".params(lang, e.message)) } } changeLanguage("zh")
I found a 'elegant' solution
first you need a file lang.js like this
import Vue from 'vue' import VueI18n from 'vue-i18n' import { ptBR } from './ptBR' Vue.use(VueI18n) // Create VueI18n instance with options export const i18n = new VueI18n({ locale: 'pt-BR', // set locale messages: { 'pt-BR': ptBR } })
then you need to import it inside your js file and use the tc ou t method in your js code
import { i18n } from './language/lang' export default { items: [ { name: 'Home', url: '/dashboard', icon: 'icon-speedometer' }, { name: i18n.tc('general.constructions'),`
Won't this make new instance of i18n for every imports? Let's say I have 20 js files, then it will create 20 new instances...?
import i18n from "@/i18n";
I found a 'elegant' solution
first you need a file lang.js like this
import Vue from 'vue' import VueI18n from 'vue-i18n' import { ptBR } from './ptBR' Vue.use(VueI18n) // Create VueI18n instance with options export const i18n = new VueI18n({ locale: 'pt-BR', // set locale messages: { 'pt-BR': ptBR } })
then you need to import it inside your js file and use the tc ou t method in your js code
import { i18n } from './language/lang' export default { items: [ { name: 'Home', url: '/dashboard', icon: 'icon-speedometer' }, { name: i18n.tc('general.constructions'),`
I did the same, but I want to translate the error message received from an API, it didn't work for this. Can anyone help on this
This approach works for me like a charm - I use this statement inside a store action:
this.app.i18n.t("example.message.key")
Found in the Vue forum here: https://forum.vuejs.org/t/how-to-use-t-from-vue-i18n-inside-vuex-action/22146/3
use ()=>string instead string,data can't be reactive, but function can.
const header = i18n.global.t('header'); // not work
const header = () => i18n.global.t('header');
header() // work, reactive
Syntax has changed from v8 to v9. Thanks @codelegant!
i18n.t('string') // v8
i18n.global.t('string') // v9
@SimonHawesome just saved my life, thanks for the recent update!
Syntax has changed from v8 to v9. Thanks @codelegant!
i18n.t('string') // v8 i18n.global.t('string') // v9
Thanks a lot!!
import { useI18n } from 'vue-i18n';
const name = ref(useI118n().t('name'));
I have use vue-i18n in template, and it works. but now I also need it can work in js , I have read a issue about <Use $t function outside template enhancement>, i don't know how to config that.
thanks.