国际化和本地化您的应用程序,第3部分:技术挑战

尼克·布兰德
7月16日 · 11分钟阅读
图片由Michael Dziedzic.uns

在这一四部分教程中的第三部分中,了解如何解决语言的各种考虑和细微差别。这包括多个,可访问性,格式化日期和数字,以及更多!

请参阅本系列的第2部分这里

让Unicode引领潮流吧

2003年,Unicode联盟发布了称为项目的第一个主要版本公共区域设置数据存储库,缩短到CLDR,一个大规模的XML数据集,包括许多国际化,本地化和翻译特定数据和规则。自从以来,存储库已经成长,现在在撰写本文时达到主要版本39。一些事情由CLDR编码包括:

  • 语言名称的翻译
  • 地区和国家名称的翻译
  • 货币名称的翻译,包括单数/复数修改
  • 翻译工作日时代,一天中的一段时间,完整和简短的形式
  • 时区的翻译和时区的示例城市(或类似的城市)
  • 日历字段的翻译
  • 格式化/解析日期或一天中的时间的模式
  • 用于编写语言的示例套字符
  • 格式/解析号码的模式
  • 适应语言的单数、复数和序数短语的规则
  • language-adapted规则整理
  • 在传统数字系统中格式化数字的规则(如罗马数字亚美尼亚的数字等)。
  • 把数字拼成单词的规则
  • 规则音译脚本之间。它的大部分是基于BGN / PCGN皈依天主教

利用这些数据就像下载和解析XML一样简单,但是,依赖标准化的、cldr支持的库或api通常是有用的,例如大多数现代浏览器和最新版本的Node提供的Intl api(或某些类似的语言/平台特定于CLDR数据执行)。

Unicode联盟考虑的另一个问题是如何通过使用Grapheme集群,以便在保留有意义的文本块的同时,确定一组字符可以被分割的适当位置。仅这一点就可以构成一篇完整的文章,但可以这么说String.slice(…)如果您需要以任何原因手动操纵您的琴弦,就不够。

地区特定的格式

当然,每种语言环境都有处理特定数据格式化的独特方法。最常见的例子,也是你以前很可能遇到过的,是每种货币都使用一些特定的符号,这样一个要么.最重要的是,根据每个地区表示数字的方式,不同地区之间的货币格式也不同,这是很常见的。例如,让我们用Intl.numberformat.API检查几个数字:

货币格式的差异

当然,这适用于不仅仅是货币,还适用于类似的东西, OkCupid上到处都用它来表示两个用户之间的匹188bet金宝搏官网配百分比。以下是百分比本地化的例子:

百分比格式的差异

这些api非常强大,是最新浏览器的一部分(在最新的Node版本中也有)。它们还提供了格式化数字的方法,例如为某些地区使用不同的数字集,本地化距离/速度/度量,等等。

我们还应该确保在应用程序中正确地本地化其他内容,如日期、时间、相对时间,甚至列表:

利用INTL API的示例

还值得一提的是,在本地化值时经常被忽视的另一件事是,“按字母顺序排序”的概念会根据使用的语言而改变,正如给定语言中使用的符号会改变和简单。种类(...)默认情况下,肯定不会考虑区域设置。幸运的是,CLDR让我们再次覆盖提供校对规则因此,还可以本地化排序。这IntlAPI也暴露了一个排序器为这个目的。

当然,所有这些信息的最佳真实来源总是公共区域设置数据存储库的最新版本,并利用该数据源的任何API实现(例如IntlAPI)是确保为给定区域设置提供正确数据的好方法。

无障碍

可访问性是许多应用程序的核心特性,这可能是软件领域中最重要的主题之一,特别是在过去几年。Mozilla将可访问性定义为

可访问性是指让你的网站能够被尽可能多的人使用。我们传统上认为这是针对残疾人的,但使网站可访问的做法也有利于其他群体,如使用移动设备的人,或那些网络连接缓慢的人。

如果我们在脸上采取这个定义,那么我就会在这里有一个延伸,在那里.我们正致力于将我们的软件开拓整个人,以前有限或没有有意义的访问权限,并使其与这些人一起访问和相关。

