плюрализация как i18n
Я хочу иметь возможность переводить несколько строк в i18n в rails. Строка может быть :
You have 2 kids
или
You have 1 kid
Я знаю, что могу использовать метод pluralize helper, но я хочу встроить это в переводы i18n, чтобы мне не пришлось путаться с моими взглядами в любой момент в будущем. Я читал это :count как-то используется в переводах для множественного числа, но я не могу найти никаких реальных ресурсов о том, как он реализуется.
обратите внимание, что я знаю, что я могу передайте переменную в строке перевода. Я также попробовал что-то вроде :
<%= t 'misc.kids', :kids_num => pluralize(1, 'kid') %>
который отлично работает, но имеет фундаментальную проблему той же идеи. Мне нужно указать строку 'kid' в помощнике pluralize. Я не хочу этого делать, потому что это приведет к рассмотрению проблем в будущем. Вместо этого я хочу сохранить все в переводе и ничего в представлении.
как я могу это сделать ?
7 ответов
попробуйте это:
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! 
Я надеюсь, что русскоязычные программисты Ruby on Rails смогут найти это. Просто хочу поделиться своей очень точной русской формулой плюрализации. Он основан на Спецификации 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 запрос/курица/яблоко
- немногие: 3 запроса/курицы/
- многие: 5 запросов/куриц/
- один: 101 запрос / курица/
- немногие: 102 запроса/курицы/
- многие: 105 запросов/куриц/
- многие: 111 запросов/куриц/
- многие: 119 запросов/куриц/
- один: 121 запрос/курица/яблоко
- немногие: 122 запроса/курицы/
- много: 125 запросов/куриц/яблок
Спасибо за первоначальный ответ!
во-первых, помните, что количество форм множественного числа зависит от языка, для английского есть два, для румынского есть 3 и для арабского есть 6 !.
Если вы хотите правильно использовать формы множественного числа, вы должны использовать gettext.
для Ruby и rails вы должны проверить это http://www.yotabanana.com/hiki/ruby-gettext-howto-rails.html
Rails 3 обрабатывает это надежно с помощью переменной интерполяции CLDR и count. См.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
на самом деле существует альтернатива громоздкому подходу i18n. Решение называется Tr8n.
ваш код выше будет просто:
 <%= tr("You have {num || kid}", num: 1) %>
вот именно. Нет необходимости извлекать ключи из кода и хранить их в пакетах ресурсов, нет необходимости реализовывать правила плюрализации для каждого языка. Tr8n поставляется с числовыми правилами контекста для всех языков. Он также поставляется с гендерными правилами, правилами списка и языковыми случаями.
полное определение приведенный выше ключ перевода будет выглядеть следующим образом:
 <%= tr("You have {num:number || one: kid, other: kids}", num: 1) %>
но поскольку мы хотим сэкономить пространство и время, num автоматически сопоставляется с числовыми правилами, и нет необходимости предоставлять все параметры для значений правил. Tr8n поставляется с pluralizers и инфлекторы, который будет делать работу за вас на лету.
перевод для вашего ключа на русский язык, будет просто:
 "У вас есть {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 имеет механизм для сопоставления одного ключа с несколькими переводы на основе языка и контекста-все делается на лету.
одна последняя вещь. Что, если бы тебе пришлось сделать графа смелым? Это было бы просто:--6-->
<%= tr("You have [bold: {num || kid}]", num: 1, bold: "<strong>{}</strong>") %>
на всякий случай, если вы хотите переопределить свой "жирный" позже - это было бы очень легко - вам не придется просматривать все ваши файлы YAML и изменять их - вы просто делаете это в одном месте.
чтобы узнать больше, пожалуйста, взгляните здесь:
https://github.com/tr8n/tr8n_rails_clientsdk
раскрытие информации: я разработчик и сопровождающий tr8n framework и всех его библиотек.
английский язык
это просто работает из окна
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"
русский (и другие языки с несколькими формами множественного числа)
установить рельсы-18 Н 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: ''
 => "дети"
О Redmine. Если вы копируете правила файла плюрализации в config/ locales / as plurals.rb и другие не совпадают с именем локали (ru.rb, pl.рубидий.. etc) эти не работают. Необходимо переименовать правила файлов в "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**
