构建优秀的多语言应用
Build multilingual-ready apps
2024年6月10日
一句话判断
如果你的 App 有任何非英语用户(基本上就是所有 App),这场 Session 提供的几个”一行代码修 bug”方案值得立刻加进你的代码库。
这场 Session 讲了什么
Apple 在 iOS 18 推出了多项多语言增强,包括全新的 Multilingual Keyboard(多语言键盘,无需手动切换即可输入多种语言)、Live Text 对阿拉伯语的支持、以及 10 种新的印度语系数字支持。但这场 Session 的核心不在这些系统功能,而在于教开发者如何避免多语言场景下的常见 bug。
Session 分三个部分——输入(Input)、显示(Display)、本地化(Localization)——通过三个来自不同地区的朋友的故事,逐个拆解真实场景中多语言支持容易翻车的地方。从中文输入法 marked text 和自动补全的冲突,到印地语搜索结果中文字断裂的问题,再到乌尔都语渲染崩坏,每个问题都配有简单直接的修复方案。
值得深挖的点
marked text 与自动补全的冲突
中文和日文等语言使用输入法时,用户打的拼音在确认候选词之前会显示为带下划线的”marked text”。很多 App 在实现 inline autocompletion 时会在每次按键时修改文本内容——这直接打断了输入法的工作流程。修复方式很简单:在修改文本之前检查 markedTextRange 是否为空。如果存在 marked text,就不动 inline 文本,但仍然可以基于当前输入进行搜索并在其他位置(比如 table view)显示建议。Spotlight 就是这么做的:它在你输入拼音时实时更新搜索建议列表,但只在确认候选词后才替换 inline 文本。
这个 bug 的根源在于开发者对 IME 工作机制理解不足。CJK 语言用户在你的 App 里遇到打字被中断、候选词消失的问题,大概率就是这里出了错。
localizedStandardRange 的 iOS 18 升级
很多语言的同一句话有多种合法拼写方式。英语里大小写不敏感搜索是标配,但印地语、德语等语言的拼写变体规则要复杂得多。iOS 18 对 localizedStandardRange API 做了大幅升级:现在支持跨拼写规范的匹配,也支持跨数字系统的匹配(比如天城文数字匹配阿拉伯数字)。这意味着开发者只需调用这一个 API,就能让搜索结果覆盖各种合法的拼写变体,而不是强迫用户精确输入。
代码片段
为每个对话记住键盘语言
场景:让 App 记住用户在不同对话中使用的语言,避免每次手动切换键盘。
// 重写 UIResponder 的 textInputContextIdentifier
// 返回一个唯一标识符(比如对话 ID)
override var textInputContextIdentifier: String? {
return "conversation-\(conversation.id)"
}
坑:不实现这个方法的话,系统无法区分不同上下文的输入语言偏好。
安全处理 inline autocompletion
场景:在输入法使用 marked text 的语言(中文、日文等)中显示自动补全。
// 检查是否存在 marked text
if let markedTextRange = textView.markedTextRange,
textView.offset(from: markedTextRange.start, to: markedTextRange.end) > 0 {
// 有 marked text,不要修改 inline 文本
// 但可以基于当前文本做搜索,在其他位置显示建议
} else {
// 没有标记文本,安全地修改文本显示自动补全
updateInlineCompletion()
}
坑:在 marked text 存在时修改文本会导致输入法候选词消失,用户体验极差。
用颜色代替粗体高亮搜索结果
场景:高亮搜索匹配文本时,避免印地语等语言的文字断裂。
// 不要用粗体(会导致某些语言文字断裂)
// 用颜色属性来高亮
let attributedString = NSMutableAttributedString(string: fullText)
attributedString.addAttribute(.foregroundColor,
value: UIColor.systemBlue,
range: highlightRange)
坑:粗体和常规字重在技术上是不同字体,某些语言的字符在不同字体间无法正确连接,导致文字看起来”断开了”。
最佳实践
已有项目:立刻检查三个地方——搜索是否用了 localizedStandardRange(而不是 range(of:))、自动补全是否正确处理了 marked text、搜索高亮是否用了粗体而不是颜色。这三个改动量极小,但能立刻改善 CJK 和印度语系用户的体验。
新项目:从第一天就把 TextKit 2 作为文本渲染引擎。Session 明确提到 TextKit 2 是 Apple 的”下一代文本引擎”,能确保像乌尔都语这样的 Nastaliq 脚本正确渲染。同时,斜体(italicization)在很多语言中不存在对应概念,不要在多语言场景中依赖斜体来传达信息差异。
还有什么值得关注
- iOS 18 的 Multilingual Keyboard 支持韩语和英语同时输入,无需手动切换,这是第一个 multiscript typing 体验。
- 斜体在 10 种语言的”你好”中只有 3 种产生了视觉变化,其余 7 种完全无效——多语言场景慎用斜体。
inputAccessoryView和keyboardLayoutGuide在处理手写键盘拉高时行为不同,前者会把 view 固定在键盘上方(硬件键盘时在屏幕底部),后者则提供更灵活的布局控制。