Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
pzuopin opened this issue Apr 20, 2017 · 36 comments

Comments

@pzuopin
Copy link

pzuopin commented Apr 20, 2017

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.

@taotao365s
Copy link

taotao365s commented Apr 22, 2017

this.$t('COMMON.LOGIN')

@blogui91
Copy link

same here :( ,
@shipengyan as @pzuopin said, the requiment is to call $t helper in js files, it means not inside a Vue component

@blogui91
Copy link

blogui91 commented Apr 29, 2017

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.

@kazupon
Copy link
Owner

kazupon commented May 9, 2017

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

@kazupon kazupon closed this as completed May 9, 2017
@ShiraMiyuko
Copy link

ShiraMiyuko commented Nov 19, 2017

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

@3ss0
Copy link

3ss0 commented Nov 21, 2017

try
metaInfo: {
title: this.$i18n.t('message.blog'),
},

@verizecom
Copy link

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

@ShiraMiyuko
Copy link

@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 ^^

@lucpotage
Copy link

@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

@anselmobattisti
Copy link

anselmobattisti commented Jan 13, 2018

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

@cb109
Copy link

cb109 commented Mar 28, 2018

@anselmobattisti Looks like the preferred solution to me, since import order does not matter then and things are nicely separated, well done 👍

@hyunoosung
Copy link

@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?

@laurentpayot
Copy link

laurentpayot commented May 18, 2018

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

@WillieYang
Copy link

WillieYang commented Jun 19, 2018

@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!!!

@joshua1988
Copy link

@anselmobattisti - well done! Thanks a lot!

@ThinkerBell1
Copy link

@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... )

@WillieYang
Copy link

@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.

@ThinkerBell1
Copy link

@WillieYang - thanx, that was also what i did at the end..

@sensoeurn
Copy link

sensoeurn commented Dec 27, 2018

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]
						}
					]
				}
		}
    }

@duykhanhrc
Copy link

@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

@n05la3
Copy link

n05la3 commented Mar 12, 2019

@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

@SkynI25
Copy link

SkynI25 commented Mar 13, 2019

@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!

@jonnyparris
Copy link

@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'
};

@ebubekirtabak
Copy link

ebubekirtabak commented Nov 12, 2019

You have to import 'i18n' in your component.
For example:

<script>
import i18n from '@/i18n'

{
...
data: () => {
return {
 message: i18n.t('message'),
}
}
...
}

@wilsonwu
Copy link

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?

@ebubekirtabak
Copy link

@wilsonwu
Actually I don't know, maybe it was lazy loading.

@jingyuLin1999
Copy link

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")

@christhofer
Copy link

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...?

@zhouhanxiaoxiao
Copy link

import i18n from "@/i18n";

@abhimatta
Copy link

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

@alex-gru
Copy link

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

@codelegant
Copy link

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

@SimonHawesome
Copy link

Syntax has changed from v8 to v9. Thanks @codelegant!

i18n.t('string') // v8
i18n.global.t('string') // v9

@brennanleez-coder
Copy link

@SimonHawesome just saved my life, thanks for the recent update!

@jeancampregher
Copy link

Syntax has changed from v8 to v9. Thanks @codelegant!

i18n.t('string') // v8
i18n.global.t('string') // v9

Thanks a lot!!

@ahmedmohamedeid98
Copy link

ahmedmohamedeid98 commented Jul 12, 2023

import { useI18n } from 'vue-i18n';
const name = ref(useI118n().t('name'));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests