前端如何做国际化(中)

2,235 阅读4分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文同时参与 「掘力星计划」  ,赢取创作大礼包,挑战创作激励金

上篇文章 <前端如何做国际化(上)> 主要讲了功能裁剪定制

前端如何做国际化(下)

连载阅读体验更佳

文案国际化

vue 的工程进行文案国际化,主要是使用 vue-i18n 插件进行国际化:vue-i18n 文档。

安装 vue-i18n:

npm i vue-i18n

之后,我们在 src 下创建 locale 文件夹,其目录结构如下:

├── locale
│   ├── district.js         获取保存上一节中通过webpack传入的国家配置
│   ├── index.js            i18n主要的功能代码以及与elementUI(京东商家版)的设置
│   ├── langInterceptor.js  语言路由拦截器,用于控制懒加载哪一个语言包,以及设置显示语言
│   ├── langMap.js          语言映射表,用于对应各个语言的名称,用于语言切换的列表展示
│   ├── langs               存放语言的文件映射
│   │   ├── en_US.js        中文映射
│   │   └── zh_CN.js        英文映射
│   └── utils.js            国际化通用的功能

district.js

地区配置。

// 从webpack的环境变量中读取地区配置,格式为 { name: '', config: '' }
export const district = process.env.DISTRICT
 
// 通过key获取地区配置项
export const getDistrictConfig = key => {
  return district.config[key]
}
 
// 取出语言列表项
export const languages = getDistrictConfig('languages')
 
// 取出cookie domain
export const cookieDomain = getDistrictConfig('cookieDomain')
 
// 不同地区的域名/url
export const urls = getDistrictConfig('urls')
 
// 不同地区的功能裁剪
export const functional = getDistrictConfig('functional')
 
export const passport = getDistrictConfig('passport')

lang/zh_CN.js

// 如果有引用组件库如 element-ui,则需要将组件库的对应的翻译文件引入
import zhCN from 'element-ui/lib/locale/lang/zh'
 
export default {
  ...zhCN,
  locale: '语言',
  title: '新宙斯 更能量',
  ...
}

这里的key随开发者自己定义。

index.js

/**
 * VueI18n国际化配置
 * */
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import zh_CN from '@/locale/lang/zh_CN'
import en_US from '@/locale/lang/en_US'
import th_TH from '@/locale/lang/th_TH'
// 如果有引入组件库如element-ui,则需要修改其翻译函数
import locale from 'element-ui/lib/locale'
 
const languageMsg = {
  zh_CN,
  en_US,
  th_TH
}
 
const msg = {}
languages.forEach(lang => {
  msg[lang] = languageMsg[lang]
})
 
Vue.use(VueI18n)
 
// 配置语言
const i18n = new VueI18n({
  locale: languages[0], // 默认取第一个语言
  messages: msg
})
 
locale.i18n((key, value) => i18n.t(key, value))
 
export default i18n

langMap.js

用于映射语言选择列表,切换语言选择项文案应该与其语言保持一致

export default {
  zh_CN: '简体中文',
  en_US: 'English',
}

utils.js

国际化工具类函数。

/**
 * VueI18n 国际化语言配置
 */
/* eslint-disable */
import Cookies from '@/utils/js-cookie'
import i18n from './i18n'
import axios from 'axios'
import { cookieDomain } from './district'
/**
 * 根据语言重定向 Url,此函数可用于切换语言
 * @param {String} lang 语言标识
 */
export function setLocaleUrl(lang) {
  Cookies.set('language', lang, {
    domain: cookieDomain,
    expires: 1
  })
  let href = location.href.replace(/language=([^&]*)/, `language=${lang}`)
  location.href = href
}
 
/**
 * 设置语言
 * @param {String} lang 语言标识
 */
function setLocale(lang) {
  i18n.locale = lang
  // 修改ajax请求头,如果你是其他http包,则对应做修改
  axios.defaults.headers.common['Accept-Language'] = lang
  // 修改页面标题
  document.title = i18n.t('title')
  return lang
}

langInterceptor.js

语言路由拦截器,在进入页面之前,获取语言,并设置语言。

/**
 * 语言 统一路由拦截
 */
import Cookies from '@/utils/js-cookie'
import { languages } from './district'
 
let LangInterceptor = {}
 
