应用程序本地化和RTL支持。 报告Yandex.Taxi

在对服务进行本地化时,务必仔细考虑彼此之间的传输协调。 Yandex.Taxi客户Android开发团队的负责人Alexander Bonel谈到了简化本地化的实践和工具。 在报告的第二部分中,Sasha共享了在应用程序中支持RTL的经验:什么是好的,什么不适用于Android,即开即用,由于RTL支持而出现的问题以及如何在将来将其最小化。


-在我的报告中,我想告诉您我们在移动应用程序开发团队中使用了哪些基本思想和实践来解决与应用程序中翻译的本地化和更新有关的问题。 然后,我将告诉您我们如何实现在应用程序中从右到左以绘图模式工作的支持。



我将从本地化开始。 首先,我想澄清一下术语。 根据我的观察,很多人认为本地化仅限于翻译,尽管实际上它也解决了与格式化数字,日期,时间,使用文本和符号,法律方面,以这种方式向消费者提供内容有关的问题。他对他具有语义价值,并没有被模棱两可。 还有更多。 (与观众交流有关谁在应用程序中支持多少种语言的信息?)。

我想告诉你一个我们2014年发生的故事。 然后,我们对Taxi应用程序进行了重大的重新设计。 在下一个版本中,我们为用户提供了机会,以指明入口号,并在旅行信息屏幕上,并且最重要的是,在向所有用户显示的订单等级屏幕上查看此信息,因为我们绝对希望获得旅行等级。



那时,我们对本地化过程和翻译相当轻描淡写。 在大多数情况下,整个过程都是手动的。 更新必需的XML文件中的文本,添加新的翻译是手动执行的。 人为因素起了作用。 开发人员确定下一次传输不在默认语言环境中。 这导致以下事实:对于使用与俄语不同的系统区域设置的用户,如果他们询问入口,则该应用程序在旅行结束时崩溃。 人们无法再下订单。

当时,我们在应用程序中支持两种语言:俄语和英语。 而且我们仅在俄罗斯的三个城市工作:莫斯科,叶卡捷琳堡,圣彼得堡。



我们目前在16个国家/地区开展业务,并已翻译成18种语言。 如果我们当时处于这种状态,我认为您理解了整个问题。 那时我们已经意识到需要进行一些更改。



在Yandex中,大多数移动应用程序开发人员都使用内部开发的服务来解决与本地化有关的问题。 它具有非常方便的UI界面,可以定义您的项目,设置一组键,需要将项目翻译成的语言。 在翻译出现后,可以以任何方便的格式上载它们。 他还与我们的内部服务很好地集成在一起。 有版本控制。 但是对我个人而言,作为开发人员,最重要的是他拥有API,因为这已经表明与翻译相关的所有手动工作都可以自动化。 我们做到了。 我们为Gradle开发了一个插件。 实际上,现在更新应用程序中的翻译归结为开发人员执行一项任务:updateTranslations。



首先,他去了本地化服务。 检查最新的翻译,将其上传到项目中,并将其放入必要的文件中。 但是除此之外,他还验证了本地化服务中与项目中现有内容相关的翻译状态。



下次执行git status时,开发人员会在工作目录中查看哪些文件已更改。



他还可以在生成的HTML报告中查看有关哪种键的值在哪种语言中已更改的信息。



他还可以查看他的项目的翻译中当前存在哪些问题。



该插件是可配置的。 我们可以确定应用程序支持的语言数量。 如果本地化人员开始使用一种新的语言,并且在没有经过校对和校对的情况下,它不经意间渗入了项目,则非常重要。



还有一个特定的重新映射功能。 当我谈论RTL时,我将在后面详细讨论。

该插件现在分析哪些问题? 我们在2014年遇到的问题很普遍,缺乏翻译。 现在,为了向项目添加新行,新转换,开发人员仅在XML文件中定义它是不够的。



首先,如果他不在默认语言环境中执行此操作,那么他新缠绕的密钥将在下一次同步期间简单消失,并且他将在编译阶段知道这一点。



如果他确定了默认文件中的密钥,却忘记了在本地化服务中进行操作,则下次执行updatetranslations时,他将从插件中收到错误消息,该错误将告诉他:“此密钥在您的项目中,但不在本地化服务中,它存在需要开始。”



第二个典型问题是缺乏翻译。 我们获得了到这些键的链接列表,这些键没有翻译,通常,我们将其推荐给我们的经理,以便他们以后与翻译建立联系。 当他们决定以某种方式重新考虑使用格式参数时,通常会发生第三点,例如,他们开始使用字符串格式,而不是整数格式。

但是同时,在某些翻译中,他们忘记更改在线号。



第四个问题也是由人为因素引起的,主要是翻译。 如果在翻译中使用Unicode字符,则很容易在字符的位置上感到困惑,而不是用不可分割的空格来使另一行成为连字符-这就是我们要摆脱的问题。

这都是关于本地化的。

现在,我要谈谈使用Israel实例在应用程序中实现从右到左的渲染支持的经验。 我们于2018年在以色列推出了品牌Yango。 事实证明,在以色列,人们的阅读方式与您和我不同。 他们从右到左阅读。



您想从哪里开始? 原则上,使用Android,可以很好地实现从右到左的渲染支持。

首先,需要在应用程序清单的Application元素中声明supportRtl =“ true”属性。 但我想请您:如果您在应用程序中集成了用于社交授权的Facebook SDK,那么有心的Facebook开发人员已经为您完成了这项工作。 而且,如果您在合并时未验证清单,则值为true的此属性将适合您的应用程序,并且已经可以在Rtl中使用。 这是需要考虑的事情。

我认为听众中的大多数人可能对Android 4.4的支持很少。 有人更幸运-这是5.0或更高。 有人可能不那么幸运,他们支持4.0,或者上帝禁止使用2.3。 在这种情况下,您会遇到很大的问题,因为自版本4.2起就出现了Android对Rtl的全面支持。 因此,使用minSdk 17th,您的生活将减少一个数量级。

转移项目以使用Rtl可以从Android Studio中的重构工具开始-尽可能添加RTL支持。 我们必须致敬,它运作良好。 它遍历标记的XML文件,查看具有左右值的重力,填充,边距属性的存在,并将其替换为开始和结束。 如果您想查看默认情况下应用程序在从右到左模式下的工作方式,则无需使用希伯来语或阿拉伯语中所谓的RTL强字符的内容。 您只需要在开发人员的设置中启用“强制RTL布局方向”即可。

自定义UI和渲染Android为RTL提供的文本有哪些选项?



第一点是layoutDirection属性,它使用描述的“强制RTL布局方向”选项。 她只有四个可能的含义。 也就是说,默认情况下它是从父级继承的。 可以说,布局是根据所选区域设置绘制的。 您可以清楚地说是从右到左或从左到右绘制的。

许多人在进行文本对齐时最有可能摆脱习惯的第二个要素是textAlignment。 许多人仍然继续使用重力。 不要使用重力来对齐文本,而要使用textAlignment。

第三个属性是文本渲染方向textDirection。 它具有相当灵活的配置。 它允许您根据文本中第一个强字符来确定文本的呈现方式,无论是来自拉丁强LTR字符集还是来自希伯来语强RTL字符集。 但是,如果您在应用程序中完全支持RTL,则无需绕过它,因为会忽略这种有趣的工件。



这是一个复活节彩蛋,还是在editText实现中的这种副作用:您对editText的提示开始消失。 因此,无论如何,您都必须为他设置一些价值。


幻灯片链接

如果您需要在RTL模式下观察某些图形资源或标记的某种呈现方式,那么Android可以在爸爸中设置限定符ldrtl,您可以在其中放置任何资源,并将按照您指定的RTL呈现方式进行绘制。

有时需要运行时绘制来自后端的文本,即文本的来源,而忽略应用程序当前工作的模式。 实际上,在文本渲染器中完成此操作是由于文本由所谓的Bidi Unicode控制字符构成框架。 用于处理这些字符的逻辑本身包含BidiFormatter类,仅提供一种unicodeWrap方法。 它以CharSequence作为输入,并返回由这些字符构成的字符串。 其中有很多,原则上应该可以解决您的大多数问题。

但是,如果有那么具体的内容,w3.org上有一篇很好的文章介绍了如何使用这些符号。

在我们的应用程序中开始RTL支持时遇到了什么问题? 首先,这是本地化标准的冲突。

