purpose

The project needs to support multiple languages, so we need to extract the static text used in the project and use the language package for management. When switching the language setting, the text display of the whole project can be automatically switched.

The corresponding component VUE-I18N was found in the Vue project, and the code of the project was not changed much, so we used this component to modify the code in the project.

The installation

// script introduces <script SRC ="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-i18n/dist/vue-i18n.js"></script> // NPM install NPM install vue-i18n // yarn install yarn add vue-i18nCopy the code

Generally used in a project is through the installation package to run, script introduced less.

use

The i18N is configured in the project

import VueI18n from 'vue-i18n'
Vue.use(VueI18n)

const i18n = new VueI18n({
    local: 'cn'}) new Vue({el:'#app'. I18n}) {cn: {name:'name'}, us: {name:'Name'}}Copy the code

The use of i18n

Simple to use

// HTML needs to wrap name around {{}}$t('name')}}

// js
$t('name')
Copy the code

Passable variable

// messages: {cn: {name:'Name: {name}'
    },
    us: {
        name: 'Name: {name}'}}$t('name', {name: 'Jack'}) // messages: {cn: {Name:'Name: {0}{1}'
    },
    us: {
        name: 'Name: {0}{1}'
    }
}

// array
$t('name'['Jack'.'Job'])
// object
$t('name', {'0':'Jack'.'1': 'Job'])
Copy the code

The plural format

Use the separator |

// messages: 
{
    us: {
        car: 'car | cars | {count} cars'}}$tc('car', x) // Select different car typesCopy the code

Time format

const dateTimeFormats = {
  'us': {
    short: {
      year: 'numeric', month: 'short', day: 'numeric'
    },
    long: {
      year: 'numeric', month: 'short', day: 'numeric',
      weekday: 'short', hour: 'numeric', minute: 'numeric'}}, cn: {XXX}} const i18n = new VueI18n({locale:' ', messages, dateTimeFormats}) // Use$d(new Date(), 'short')
$d(new Date(), 'long')
$d(new Date(), 'short'.'cn')
Copy the code

Amount of symbols

