即时通讯 SDK 的多语言界面开发实现步骤

即时通讯 SDK 的多语言界面开发实现步骤

去年这个时候,我接了一个海外社交产品的开发任务,甲方明确要求支持 12 种语言。说实话,刚开始我觉得这事儿挺简单的,不就是把文字翻译一下换成吗?真正上手才发现,这里面的坑远比想象的多。文本长度不一样导致界面错乱,阿拉伯语从右往左的排版让人崩溃,还有那些连字符、复数规则的处理,每一个都能让人熬秃头。

这篇文章我想把做多语言界面开发的一些实际经验和完整步骤分享出来,都是实操中踩出来的经验,希望能给正在做类似项目的同学一些参考。整个过程我会按照开发节奏来写,不是那种干巴巴的步骤罗列,而是带着场景和问题来讲。

一、开发前的准备工作

在做多语言界面之前,有几件事必须提前想清楚,不然做到一半再改成本会非常高。我第一次做多语言项目时就是吃了这个亏,没规划清楚就开始写代码,结果做到一半发现现有的架构根本不支持动态切换语言,整整重构了两周。

1.1 明确语言范围和优先级

不是所有语言都需要同等对待的。你需要先和业务方对齐:哪些是必须支持的必选语言,哪些是可选的。就像我们做声网的服务时,也会根据客户所在地区重点优化特定语言的体验。我的建议是先把目标市场的主流语言列出来,按照用户占比排个优先级。

这里有个小技巧:先把英语和中文这两种最长和最短的语言做进去,你会发现这两个极端能覆盖大部分布局问题。比如中文通常比较紧凑,英语相对较长,如果这两者你的界面都能撑住,其他语言基本不会出大问题。

1.2 技术方案的选择

多语言的技术实现方案主要有两种,我分别说下优缺点。第一种是资源文件分离,iOS 用 Strings 文件,Android 用 strings.xml,Web 端用 JSON,这种方式最成熟,各个平台都有官方支持。另一种是把所有翻译存在服务端,运行时动态拉取,这种适合需要频繁更新翻译或者想做 A/B 测试的场景。

我个人的经验是,如果你的产品不是那种需要天天改文案的类型,第一种方案就够了。但如果你的运营团队比较灵活,经常想小范围测试不同文案的转化率,那服务端方案会更合适。两种方案也可以结合用,核心文案走本地配置,运营文案走服务端下发。

顺便提一嘴,资源文件的命名规范最好提前定好。我们当时用的是语言缩写加地区编码的方式,比如 en-US、zh-CN、pt-BR,这样能区分同语言不同地区的差异。比如英式英语和美式英语在一些用词上是有区别的,虽然大部分场景可以忽略,但做精细了总是更好。

二、字符串资源的组织与管理

字符串资源是多语言界面的核心,这部分如果没做好,后面全是坑。我见过太多项目把所有字符串堆在一个大文件里,结果就是找不到、改不动、容易冲突。

2.1 分类策略

建议按照功能模块来拆分字符串资源文件。比如登录注册相关的放一个文件,个人设置相关的放另一个,聊天界面的再单独一个。这样做的好处太明显了:翻译同学不用在一万个字符串里找他要改的那条,开发者更新文案时也能快速定位。

我们来具体看个例子,聊天模块的字符串你可以这样组织:

分类 示例字符串 Key 说明
通用 chat_time_format 时间格式,如"14:30"
消息气泡 chat_text_message 文字消息前缀
操作菜单 chat_action_copy 复制菜单项
状态提示 chat_status_sending 发送中状态

这样做还有一个好处是便于统计每个模块的翻译工作量,有时候产品会问加一个功能需要多少翻译成本,你直接看对应文件有多少条就能估个大概。

2.2 复数形式的处理

英语的复数形式比较好处理,就两种:单数和复数。但俄语有三种,阿拉伯语更是能达到六种。很多初学者会忽略这个问题,导致出现"1 条消息"这种正确写法,但"5 条消息"后面却跟着个单数形式的词。

iOS 的做法是在字符串里定义多个形态,用竖线分隔:

"message_count" = "%d 条消息|%d 条消息"; // 竖线前面是单数,后面是复数

Android 的做法略有不同,它用 quantity 标签来包裹不同的形态,写起来稍微繁琐一点,但更严谨。比如俄语的配置大概是这样的:

<plurals name="message_count"><item quantity="one">%d сообщение</item><item quantity="few">%d сообщения</item><item quantity="many">%d сообщений</item></plurats>

这个问题一定要在开发初期就考虑到,因为复数规则是平台底层处理的,你的代码层面只需要根据数量传参就行。但如果早期没规划,后面再加复数支持等于重写一遍字符串调用逻辑。