BCP47是更新的本地化标准,尤其是更改了某些语言环境的代码。 事实是,语言环境Java类存在问题。 默认情况下,它在向后兼容模式下工作,并将语言环境代码从BCP转换为ISO。 也就是说,当iw代码而不是he代码开始在Accept-Language标头中进入我们的后端时,我们看到了这一点。


幻灯片链接

如果您还记得带有我们插件配置的幻灯片,则仅需要对此进行重新映射-以便将内容从他转换为iw。

如果您需要使用BCP格式,则可以在Apache Cordova项目中完全实现。 它们具有一个全球化类和localeToBcp47Language的实现。



在应用程序中“提供” RTL支持的另一点是动画。 实际上,这里的好处是仅影响沿X轴的动画,也许唯一可以帮助您避免更多问题的解决方案或方法是能够在相对动画方向上重新考虑绝对动画。

也许只能通过反射解决的问题之一是因为TextInputLayout的提示对齐是在组件本身中严格实现的。 事实是,即使在希伯来语的RTL强字符中指定了提示,即使您在编辑文本中输入的内容可以来自拉丁字符,也可以将其右对齐。 反之亦然。 如果您的提示是拉丁语,则将其清楚地对齐到左侧。 这只能通过反射来解决。



最终,在应用程序中实现了RTL之后,重新考虑Lint分析的RTL问题的严重性是有意义的。 只有四个。 如果您的应用程序中不支持RTL,而是在某处显式使用RTL特定的属性,则为RtlEnabled(Lint会告诉您有关信息)。


幻灯片链接

如果您在应用程序中支持RTL,但是您的应用程序的minSdkVersion在17以下,那么您还必须继续使用left和right类型的属性,您不能仅在标记中使用start和end属性。 这就是RtlCompat解析的内容。 当看到不对称的填充时,RtlSymmetry发誓。 通常,我认为aapt在处理资源时,如果遇到对称填充,则应该崩溃。 如果您需要某种非对称访问,请使用边距作为完整的布局参数。

最后,第四个问题是硬编码的RTL。 只是在属性中仅指示了left和right的值。 本质上,这否定了重构工具“尽可能添加RTL支持”。 这一切都来自Lint进入RTL时的结果。 AOSP的RtlDetector类中也提供了一种分析实现。 也就是说,如果想像力允许,您可以通过查看分析的进行情况来提出自己的想法。

我的报告快要结束了。 我想提供一些关于在我们的应用程序中构建正确的本地化的论文,随着时间的推移,我们已经涉及到了这些。



首先,在项目开始时,请考虑国际化。 我没有真正提到它。 这与本地化完全不同。 实际上,国际化使应用程序和产品中的本地化成为可能。 由于它具有完全的Unicode支持,因此在Java中是开箱即用的,而在Android中则是由于其丰富的资源系统而实现的。 也许唯一可能发生的事情就是我们作为开发人员对“我只为俄语编写应用程序,这意味着我将仅使用俄语检查应用程序”这一主题的关注。 当您开始在应用程序中使用亚美尼亚语,格鲁吉亚语,希伯来语或阿拉伯语时,图片看起来会完全不同,并且会破坏您通常的范例。

第二刻 考虑将本地化嵌入CI中。 在候选发布者的测试阶段了解与翻译相关的问题非常令人失望,您可以为此准备几个星期。 也就是说,我们现在针对每个池请求都运行此任务,以便我们可以事先确定一切都很好,并且可以将新代码冻结到项目的主分支中。

第三点。 尊重翻译人员的工作和预算。 首先,删除未使用的资源,因为人们可以继续花费时间和金钱来翻译您最终在项目中不使用的字符串。 其次,遵循本地化服务中存储库中的翻译,而不是代码中的翻译。

理想情况下,如果本地化服务的API提供有关何时打开特定密钥的信息,并且您可以使用启发式方法(例如“如果密钥是在一个月前打开的”),请在主早午餐的最新版本中检查其是否存在。 如果他不在,很可能是将其删除的明确候选人,这样本地化人员就不会花时间在上面。

一个或多或少通用的选择是将字符串存储在后端而不是客户端上。 至少,这将使您有机会始终将它们与应用程序相关。

我们的用户群体非常多样化,每个人都以自己的方式感知世界和应用程序内容。 作为开发人员,我们的任务是帮助保持这种看法。 我对此的报告已经结束。 非常感谢!

Source: https://habr.com/ru/post/zh-CN456250/


All Articles