前言
air-ui
组件库的某些组件也会用到一些提示语,除了允许用传参来自定义之外,肯定会有预设值。 比如 air-select
组件的时候,可以允许搜索的,
如果搜索不到,会有一个默认提示: 无匹配数据
, 这个就是这个组件的其中一个提示语预设值。而且这个预设值其实是中文。接下来我们看看是怎么实现的?
组件接入语言文件
有些组件的交互会用到一些预设的提示语,比如 select
, data-picker
, color-picker
, messagebox
这些组件。我们以 select
组件为例:
这个组件的代码不少,这边不全部列出来,如果想看源码的,可以参照
element-ui
组件的select.vue
代码, 两者的代码除了引用路径不太一样之外(element-ui
有些资源的引入是绝对路径,而air-ui
全部用相对路径引入),其他几乎都一样
1 | <script type="text/babel"> |
他有一个计算属性 emptyText
, 这个属性经常被使用,每次使用的时候,都会去判断各种状态:
- 如果是 loading 状态,就会显示 loading 提示语,如果没有额外对这个提示语进行传参,就使用默认的这个词条:
air.select.loading
- 如果是允许搜索的,就匹配选项值,如果匹配不到,并且没有额外对这个提示语进行传参,就使用默认的这个词条:
air.select.noMatch
- 如果没有选项值,并且没有额外对这个提示语进行传参,就使用默认的这个词条:
air.select.noData
我们可以看到默认预设值的提取是通过 t()
这个方法来处理的,我们看下这个方法,这个方法在 src/mixins/local.js
这个文件里面有定义(这个文件在上面有引入):
1 | import { t } from '../locale'; |
他返回了一个 t 的方法,并且因为是用 mix 的方式引入的,所以实例里面就可以使用这种方式调用: this.t(xxx)
:
1 | mixins: [..., Locale, ...], |
而这个 t 的方法,其实是从 src/locale/index.js
这个文件导出的:
1 | import defaultLang from '../lang/zh-CN'; |
这个文件的逻辑也很简单:
- 首先导入默认的中文的语言包文件,得到
lang
这个 map 对象 - 我们先看 t 方法,这个方法就是根据传入的多语言的key,先通过
i18nHandler
这个方法看能不能找到对应的值,如果还找不到, 那么就从默认语言包的lang
这个map对象里面得到对应的 value 并返回。
接下来我们看下,这个默认的中文的语言包里面是怎么存的 src/lang/zh-CN.js
:
1 | export default { |
所以如果 key 是 air.select.noMatch
那么就会找到 air 对象中的 select 对象中的 noMatch 这个key,然后得到对应的 value,并且返回。 这样就可以使用语言包的语言了。
组件使用多语言
我们已经知道怎么在组件里面接入语言文件了,并使用语言文件的词条了。但是还有一个问题,就是 air-ui
默认加载的语言文件是中文
,那么我怎么加载其他的多语言文件?? 所有的多语言文件都放在了 src/lang
这个目录里面。
这边就涉及到上面所列文件 src/locale/index.js
文件里面的 use 方法了:
1 | export const use = function (l) { |
我们知道其实 t 方法在获取对应 key 的 value 的时候,是从 lang 这个对象获取的,而 lang 初始化的时候,就是中文语言包对象赋值给它的。所以我们要用其他语言的语言包,比如 en,只需要将 en 的语言包导出并且调用 use 方法,重新覆盖 lang 对象就行了:
1 | import locale from './locale/index' |
这样子,就会用 en 的语言包了,截图如下:
结合到 air-ui
虽然我们可以通过以上的语法来实现用其他语言的语言包,但是毕竟这种写法不够优雅,因此我们可以将这个语法嵌入到 air-ui
初始化中,所以我们在 components/index.js
改一下,在原来的基础上加上:
1 | import locale from '../../src/locale' |
可以看到除了将 locale 对象引入之外,还改了两个地方:
- install 方法增加了对 use 和 i18n 的处理。然后直接从 opts 参数可以得到传进来的多语言对象和 i18n 的获取方法
- 导出的时候,也单独导出 locale 对象和里面的 i18n方法,以便后面单独引用组件的时候,会用到多语言
所以就会引用就会变成这样子:
1 | import AirUI from './components/index' |
这样语法上更好看。
兼容 i18n 插件
src/locale/index.js
导出来的三个方法:
t
根据 key 获取 词条use
更换新的语言包文件i18n
自定义获取的方法
其中 1 和 2 都讲过了。接下来讲讲第三个方法 i18n
, 也就是怎么兼容项目中已经存在的 i18n
插件或者自定义自己获取多语言 value 的方法???
有时候项目中有自己的多语言文件,然后 air-ui
又有自己的多语言文件,如果对于 air-ui
本身自带的多语言文件中的词条也要调整的话,那么就要需要同时维护两份多语言文件。而且其中一份还是第三方库自带的多语言文件。这样子就会变得很麻烦。 所以 air-ui
提供了一种方式,就是允许你通过在引用 air-ui
的时候, 可以自己定制获取多语言的语法以及对应的多语言 map, 具体的逻辑代码如下:
1 | let i18nHandler = function () { |
因为在 t 方法的时候,会先去通过 i18nHandler 方法去获取 value,只有当获取不到的时候,才用自带的语言包来处理。 所以我们只需要对 i18nHandler 方法进行赋值就可以自定义获取多语言的方法了,比如这样子:
1 | const customLangMap = { |
这样的效果就是调用 t 方法的时候,就会使用我们自定义的 i18n 的方法,然后得到值,只有当返回值为 null 或者 undefined 的时候,才会用原来的方式再去获取一次。所以结果如下:
可以说也是非常的方便。
兼容 vue-i18n 插件的情况
上面通过定制 i18n 方法可以随便定制获取的方法。但是其实 vue 项目中用到的最多的 i18n 组件还是属于 vue-18n, 所以 air-ui
也是有对 i18n 的不同的版本有进行不同程度的兼容
vue-i18n@5.0.3
如果你用的是 vue-i18n
的 5.0.3
这个版本,就是有 Vue.locale
这个方法的。那么就不太需要对 i18n 方法进行定制了。因为我们有在 i18nHandler 方法中内置了对这个版本的兼容了:
1 | let i18nHandler = function () { |
所以调用直接变成这样子:
1 | import Vue from 'vue' |
vue-i18n@6.x
如果是最新版本的 6.x,那么是不兼容的,还是要调用 i18n 去自定义,比如:
1 | import Vue from 'vue' |
总结
本节主要是讲 air-ui
怎么接入 i18n 多语言机制的。 但是还存在以下几个问题:
- 我们现在是有默认引入
zh-CN.js
这个文件的,这样会导致我们后面打包出来的air-ui.common.js
体积变大,我们要怎么将之抽出来?? - 组件单独打包出来的话,引入的时候,要怎么接入多语言机制??
这个将在下一节来解决。
系列文章:
自建vue组件 air-ui (1) -- 为啥我要自建一个类 element ui 的组件
自建vue组件 air-ui (2) -- 先分析一下 element ui 项目
自建vue组件 air-ui (3) -- css 开发规范
自建vue组件 air-ui (4) -- air-ui 环境搭建和目录结构
自建vue组件 air-ui (5) -- 创建第一个组件 Button
自建vue组件 air-ui (6) -- 创建内置服务组件
自建vue组件 air-ui (7) -- 创建指令组件
自建vue组件 air-ui (8) -- 实现部分引入组件
自建vue组件 air-ui (9) -- 用 vuepress 写文档
自建vue组件 air-ui (10) -- vuepress 写文档 (进阶版)
自建vue组件 air-ui (11) -- vuepress 写文档 (爬坑版)
自建vue组件 air-ui (12) -- 国际化机制
自建vue组件 air-ui (13) -- 国际化机制(进阶版)
自建vue组件 air-ui (14) -- 打包构建(dev 和 dist)
自建vue组件 air-ui (15) -- 主题定制
自建vue组件 air-ui (16) -- 打包构建 pub 任务
自建vue组件 air-ui (17) -- 开发爬坑篇以及总结