17

对 Ruby 有点陌生,我正在探索现有的库来做我通常在其他脚本语言中做的事情,我对本地化库感到有点难过,这些本地化库可能可用于构建在 Sinatra/Sequel 之上的东西(Rails /AR 对我来说有点太固执了)。

现在,我通过这个 wiki 页面遇到了一对(i18n,r18n,GetText),并且显然在 Padrino 中使用了一个额外的库(基于 Rails 的 i18n 东西?);显然还有更多。

除了明显的(即 GetText mo/po 样式与 yml 文件)之外,我对这些选项可能有何不同感到有些困惑。wiki 在这方面并没有指出太多,只是说它们存在。不是他们有什么不同。

更令人困惑的是,基本上每一份文档似乎都涵盖了其中一个(通常在 RoR 上下文中)。此外,仔细检查后,这些选项看起来并不完全不兼容——从某种意义上说,如果我正确理解这一点,它们可以在很大程度上理解彼此的文件。

这里的任何人都可以对这些库进行快速而中肯的解释/概述,并概述它们之间的区别吗?如果您知道任何有关性能的指示(除了 fast_gettext 文档中的指示,考虑到我缺乏理解这些选项之间的区别,这毫无意义),也将受到欢迎。

4

4 回答 4

30

在不了解 Ruby 中 i18n/l10n 库的一些历史的情况下,我可以看到这种情况是如何令人困惑的。我可能应该就此写几句话,但现在我将尝试从我的角度给出一个概述:

Gettext显然是这款游戏中最年长的玩家,它继承了它的祖先的优点和缺点,这是为 C 语言主导的世界而发明的。它具有大多数人需要的功能,附带一些其他人缺乏的工具支持(如桌面 po 文件编辑器),并且在所谓的企业世界中被广泛接受。

Gettext 本身定义了一个API,并且在 Ruby 世界中基本上有两个库实现它,Masao Mutoh的传统Ruby Gettext包和Michael Grosser的fast_gettext gem 。

Ruby Gettext 非常强大,并且提供了许多您可能需要也可能不需要的功能。另一方面,fast_gettext gem 专注于原始速度,并被实现为一个闪亮的、现代的代码风格的 Ruby 库,它很容易被破解,作者是一个非常聪明和支持的人。在这两者中,我个人强烈推荐 fast_gettext。

I18n gem是几年前存在的各种 Ruby i18n/l10n 解决方案共同努力的结果,当时出于各种原因,所有这些解决方案都在努力取代 Gettext。由此产生的I18n API基本涵盖了当时所有涉及的i18n/l10n解决方案的需求和用例,包括Gettext的API。因此,今天的 Ruby I18n API 是 90 年代初期 Gettext 的 API 的超集。

今天,I18n gem 是Ruby on Rails 附带的官方解决方案,但它也可能是 Ruby 世界中最受欢迎的解决方案。

I18n gem 还使得扩展功能集和添加缓存、其他存储机制(如 Gettext po 文件、数据库表、键值存储;存储默认为纯 Ruby 文件和 YAML)等变得非常容易,并且它附带为此提供了许多模块(但可以轻松地制作、测试和集成外部或自定义模块)。

Ruby on Rails(在其他项目中也很有用)使用的字符串有70 多种语言(语言环境)的翻译文件,由社区维护。

关于R18n ,我不能说太多,除了它是在 I18n 首次发布之后发明的,据我所知,它起源于 Merb 社区。它在俄罗斯 Ruby 世界中似乎相当强大,但我可能对所有这些断言都错了。

因此,除非您有充分的理由选择任何其他解决方案,否则我强烈建议您使用 I18n。

另一方面,这没有任何意义,因为自从它被发明以来,我或多或少地一直在领导这个项目。

我希望这有帮助。

[编辑] 添加了指向各种参考的链接

于 2011-06-21T13:41:18.197 回答
5

I18n 是主流。

R18n 是一个替代方案,它具有一些额外的特性(模型翻译、语法糖)以及意识形态和架构的一些差异(强大的过滤器的弹性可扩展性)。

G18n 需要将模型转换添加到 I18n。

Padrino 不是 i18n 库,它只是带有内置 I18n 的 Sinatra 框架。

Gettext 是恕我直言的旧概念,格式非常丑陋,并且存在复数问题。无论如何,它在 Ruby 社区中并不流行。