2.3 占位符与参数顺序

不同语言的语序是不一样的。比如中文说"张给你发来一条消息",英语是"Zhang sent you a message",日语可能是"张さんからメッセージが届きました"。如果你的字符串里有多个占位符,直接按顺序替换可能会出问题。

比如这个字符串:"%1$s 邀请 %2$s 加入群聊"

在中文里这样写没问题,但翻译成日语时,动词在句子最后,可能需要调整占位符的顺序。最稳妥的做法是给每个占位符加上编号,这样翻译时可以根据语言习惯调整顺序,代码层面也能正确填充。

再强调一点,占位符的类型要对应好。数字就用 %d,字符串用 %s,浮点数用 %f,不要混用,不然某些语言环境下会崩溃或者显示乱码。

三、界面布局的适配策略

多语言不光是文字翻译的问题,界面布局也要跟着调整。中文可能两个字就把按钮占满了,翻译成德语可能需要两行。这就是为什么做多语言界面,不能只关注文案本身。

3.1 文本扩展的预留空间

我一般会留 30% 到 50% 的扩展空间。比如一个按钮,中文显示是两个字,翻译成英语可能需要十个字母,这时候如果按钮宽度写死,肯定会显示不全。Android 的 layout_width 用 wrap_content 是基础,更高级的做法是给 TextView 设置 minWidth。

还有一种情况是文本特别长的时候需要截断处理。比如一个标签,中文可能最多两个字,但芬兰语翻译可能特别长。这时候你要定义清楚截断策略:是尾部截断加省略号,还是中间截断,要不要考虑单词边界。

声网在服务全球客户时也遇到过类似问题,他们的做法是针对不同语言准备两套布局,一套适用于拉丁语系这些字母较短的语言,另一套适用于亚洲语言。极端情况下,文字特别长的语言会采用不同的字体大小或者行数限制。

3.2 列表项的高度自适应

聊天列表应该是多语言适配的重灾区。同一条消息,中文可能一行,德语可能需要两行甚至三行。如果列表项高度固定,就会出现文字被截断或者留白过多的问题。

解决方案是让列表项高度自适应内容。在 iOS 里 UITableViewCell 默认就是这样,Android 需要注意布局容器的选择。RelativeLayout 和 ConstraintLayout 都支持内容自适应,但 LinearLayout 如果设置了固定高度就不行。

测试的时候建议重点关注这几种场景:德语的超长单词、芬兰语的超长词汇、阿拉伯语从右往左的文字。最好能让翻译团队的native speaker帮忙看一下,他们能发现很多你意识不到的问题。

3.3 图标与文字的组合

有些图标里面自带文字,比如金额符号、箭头符号,这些在不同语言里可能不一样。比如货币符号,美元是 $,欧元是 €,日元是 ¥,这些符号的位置和间距也有差异。最好是把这些符号也做成可配置的,而不是写在图标里。

还有日期格式的显示,不同地区习惯的格式不一样。美国用 MM/DD/YYYY,欧洲用 DD/MM/YYYY,中国用 YYYY年MM月DD日。不要在代码里写死格式,要根据用户的语言环境动态选择。

四、RTL 布局的特殊处理

从右往左(RTL)的语言是多语言开发里的硬骨头。阿拉伯语、希伯来语、波斯语都是 RTL,这些语言的阅读习惯是从右到左,界面布局也需要相应翻转。

4.1 布局方向的自动切换

现代操作系统都支持 RTL 布局的自动适配。Android 从 4.2 开始原生支持,开发者只需要在布局文件中设置 android:layoutDirection="locale",系统会自动根据当前语言翻转布局。iOS 8 以后也有类似的支持。

但这里有个关键点:语义翻转和布局翻转是两回事。阿拉伯语的书籍是从右往左翻页,但页码仍然是左边小右边大自然增长。微信的聊天界面,消息气泡的位置会翻转,但时间戳的位置可能不需要翻转。

我的经验是先让系统做默认翻转,然后针对特殊控件再手动调整。比如返回箭头,RTL 模式下应该指向右边而不是左边,这时候需要单独处理。

4.2 混合内容的方向处理

最麻烦的情况是一个 RTL 界面里出现了 LTR 内容。比如一个阿拉伯语界面里有个英文单词,这个英文单词应该从左往右显示,还是跟随整体界面从右往左?答案是应该从左往右,不然阅读体验会很奇怪。

Android 和 iOS 都有对应的 API 来显式声明某段文字的方向。最简单的做法是在显示英文内容时,用对应的标签或者属性强制它从左到右显示。

