羽暮
不服输的才是青春.✨
10文章
3评论
2微语

个人档

访客排行

i18n国际化实现数据后端获取

2021-4-21
0 65

工作需要,新项目也需要实现多语言,因为以前都是i18n包进行多语言的切换,此次也不例外。就在昨天,我在github查看i18n的demo的时候再created中看到了这么一个函数调用 this.$i18n.mergeLocaleMessage('en', local.en),百度之后发现,这是往指定的语言包内插入新数据的函数,由此可实现我们的目的。

利用mergeLocaleMessage动态添加语言包

从后端获取数据,然后根据自己语言包的格式把数据进行排版,最后用mergeLocaleMessage添加进语言包内。

// 获取语言包
export function getLangs(vm){
	// 获取语言
	vm.$u.get('/Sys/I18n/lng?l=' + vm.$i18n.locale + "&p=BGAPP").then(res => {
		// console.log(res)
		var list = res.data
		var local = {}
		list.forEach(d => {
			// local[d.key] = d.value
			let sign = d.key.substr(0, d.key.indexOf('.')).toLocaleLowerCase()
			let key = d.key.substr(d.key.indexOf('.') + 1).toLocaleLowerCase()
			let value = d.value
			if (sign) {
				if (local[sign]) {
					local[sign][key] = value
				} else {
					local[sign] = {}
					local[sign][key] = value
				}
			} else {
				local[d.key] = d.value
			}
	
		})
		// console.log('langList', local)
		// 设置语言包
		vm.$i18n.mergeLocaleMessage(vm.$i18n.locale, local)
		console.log('langList', vm.$i18n.messages)
	})
}

切换语言的时候,根据所选语言动态添加语言包

langCallback(index) {
	this.lang = this.langList[index].text
	this.$i18n.locale = index === 0 ? 'zh' : 'km' // 切换语言
	this.setpagetitle() // 切换标题语言
	this.$u.vuex('vuex_lang', this.$i18n.locale) // 存储到vuex
	getLangs(this) // 获取语言
}

利用正则匹配,实现多语言中存在变量的问题

遇到如下这种字符串中穿插变量,190700045为员工编号,无法直接写进语言包内。需要进一步的处理。

QQ截图20210421154759.png

实现方式:

showModal(this, {
	title: this.$t('home.tips'),
	content: this.$t('home.content'),
	content_paraters: { staff_code: staff.staff_code },
        ...
}

在这个弹窗提示中,content就是存在变量的属性,先看看语言包中的定义

content:'请确认是否取消员工[ {staff_code} ]的工序任务?',

我用了一对大括号包裹需要变量的地方,之后利用正则匹配替换成真正的变量。你也可以使用其他的符号进行匹配。content_paraters这个就是传入的变量。

export function showModal(vm,options){
	 var opts = options
	 opts.title =vm.$t(template(options.title,options.title_paraters))
	 opts.content =vm.$t(template(options.content,options.content_paraters))
	uni.showModal(opts)
}

这里看到,我用了template这个函数,就是为了匹配大括号替换其中的变量。

export function template(str, ...argus) {
  var args
  if (argus.length === 1 && typeof argus[0] === 'object') {
    args = arguments[1]
  } else {
    args = argus
  }
  if (!args || !args.hasOwnProperty) {
    args = {}
  }
  const nargs = /\{([0-9a-zA-Z_]+)\}/g

  return str.replace(nargs, function replaceArg(match, i, index) {
    var result

    if (str[index - 1] === '{' && str[index + match.length] === '}') {
      return i
    } else {
      result = args.hasOwnProperty(i) ? args[i] : null
      if (result === null || result === undefined) {
        return ''
      }
      return result
    }
  })
}

至此,多语言遇到的问题都解决了。

变量问题——i18n提供的解决方案

这几天看到一篇关于vue-i18n的文章,才了解到一些关于它的用法。原来早已经提供了相关的简便方法

最为直接的用法:

msg:"我今年{ age }岁" // 在使用变量的字段中采用这种单括号的形式。
<view>{{ $t(msg,{ age:'12' }) }}</view> // 直接在$t方法内传入第二个参数对象形式。

但还存在一些局限性,例如无法修改变量的css样式

我们可以修改一下,利用v-html的特性去实现这一需求

msg:"我今年<text class='age'>{ age }</text>岁" // 添加一个text标签然后对其进行设置css样式
<view v-html="$t(msg,{ age:'12' })"></view> // 通过v-html进行渲染

注意:这种方法会引发XSS攻击,所以不推荐

使用place属性

msg:"我今年{ age }岁" 

<i18n path="msg" tag="view"> // tag为i18n标签渲染为view标签
    <text class="age" place="age">12</text> // place指向变量 标签内的内容为变量内容
</i18n>

终极解决方案

place的方案看着就知道是利用了vue的插槽所以我们可以这样做

msg:"我今年{ age }岁" 

<i18n path="msg" tag="view"> // tag为i18n标签渲染为view标签
  <template v-slot:age> // 插槽指向变量即可
    <text>12</text>
  </template>
</i18n>

咳,其实这就是没有养成看文档的习惯造成的,文档里当然早就说明了相关的使用方法,有兴趣的可以直接去看看文档。

文档地址:https://kazupon.github.io/vue-i18n/zh/introduction.html

羽暮

不服输的才是青春.✨
userAvatar
撰写评论