解析 Vue I18n?

2,916 阅读1分钟

为何称之为 Internationalization ?为何写作 i18n ?

国际化是一种设计过程,可以确保产品(通常是软件应用程序)可以适应各种语言和地区,而无需对源代码进行修改。

有时写作 i18n ,其中18代表国际化中i和n之间的18个字符。

类似 a11y,可访问性 accessibility

优点:

  • 使软件更容易适应多种语言环境
  • 减少本地化的时间和成本
  • 产品所有版本使用单一国际化源代码
  • 维护简单
  • 改进代码质量和代码架构
  • 降低产品多个版本的成本
  • 遵守国际标准

基本实现思路

// @/components/HelloWorld.vue
<template>
  <div class="hello">
    <h2>{{ localised("hello") }}</h2>
    <h2>{{ localised("goodbye") }}</h2>
    <button @click="activeLocale = 'en'">English</button>
    <button @click="activeLocale = 'es'">Spanish</button>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      activeLocale: "en",
      messages: {
        en: {
          hello: "Hello",
          goodbye: "Goodbye",
        },
        es: {
          hello: "Hola",
          goodbye: "Adiós",
        },
      },
    };
  },
  methods: {
    localised(key) {
      return this.messages[this.activeLocale][key];
    },
  },
};
</script>

配置

一般使用,直接参考官方文档即可,以下记录自己在配置单文件组件中出现的问题:

安装:

yarn add vue-i18n

修改配置文件:

// @/main.js
import Vue from "vue";
import App from "./App.vue";
+ import i18n from "./i18n";

Vue.config.productionTip = false;

new Vue({
+	i18n,
  render: h => h(App)
}).$mount("#app");
// @/i18n.js
import Vue from "vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);

function loadLocaleMessages() {
  const locales = require.context(
    "./locales",
    true,
    /[A-Za-z0-9-_,\s]+\.json$/i
  );
  const messages = {};
  locales.keys().forEach(key => {
    const matched = key.match(/([A-Za-z0-9-_]+)\./i);
    if (matched && matched.length > 1) {
      const locale = matched[1];
      messages[locale] = locales(key);
    }
  });
  return messages;
}

export default new VueI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || "en",
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
  messages: loadLocaleMessages()
});
// @/locales/en.json
{
    "message": "hello i18n !!"
}
// @/components/HelloWorld.vue
<template>
  <div class="hello">
    <p>{{ $t("hello") }}</p>
  </div>
</template>

<i18n>
{
  "en": {
    "hello": "hello worldddd!"
  },
  "es": {
    "hello": "Hola"
  }
}
</i18n>

<script>
export default {
  name: 'HelloWorld'
}
</script>

以上配置完运行时,会在控制台提示

> [vue-i18n] Value of key 'message' is not a string or function !
> [vue-i18n] Fall back to translate the keypath 'message' with root locale.

根据官网文档提示

npm i --save-dev @kazupon/vue-i18n-loader

但并未生效,应该是加载

yarn add @intlify/vue-i18n-loader vue-cli-plugin-i18n

则可正常使用 单文件组件

输出 i18n 报告的两种方法

// package.json 文件的 script 中添加
"scripts": {
	"i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'"
},
// i18n.js -- package.json 同级目录创建
/* eslint-disable @typescript-eslint/no-var-requires */
const { exec } = require("child_process");
const cmd =
    'npx vue-cli-service i18n:report --src "./src/**/*.?(vue)" --locales "./src/locales/**/*.json"';
exec(cmd, (error, stdout, stderr) => {
    if (error) {
        console.log(`error: ${error.message}`);
        return;
    }
    if (stderr) {
        console.log(`stderr: ${stderr}`);
        return;
    }
    console.log(`${stdout}`);
});
// package.json 文件的 script 中添加
"scripts": {
	"i18n:report": "node i18n.js"
},

添加语言切换

// @/components/HelloI18n.vue
<template>
  <div>
    <p>{{ $t("hello") }}</p>
    <p>{{ $t("goodbye") }}</p>
    <button @click="setLocale('en')" class="button">{{ $t("english") }}</button>
    <button @click="setLocale('es')" class="button">{{ $t("spanish") }}</button>
    <button @click="setLocale('de')" class="button">{{ $t("german") }}</button>
  </div>
</template>

<script>
export default {
  name: "HelloI18n",
  methods: {
    setLocale(locale){
      this.$i18n.locale = locale;
    }
  }
};
</script>
// @/locales/en.json
{
  "english": "English",
  "german": "German",
  "goodbye": "goodbye",
  "hello": "Hello",
  "spanish": "Spanish"
}

// @/locales/es.json
{
  "english": "inglés",
  "german": "alemán",
  "goodbye": "Adios",
  "hello": "Halo",
  "spanish": "español"
}

// @/locales/de.json
{
  "english": "Englisch",
  "german": "Deutsche",
  "goodbye": "Auf wiedersehen",
  "hello": "hallo",
  "spanish": " Spanisch"
}

对 i18n 组件测试

参考文献:

[1]. What is Internationalization?
[2]. What is accessibility?
[3]. Yarn 安装 Vue I18n
[4]. Vue I18n - 单文件组件