库版本
packageversion
vue2.6.11
vant2.12.6
vue-i18n8.23.0

最近一个用 react-mobile 的小型 IM App 被客户吐槽UI,所以现在用传说Vue中最漂漂的 Vant 重构一下,没办法,react实在是没有省心又好看的移动端库了[手动哭脸T_T],所以喽,搞起!

第一步:导出 i18n 模块

模块代码如下:

import Vue from "vue";
import VueI18n from "vue-i18n";

import { getLanguage } from "@/utils/cookies";

// Vant built-in lang
import { Locale } from 'vant';
import enUS from "vant/es/locale/lang/en-US";
import zhCN from "vant/es/locale/lang/zh-CN";
import zhTW from "vant/es/locale/lang/zh-TW";
import jaJP from "vant/es/locale/lang/ja-JP";

// User defined lang
import enUsLocale from "./en_US";
import zhCnLocale from "./zh_CN";
import zhTwLocale from "./zh_TW";
import jaJpLocale from "./ja_JP";

Vue.use(VueI18n);

const messages = {
  'zh-CN': {
    ...zhCN,
    ...zhCnLocale
  },
  'zh-TW': {
    ...zhTW,
    ...zhTwLocale
  },
  'en-US': {
    ...enUS,
    ...enUsLocale
  },
  'ja-JP': {
    ...jaJP,
    ...jaJpLocale
  }
};

export const getLocale = () => {
  const cookieLanguage = getLanguage();
  if (cookieLanguage) {
    document.documentElement.lang = cookieLanguage;
    return cookieLanguage;
  }

  const language = navigator.language.toLowerCase();
  const locales = Object.keys(messages);
  for (const locale of locales) {
    if (language.indexOf(locale) > -1) {
      document.documentElement.lang = locale;
      return locale;
    }
  }

  // Default language is english
  return "en-US";
};

const CURRENT_LANG = getLocale();
// first entry
Locale.use(CURRENT_LANG, messages[CURRENT_LANG])

const i18n = new VueI18n({
  locale: CURRENT_LANG,
  messages
});

export default i18n;

业务语言包结构如下:

export default {
    appHeader: {
        title: 'Vue App'
    },
    langSelect: {
        pickerTitle: '当前语言',
    }
};

getLanguage 是使用 js-cookie 封装的方法,cookie.js 代码如下:

import Cookies from 'js-cookie'

// App
const languageKey = 'language'
export const getLanguage = () => Cookies.get(languageKey)
export const setLanguage = (language) => Cookies.set(languageKey, language)

i18n模块关键点

引入 vant 内置默认语言包:
import enUS from "vant/es/locale/lang/en-US"
import zhCN from "vant/es/locale/lang/zh-CN"
......
引入项目业务组件语言包:
import enUsLocale from "./en_US"
......
语言包整合成 messages 对象然后添加到 i18n 实例中,导出的 i18n 实例里设置的 locale 属性仅设置组件内置的语言显示,业务组件语言显示需要使用 vant导出的 Local.use 方法进行切换。

第二步:把 i18n 挂载到 Vue 实例

main.js 里引入 i18n 模块,添加到 Vue 实例中。

import Vue from "vue";

import "@/registerServiceWorker";
import App from "@/App.vue";
import router from "@/router";
import store from "@/store";
import i18n from '@/lang';

import 'amfe-flexible';

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  i18n,
  render: h => h(App)
}).$mount("#app");

第三步:语言切换组件逻辑

逻辑代码如下:

<template>
  <van-popup
    v-model="showPicker"
    v-bind="popupConfig"
  >
    <van-picker
      show-toolbar
      item-height="1rem"
      swipe-duration="300"
      :title="$t('langSelect.pickerTitle')"
      :columns="langs"
      :default-index="defaultIndex"
      @confirm="onConfirm"
      @cancel="onClose"
    />
  </van-popup>
</template>

<script>
import { Popup, Picker, Toast, Locale } from 'vant';
import { setLanguage } from "@/utils/cookies";

export default {
  name: "LangSelect",
  components: {
    [Popup.name]: Popup,
    [Picker.name]: Picker,
    [Toast.name]: Toast
  },
  props: {
    popupConfig: {
      type: Object,
      default: () => ({
        overlay: true,
        position: 'bottom',
        duration: 0.3,
        closeOnPopstate: true,
        transitionAppear: true,
        safeAreaInsetBottom: true
      })
    }
  },
  data() {
    return {
      langs: [
        {
          text: '中文(简体)',
          value: 'zh-CN'
        },
        {
          text: '中文(繁体)',
          value: 'zh-TW'
        },
        {
          text: 'English',
          value: 'en-US'
        },
        {
          text: '日本語',
          value: 'ja-JP'
        },
        // {
        //   text: 'Español',
        //   value: 'en-US'
        // },
        // {
        //   text: '한국어',
        //   value: 'en-US'
        // },
        // {
        //   text: 'Italiano',
        //   value: 'en-US'
        // }
      ]
    };
  },
  computed: {
    showPicker: {
      get() {
        return this.$store.getters.langPicker;
      },
      set(val) {
        this.$store.dispatch('app/toggleLangPicker', val);
      }
    },
    defaultIndex() {
      return this.langs.findIndex(item => item.value === this.$i18n.locale) || 0;
    }
  },
  methods: {
    onConfirm({ value }) {
      // Vant basic
      Locale.use(value, this.$i18n.messages[value]);
      // Business component
      this.$i18n.locale = value;
      // Cookie
      setLanguage(value);
    },
    onClose() {
      this.$store.dispatch('app/toggleLangPicker', false)
    }
  }
};
</script>
语言包在组件中的使用要点:
  • 进行到这一步,在 template 中使用 $t('langSelect.pickerTitle') 就已经可以获取到自己设置的语言包了,逻辑代码中一样使用 this.$t('langSelect.pickerTitle') 即可拿到。
  • 我代码里使用的是 Vant 的 Popup + Picker 封装的公用组件,需要注意语言切换的时候需要同时切换业务组件和内置组件的语言包,即使用:
    Local.use('xxx', {...})
    this.$i18n.locale = 'xxx' || 'en-US'

效果图:
switch language

OK,vue + vant 的国际化到这就 over 了,对上述功能点有疑惑或者有更好的建议,欢迎留言~~

Logo

前往低代码交流专区

更多推荐