Vue-i18n: How can i use vue-i18n in '.js' file, I have use it in Vue template and it works.

Created on 20 Apr 2017  Â·  31Comments  Â·  Source: kazupon/vue-i18n

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 , i don't know how to config that.

thanks.

Most helpful comment

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'),`

All 31 comments

js 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

  • v6.x or later: t method of VueI18n
  this.$i18n.t('path', 'en', { foo: 'bar' })

See details:
https://kazupon.github.io/vue-i18n/en/api.html

  • v5.x: 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
            }
        }
    }
}

https://github.com/declandewet/vue-meta#how-do-i-use-component-props-andor-component-data-in-metainfo

@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)
const router = new VueRouter()
export default router
// 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))

  • seperate i18n related codes in main.js and make a .js file (ex : i18n.js)
  • export i18n.js like this -> export default new VueI18n({..})
  • import i18n.js in pure js file.

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

Was this page helpful?
0 / 5 - 0 ratings