i18n Pluralization

2019-01-20 21:32发布

I want to be able to translate pluralized strings in i18n in rails. A string can be :

You have 2 kids

or

You have 1 kid

I know that I can use pluralize helper method, but I want to embed this in i18n translations so that I don't have to mess up with my views at any point in the future. I read that :count is somehow used in translations for plural, but I can't find any real resources on how it gets implemented.

Notice that I know that I can pass a variable in a translation string. I also tried something like :

<%= t 'misc.kids', :kids_num => pluralize(1, 'kid') %>

Which works fine, but has a fundamental problem of the same idea. I need to specify the string 'kid' in the pluralize helper. I don't want to do that because it will lead to view problems in the future. Instead I want to keep everything in the translation and nothing in the view.

How can I do that ?

7条回答
神经病院院长
2楼-- · 2019-01-20 22:15

There is actually an alternative to the cumbersome i18n approach. The solution is called Tr8n.

Your above code would simply be:

 <%= tr("You have {num || kid}", num: 1) %>

That's it. No need to extract your keys from your code and maintain them in resource bundles, no need to implement pluralization rules for each language. Tr8n comes with numeric context rules for all language. It also comes with gender rules, list rules and language cases.

The full definition of the above translation key would actually look like this:

 <%= tr("You have {num:number || one: kid, other: kids}", num: 1) %>

But since we want to save space and time, num is automatically mapped to numeric rules and there is no need to provide all options for the rule values. Tr8n comes with pluralizers and inflectors that will do the work for you on the fly.

The translation for your key in Russian, would simply be:

 "У вас есть {num || ребенок, ребенка, детей}"

By the way, your translation would be inaccurate in languages that have gender specific rules. For example, in Hebrew, you would actually have to specify at least 2 translations for your example, as "You" would be different based on the gender of the viewing user. Tr8n handles it very well. Here is a transliteration of Hebrew translations:

 "Yesh leha yeled ahad" with {context: {viewing_user: male, num: one}}
 "Yesh leha {num} yeladim" with {context: {viewing_user: male, num: other}}
 "Yesh lah yeled ahad" with {context: {viewing_user: female, num: one}}
 "Yesh lah {num} yeladim" with {context: {viewing_user: female, num: other}}

So your single English key, in this case, needs 4 translations. All translations are done in context - you don't have to break the sentence. Tr8n has a mechanism to map one key to multiple translations based on the language and context - all done on the fly.

One last thing. What if you had to make the count part bold? It would simply be:

<%= tr("You have [bold: {num || kid}]", num: 1, bold: "<strong>{$0}</strong>") %>

Just in case you want to redefine your "bold" later - it would be very easy - you won't have to go through all your YAML files and change them - you just do it in one place.

To learn more, please take a look here:

https://github.com/tr8n/tr8n_rails_clientsdk

Disclosure: I am the developer and the maintainer of Tr8n framework and all its libraries.

查看更多
登录 后发表回答