于 2011-06-21T13:35:28.347 回答
5

首先:
正如 svenfuchs 所写,I18n它是一个为许多翻译和国际化方法提供模块的框架。
'gettext' 只是众多模块之一。

所以使用起来真的没有问题I18n

Rails 应用程序的默认设置是I18n与 YAML 后端一起使用,我理解您的部分问题是将该后端与其他后端进行比较。


gettext恕我直言,基于方法和基于方法之间有两个主要区别YAML

  • 生命周期支持
  • 等级制度

获取文本

一个想法gettext是,翻译应用程序不是一个单一的事件,而是一个生命周期过程。
它是为支持这个生命周期而构建的。

gettext旨在使用简单的英语作为翻译的关键。所以想法是用英语编写应用程序并标记所有要翻译的文本,通常用_().
因此,应用程序源代码很容易用英文阅读。

然后程序扫描所有源代码并提取要翻译的文本并构建这些文本的存储库.pot文件)。

在下一步中,这里是实时循环,存储库与现有翻译(.po文件,每种目标语言一个)合并,并标记新的或更改的项目

成熟的编辑通过关注新的和更改的项目来支持翻译。此外,项目特定的词典可以支持部分自动翻译。

gettextflat,这意味着每个关键短语在翻译文件中只翻译一次。没有等级制度。但有上下文。在翻译文件中,列出了一个关键短语的所有源代码位置。有权访问源代码的编辑器可以将源代码与翻译一起显示(有些人会这样做)。

最后,.po文件被翻译成机器可读的快速访问形式(可以是.mo,经典标准,或数据库或 json 或……)

YAML

另一方面,YAML 是分层的,因此很容易在不同的上下文中产生不同的翻译。当使用以点开头的键时,
I18n 使用此结构来支持并使用当前文件路径作为作用域。 没有信息,项目中使用的密钥(除非自动范围,但密钥可以在其他地方明确使用)。 没有任何信息,是否有任何变化。 除非您的 IDE 支持您,否则开发人员必须找到在 YAML 中放置密钥的正确位置,并且搜索用法可能很麻烦。其他答案中说了很多。scopes


I18n

我故意说YAML而不是I18n,因为I18n是一个国际化框架(不仅仅是翻译),而YAML只是一个可能的后端。
I18n 中的复数支持不同于普通 gettext 的复数支持。我没有他们如何合作的经验。

例子

带有位置参数的gettext :

sprintf(
_('Do you really want to delete tour %1$s_%2$s? Only empty tours can be deleted!'),
tag, idx)

翻译是文本文件,但 PO 编辑器提供 GUI:

#: js/addDelRow.js:15
msgid "" "Do you really want to delete tour %1$s_%2$s? Only empty tours can be deleted!" 
msgstr "" "Wollen sie die Spalte %1$s_%2$s wirklich löschen? Nur leere Spalten können "
"gelöscht werden."

带参数的YAML :

来源

<%= t('.checked_at', ts: l(checked_at), user: full_name) %>

翻译

en:
  hotels:
    form:
      checked_at: „set to checked by %{user} on %{ts}“

de:
  hotels:
    form:
      checked_at: "geprüft gesetzt am %{ts} von %{user}“

结论

YAML更容易上手,尤其是在您有 IDE 支持的情况下。
Vanilla RAILS 内置了它。
它不是母语。第一个翻译可以是任何语言。随着越来越多的项目和多种语言,我的 YAML 文件倾向于重复(相同的翻译分散在层次结构中)和跟踪更改,因此新的翻译很麻烦。

gettext需要一个额外的工具链,因此设置起来更加困难。
它支持开发应用程序持续翻译的整个生命周期。
它基于英文源代码。

我通常使用两者中最好的部分,使用 YAML 进行国际化(数字和日期格式,也许是模型名称?)和 gettext 进行翻译。

于 2015-07-23T08:36:59.577 回答
2

安德烈的回应让我回到r18n 文档,它基本上将其分解为一行:

默认情况下,R18n 使用分层而非以英语为中心的 YAML 格式进行翻译。

从 Andrey 那里找到了这张幻灯片。它是俄语的,但现在更有意义了(幻灯片 7 到 9,特别是 i18n 和 r18n 之间的明显区别):

http://www.slideshare.net/iskin/r18n

于 2011-06-21T13:26:14.940 回答