LangInterceptor.install = (Vue) => {
  Vue.mixin({
    beforeRouteEnter (to, from, next) {
      let currentLanguage = ''
      // languages指的是当前地区使用的语言列表
      // Cookies指的是操作cookies的方法
      // 先从 query 中取语言标识,并判断是否属于语言列表中的语言
      if (to.query.language && languages.indexOf(to.query.language) > -1) {
        currentLanguage = to.query.language
      }
      // 如果 query 中没有语言标识,则从 cookie 中获取,如果 cookie 中也没有,则取默认语言
      if (!currentLanguage) {
        let cookieLang =  Cookies.get('language')
 
        if (cookieLang && languages.indexOf(cookieLang) > -1) {
          currentLanguage = cookieLang
        } else {
          currentLanguage = languages[0]
        }
      }
      next()
    }
  })
}
 
export default LangInterceptor

之后在项目的入口文件 main.js 中,使用 LangInterceptor :

main.js

import Vue from 'vue'
import App from './App.vue'
import i18n from './locale/index'
import LangInterceptor from './locale/langInterceptor'
 
Vue.config.productionTip = false
 
Vue.use(LangInterceptor)
 
new Vue({
  i18n,
  render: h => h(App)
}).$mount('#app')

之后是在项目中对需要翻译的文案进行翻译:

<div id="app">
  <p>{{ $t('title') }}</p>
</div>

中英文切换的业务代码示例:

<template>
  <!-- 这里使用的是 element-ui -->
  <el-dropdown @command="handleCommand">
    <span class="el-dropdown-link">
      {{langMap[$i18n.locale]}}
      <i class="el-icon-arrow-down el-icon--right"></i>
    </span>
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item
        v-for="(lang, index) in languages"
        :key="index"
        :command="lang"
      >{{ langMap[lang] }}</el-dropdown-item>
  </el-dropdown-menu>
</template>
 
<script>
import langMap from "@/locale/langMap"
import { setLocaleUrl } from "@/locale/utils"
import { languages } from "@/locale/district"
 
export default {
  name: "Header",
  data() {
    return {
      langMap,
      languages
    }
  },
  methods: {
    handleCommand(command) {
      setLocaleUrl(command);
    }
  }
};
</script>

再回到功能裁剪

功能裁剪一般需要裁剪功能入口以及对应的页面路由。

裁剪入口:

<template>
  <header class="header">
    <router-link v-if="functional.vapp" to="/vapp">小程序</router-link>
  </header>
</template>
 
<script>
import { functional } from '@/locale/district'
 
export default {
  data () {
    return {
      functional
    }
  }
}
</script>

裁剪路由:

router.js

import Vue from 'vue'
import Router from 'vue-router'
import { functional } from '@/locale/district'
import Index from '@/views/index.vue'
 
const router = new Router({
  routes: [
    {
      path: '/',
      component: Index
    },
    // 裁剪 vapp 页面
    ...(functional.vapp ? [{
      path: '/vapp',
      component: () => import('@/views/vapp.vue')
    } : [])
  ]
})

index.html 中怎么获取变量使用的配置

index.html 文件是 html-webpack-plugin 插件处理的,该插件从 3.0 开始,是支持向 html 中传入配置的。

vue-cli3 开始,自动将 vue.config.js 的配置传入了 index.html 中

html-webpack-plugin 通过添加 templateParameters 函数,自定义传入的数据。

const localeConfig = require('path/to/locale')

    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true,
      templateParameters: (compilation, assets, pluginOptions) => {
        let stats
        return {
          get webpack () {
            return stats || (stats = compilation.getStats().toJson())
          },
          compilation: compilation,
          webpackConfig: {
            ...compilation.options
          },
          htmlWebpackPlugin: {
            files: assets,
            options: pluginOptions
          },
          config: {
            stream: localeConfig.config.stream
          }
        }
      }
    })

vue-cli 2 创建的项目需要升级下 html-webpack-plugin,手动执行 npm i html-webpack-plugin@3 -D

上篇文章 <前端如何做国际化(上)> 主要讲了功能裁剪定制

前端如何做国际化(下)

连载阅读体验更佳

点赞支持、手留余香、与有荣焉,动动你发财的小手哟,感谢各位大佬能留下您的足迹。

11.png

往期精彩推荐

React 开发规范

Vue 开发规范

移动端横竖屏适配与刘海适配

移动端常见问题汇总

前端常用的几种加密方法

canvas 爬坑路【方法篇】

不懂 seo 优化?一篇文章帮你了解如何去做 seo 优化

canvas 爬坑路【属性篇】

【实战篇】微信小程序开发指南和优化实践

聊一聊移动端适配

前端性能优化实战

聊聊让人头疼的正则表达式

获取文件blob流地址实现下载功能

Vue 虚拟 DOM 搞不懂?这篇文章帮你彻底搞定虚拟 DOM

Git 相关推荐

通俗易懂的 Git 入门

git 实现自动推送

面试相关推荐

前端万字面经——基础篇

前端万字面积——进阶篇

更多精彩详见:个人主页