查看原文
其他

【第1538期】聊聊前端国际化文案该如何处理

ES2049 前端早读课 2019-06-26

前言

不知道读者里做海外的需求多么?今日早读文章由阿里@ES2049 Studio授权分享。

正文从这开始~~

背景

最近接到一个海外项目业务需求,项目最终会被来自不同国家的客户所使用,期望能让客户有一个良好的用户体验,因此前端需要适配国际化。

面临的挑战

乍一听,这个海外项目需求并没有什么特别的地方,似乎就多了一个国际化适配。但细细一想,事情可没这么简单,前端开发面临了很多新的问题。下面梳理一下国际化开发中通常会面临的挑战:

页面文案全部可配置

需要配置的文案大致有四种:label、placeholder、字段校验提示信息、超链接。

页面文案样式处理

文案样式需要特别注意,不同语言的文字,可能会有不同的表现。例如下面两张图所示:

英语(页面样式正常)

俄语(页面样式异常)

日期、数字格式处理
页面上展示日期或数量的地方,也是需要做国际化适配。

LTR/RTL
很多中东国家的语言习惯都是 RTL,可以尝试使用 direction 和 transform 来解决。

图片(banner)国际化
如果你想把国际化做的足够精细,那么图片国际化也是需要考虑的。

第三方 UI 组件
如果使用了第三方 UI 组件,如:elementUI、ant design UI 等,这些 UI 框架通常都宣称支持国际化,但支持的国际化语言数量有限,并不一定能满足业务需求。

前端开发工作量和后期维护成本激增
大量的文案需要被提取出来,被提取出来的文案最终会被合并到一个文件中去,如:en-US.json。这些工作如果通过手工完成,那么工作量会是非常巨大的。

国际化文案的处理思路

以上列举出了很多挑战,但实际上“页面文案处理”才是最主要的矛盾,因为它直接导致前端开发工作量和维护成本的激增。下面我们重点来讨论文案处理思路,其实从实现国际化的角度来看,jQuery、Vue、React 等都只是载体而已,实现思路都是相通的,因此国际化文案处理与具体的技术框架并不耦合。接下来将会抛出几种国际化文案处理思路,每种思路对生产力和生产关系的要求有高有低,姑且将其分别对应为石器时期、青铜时期、黄金时期。

石器时期

传统的国际化开发流程:前端开发到一定阶段,将文案提取到资源文件(通常为 en-US.json),然后将资源文件发送给翻译团队,翻译团队翻译出各国语言版本的文案,每种语言对应一个资源文件,最后将这些资源文件发回给前端开发人员,前端开发人员更新到自己本地。如下图所示:

适用场景

  • 页面上要提取的文案不多

  • 支持的国际化语言较少,比如:只需要支持中文和英文

  • 项目需求较固定,后期只做简单维护,不会新增大的需求

  • 分析

这是国际化开发的基本流程,“前端开发”和“翻译团队”是必不可少的两个节点,但它们相互之间依赖的太重。“提取文案”的过程本质上是在重复劳动,因此可以考虑由程序来完成。

  • 代码示例

  • App.js


import React, { Component } from 'react';
import { IntlProvider, FormattedMessage } from 'react-intl';
import qs from 'querystring';
import logo from './logo.svg';
import './App.css';
import DEFAULT_MESSAGES from './i18n/en-US.json';
const DEFAULT_LOCALE = 'en-US';
class App extends Component {
 state
= {
 messages
: DEFAULT_MESSAGES,
 
};

 componentWillMount
() {
 
const search = window.location.search.slice(1);
 
const params = qs.parse(search);
 
const locale = params.locale || DEFAULT_LOCALE;
 
const messages = require(`./i18n/${locale}.json`);
 
debugger;
 
this.setState({
   messages
,
 
});
 
}

 render
() {
 
const { messages } = this.state;
 
return (
   
<IntlProvider locale="en" messages={messages}>
   
<div className="App">
     
<header className="App-header">
     
<img src={logo} className="App-logo" alt="logo" />
     
<p>
       
<FormattedMessage
       id
="welcome"
       defaultMessage
={`Hello world!`}
       
/>
     
</p>
     
<a
       className
="App-link"
       href
="/?locale=zh-CN"
       rel
="noopener noreferrer"
     
>
       zh
-CN
     
</a>
     
<a
       className
="App-link"
       href
="/?locale=en-US"
       rel
="noopener noreferrer"
     
>
       en
-US
     
</a>
     
</header>
   
</div>
   
</IntlProvider>
 
);
 
}
}
export default App;

