Vue-i18n与Vuex-i18n等vue的国际化方案

Vue-i18n与Vuex-i18n等国际化方案

文档时间:2021-01-04
vue-i18nvuex-i18n两者皆为vue项目的国际化方案。

文章目录

  • Vue-i18n与Vuex-i18n等国际化方案
    • 基础资料
      • vue-i18n
      • vuex-i18n
    • 基本概念
      • 1.初始化配置
        • 通过插件方式初始化一
      • 2.语言环境信息/翻译信息
      • 3.模板中使用
      • 4.脚本中使用
      • 5.修改语言环境
    • 特殊功能
      • 1.链接翻译/镶嵌翻译
      • 2.单文件组件翻译
      • 3.热重载
      • 4.组件差值
      • 5.延迟加载
    • 常见方案
      • 1. vue+vue-i18n
      • 2. vuex+vue-i18n
      • 3. vuex+vuex-i18n
    • vuex-i18n和vue-i18n语法对比
    • 其他方案
      • 1.vuex+自定义i18n
        • 将vue-i18n和自定义i18n融合
      • 2.uniapp+vuex-i18n
      • 3.vux+vuex-i18n

基础资料

vue-i18n

主要可参考此官网,掌握基础知识。
官网:http://kazupon.github.io/vue-i18n/zh/introduction.html
git:https://github.com/kazupon/vue-i18n

vuex-i18n

vuex-i18n是使用vuex作为存储的本地化插件,并非vue-i18n的升级版本,语法有一定的差异,不通用。
npm:https://www.npmjs.com/package/vuex-i18n
git:https://github.com/dkfbasel/vuex-i18n

基本概念

不论使用哪种方案国际化,自然都需要掌握以下基础的几点:初始化配置 语言环境信息 模板中使用 脚本中使用 修改语言环境
至于更复杂的功能可自行查阅相关文档。
以下例子主要基于vue-i18n讲解,实际使用时,vuex-i18n差别不大。

1.初始化配置

首先,需要安装和初始化i18n模块,安装比较简单,但是初始化就有多种方式了,可挑选适合自己项目的方式。

npm install vue-i18n --save

或者

yarn add vue-i18n

简易初始化,官网原文

// 通过选项创建 VueI18n 实例
const i18n = new VueI18n({
  locale: 'en', // 设置地区
  messages, // 设置地区信息
})
// 通过 `i18n` 选项创建 Vue 实例
new Vue({ i18n }).$mount('#app')

通过插件方式初始化一

通过插件方式初始化,是较为推荐的方式,以下是例子一:
添加i18n.js文件

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

const i18n = new VueI18n({
      // 使用localStorage存储语言状态是为了保证页面刷新之后还是保持原来选择的语言状态
    locale: localStorage.getItem('lang') || 'en', // 定义默认语言
    messages: {
        'zh': require('@/assets/languages/zh.json'),
        'en': require('@/assets/languages/en.json')
    }
})

export default i18n

在main.js中引入

import i18n from '@/plugins/i18n' // 导入vue-i18n
new Vue({
  router,
  i18n, // 此处需要挂载上i18n,不要忘记
  render: h => h(App)
}).$mount('#app')

2.语言环境信息/翻译信息

即不同语言环境情况下的相关信息,最终会被显示在网页上。
一般的简介/教程,里都是直接定义个对象,实际项目使用中一般都使用文档,可以是js文件,也可以是json文件
每种语言单独对应一个文档,如此可以将文件交给不同的翻译。
此外,还可以用数据库存储翻译信息,然后在页面初始化时通过API同步到最新翻译,最好存储在vuex中。
en.js文件

//en.js
export default {
	common:{
		btnOK:"OK",
		btnCancel:"Cancel",
	},
	message:{
		greeting:"hello, world",
		hello: '{msg} world',
		hello2: '{0} world',
	},
	banana: 'no bananas | {n} banana | {n} bananas',//复数
}

zh.js文件

//zh.js
export default {
	common:{
		btnOK:"确定",
		btnCancel:"取消",
	},
	message:{
		greeting:"你好,世界",
		hello: '{msg} 世界',
	},
}

3.模板中使用

vue代码主要分为模板和脚本两部分,如何在模板中使用将直接决定显示效果。
尤其注意的是可以善用其多种format的写法。

<span>{{$t('message.greeting')}}</span>

强制翻译成某种语言,忽略全局设置

<span>{{$t('message.greeting', 'en')}}</span>

格式化 $t()
具名格式化,除了最基本的写法,此种写法比较常见

<p>{{ $t('message.hello', { msg: 'hello' }) }}</p>

列表格式,以下两种写法都支持

<p>{{ $t('message.hello', ['hello']) }}</p>
<p>{{ $t('message.hello', {'0': 'hello'}) }}</p>

