为何称之为 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 - 单文件组件