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