还有一个坑是输入框。用户可能在阿拉伯语界面下输入英文,也可能在英文界面下输入阿拉伯语。输入法的光标方向、文本对齐方式都需要正确处理,不然用户会觉得很别扭。

4.3 镜像资源的处理

有些图标在 RTL 模式下需要镜像翻转。比如返回箭头, RTL 下应该指向右边而不是左边。分享图标、编辑图标可能也需要翻转。但像播放进度条、音量调节滑块这类控件就不应该翻转,它们表示的是物理量,不是方向。

判断一个图标是否需要镜像有个简单原则:如果图标的含义和方向相关,就需要翻转。比如"下一步"箭头是方向相关的,应该翻转;"设置"齿轮和方向无关,就不需要翻转。

五、字体与排版的细节

字体看起来是个简单问题,实际上有很多讲究。同一个字符在不同语言里可能长得不一样,比如阿拉伯语的字母在不同词里的形态会变化,这需要专门的字体支持。

5.1 默认字体的覆盖策略

系统默认字体不是对所有语言都友好的。比如 Android 的默认 Roboto 字体对中文的支持就一般,日语字符的显示也不够细腻。你需要为不同语言指定不同的字体文件。

做法是创建一个字体资源池,不同语言对应不同的默认字体。中文用支持中文的字库,阿拉伯语用专门优化过的 RTL 字体。字体文件不小,所以要注意资源加载的性能。

字体下载策略也要考虑周全。没必要让用户一次下载所有语言的字体,可以按需加载,用户切换语言时再去下载对应的字体包。这样可以节省安装包体积和用户流量。

5.2 行高与字间距的调整

不同语言对行高的需求不一样。中文通常行高可以紧凑一些,但日语和韩语可能需要更大的行高来区分连在一起的字符。阿拉伯语因为有元音符号的标注,可能需要额外的垂直空间。

如果你用的是固定行高,RTL 语言下可能出现文字和上下行的符号打架的情况。解决方案是让行高根据语言动态调整,或者在布局中预留足够的垂直 padding。

六、本地化测试的完整流程

测试是很多人容易忽视的环节。我见过太多产品翻译上线后才发现问题,不是翻译错了,就是界面显示异常。多语言测试需要一套完整的流程。

6.1 功能测试要点

功能测试要覆盖所有文案触点,不是点点就完事了。表单提交、错误提示、成功消息、推送通知、邮件模板,这些地方都要检查到。特别是那些不常走的异常分支,比如网络出错、权限被拒的提示,运营同学可能根本没想到要翻译。

还有变量替换的测试。确保每个占位符都被正确填充,数字格式、日期格式在每种语言下都正确。特别是那些复数形式的字符串,要用不同的数量去测试,确保复数规则生效了。

6.2 视觉测试关注点

视觉测试的重点是布局完整性。每一张截图都要检查:文字有没有被截断、按钮有没有被撑爆、列表项高度是否正常、图标有没有正确翻转。

建议制作一份各语言的截屏对比表,标记出有问题的界面,方便翻译团队和设计团队沟通。有时候翻译的文字风格和原有界面不搭,也可以在这个阶段发现。

6.3 真机测试与用户反馈

模拟器测试只能解决大部分问题,真机上还是会有差异。不同厂商对字体的渲染不一样,分辨率不同也会影响显示效果。尽量覆盖主流的设备型号。

上线后用户的反馈渠道要畅通。多语言用户遇到问题时,可能因为语言障碍不会主动反馈,你可以设置一个反馈入口,让用户方便地报告翻译错误或者显示问题。

写在最后

多语言界面开发这件事,做过一次和做过十次的经验是完全不同的。我第一次做完一个多语言项目后,回头看最初的代码,发现好多设计决策都不合理。字符串硬编码、布局宽度写死、占位符顺序混乱,这些都是血泪教训。

如果你正在准备做多语言项目,我的建议是:前期多花时间规划,别急着写代码。技术方案、资源结构、测试流程,这些想清楚了再动手。中途遇到问题不要硬凑解决方案,该重构就重构,一次性做好比后面修修补补强多了。

对了,找native speaker帮忙审阅非常重要。翻译公司的翻译质量参差不齐,有些明显是机器翻译的痕迹,让目标语言的母语者看一遍能避免很多尴尬。毕竟产品是给用户用的,用户觉得自然才是真的做对了。

上一篇即时通讯SDK的版本兼容性测试的自动化工具
下一篇 实时通讯系统的群聊成员禁言的解除提醒

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱:

工作时间:周一至周五,9:00-17:30,节假日休息
关注微信
微信扫一扫关注我们

微信扫一扫关注我们

手机访问
手机扫一扫打开网站

手机扫一扫打开网站

返回顶部