对国际化 i18n 项目的一点思考

发表于 2年以前  | 总阅读数:348 次

国际化是什么?

国际化 对应的英文单词为 Internationalization,又称 **i18n**:

  • i 为单词的 【第一个】 字母
  • 18 为 【**in 之间**】 单词的个数
  • n 代表这个单词的 【最后一个】 字母

如果你的项目是 Vue,那么相信你在实现国际化功能时,也必不可少的会使用到 **vue-i18n**[2] 这个库,接下来本文也是通过这个库搭配 Vue 实现最基本的国际化功能,但关注点并不是如何使用这个库,而是在实现的过程中思考 可优化的点

实现基本国际化功能

这里就不再多余演示 demo 项目的创建过程了,并且文中只演示最基本的 中英文 切换,好了现在直奔核心吧!

05873B02.jpg

集成 vue-i18n

安装依赖

熟悉的命令:npm install vue-i18n \-S

配置 vue-i18n

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 的方式为应用添加 全局属性/方法,实际上是对 Vue2Vue.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 目录下映射关系

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

优化 i18n 配置

基于以上简单的例子,已经能够实现了国际化切换功能,但其中需要考虑的优化点还不少,下面的内容仅属于 抛转引玉,不一定全面。

05F51BEA.jpg

优化翻译文件中的 key

现在很明显的一点,就是 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 转 .json

上述的翻译文件是 .js 文件,因此,为了能够让其能被其他文件导入,我们不得不在文件中使用 export defualtexport 将对应文件内容向外导出,但其实我们可以将 .js 文件转换为 .json 文件直接使用,如下:

excel 转 .json

在实际项目中翻译的内容通常是由业务专门找对应的翻译人员提供的,而真正到了开发者手中往往就是一个 excel 类型的表格文件,如果我们使用的是前面的纯 json 方式,免不了要自己一个一个从表格中复制对应的内容到我们对应的 .json 文件中,而且是分别填充到 zh.jsonen.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"
  }
复制代码

具体效果如下:

升级为 i18n 系统

上面已经将对应的翻译包从 *.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/ySZYN3-md6YRwuDDJnELtQ

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237226次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8062次阅读
 目录