此时,你会注意到en.js中有hello2,但是zh.js中没有,如果此时配置了回退本地化,指向英文,则会显示英文,否则会报错。
参考:官网回退本地化

复数 $tc()
利用分隔符|定义语言信息,可得到多种灵活多变的结果

banana: 'no bananas | {n} banana | {n} bananas',//复数
<p>{{ $tc('banana', 0) }}</p>
<p>{{ $tc('banana', 1, { n: 1 }) }}</p>
<p>{{ $tc('banana', 1) }}</p>
<p>{{ $tc('banana', 10) }}</p>
<p>{{ $tc('banana', 100, { n: 'too many' }) }}</p>

输出,也就是页面展示如下:

<p>no bananasp>
<p>1 bananap>
<p>1 bananap>
<p>10 bananasp>
<p>too many bananasp>

第二个参数choice,是具体数量,同时也是筛选用第几个语言信息的标志,可以自动替换原文中的{n}或者{count}。
第三个参数{n: 'too many'}, 是用来替换n的。
以上内容,可以用变量x来写,达到相似效果。

<p>{{ $tc('banana', x, { n: (x>99? 'too many':x) }) }}</p>

Vuei18n初始化的时候,可以传入函数pluralizationRules,作为复数的运算规则。
使得某个特殊的语言不再使用英文的复数逻辑。

new VueI18n({
	pluralizationRules: {
		'en': function(choice, choicesLength) {
			if (choice == 0) return 0;
			return choicesLength>choice ? choice : choicesLength-1;
		}
	}
})

choice是具体数量。
choicesLength是语言配置中,配置了多少项。
函数返回值代表使用语言配置中的第几项。

自定义指令本地化 v-t

<p v-t="'hello'"></p>

若vue的js脚本中data有定义如data: { path: 'hello' }
则也可以写成

<p v-t="path"></p>

这使得model层的数据可以与i18n对接起来。
$t与v-t的对比官网资料
在官方对比中,可以看到如下缺点描述:

$t 在每次重新渲染时都会被执行,因此它确实有翻译成本。

所以实际上直接使用$t界面的效率并不高,当然小项目可以忽略此问题。

特别说明:官网的时间本地化$d()和数字本地化$n()说的不是很清楚,可能产生和预期不符的结果,一般不推荐使用,如果硬要使用,请先查阅一定的相关文档再用。

4.脚本中使用

主要用于在脚本中,生成一些语言文案相关的参数,例如生成文案,然后弹出toast、alert、confirm等等。
其参数与模板中使用一致。

this.$t('message.greeting')
this.$i18n.translate('message.greeting')

检测某个key是否存在,(检测某个语言环境下的key是否存在)

this.$te('message.greeting2');
this.$te('message.greeting2', "jp");

5.修改语言环境

直接修改实例的locale值即可。

this.$i18n.locale = "en";

或者像官网那样,设计一个select来手动挑选。官网例子
还可以考虑将值保存在cookielocalStorage里面,推荐localStorage,然后每次初始化语言系统的时候,先获取localStorage中的值。
为了避免和别的项目冲突,存储的时候,最好带上你的app_name
因此,初始化的时候,你可以这么写:

const i18n = new VueI18n({
  locale: localStorage.getItem('app_name_lang') || 'en',
  messages 
})

保存的时候

localStorage.setItem('app_name_lang', 'en');
this.$i18n.locale = "en";

特殊功能

基础功能是那些你只要使用i18n基本就一定会用到的功能,而特殊功能,只在少数情况下会用到,因此只做简单举例。

1.链接翻译/镶嵌翻译

翻译信息如下:

      the_world: 'the world',
      dio: 'DIO:',
      linked: '@:message.dio @:message.the_world !!!!'

此时,message.linked会被翻译成DIO: the world !!!!
除了@:的写法之外,还可以写成@:(message.foo.bar.baz)这种形式,要注意的是,层级比较深的时候,一定要使用括号,这样会有一个清晰的结构。

2.单文件组件翻译

简单点说,先安装vue-i18n-loader

npm i --save-dev @kazupon/vue-i18n-loader

然后在单文件组件,添加,增加翻译信息。
并且,你可以指定多个,或者是指定某个特有文件为翻译,这些翻译信息会自动合并。

<i18n src="./common/locales.json">i18n>
<i18n>
{
  "en": {
    "hello": "hello world!"
  },
  "ja": {
    "hello": "こんにちは、世界!"
  }
}
i18n>
<template>
	<p>message: {{ $t('hello') }}p>
template>
<script>
script>

注意,当使用webpack等工具时,需要配置,参考文档
loader: 'vue-loader',之后,添加如下所示的5行配置。

  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        resourceQuery: /blockType=i18n/,
        type: 'javascript/auto',
        loader: '@kazupon/vue-i18n-loader'
      }
    ]
  },

此外,函数式组件