Rails 5:你能用两个不同的计数复数两个单词吗?

时间:2017-07-19 19:33:39

标签: ruby-on-rails internationalization rails-i18n

我为商店构建了一个视图,其中列出了产品评论的摘要。我按分数对评论进行分组,我想在表格的每个组的顶部添加一个字符串" 10评论5星"。我知道,如果我只想复数"请回顾",我可以在en.rb中执行此操作:

en: {
  reviews_header: {
    one: "1 review",
    other: "%{count} reviews"
  }
}

是否有reviews_header哈希的格式,可让我指定"审核"和"明星"所以他们在必要时都是多元化的?在伪代码中,我想象的是:

en: {
    reviews_header: {
        counts: [ :review_count, :star_count ],
        review_count: {
            one: {
                star_count: {
                    one: "1 review with 1 star",
                    other: "1 review with %{star_count} stars"
                }
            },
            other: {
                star_count: {
                    one: "%{review_count} reviews with 1 star",
                    other: "%{review_count} reviews with %{star_count} stars"
                }
            }        
        }
    }
}

我会得到t(:reviews_header, review_count: 10, star_count: 5)的字符串。

我现在正在做的是将字符串更改为" 10个5星评价",它解决了多元化" star"的问题,但是不会用其他语言工作。

1 个答案:

答案 0 :(得分:0)

这里有一个嵌套复数的例子。尽管我对Ruby的熟悉程度尚不高,但我找不到任何通过Ruby内置的i18n功能为这个嵌套复数形式提供解决方案的文档。但是,在支持ICU Library的编程语言中,可以从MessageFormat中受益。

使用this library进行Ruby for MessageFormat解析和格式化,可以手工创建嵌套的MessageFormat来覆盖此字符串的所有变体,以涵盖任何语言中嵌套复数规则的复杂性。请记住,对于大多数语言而言,您不需要大多数这些规则,但很少有像阿拉伯语和俄语这样需要其中许多语言的语言;阿拉伯语有两个特殊情况,俄语有特殊情况(1,21,31,1001,但不是11)。可以找到列出所有语言的复数规则的Unicode CLDR项目的图表here

通常,我会训练翻译人员使用this online tool(来自message-format-rb的同一个开发者)并根据他们语言的需要翻译MessageFormat。

MessageFormat for Translators tool

这是一个完整的,最大的MessageFormat,后面是一个Ruby代码段:

{review_count, plural, 
=0 {
    {star_count, plural,
        other {no reviews}}
}
zero {
    {star_count, plural,
        zero {{review_count} reviews with {star_count} stars} 
        one {{review_count} review with {star_count} star}
        two {{review_count} reviews with {star_count} stars}
        few {{review_count} reviews with {star_count} stars}
        other {{review_count} reviews with {star_count} stars}}
}
one {
    {star_count, plural,
        zero {{review_count} review with {star_count} stars}
        one {{review_count} review with {star_count} star}
        two {{review_count} review with {star_count} stars}
        few {{review_count} review with {star_count} stars}
        other {{review_count} review with {star_count} stars}}
}
two {
    {star_count, plural,
        zero {{review_count} reviews with {star_count} stars}
        one {{review_count} review with {star_count} star}
        two {{review_count} reviews with {star_count} stars}
        few {{review_count} reviews with {star_count} stars}
        other {{review_count} reviews with {star_count} stars}}
}
 few { 
    {star_count, plural,
         zero {{review_count} reviews with {star_count} stars} 
         one {{review_count} review with {star_count} star}
         two {{review_count} reviews with {star_count} stars}
         few {{review_count} reviews with {star_count} stars}
         other {{review_count} reviews with {star_count} stars}}
}
other {
    {star_count, plural,
        zero {{review_count} reviews with {star_count} stars}
        one {{review_count} review with {star_count} star}
        two {{review_count} reviews with {star_count} stars}
        few {{review_count} reviews with {star_count} stars}
        other {{review_count} reviews with {star_count} stars}}
}
}

Ruby片段:

require 'message_format'
require 'test/unit/assertions'
include Test::Unit::Assertions

icumf = "{review_count, plural, =0 {{star_count, plural,other {no reviews}}} zero { {star_count, plural, zero {{review_count} reviews with {star_count} stars} one {{review_count} review with {star_count} star} two {{review_count} reviews with {star_count} stars} few {{review_count} reviews with {star_count} stars} other {{review_count} reviews with {star_count} stars}}}one {{star_count, plural, zero {{review_count} review with {star_count} stars} one {{review_count} review with {star_count} star} two {{review_count} review with {star_count} stars} few {{review_count} review with {star_count} stars} other {{review_count} review with {star_count} stars}}} two {{star_count, plural, zero {{review_count} reviews with {star_count} stars} one {{review_count} review with {star_count} star} two {{review_count} reviews with {star_count} stars} few {{review_count} reviews with {star_count} stars} other {{review_count} reviews with {star_count} stars}}} few {{star_count, plural,zero {{review_count} reviews with {star_count} stars} one {{review_count} review with {star_count} star} two {{review_count} reviews with {star_count} stars} few {{review_count} reviews with {star_count} stars} other {{review_count} reviews with {star_count} stars}}} other {{star_count, plural, zero {{review_count} reviews with {star_count} stars} one {{review_count} review with {star_count} star} two {{review_count} reviews with {star_count} stars} few {{review_count} reviews with {star_count} stars}        other {{review_count} reviews with {star_count} stars}}}}"

# Set the locale to get the plural rules for that locale
message = MessageFormat.new(icumf, 'en')
assert_equal message.format({ :review_count => 0, :star_count => 0 }), 'no reviews'
assert_equal message.format({ :review_count => 0, :star_count => 100 }), 'no reviews'
assert_equal message.format({ :review_count => 1, :star_count => 2 }), '1 review with 2 stars'
assert_equal message.format({ :review_count => 2, :star_count => 5 }), '2 reviews with 5 stars'