web-dev-qa-db-ja.com

国際化の複数化

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

You have 2 kids

または

You have 1 kid

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

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

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

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

どうやってやるの ?

81
Spyros

これを試して:

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! 
168
Zabba

ロシア語を話す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запросов/куриц/яблок
  • 1:1запрос/курица/яблоко
  • 少数:3запроса/курицы/яблока
  • 多く:5запросов/куриц/яблок
  • one:101запрос/курица/яблоко
  • 少数:102запроса/курицы/яблока
  • 多く:105запросов/куриц/яблок
  • 多く:111запросов/куриц/яблок
  • 多く:119запросов/куриц/яблок
  • 1つ:121запрос/курица/яблоко
  • 少数:122запроса/курицы/яблока
  • 多く:125запросов/куриц/яблок

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

34
sashaegorov

まず、複数形の数は言語に依存することに注意してください。英語には2つ、ルーマニア語には3つ、アラビア語には6つあります!.

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

Ruby and Railsこれを確認する必要があります http://www.yotabanana.com/hiki/Ruby-gettext-howto-Rails。 html

11
sorin

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
8
Luke W

実際には、面倒な国際化アプローチに代わるものがあります。ソリューションは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フレームワークとそのすべてのライブラリーの開発者および管理者です。

3

英語

そのまま 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をインストールし、 example のように.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: ''
 => "дети"
0
installero

Redmineについて。 config/locales /にある複数形化ファイルのルールを、locales.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**
0