国际化 对应的英文单词为 Internationalization,又称 **i18n
**:
i
为单词的 【第一个】 字母18
为 【**i
和 n
之间**】 单词的个数n
代表这个单词的 【最后一个】 字母如果你的项目是 Vue
,那么相信你在实现国际化功能时,也必不可少的会使用到 **vue-i18n
**[2] 这个库,接下来本文也是通过这个库搭配 Vue
实现最基本的国际化功能,但关注点并不是如何使用这个库,而是在实现的过程中思考 可优化的点。
这里就不再多余演示 demo
项目的创建过程了,并且文中只演示最基本的 中英文 切换,好了现在直奔核心吧!
05873B02.jpg
熟悉的命令:npm install vue-i18n \-S
image.png
src
目录下创建 language
目录用于保持和语言切换相关的内容language
目录下创建 lang
目录用于保存不同语言的映射关系,如中文对应 zh.js
、英文对应 en.js
等language
目录下创建 index.js
作为默认导出,并在其中创建 i18n
对象import { createI18n } from "vue-i18n"; import zh from './lang/zh'; import en from './lang/en'; const i18n = createI18n({ legacy: false, locale: "zh", // 初始化配置语言 messages: { zh, en, }, });
export default i18n; 复制代码
### main.js 注册 i18n
内容非常简单,直接上代码:
```js
import { createApp } from "vue";
import i18n from "./language";
import store from "./store";
import App from "./App.vue";
createApp(App)
.use(store)
.use(i18n)
.mount("#app");
复制代码
实际上在通过 use(i18n)
时,会调用 i18n.install()
方法,大概内容如下:
通过 app.provide(app.__VUE_I18N_SYMBOL__, i18n)
将 i18n
对象提供给应用中的所有后代组件可通过 inject
注入
通过 app.config.globalProperties.xxx = xxx
的方式为应用添加 全局属性/方法,实际上是对 Vue2
中 Vue.prototype
使用方式的一种替代
常见全局属性,如 $i18n
通过 app.config.globalProperties.$i18n = i18n
添加到全局
常见全局方法,如:$t, $rt, $d, $n, $tm
通过 Object.defineProperty(app.config.globalProperties,
$${method}, desc)
添加到全局
通过 aplly(...)
方法注册常用的 全局指令 v-t
和 全局组件 i18n
等
在根组件卸载时移除/释放 i18n
相关内容
const unmountApp = app.unmount;
app.unmount = () => {
i18n.dispose();
unmountApp();
};
复制代码
vue-devtools
的相关插件假设需要渲染如下数据对应的列表,并且要实现国际化:
const data = [
{
url: vueImg,
title: 'Vue',
describe: '渐进式 JavaScript 框架'
},
{
url: reactImg,
title: 'React',
describe: '用于构建用户界面的 JavaScript 库'
},
{
url: angularImg,
title: 'Angular',
describe: '现代 Web 开发平台'
},
{
url: nodeImg,
title: 'Node',
describe: 'Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时'
},
{
url: webpackImg,
title: 'Webpack',
describe: 'webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具'
},
];
复制代码
对应 App.vue
组件模板内容如下:
<template>
<button class="btn" @click="changeLang">{{ $t("中/英") }}</button>
<List :data="data" />
</template>
复制代码
对应的页面效果如下:
image.png
在 lang/zh.js
文件中:
export default {
"渐进式 JavaScript 框架": "渐进式 JavaScript 框架",
"用于构建用户界面的 JavaScript 库": "用于构建用户界面的 JavaScript 库",
"现代 Web 开发平台": "现代 Web 开发平台",
"Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时":
"Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时",
"webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具":
"webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具",
"中/英": "中/英",
};
复制代码
在 lang/zh.js
文件中:
export default {
"渐进式 JavaScript 框架": "Progressive JavaScript framework",
"用于构建用户界面的 JavaScript 库":
"JavaScript library for building user interface",
"现代 Web 开发平台": "Modern web development platform",
"Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时":
"Node.js is a JavaScript runtime based on the chrome V8 engine",
"webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具":
"Webpack is a static module packaging tool for modern JavaScript applications",
"中/英": "Chinese / English",
};
复制代码
<List />
组件中进行翻译处理翻译处理可通过如下方式处理:
$t(...)
方法v-t
指令<i18n-t></i18n-t>
组件这里选择第一种,因为它更灵活,能使用的范围也更广,指令和组件形式限定在了 template
中:
1.gif
基于以上简单的例子,已经能够实现了国际化切换功能,但其中需要考虑的优化点还不少,下面的内容仅属于 抛转引玉,不一定全面。
05F51BEA.jpg
现在很明显的一点,就是 zh.js、en.js
文件中用于映射的 key
太长了,导致整个文件看起来会很多、很乱,因此我们可以将对应的 key
进行精简,如下:
// zh.js
export default {
"Vue 简介": "渐进式 JavaScript 框架",
"React 简介": "用于构建用户界面的 JavaScript 库",
"Angular 简介": "现代 Web 开发平台",
"Node 简介": "Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时",
"Webpack 简介":
"webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具",
"中/英": "中/英",
};
// en.js
export default {
"Vue 简介": "Progressive JavaScript framework",
"React 简介": "JavaScript library for building user interface",
"Angular 简介": "Modern web development platform",
"Node 简介": "Node.js is a JavaScript runtime based on the chrome V8 engine",
"Webpack 简介":
"Webpack is a static module packaging tool for modern JavaScript applications",
"中/英": "Chinese / English",
};
复制代码
那么对应到外部传入需要渲染的数据源 data
就可以简写为:
const data = [
{
url: vueImg,
title: "Vue",
describe: "Vue 简介",
},
{
url: reactImg,
title: "React",
describe: "React 简介",
},
{
url: angularImg,
title: "Angular",
describe: "Angular 简介",
},
{
url: nodeImg,
title: "Node",
describe: "Node 简介",
},
{
url: webpackImg,
title: "Webpack",
describe: "Webpack 简介",
},
];
复制代码
另一种精简方式就是将
key
用对应的类似于 变量命名 的方式来定义,但我个人不是很喜欢这种方式,首先在语义上很难直接读出相关信息,而且很难用一两个英文单词去概括文字内容,而且在后期需要排查对应问题并需要定位tmeplate
时是极其不方便.
上述的翻译文件是 .js
文件,因此,为了能够让其能被其他文件导入,我们不得不在文件中使用 export defualt
或 export
将对应文件内容向外导出,但其实我们可以将 .js
文件转换为 .json
文件直接使用,如下:
在实际项目中翻译的内容通常是由业务专门找对应的翻译人员提供的,而真正到了开发者手中往往就是一个 excel
类型的表格文件,如果我们使用的是前面的纯 json
方式,免不了要自己一个一个从表格中复制对应的内容到我们对应的 .json
文件中,而且是分别填充到 zh.json
和 en.json
中,值得注意的是现在才是仅支持两个国家的语言,如果后续支持的国家变多,那么手动复制的方式岂不是要
因此,最好的做法是我们根据业务方提供的表格自动转成 json
格式的数据,避免不必要的手动操作,用命令帮我们处理这个内容:
npm install xlsx-to-json
excel2json.js
文件中,基于第三方库简单封装即可 const xlsx2json = require("xlsx-to-json");
const path = require("path");
xlsx2json(
{
input: path.join(__dirname, "./i18n.xlsx"),
output: path.join(__dirname, "./i18n.json"),
},
function (err, result) {
if (err) {
console.error(err);
} else {
console.log(result);
}
}
);
复制代码
i18n
配置的入口文件 src\language\index.js
import { createI18n } from "vue-i18n";
import i18njson from "./i18n.json";
// 动态获取 message 信息
function getMessage() {
const messages = { zh: {}, en: {} }; i18njson.forEach(({Short, Chinese, English}) => { messages.zh[Short] = Chinese; messages.en[Short] = English; }); return messages; }
const i18n = createI18n({ legacy: false, locale: "zh", // 初始化配置语言 messages: getMessage(), });
export default i18n; 复制代码
- 提供 `i18n.xlsx` 文件作为数据源
![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/48e8dc4d4cf8411e9884d42f1f4b9728~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp?)
- 在 `package.json` 问文件中添加对应转换命令
```js
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"i18n": "node ./src/language/excel2json.js"
}
复制代码
具体效果如下:
上面已经将对应的翻译包从 *.xlsx
转成了 *.json
的形式,这样一定程度上能减少重复劳动力,但在 复用/协作 方面还是不够理想,因此可以从更高的维度将这整个内容升级到 i18n
系统,并提供对应的翻译包上传、自动解析、去重、添加命名空间等功能,再加上对应的列表管理功能,重点是可供多人员、多系统进行 复用/协作,对前端来讲就可以通过 接口 获取对应的翻译包数据,也能减少前端最终构建产物的体积。
06A99BDD.gif
什么叫重复的内容呢?其实很简单,比如有个文字内容为 确认 按钮,它在 A
页面需要翻译为 Confirm
,它在 B
页面需要翻译为 OK
,而它的中文内容就是 **确认
**,意味着它对应的数据内容为:
[
{ "Short": "确认", "Chinese": "确认", "English": "Confirm" },
{ "Short": "确认", "Chinese": "确认", "English": "OK" }
]
复制代码
但这样其实是不行的,这样最终会被后面的内容覆盖掉,即 A、B
页面最终的翻译内容都为 OK
,因为数据中的 Short
其实就是最终的不同语言映射的 key
,如下:
const messages = {
zh: {
"确认": "确认",
"确认": "确认"
},
en: {
"确认": "Confirm",
"确认": "OK"
}
};
复制代码
既然这样,那么其实我们只要为不同的翻译内容设置不同的 Short
值即可,如下:
[
{ "Short": "确认1", "Chinese": "确认", "English": "Confirm" },
{ "Short": "确认2", "Chinese": "确认", "English": "OK" }
]
复制代码
这样变动小,并且也没有丢失掉原本的语义。
由于不同语言的表现形式不同,内容长度也不一致,因此在前端进行展示时,就必须要考虑到最终的显式问题,否则一旦切换语言环境那么一定会导致页面的布局展示出现问题,处理方式无非几种:
允许文字内容换行展示,在文字发生换行时,要通过 CSS
设置按完整词换行
不允许换行的,就要控制固定宽度,超出部分打点展示,鼠标移入展示全部内容等
单独为不同语言环境设置样式,具体还是得看展示需求,如需要考虑不同语言环境下文字的对齐方式、文字间距等
针对难以处理的翻译内容,可以通过和业务沟通是否可以替换翻译内容、缩减文字长度等等
06C8791C.png
一个项目的国际化不可能都是前端来实现的,一些接口动态返回的内容也是需要后端去处理的,通常接口的请求头中会存储一个用于标识当前页面语言环境的字段,然后再决定返回给前端页面的具体内容。
06D25789.jpg
基于前面处理的国家化切换功能,本身是会基于 vue
的响应式来切换翻译内容的,即不会刷新页面,因此在切换对应翻译内容后,同样需要修改后续接口请求头中的语言环境。
但这样还是有问题的,已经通过接口返回的数据内容,此时没有办法切换成对应的翻译内容,因为当前的国际化切换是基于页面的变动,但基于接口变动的部分还没重新请求获取新的内容,那怎么处理呢?
以上内容是基于国际化功能的一点思考,文中对应的思考点是笔者自己在项目中遇到的点,并不一定适合所有项目,当然也期待评论区给出更多、更好的方案。
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/GN41pMX6dBSlha5zp091kw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。