kazupon / vue-i18n

:globe_with_meridians: Internationalization plugin for Vue.js
https://kazupon.github.io/vue-i18n/
MIT License
7.28k stars 861 forks source link

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

Closed pzuopin closed 7 years ago

pzuopin commented 7 years ago

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 commented 7 years ago
this.$t('COMMON.LOGIN')
blogui91 commented 7 years ago

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

blogui91 commented 7 years ago

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 commented 7 years ago

You can use the below APIs

  this.$i18n.t('path', 'en', { foo: 'bar' })

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

See details: https://github.com/kazupon/vue-i18n/blob/5.x/gitbook/api.md

ShiraMiyuko commented 6 years ago

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 commented 6 years ago

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

verizecom commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

@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 commented 6 years ago

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 commented 6 years ago

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

hyunoosung commented 6 years ago

@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 commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

@anselmobattisti - well done! Thanks a lot!

ThinkerBell1 commented 6 years ago

@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 commented 6 years ago

@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 commented 6 years ago

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

sensoeurn commented 5 years ago

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 commented 5 years ago

@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 commented 5 years ago

@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 commented 5 years ago

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

jonnyparris commented 5 years ago

@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 commented 5 years ago

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

<script>
import i18n from '@/i18n'

{
...
data: () => {
return {
 message: i18n.t('message'),
}
}
...
}
wilsonwu commented 4 years ago

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 commented 4 years ago

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

jingyuLin1999 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

import i18n from "@/i18n";

abhimatta commented 4 years ago

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 commented 3 years ago

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 commented 2 years ago

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 commented 2 years ago

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

i18n.t('string') // v8
i18n.global.t('string') // v9
brennanleez-coder commented 2 years ago

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

jeancampregher commented 2 years ago

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

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

Thanks a lot!!

ahmedmohamedeid98 commented 1 year ago
import { useI18n } from 'vue-i18n';
const name = ref(useI118n().t('name'));