这里总结了自己静态站项目中遇到的问题和解决办法
安装
yarn add vue-i18n
//安装 js-cookie 通过 cookie 判断浏览器语言设置默认语言
yarn add js-cookie --save
main.js配置
import VueI18n from 'vue-i18n'
import Cookies from 'js-cookie'
import zh from '@/assets/lang/zh.js'
import en from '@/assets/lang/en.js'
import es from '@/assets/lang/es.js'
Vue.use(VueI18n)
const messages = {
zh: {
...zh
},
en: {
...en
},
es: {
...es
}
}
function getLanguage() {
const chooseLanguage = Cookies.get('language')
if (chooseLanguage) return chooseLanguage
// if has not choose language
const language = (navigator.language || navigator.browserLanguage).toLowerCase()
const locales = Object.keys(messages)
for (const locale of locales) {
if (language.indexOf(locale) > -1) {
return locale
}
}
return 'en' //没有目标语言默认显示英文
}
const i18n = new VueI18n({
// 调用 Cookie 设置语言函数
locale: getLanguage(),
// 引入语言包对象
messages
})
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount('#app')
js语言包文件
zh.js:
module.exports = {
common: {
home: "中文",
title: "示例"
},
user: {
name: "名字"
}
}
en.js:
module.exports = {
common: {
home: "English",
title: "demo"
},
user: {
name: "Avery"
}
}
组件调用方式
全局通过 $t('') 调用获取每个语言包内的对应的属性,
//html
$t('common.home')
//js
this.$t('common.home')
切换语言组件
通过 this.$i18n.locale = "zh" 修改当前语言
<template>
<div class="box">
<button class="btn">{{ $t('mainNav.lang') }}</button>
<div class="select">
<p @click="zh">中文简体</p>
<p @click="en">English</p>
<p @click="es">Español</p>
</div>
</div>
</template>
<script>
export default {
name: "langSelect",
methods: {
zh() {
this.$i18n.locale = "zh";
},
en() {
this.$i18n.locale = "en";
},
es() {
this.$i18n.locale = "es";
}
}
};
</script>
获取当前语言
通过 $i18n.locale 获取当前语言,
console.log(this.$i18n.locale) //zh
语言包管理
[Excel语言包管理 - 百度云](pan.baidu.com/s/1MIwdsm4p… 提取码: vnx8)
当整个项目过大,分开管理各个语言包就显得非常繁琐,这时可以使用 excel 来集中管理语言包,通过宏来导出各个语言包
在最左侧表格 列表 的右侧输入要导出的文件夹名,和需要翻译的语言包,左侧不用填写,运行宏后会按顺序自动填写每个表格内的中英文变量名方便查看
在右侧复制表格格式,填写变量名和各语言的值
通过 视图 > 宏 > 查看宏 > MakeAll > 执行 来导出语言包,宏速度很快,点击执行后就已经完成了导出,在C盘的 DbSql 文件夹 Website 内找到语言包放入项目的语言包文件夹内使用
添加更多语言,或删除西班牙语,需要更改宏,点击宏对话框的编辑,在打开的宏里找到MakeAll,修改为对应数量
修改上图目录为项目目录,表格 列表 内的文件夹名改成lang,直接生成语言包到项目目录的lang文件夹下
sBaseFolderName = "d:\\App\\src\\assets"
v-for 列表渲染
语言包为列表渲染的内容单独声明了数组或对象,直接 v-for = "item in $t( 'list' )" 就可以
data内可以 $t 获取语言包内的变量,但是对切换语言是无法做出响应的
所以当需要拼凑一个对象用于列表渲染,需要在计算属性内 return 这个拼凑的语言包对象,这个对象就可以通过计算属性来响应语言的切换
computed: {
list() {
return {
listTitle: this.$t("list.mainTitle"),
advantage: [
{
title: this.$t("list.title1"),
text: this.$t("list.text1")
},
{
title: this.$t("list.title2"),
text: this.$t("list.text2")
},
{
title: this.$t("list.title3"),
text: this.$t("list.text3")
}
]
};
}
}
组件复用情况
结合上方计算属性返回对象的操作,再通过 $route 获取路由,计算属性嵌套,来让组件显示固定的不同内容
computed: {
content() {
let content;
let type = this.$route.matched[0].name;
switch (type) {
case "page1":
content = this.list1;
break;
case "page2":
content = this.list2;
break;
case "page3":
content = this.list3;
break;
}
return content;
},
list1() {
return {
listTitle: this.$t("list.mainTitle"),
advantage: [
{
title: this.$t("list.title1"),
text: this.$t("list.text1")
},
.....
]
};
},
list2() {
return {
listTitle: this.$t("list.mainTitle"),
advantage: [
{
title: this.$t("list.title1"),
text: this.$t("list.text1")
},
.....
]
};
},
list3() {
return {
listTitle: this.$t("list.mainTitle"),
advantage: [
{
title: this.$t("list.title1"),
text: this.$t("list.text1")
},
.....
]
};
}
}
不同语言CSS适配
绑定元素属性并选择元素
因为语言不同使用同一个 css 导致的标题或其他内容,宽度超出或其他意外情况,或者不同语言使用不同的背景图片
可以使用 :lang() 伪选择器,来对不同语言的个别内容进行单独调整适配
首先需要对元素动态绑定语言类型,通过:
<h3 :lang="$i18n.locale">{{content.title}}</h3>
h3 {
color: #fff;
text-align: center;
white-space: nowrap;
&:lang(zh) {
font-size: 0.8rem;
}
&:lang(en) {
font-size: 0.59rem;
}
&:lang(es) {
font-size: 0.5rem;
}
}
多个语言包同语种选择器
如果是适配 zh-cn、zh-hk、zh-tw,或者 en-uk、en-us....这种多语言包但是同语种长度相同的语言
改为使用 属性选择器 会更灵活,注意 lang 后的管道符 |
//选择属性 lang 值以 zh 或 zh- 开头的元素
h3[lang|='zh']{
font-size: 0.8rem;
}
//绑定属性为zh_cn的话,可以使用以开始字符为特征选择
h3[lang^='zh']{
font-size: 0.8rem;
}
标题过长超出部分省略
一些并不是很重要的标题,可以给的空间又非常有限,可以采用css的方法将超出部分省略
h3{
overflow: hidden;
white-space: nowrap;
text-overflow:ellipsis;
}
深度作用选择器
因为vue组件在 css 设置 scoped 的情况下编译,会在标签内生成 data-v-xxxx ,css 通过属性选择器选择,来避免 css 污染全局
<div data-v-654a55d5 class="box"></div>
.box[data-v-654a55d5] {
...
}
当使用 v-html 导入的变量带有标签和类名,是无法通过当前组件的 css 来控制的
vue提供了 深度作用选择器 来完成这个操作
// css:
.box >>> .title{
...
}
// sass/less
.box {
/deep/ .title{
...
}
}
编译结果:
.box[data-v-654a55d5] .title {
...
}
这个方法同样适用于插件导入的内容
主副意思相同
当英文副标题和中文主标题意思相同时,语言包内英文副标题值为空,不会占用页面空间,空值也不会报错