const numberFormats = {
  'en-US': {
    currency: {
      style: 'currency', currency: 'USD'}},'ja-JP': {
    currency: {
      style: 'currency', currency: 'JPY', currencyDisplay: 'symbol'Const i18n = new VueI18n({numberFormats}) // use$n(100, 'currency') / /The $10000.$n(100, 'currency'.'ja-JP') RMB 100 / /Copy the code

Provide a default language settingfallbackLocale

Provide a default full language to handle when a language does not exist

const messages = {
  cn: {
    name: 'Name:'} us: {}} const i18n = new VueI18n({locale: locale) {}} const i18n = new VueI18n({locale:'us',
  fallbackLocale: 'cn',
  messages
})

Copy the code

v-tCan be used to reference variables, similar to$t

V – t instruction

New Vue({i18n: new VueI18n({locale:'en',
    messages: {
      en: { hello: 'hi {name}! ' },
      ja: { hello: 'Kohii | | | | | | | | | | | | | | | | | | | | | | | | | | | | ' }
    }
  }),
  computed: {
    nickName () { return 'kazupon' }
  },
  data: { path: 'hello'}}).$mount('#object-syntax')


<div id="object-syntax"> <! -- literal --> <p v-t="{ path: 'hello', locale: 'ja', args: { name: 'kazupon' } }"></p> <! -- data biniding via data --> <p v-t="{ path: path, args: { name: nickName } }"></p>
</div>

<div id="object-syntax"> <p> Kohiko: From proverb to proverb! </p> <p>hi kazupon! </p> </div>Copy the code

$t versus v minus t

  • $tIs a method call,v-tIt’s an instruction
  • v-tPerformance than$tEven better, there is a cache of custom instructions
  • $tIt is more flexible and simpler to use

There e are some other uses, please refer to the official documentation for details.

To switch languages, use built-in variables:

// Switch the language this by setting locale.$i18n.locale = cn | us
Copy the code

Insert the components

If encountered such a scenario, how to deal with?

<p>I accept xxx <a href="/term">Terms of Service Agreement</a></p>
Copy the code

My first reaction was to divide it into two fields. Tag A does not belong to the translation content, as long as it is written as:

<p>{{ $t('xx1') }}<a href="/term"> {{$t('xx2') }}</a></p>
Copy the code

This is too unwieldy and can be handled as a component

// I81n <i18n path="term" tag="label" for="tos">
    <a :href="url" target="_blank"> {{$t('tos') }}</a>
</i18n>

const messages = {
  en: {
    tos: 'Term of Service',
    term: 'I accept xxx {0}.'
  }
}

new Vue({
  el: '#app',
  i18n,
  data: {
    url: '/term'}})Copy the code

As you can see, two variables are still used to store information, but the tag is produced by tag and the path specifies the content of the tag.

$t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)** $t(“)**”

More advanced use, you can control where AN HTML element is inserted, using place to specify where it appears in the HTML.

<i18n path="info" tag="p">
    <span place="limit">{{ changeLimit }}</span>
    <a place="action" :href="changeUrl"> {{$t('change') }}</a>
</i18n>

const messages = {
  en: {
    info: 'You can {action} until {limit} minutes from departure.',
    change: 'change your flight',
    refund: 'refund the ticket'
  }
}

const i18n = new VueI18n({
  locale: 'en',
  messages
})
new Vue({
  i18n,
  data: {
    changeUrl: '/change',
    refundUrl: '/refund',
    changeLimit: 15,
    refundLimit: 30
  }
}).$mount('#app')

// result
<p>
    You can <a href="/change">change your flight</a> until <span>15</span> minutes from departure.
</p>

Copy the code

The unity of the sentence is preserved, but it may not be used if it is only for multi-language translation of nouns without grammar requirements.

Load language packs dynamically

It is not necessary to load all the language packages at one time, especially if the language packages are used. I also raised this problem before and found that the official website provides a solution.

//i18n-setup.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from '@/lang'// Address of the language package, depending on the project Settings import axios from'axios'Use (VueI18n); use(VueI18n);export const i18n = new VueI18n({
  locale: 'en', / /set locale
  fallbackLocale: 'en', // Default language Settings, when other languages are not available, use en as the default language messages //set locale messages
})

const loadedLanguages = ['en'] // our default language that is prelaoded 

function setI18nLanguage (lang) {
  i18n.locale = lang
  axios.defaults.headers.common['Accept-Language'] = lang // Set request header document.querySelector('html').setAttribute('lang', lang) // The root element adds the lang attributereturn lang
}

export function loadLanguageAsync (lang) {
  if(i18n.locale ! == lang) {if(! loadedLanguages.includes(lang)) {return import(/* webpackChunkName: "lang-[request]" */ `@/lang/${lang}`).then(msgs => {
        i18n.setLocaleMessage(lang, msgs.default)
        loadedLanguages.push(lang)
        return setI18nLanguage(lang)
      })
    } 
    return Promise.resolve(setI18nLanguage(lang))
  }
  returnResolve (lang)} // Handle router in vue-router's beforeEach global hook. BeforeEach ((to, from,) next) => { const lang = to.params.lang loadLanguageAsync(lang).then(() => next()) })Copy the code

Generation of language pack & replacement of original static text in project

This is the most important step,

  • Pull out all the characters that appear
  • replace$t('xxx').$n.$d.v-tAnd so on, according to the appropriate situation of their own choice
  • Maintain multiple versions of language files

Add a new directory languages under the project

- languages - lib - cn. Js / / Chinese language pack -- us. Js / / English language pack -.. // Other languages, not yet implemented -- index.js // Export language packageCopy the code

cn.js

export default {
    common: {
        message: 'message'
    },
    xxx: {

    }
}
Copy the code

us.js

export default {
    common: {
        message: 'Messages'
    },
    xxx: {

    }
}
Copy the code

index.js

import cn from './lib/cn.js'

export default {
    cn,
    us
}
Copy the code

Replace text

<template>
    ...
    <div>{{$t('message')}}</div>
    ...
</template>

Copy the code

The problem

  • Different languages, different formats, different lengths, may need to adjust the style of the project to keep it normal
  • For a project that is already in use, generating the language package is a time-consuming and time-consuming step