i18n多元化

时间:2011-05-29 05:06:53

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

我希望能够在rails中翻译i18n中的复数字符串。字符串可以是:

You have 2 kids

You have 1 kid

我知道我可以使用复数辅助方法,但我希望将其嵌入到i18n翻译中,以便我在将来的任何时候都不必弄乱我的观点。我读到:count以某种方式用于复数的翻译,但我找不到任何关于它如何实现的真实资源。

请注意,我知道我可以在翻译字符串中传递变量。我也尝试过这样的事情:

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

哪个工作正常,但有一个相同想法的根本问题。我需要在pluralize helper中指定字符串'kid'。我不想这样做,因为它将导致将来查看问题。相反,我想保留翻译中的所有内容,而不是视图中的任何内容。

我该怎么做?

7 个答案:

答案 0 :(得分:166)

试试这个:

en.yml

en:
  misc:
    kids:
      zero: no kids
      one: 1 kid
      other: %{count} kids

在视图中:

You have <%= t('misc.kids', :count => 4) %>

更新了多个复数的语言答案(使用Rails 3.0.7测试):

档案 config/initializers/pluralization.rb

require "i18n/backend/pluralization" 
I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)

档案 config/locales/plurals.rb

{:ru => 
  { :i18n => 
    { :plural => 
      { :keys => [:one, :few, :other],
        :rule => lambda { |n| 
          if n == 1
            :one
          else
            if [2, 3, 4].include?(n % 10) && 
               ![12, 13, 14].include?(n % 100) && 
               ![22, 23, 24].include?(n % 100)

              :few 
            else
              :other 
            end
          end
        } 
      } 
    } 
  } 
}

#More rules in this file: https://github.com/svenfuchs/i18n/blob/master/test/test_data/locales/plurals.rb
#(copy the file into `config/locales`)

档案 config/locales/en.yml

en:
  kids:
    zero: en_zero
    one: en_one
    other: en_other

档案 config/locales/ru.yml

ru:
  kids:
    zero: ru_zero
    one: ru_one
    few: ru_few
    other: ru_other

<强>测试

$ rails c
>> I18n.translate :kids, :count => 1
=> "en_one"
>> I18n.translate :kids, :count => 3
=> "en_other"
>> I18n.locale = :ru
=> :ru
>> I18n.translate :kids, :count => 1
=> "ru_one"
>> I18n.translate :kids, :count => 3
=> "ru_few"  #works! yay! 
>> I18n.translate :kids, :count => 5
=> "ru_other"  #works! yay! 

答案 1 :(得分:33)

我希望讲俄语的Ruby on Rails程序员能找到这个。只是想分享我自己非常精确的俄罗斯复数公式。它基于Unicode Specs。 以下是config/locales/plurals.rb文件的内容,其他所有内容都应与上面的答案相同。

{:ru => 
  { :i18n => 
    { :plural => 
      { :keys => [:zero, :one, :few, :many],
        :rule => lambda { |n| 
          if n == 0
            :zero
          elsif
            ( ( n % 10 ) == 1 ) && ( ( n % 100 != 11 ) )
            # 1, 21, 31, 41, 51, 61...
            :one
          elsif
            ( [2, 3, 4].include?(n % 10) \
            && ![12, 13, 14].include?(n % 100) )
            # 2-4, 22-24, 32-34...
            :few
          elsif ( (n % 10) == 0 || \
            ![5, 6, 7, 8, 9].include?(n % 10) || \
            ![11, 12, 13, 14].include?(n % 100) )
            # 0, 5-20, 25-30, 35-40...
            :many
          end
        } 
      } 
    } 
  } 
}

母语人士可能会喜欢111121等案例。 在这里测试结果:

  • 零:0запросов/куриц/яблок
  • one:1запрос/курица/яблоко
  • 很少:3запроса/курицы/яблока
  • 很多:5запросов/куриц/яблок
  • one:101запрос/курица/яблоко
  • 很少:102запроса/курицы/яблока
  • 很多:105запросов/куриц/яблок
  • 很多:111запросов/куриц/яблок
  • 很多:119запросов/куриц/яблок
  • one:121запрос/курица/яблоко
  • 很少:122запроса/курицы/яблока
  • 很多:125запросов/куриц/яблок

