Rails I18n 复数形式,没有明确的计数数字

问题描述 投票:0回答:1

Rails 为 String 提供了内置的复数方法,例如

"apple".pluralize
返回“apples”,而
"apple".pluralize(1)
则返回“apple”(参见 this Question)。但是,它仅适用于英语。有没有什么简单的方法可以让它适用于另一种语言?

具体来说,我想让它在日语版 Rails 7 中工作(

ja
),其中单数和复数形式没有区别。所以,基本上,当(用户的)语言环境
I18n.locale
为“ja”时,我想禁用复数。然而,
"林檎".pluralize(locale: :ja)
返回“
林檎s
”,这显然是错误的。

与Rails标准的I18n翻译框架配合使用的方式是最好的。

ruby-on-rails internationalization rails-i18n pluralize
1个回答
0
投票

也许是最简单但不干的方法

在 Rails 中,

String#pluralize
(我理解)基于 ActiveSupport::Inflector.pluralize。虽然它只支持英语,但它不会更改其他语言(区域设置)的字符串,这正是您想要的:

I18n.backend.store_translations :en, Article: "Article"
I18n.backend.store_translations :ja, Article: "記事"

I18n.t(:Article, locale: :en).pluralize(1, :en) #=> "Article"
I18n.t(:Article, locale: :en).pluralize(2, :en) #=> "Articles"
I18n.t(:Article, locale: :ja).pluralize(1, :ja) #=> "記事"
I18n.t(:Article, locale: :ja).pluralize(2, :ja) #=> "記事"

 # Wrong examples
I18n.t(:Article, locale: :ja).pluralize              #=> "記事s"
I18n.t(:Article, locale: :ja).pluralize(locale: :ja) #=> "記事s"

要指定除英语之外的任何语言,第一个参数似乎是强制性的(在我看来,既不直观又冗长)。

令人困惑的是,语言环境不是String#pluralize

的关键字参数,与
ActionController::Base.helpers.pluralize
不同,而是可选的主要参数!
如果您仅以关键字参数的形式指定带有冒号的区域设置(如上例中的最后一行),结果将会令人惊讶。

对于区分单复数形式但规则与英语不同的语言,例如法语中的“un Animal”和“des animaux”,您可以根据

Rails 文档指定自己的屈折规则。

然而,这并不理想,因为它违反了 DRY 原则,其中语言环境必须指定两次。

明确指定复数形式

您可以通过使用

I18n 框架中的 Rails

count
选项来实现类似的效果:

I18n.backend.store_translations :en, Article: { one: "Article", other: "Articles" } # not using "%{count} Articles" I18n.backend.store_translations :ja, Article: "記事" # no distinction betwwen singular and plural for ja I18n.t(:Article, locale: :en, count: 3) #=> "Articles" I18n.t(:Article, locale: :ja, count: 3) #=> "記事" I18n.t(:Article, locale: :en, count: 1) #=> "Article" I18n.t(:Article, locale: :ja, count: 1) #=> "記事" # Wrong example I18n.t(:Article, locale: :en) #=> {:one=>"Article", :other=>"Articles"} I18n.t(:Article, locale: :ja) #=> "記事" # this works, though.
这个方法确实遵循了DRY原则。

但是,有几个主要缺点。首先,说实话,我觉得为所有(也许数百个?)定义翻译的英语单词定义复数形式是愚蠢的,考虑到 Rails 知道如何对这些英语单词进行复数形式。

其次,一旦您指定了一组这样的翻译,您必须始终使用

count

 选项来调用它们。

此外,

count

中的
I18n.t
选项的要点可以说是,您不必通过在定义中包含
%{count}
来将计数写两次。在上面的例子中,我故意排除了 
%{count}
,这样你就可以并且确实得到了结果 
没有 OP 要求的计数。然而,这种方法有点违背了 I18n.t
 (
I18n.translate
) 的设计目的,因为您仍然需要明确指定数字的放置位置和方式,例如,

sprintf "%d %s", cnt, I18n.t(:Article, locale: I18n.locale, count: cnt)
这个缺点对于某些语言尤其重要,在某些情况下,这些语言将数字放在主词之后。例如,美式英语表达日期和月份的“November 7”,与“7 Nov”(英式英语)相反,就是一个例子。或者,标准货币表达式因语言而异,例如“£4”(en-gb)、10.50 €(fr)、300円(ja)。

另一种方法

您可以像下面的示例一样使用

ActionController::Base.helpers.pluralize

,并结合您自己的翻译。虽然这不是OP所要求的(即获得没有计数的复数形式),但为了完整性,我在这里将其包括在内。

I18n.backend.store_translations :en, Article: "Article" I18n.backend.store_translations :ja, Article: "記事" helper.pluralize(1, I18n.t(:Article, locale: :en), locale: :en) #=> "1 Article" helper.pluralize(2, I18n.t(:Article, locale: :en), locale: :en) #=> "2 Articles" helper.pluralize(1, I18n.t(:Article, locale: :ja), locale: :ja) #=> "1 記事" helper.pluralize(2, I18n.t(:Article, locale: :ja), locale: :ja) #=> "2 記事" # Wrong example helper.pluralize(2, I18n.t(:Article, locale: :ja)) #=> "2 記事s"
一个主要区别是数字被强制包含在返回的 String 中。

格式也不一样,比较冗长,打破了DRY原则。

© www.soinside.com 2019 - 2024. All rights reserved.