Rails 5: Can you duplicate two words in a string with two different meanings?

I am creating a view for a store that contains a summary of product reviews. I am grouping reviews by score, and I want a row at the top of each group on the 10 out of 5 stars form. I know that if I just wanted to pluralize the "overview" I could do it in en.rb

:

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

      

Is there a hash format reviews_header

that allows me to specify counts for both "overview" and "star", so they pluralize when needed? In pseudocode, I imagine something like:

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"
                }
            }        
        }
    }
}

      

And I would get a line with t(:reviews_header, review_count: 10, star_count: 5)

.

What I am doing now, I changed the line to a "10 5-star reviews" form which addresses the issue of "star" pluralization, but this will not work in other languages.

+3


source to share


1 answer


You have a case of nested plurals. Although my familiarity with Ruby is rudimentary, I could not find any documentation that offers a solution for this nested plural case via Ruby built into i18n functions. However, in programming languages ​​that support ICU Library, you can use MessageFormat .

Using this Ruby for MessageFormat parsing and formatting library, it would be possible to nest nested MessageFormats to cover all variations of that string to cover the complexities of nested multiple rules in any language. Please keep in mind that you do not need most of these rules for most languages, but there are several languages ​​such as Arabic and Russian that do need many of these cases; There are special cases of two in Arabic, Russians have special cases of them (1, 21, 31, 1001, but not 11). A diagram from the Unicode CLDR project listing multiple rules for all languages ​​can be found here .

Usually, I train translators to use this online tool (which is the same development message-format-rb

) and translate the MessageFormat according to the need of their language.

MessageFormat for translator tools



Here is the complete, maximum MessageFormat following the Ruby snippet:

{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}}
}
}

      

And a Ruby snippet:

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'

      

0


source







All Articles