感谢您的初步回答!

答案 2 :(得分:11)

首先,请记住复数形式的数量取决于语言,英语有两个,罗马尼亚语有3个,阿拉伯语有6个。

如果您希望能够正确使用复数表格,则必须使用gettext

对于Ruby和rails,您应该查看http://www.yotabanana.com/hiki/ruby-gettext-howto-rails.html

答案 3 :(得分:8)

Rails 3通过CLDR考虑和计数插值变量来稳健地处理这个问题。见http://guides.rubyonrails.org/i18n.html#pluralization

# in view
t('actors', :count => @movie.actors.size)

# locales file, i.e. config/locales/en.yml
en:
  actors:
    one: Actor
    other: Actors

答案 4 :(得分:2)

实际上有一种替代麻烦的i18n方法。该解决方案称为Tr8n。

您的上述代码只是:

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

那就是它。无需从代码中提取密钥并将其保存在资源包中,无需为每种语言实现复数规则。 Tr8n附带所有语言的数字上下文规则。它还附带性别规则,列表规则和语言案例。

上述翻译密钥的完整定义实际上如下所示:

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

但是由于我们想节省空间和时间,num会自动映射到数字规则,并且不需要为规则值提供所有选项。 Tr8n配备了多元化和变形器,可以随时为您完成工作。

您的俄语密钥翻译只需:

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

顺便说一下,对于具有性别特定规则的语言,您的翻译不准确。 例如,在希伯来语中,您实际上必须为您的示例指定至少2个翻译,因为&#34;您&#34;将根据观看用户的性别而有所不同。 Tr8n处理得非常好。以下是希伯来语翻译的音译:

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

因此,在这种情况下,您的单个英语密钥需要4个翻译。所有翻译都是在上下文中完成的 - 您不必打破句子。 Tr8n有一种机制,可以根据语言和上下文将一个键映射到多个翻译 - 所有这些都是动态完成的。

最后一件事。如果你必须把计数部分加粗怎么办?它只是:

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

万一你要重新定义你的&#34;粗体&#34;之后 - 这将非常简单 - 您不必浏览所有YAML文件并进行更改 - 您只需在一个地方完成。

要了解更多信息,请点击此处:

https://github.com/tr8n/tr8n_rails_clientsdk

披露:我是Tr8n框架及其所有库的开发者和维护者。

答案 5 :(得分:0)

英语

开箱即用works

<强> en.yml

en:
  kid:
    one: '1 kid'
    other: '%{count} kids'

用法(当然,您可以在视图文件中跳过I18n):

> I18n.t :kid, count: 1
 => "1 kid"

> I18n.t :kid, count: 3
 => "3 kids"

俄语(以及其他多种复数形式的语言)

安装rails-18n gem并在.yml文件中添加翻译,如example

<强> ru.yml

ru:
  kid:
    zero: 'нет детей'
    one: '%{count} ребенок'
    few: '%{count} ребенка'
    many: '%{count} детей'
    other: 'дети'

用法:

> I18n.t :kid, count: 0
 => "нет детей"

> I18n.t :kid, count: 1
 => "1 ребенок"

> I18n.t :kid, count: 3
 => "3 ребенка"

> I18n.t :kid, count: 5
 => "5 детей"

> I18n.t :kid, count: 21
 => "21 ребенок"

> I18n.t :kid, count: 114
 => "114 детей"

> I18n.t :kid, count: ''
 => "дети"

答案 6 :(得分:0)

关于Redmine。如果您在config / locales /中将复数文件规则复制为plurals.rb,而其他与语言环境名称不同的规则(ru.rb,pl.rb等)则无法使用。 您必须将文件规则重命名为'locale'.rb或更改文件/lib/redmine/i18n.rb

中的方法
def init_translations(locale)
  locale = locale.to_s
  paths = ::I18n.load_path.select {|path| File.basename(path, '.*') == locale}
  load_translations(paths)
  translations[locale] ||= {}
end

如果您使用的是旧版的Redmine,请添加

module Implementation
        include ::I18n::Backend::Base
        **include ::I18n::Backend::Pluralization**