对于开发者来说,这意味着我们还应该确保我们为确保应用程序的可访问性所做的所有工作应该与我们为应用程序的国际化所做的工作直接联系在一起。如果我们通过alt.咏叹调-*属性之类的东西,我们也应该确保它们被正确地翻译,这是很容易被忽视的。

此外,我们应该专注于,确保这些也是正确的本地化。确保我们的文档是正确标记的(例如,使用HTML是很重要的属性),以便其他软件(如易访问性辅助软件)可以知道该文档使用的是某种语言。至于手势,想象一下如果你习惯了从右到左的语言,比如阿拉伯语或希伯来语:你该如何正确定位“向左滑动”和“向右滑动”这样的功能呢?当然,这些都是源自西方经验的功能,而考虑如何将其应用于并非最初设计的布局和脚本是很有趣的。

API设计,重新设计?

本地化应该发生在哪里?

在应用程序中完成可本地化内容时,当用户向你的网络服务器或服务发出请求时,了解他们希望接收到的地点是非常重要的。尽管这是HTTP内容协商的一个特定特性,但可以抽象地跨各种协议应用具有统一方式的概念,即用户的语言环境代码可以在整个系统中传播。当然还有其他表示语言首选项的方法,最常见的方法可能是使用URL查询参数,例如www.somesite.com/home?lang=en..当然,基于标头的方法和基于显式参数的方法之间存在权衡的权衡,并且应该在您的应用程序中提供其他因素,例如请求/响应缓存机制。

对于许多在设计时没有考虑到国际化的api来说,这可能是一个常见的陷阱,确保每个数据点(或至少它们的一些表示)都有一种方法来实现它是至关重要的.在国际化服务或API的国际化时,使用字符串直接合作,因为它允许客户端和服务器代码允许删除对变量数据的依赖性。例如,让我们向我们抽象地绘制一组关于我们想要获得一些可以在后续切线请求中使用的数据的关于的一组信息:

获取“API / MENU / PIZZA_TOPPPINGS” - > [奶酪“,”PEPPERNI“,”VEGGIE“]
POST "api/my_pizza/add_topping"——> ("Pepperoni")——> {success: true}

