i18n複数化


87

Railsのi18nで複数の文字列を翻訳できるようにしたいと思います。文字列は次のようになります。

You have 2 kids

または

You have 1 kid

複数のヘルパーメソッドを使用できることは知っていますが、これをi18nの翻訳に埋め込んで、将来的に自分の意見を台無しにする必要がないようにしたいと思います。:countどういうわけか複数形の翻訳で使われているのを読んだのですが、それがどのように実装されるかについての実際のリソースを見つけることができません。

翻訳文字列で変数を渡すことができることを知っていることに注意してください。私も次のようなことを試しました:

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

これは問題なく動作しますが、同じ考えの根本的な問題があります。'kid'複数化ヘルパーで文字列を指定する必要があります。将来的にはビューの問題につながるので、やりたくありません。代わりに、すべてを翻訳に残し、ビューには何も残さないようにします。

どうやってやるの ?


2
"#{....}"上記のコードでは、「補間器」と引用符は必要ないことに注意してください。
Zabba

1
他の言語の複数形が英語のように機能していると想定しているため、間違ったアプローチがあります。正しいアプローチについては、私の答えを参照しください。
sorin

ソリン、あなたの答えをありがとう、私はこれにgettextを使いたくないだけです。Zabbaのソリューションは、i18nのニーズに最適だと思います。
スパイロス

Rails 3は、CLDRと「count」補間変数を使用してより堅牢に処理します:guides.rubyonrails.org/i18n.html#pluralization
Luke W

数年後ですが、文字列「kid」に翻訳を使用することもできます。つまり、次のようになります<%= t 'misc.kids', :kids_num => pluralize(1, t('kid')) %>。多分これは2011年に動作しませんでしたが、それは確かRailsの5.2.2になりましたし(!)
ジャービス・ジョンソン

回答:


175

これを試して:

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! 

申し訳ありませんが、これは多くの言語では機能しません。複数形は本当に複雑で、参照translate.sourceforge.net/wiki/l10n/pluralformsこのためには、私は私の答えは、より適切であると考えます。
sorin

1
@sorin、複数の複数化ルールを使用するように私の答えを更新しました。
Zabba

5
大丈夫ですが、複数形辞書を維持するための新しいフルタイムの仕事があります!。
sorin

これは素晴らしい!%{count}動作させるには、ブロック全体を引用符で囲む必要がありました。one: "%{count} kid"
firedev 2012

1
@ThePablick、はい。「/ initializer」ディレクトリ内のファイルは、httpサーバーの起動時に一度だけロードされるためです。
Zabba 2013年

37

ロシア語を話すRubyonRailsプログラマーがこれを見つけてくれることを願っています。私自身の非常に正確なロシア語の複数化式を共有したいだけです。Unicode仕様に基づいています。これは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
        } 
      } 
    } 
  } 
}

ネイティブスピーカーは、111やなどのケースを楽しむことができます121。そしてここにテスト結果:

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

最初の回答をありがとう!


1
あなたが言及した他の答えは、これを別のファイルに入れました。したがって、そのアプローチでは、コンテンツはではconfig/locales/plurals.rbなくに移動する必要がありますconfig/initializers/pluralization.rb
silverdr 2016

@silverdr回答のファイル名を修正しました。ヒントをありがとう!
sashaegorov 2016

11

まず、複数形の数は言語によって異なることを覚えておいてください。英語の場合は2つ、ルーマニア語の場合は3つ、アラビア語の場合は6つです。

複数形を適切に使用できるようにする場合は、を使用する必要がありますgettext

RubyとRailsについては、こちらを確認してくださいhttp://www.yotabanana.com/hiki/ruby-gettext-howto-rails.html


4
ソリン、これも私が考えていたものですが、これはCLDR形式(unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…)に従うことで解決されるようです。私が間違っている?
Nikos D

1番目、2番目、3番目、4番目、11番目、12番目、13番目もありますが、21番目、22番目、23番目などです。
gnasher729 2015


5

英語

箱から出してすぐに機能します

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し、例のようにファイルに翻訳を追加します。

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: ''
 => "дети"

4

実際には、面倒な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つの翻訳を指定する必要があります。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には、言語とコンテキストに基づいて1つのキーを複数の翻訳にマッピングするメカニズムがあります。これらはすべてオンザフライで実行されます。

最後に一つだけ。カウント部分を太字にする必要がある場合はどうなりますか?それは単に次のようになります:

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

後で「太字」を再定義したい場合に備えて(非常に簡単です)、すべてのYAMLファイルを調べて変更する必要はありません。1か所で行うだけです。

詳細については、こちらをご覧ください。

https://github.com/tr8n/tr8n_rails_clientsdk

開示:私はTr8nフレームワークとそのすべてのライブラリの開発者およびメンテナーです。


1
反対票が何のためにあるのかを知っていればいいのですが、答えは問題ないようです。
doug65536 2016年

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**
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.