Respondo 诞生于迪拜,而这个事实对产品的塑造,超过了我们做出的任何一项路线图决策。这里的一条客服队列,可能同时承载着一位用阿拉伯语书写的客户、另一位用英语、第三位用印地语、第四位用乌尔都语的客户——而且往往就在同一个小时之内。这款产品从来就不存在这样一个版本:把某一种语言当作默认,而把其余语言当作翻译。三十多种语言,包括那些从右到左的语言,必须是根基,而不是我们日后加上去的一层。
事实证明,这道约束反倒让一切变得清晰。当多语言并非可选项时,许多在“英语优先”的产品里看似合理的捷径,就都暴露出自己其实是死胡同。以下就是我们在 AI 与界面两端,为那个现实而构建时所学到的东西。
翻译不等于理解
那个诱人的架构是一条流水线:拿到进来的消息,通过一个翻译 API 把它译成英语,用你的英语模型处理它,生成一条英语回复,再把它译回去。它便宜,搭建起来又快,可它偏偏在客服工作赖以成立的那些情境中失灵。
客户对话中密布着上下文,而通用翻译会把它们碾平。俚语、习语、礼貌的语域、特定领域的术语,全都会在这一来一回中被磨去棱角。一个经典的例子,是某个含义有分支的单词:一位客户在零售语境下询问“return”,想问的是把商品退回去;同一个词在金融语境下,说的却是投资收益。翻译—处理—翻译的做法会丢失线索,因为等到英语模型看到它时,那个用于消歧的上下文早已被搅烂。
Respondo 转而采用针对具体语言的模型。一条阿拉伯语消息,会以阿拉伯语被原生地理解和回答,从不经过英语这个中间表示。那些真正要紧的区别——语气、语域、一个多义词的正确含义——都是在它们实际栖身的那种语言里被捕捉到的。这,就是一条“技术上正确”的回复与一条“母语者一眼就认出流利地道”的回复之间的区别。
当界面翻转过来
在模型里处理好这些语言,只是问题的一半。另一半是界面,而从右到左的语言,正是大多数设计体系悄然崩溃之处。
支持阿拉伯语和希伯来语,绝不只是翻译字符串那么简单。整个布局都要反转。文本向右对齐。阅读顺序从右向左,这意味着一段对话的视觉流向、返回按钮的位置、箭头该指向的方向——统统都要镜像。一个把从左到右的假设烘焙进固定位置里的设计,无法“翻译”成 RTL;它会直接崩坏。
微妙之处在于,并非一切都会翻转。这正是那些团队发现了 CSS 的 direction 属性、便以为大功告成时,一头栽进去的陷阱。
- 布局、文本对齐和阅读顺序 会镜像。在英语里位于左侧的侧边栏,在阿拉伯语里就该在右侧。
- 带方向性的图标会继承这种翻转。 一个“回复”箭头或一个“下一步”的尖角符号,必须指向另一边,因为它的含义本身就是有方向的。
- 本质上就是从左到右的内容,则不会翻转。 电话号码、拉丁字母的品牌名、代码片段和 URL,无论周围是什么语言,都从左向右阅读。把它们镜像过来,你就制造出了一堆胡话。
要靠人手、一个组件一个组件地、在整款产品的范围里把这件事做对,恰恰是那种随着产品成长便无从保持一致的任务。所以,我们没有靠人手去做。
基于约束,而非基于位置
让 RTL 变得可持续的那个决定,是不再用绝对位置来描述我们的组件,转而用关系来描述它们。
一个基于位置的组件会说“这个标签坐落在距离左边缘 16 像素处”。这条指令在布局一翻转的那一刻就错了。一个基于约束的组件则会说“这个标签坐落在这一行的起点,在内容开始之前留出 16 像素的间距”。如此一来,“起点”就会自动地在英语里解析为左侧、在阿拉伯语里解析为右侧,而同一份组件定义无需一个条件判断,就能在两个方向上都正确渲染。
我们借助浏览器自身的逻辑属性来表达这一点——那套以*起点*和*终点*、而非*左*和*右*来思考,以*行内*和*块*、而非水平和垂直来思考的现代 CSS。一个这样编写的组件,既不知道、也不在乎自己正朝哪个方向渲染。方向在根节点处被设定一次,其下的每一个组件都随之适配。
回报会不断累积。增加下一种 RTL 语言几乎不花什么成本,因为布局逻辑从一开始就没有被绑死在某个特定方向上。一个建立在共享基元之上的新组件,默认就在两个方向上都正确——工程师得特意绕远路,才能把它弄坏。
给文本留出舒展的空间
最后一条经验最不起眼,却最常被忽视:文本长度在各种语言之间差异悬殊,而一个只见过英语的布局,会在那些放不下的语言面前裂开。
同一个短语,在德语里可能要长上 30%,在中文里会以一套全然不同的字符集抵达——寥寥几个字就承载了英语需要一整句话才能表达的意思,或者在阿拉伯语里需要更多的垂直空间,来容纳那些位于字符上下方的变音符号。一个按英语单词“Send”来设定尺寸的按钮,一旦装进更长的译文,转瞬之间就会截断或溢出。
我们的组件从一开始就假定:它们并不知道自己的文本会有多长。它们随内容一同生长,优雅地换行,从不依赖某个字符串恰好是某个特定长度。这是一条不起眼的纪律,却能省下日后上千次一次性的布局修补——而且,正如方向处理一样,它属于那种你若从第一天起就把它构建进去便几近免费、事后再来加装则代价高昂的事情。
贯穿始终的那条线
上述每一个决定,都与同一个理念押着韵:多语言不可能是一项你事后添加的功能,因为一款单语言产品的种种假设,会一直伸进模型、布局乃至每一个具体组件之中。以英语优先来构建,你就得用产品余下的整个生命,去为那些假设渗漏之处打补丁。从一开始就为三十种语言而构建,那第三十一种便几近免费。身处一个客户每天讲十几种语言的地方,并没有让这件事变得更难——它让“悄无声息地做错”变成不可能,而这,正是设计时所能拥有的最好的一种约束。