考虑一下,如果我们想要支持返回这些数据点的翻译/ pizza_toppings因此,我们的用户可以看到文本的本地化版本,端点/ add_topping.可能不具备理解价值观的能力["奶酪”、“意大利辣香肠”、“素食”)等等,因此如果我们将这些值转换为另一种语言的等同物,我们的客户将发送虚假请求。与以下内容相比:

获取“API / MENU / PIZZA_TOPPPINGS” - > [
{id: 1220, name: "Cheese"},
{id:1234,名称:“Pepperoni”},
{id:1002,名称:“素食”}

post“api / my_pizza / add_topping” - >(1234) - > {成功:真实}

通过将api和服务的输入和输出结构成更规范化的格式,我们现在可以简单地转换的名字田野的领域/ pizza_toppings有效负载,不需要担心增加对其他语言的支持而破坏我们的软件。对于某些人来说,这似乎是显而易见的,但我要强调的是,在高速的情况下,很容易忽略一些你目前没有设计的内容(事后是二十20)因此,对于最初预期的软件来说,它可以理解的是,对于支持本地化等特征,工程师可以很容易地选择了前一个例子,以便简单起见。

最后,值得花一点时间来分析当前应用程序的架构和问题,以及是否有必要(以及随后,可能)来支持各种语言和地区。如果您有服务需要适应给定区域环境的语言,文化或法律要求,则这种可变性如何适合API和服务的当前架构。可以有可能需要提供服务专用于确定给定区域设置或区域的特征映射的任务。

样式,主题,资产

就像我之前提到的,是某些语言的一个非常重要的句法特征。出于这个原因,我认为最好避免使用像CSS这样的代码首字母s或javascript的String.toUpperCase对将显示给用户的消息的大小写执行显式更改。几乎可以保证,这将在某些时候无意中破坏消息的翻译。让我们来看一个例子,例如,我们想要大写一个用户的名字和他们的位置:

天真案例转型导致错误

嗯,现在我们实际上只是在土耳其语中误解了两条消息,因为我的名字不是NİCK而这个城市的名字却不是ci̇nci̇natti̇.,而不管这个象形文字应该成为一世在土耳其语中大写。

当涉及到我们的软件样式时,另一个需要记住的重要部分是确保我们的组件可以.如果一个短语在英语中只有几个单词或字母,那么在翻译成其他语言时,它的长度很容易翻倍或三倍(反之亦然)。这当然是设计问题的一部分,但我们也有责任确保在我们的设计中考虑到可变长度的字符串,这样翻译不会导致我们的组件以任何方式剪辑或损坏。

除了为内容设计不同的预期长度外,我们还应该记住,我们的组件应该以一种能够在各种语言的脚本中使用的方式构建,而不管具体情况如何所选脚本的。以这个精心设计的CSS为例:

使您的样式适用于多个文档方向类型

仔细使用开始结束价值观与正确的值将允许我们的样式表跨越语言轻松扩展脚本和脚本!整洁!

也许另一个区域真正让你的本地化工作脱颖而出.就像我之前提到的,颜色和象征都受文化和语言的影响,所以使用像ThemeProvider来自风格的组件要根据应用程序的主动区域设置管理主题可能是一种非常有趣的方式,使您的产品在不同地区和语言中会更加自然地脱颖而出。例如,我们的错误消息的颜色可以为Western Ligales为红色,其中颜色通常与错误相关,但不是某些东亚语言环境,其中该颜色通常不与错误相关联。这是一个小小的例子,但语言环境特定主题的可能性实际上是无穷无尽的。

一个有趣的讨论点是Okcupid目前对本地化资产的态度。188bet金宝搏官网也许您的应用程序使用大量的静态图像。.但是,它现在意味着这些资产太需要本地化,如果您计划扩展到甚至是几(更不用说数十),基于特定地区创建/导出/导入这些资产的单调乏味将会线性增加设计师和开发人员。正因为如此,我们决定尝试在我们的资产中删除嵌入式语言,并使用更多可以在各种语言和文化中工作的中立资产。这里有一个非常简单的例子来说明这一点:

基于文本的资产与插图的资产和本机文本

左侧红色中概述的元素实际上是从CDN加载的图像资产,文本和全部。在右侧的绿色中,图像已与文本分开,因此可以从React / CSS中独立地呈现文本内容和图像资产,而无需将众多图像部署到每种语言的CDN。

我们还创建了一些很酷的自定义文本呈现类,以本地化的方式处理样式。看看这个帖子这里

它真的是一个常数吗?

我想通过为我遇到的问题提供一个小小的轶事来包装更具体的技术因素,以及它在我的代码中思考的哲学/建筑点。在某些时候,我有一条准备翻译的消息,无法弄清楚为什么这条消息没有被正确翻译。

它最后变成了翻译应用文件导入时,因为它被定义为一个常数,所以它从来没有重新评估后的最初评估(在这种情况下,它还没有最新的数据进行正确的评价)。

对我们来说,将代码库的各个部分放在一起是很常见的,这通常涉及到接受原始数据类型(如字符串),并将它们声明为常量,然后在代码库中的文件和模块中重用它们。然而,当你使用React Providers和Context之类的东西跨组件或应用程序应用区域设置时,你的“常量”现在会根据应用程序的状态而变化。这肯定是一个很小的差异,但突出了像宣布常量的琐事一样微不足道的事实需要在国际化的范围内重新考虑。

这也是编写软件的一个很好的小练习!解构您的工作并自问您所做的是否在上下文中有意义是一项很难掌握的技能,但在避免这种情况(以及一般情况下构建软件)方面肯定是有价值的。

请参阅本系列的第4部分这里

188bet金宝搏官网OkCupid科技博客

阅读来自工程团队的故事,这些故事每天连接着数百万人