字符串的国际化

时间:2015-04-16 22:58:21

标签: json internationalization

目前我们在SQL Server数据库中存储国家,城市,州名,少数查找表。对于存储在这些表中的字符串的国际化,要遵循哪些最佳实践?

一些想法是将它们存储为平面json文件,并且有不同的文件来存储国际化文本并根据区域设置选择它们,但这将是一个维护噩梦。

1 个答案:

答案 0 :(得分:3)

实际上,从维护的角度来看,数据库本地化很快就会成为一场噩梦。显然,您不想让翻译人员访问您的数据库(甚至不是间接访问)。我会在一分钟内解释一下。

最典型的模式是将所有字符串外部化为所谓的资源文件,并根据区域设置加载它们 - 您调用它时的维护噩梦。
典型的资源文件格式为:

如你所见,我的短名单上没有必要使用JSON 无论如何,如果您倾向于使用标准文件格式,翻译人员可以使用他们的工具:

  • MT - 机器翻译以翻译文件的未翻译部分(然后手动修复以匹配上下文)
  • TM - 翻译记忆库,用于存储以前的翻译并在需要时使用它们(这实际上是首先使用的...)

在典型过程中,应仅对英语资源文件进行更改(不对语言文件进行手动修改)。如果是这种情况,使用我前面提到的TM工具重新创建语言文件就很容易了 现在,如果您需要更改翻译(即修复一些讨厌的本地化错误),该怎么办? 显然,您希望在翻译工具(而不是文件!)中更改它,以便在每个新版本的英文文件中使用更改。

它仍然是一场噩梦吗? :)

我提到的过程是标准过程。它遵循80/20规则,即80%的项目都有这样的过程。然而,有20%的项目不适合理想的过程 - 那些使用所谓的动态定位的项目 通过动态本地化,我的意思是英语字符串经常变化,通常由系统用户提供。

如果是这种情况,带有查找表的数据库本地化只是最简单的方法。但不幸的是,总有一个问题 问题是,正确实施它真的很难。如果用户有任何使用自由格式文本修改数据库内容的方法,那么您的系统将面临风险。没关系典型的SQL注入漏洞;那些你可以预防的。但是,如果数据库引擎本身有一个关键的零日缺陷会让用户提升他们的权限并执行一些任意的SQL语句呢?你永远不会知道 当然,安全只是一个问题。其他问题是:

  • 如何让我的用户提供翻译字符串的功能?
  • 如何跟踪并确保翻译的完整性?
  • 如何确保翻译的正确性?
  • 如何激励用户真正提供这些翻译?
  • 如何正确实现翻译引擎?

这些事情不能掉以轻心 Facebook使您能够将UI翻译成您的语言。他们创建了一个特殊的工具,可以让你翻译屏幕上的文字(你可以使用基于性别和基数的不同形式 - 即多个复数形式)。你知道吗?即使他们有这么多的贡献者,该网站仍然没有100%翻译成(我相信)它支持的大多数语言。它翻译得正确吗?好吧,大部分时间是的 croudsourcing的最大问题是故意破坏。有人会故意破坏翻译(或内容),维基百科有人吗?你必须以某种方式阻止它。

现在开始实施细节。这些问题也可能出现在典型的可本地化方案中,包括资源文件。但是,它们很常见,在很多情况下引擎会为您解析它们(Gettext是最好的例子)。在实现自己的可本地化引擎时,您需要考虑以下问题:

  1. 语言回退。我们假设您的系统已翻译为德语,您的默认语言为英语。如果来自奥地利(de-AT)的用户进来,她应该能够看到德语(de)的UI,而不是英语。这个很简单 更有问题的是简体中文和繁体中文。如果您的系统发生了这两种语言的翻译(分别是locale zh-Hans和zh-Hant),那么您需要确保适当的回退:zh-CN(中国)和zh -SG(新加坡)应该回归zh-Hans,而zh-TW(台湾),zh-HK(香港)以及zh-MO(澳门)需要回归zh-Hant。在纯zh的情况下,它可能应该再次是简体中文。

  2. 您想重用常用字符串(即OK,取消作为按钮标题),但同时您不想在不同的上下文中重用字符串(您可能想要这样做) ,但它会创建一个i18n错误)。第一部分很简单,您只需为每个重复的字符串使用相同的资源键。前提是您有资源键 我尝试实现基于数据库的本地化引擎时遇到的最常见的错误是,它们使用英文字符串作为数据库的关键字。
    不要这样做。
    这不允许在不同的上下文中对相同字符串进行不同的翻译。例如,让我带来Save对话框示例。在波兰语中," Save"按钮标题是一个动作,应该在命令式情绪中翻译(" Zapisz")。同样的" Save"在窗口标题中告知将要发生的事情,并应翻译为" Zapisywanie"。

  3. 更糟糕的是,许多语言都有多个复数形式,所以除非你重新说出英语句子以避免这个问题,否则你必须考虑到这一点。这意味着同一个密钥的翻译不止一个(最多六个)......它不是那么难,你只需使用复合主键(resource_id,locale_id,cardinality)和cardinality其中之一:零,一,二,少数,许多,其他。

  4. 性别可能是问题的根源。您可能希望尽可能使您的系统保持性别中立,但在某些情况下,翻译实际上会因性别而异。如果您让用户翻译消息,那么您很可能需要处理这些消息。

  5. 另一方面,如果您想使用专业翻译提供商的服务,您不能发送SQL文件进行翻译。您很可能需要创建导入/导出机制来创建翻译人员可用于练习其艺术的标准资源文件格式之一。
    当然,您可以发送基本上任何文件格式,但它有其后果。最明显的是,非标准文件格式(例如Excel文件)需要手动操作,因此容易出错。由于需要手动操作,翻译人员会向您收取额外费用......翻译字符串需要更长的时间 好的,您可以直接将数据库与TM和MT系统集成(但是在语言验证之前,您不应该让机器翻译的文本落在您的用户界面上),但这也是非常费力的。

  6. 您的项目是否适合80%的用例?你必须自己回答这个问题。

    编辑:资源更改时如何避免重新部署

    如果资源变化比代码更频繁,那么很明显指出应该实现动态本地化(基本上是DB驱动的)。

    另一方面,有时我们不想仅仅因为资源文件已经更改而重新部署整个应用程序。这完全可以理解。
    有许多方法可以处理这种情况,最简单的方法可能是创建一个可以读取属性文件并按需返回它们的微服务。它可以被应用程序代码的某些部分用于驱动本地化(即按需生成JSON文件)。当然,这意味着额外的复杂性和重新部署微服务的需要,但应用程序的代码(war,ear,jar?)将保持不变。

    在Java 8中,可能采用不同的方法:ResourceBundle.Control类实现Service Provider Interface,因此理论上可以简单地创建一个具有自定义ResourceBundle.Control实现的特定JAR文件来读取资源来自不同地方的文件(磁盘,jar,Web服务,实际上在任何地方)。这可用于确保只需要重新部署资源文件,而不是整个应用程序。

    不幸的是,一切都取决于背景;在某些技术中,不同的方法可行。像往常一样,避免一件事意味着增加另一件事的复杂性。