en-US.json

{
 
"welcome": "Hello world!"
}

青铜时期

前面分析了“提取文案”的过程本质上是在重复劳动,那我们看看有没有办法进行改进。我们可以先对比一下“无国际化需求”和“有国际化需求”时的前端开发流程。如图所示:

可以看出右边多了三个过程:

  • 将文案提取为变量

  • 为变量命名,要合乎其场景

  • 将变量和文案信息存到资源文件

这里我们提出一个期望或愿景:希望能像开发普通业务一样去开发有国际化需求的业务!

为了达成这一愿景,我们需要有一个工具:它能够扫描指定的文件,并能识别出文件中的字符串,然后能根据字符串的含义生成变量名,并用变量表达式替换掉原来的字符串,最后能够将提取出来的变量自动追加到资源文件中。

如何实现这样的工具?我们可以用 Babel 将js文件解析为一颗语法树,然后遍历并找出字符串节点,接下来调用 Google Cloud Translation API 将字符串翻译为英文,并以此作为变量名得到变量表达式,最后用变量表达式替换掉原来的文本即可。如下图所示:

幸运的是,i18n-pick 已经有那么点味道了~

分析

这是站在开发层面,对前端开发体验和开发效率提出的改进办法,将重复的事情交给程序去完成。

黄金时期

有了石器时期的生产方式作为铺垫,我们可以在此基础上继续做改进。既然“前端开发”和“翻译团队”之间依赖的太重,那我们可以在中间加一个节点“文案配置平台”。前端将提取的文案直接上传到“文案配置平台”,翻译团队直接在“文案配置平台”上进行文案翻译,前端直接从“文案配置平台”获取翻译后的最新文案。

文案配置平台应当具备的基本能力

  • 面向前端开发人员:文案录入、输出

  • 面向翻译团队:文案翻译、发布

  • 其他:文案版本控制

  • 适用场景

    • 有大量的国际化业务需求

    • 希望将其沉淀为通用能力平台,提升业务开发效率

    • 分析

    这是从架构层面对国际化开发方式进行优化和提效,一般大的互联网公司因为其自身业务的复杂度,都早已沉淀出很多的通用能力平台。

总结

以上每种思路都有各自适用的场景,实际生产中需要从开发成本、开发体验、后期维护、能力沉淀等多维度进行考虑。这篇文章旨在抛砖引玉打开思路,各位看官可以将自己的思路抛出来一起讨论

参考

  • Internationalization

  • 国际化 - 通用 LTR/RTL 布局解决方案

  • i18n-pick

  • Babel 插件开发指南

  • Google Cloud Translation API: Node.js Client

最后,推荐一个国际化全流程解决方案Kiwi,https://github.com/nefe/kiwi

kiwi 不仅仅一个软件国际化的代码库,而是国际化从设计到发布的整个流程的一整套解决方案。

kiwi 整体基于 kiwi-intl 国际化框架,实现与框架无关的语言切换功能。

在开发过程中,使用 kiwi linter 实现中文文案的批量自动提取,同时针对替换后的文案变量,在 VS Code 中显示对应的中文文案。当然你也可以全局搜索中文文案,跳转到对应的代码,很好的解决了国际化过程中由于中文文案缺失造成的开发体验问题。

在翻译过程中,可以使用 kiwi 命令行自动提取未送翻词汇,整理成 Excel 方便与翻译同学协作。针对翻译同学还没有返回翻译文案的期间,可以使用 kiwi 内置的支持 google 以及 多种翻译平台的自动翻译脚本,先临时翻译成对应语言,节省文案调整时间。

国际化文案翻译完成后,可以使用 kiwi 的命令行工具,一键导入到项目文件内。

kiwi 还提供了对应 TsLint 的插件,使用 TsLint 在开发过程中实时提醒未抽离文案,以及在代码提交的时候,拦截未国际化的代码提交。

关于本文
作者:@ES2049 Studio
原文:https://www.yuque.com/es2049/blog/crhazl

最后,为你推荐


【第1435期】国际化 - 通用 LTR/RTL 布局解决方案


【第1032期】前端国际化


他曾分享过


【第1477期】想写好前端,先练好内功


【第1443期】React 中同构(SSR)原理脉络梳理


【第1426期】代码优化策略 — Idle Until Urgent

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存