Je veux pouvoir traduire des chaînes pluralisées dans i18n dans Rails. Une chaîne peut être:
You have 2 kids
ou
You have 1 kid
Je sais que je peux utiliser la méthode d’assistance pluralize, mais je souhaite l’intégrer dans les traductions de l’i18n afin de ne pas avoir à me mêler de mon point de vue à l’avenir. J'ai lu que :count
est utilisé d'une manière ou d'une autre dans les traductions du pluriel, mais je ne trouve aucune ressource réelle sur la façon dont il est implémenté.
Notez que je sais que je peux passer une variable dans une chaîne de traduction. J'ai aussi essayé quelque chose comme:
<%= t 'misc.kids', :kids_num => pluralize(1, 'kid') %>
Ce qui fonctionne bien, mais a un problème fondamental de la même idée. Je dois spécifier la chaîne 'kid'
dans l'aide au pluriel. Je ne veux pas faire cela parce que cela conduira à voir les problèmes dans le futur. Au lieu de cela, je veux tout conserver dans la traduction et rien dans la vue.
Comment puis je faire ça ?
Essaye ça:
en.yml
:
en:
misc:
kids:
zero: no kids
one: 1 kid
other: %{count} kids
Dans une vue:
You have <%= t('misc.kids', :count => 4) %>
Réponse mise à jour pour les langues à pluralisation multiple (testée avec Rails 3.0.7):
Fichier config/initializers/pluralization.rb
:
require "i18n/backend/pluralization"
I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
Fichier 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`)
Fichier config/locales/en.yml
:
en:
kids:
zero: en_zero
one: en_one
other: en_other
Fichier 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!
J'espère que les programmeurs russophones de Ruby on Rails pourront le trouver. Je veux juste partager ma propre formule très précise de pluralisation en russe. Il est basé sur Spécifications Unicode . Voici le contenu du fichier config/locales/plurals.rb
uniquement, tout le reste doit être fait comme dans la réponse ci-dessus.
{: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
}
}
}
}
}
Les locuteurs natifs peuvent profiter de cas tels que 111
et 121
. Et voici les résultats du test:
Merci pour la réponse initiale!
Premièrement, rappelez-vous que le nombre de formes plurielles dépend de la langue, il y en a deux en anglais, il y en a trois en roumain et six en arabe!.
Si vous voulez pouvoir utiliser correctement les formes plurielles, vous devez utiliser gettext
.
Pour Ruby and Rails, vous devriez vérifier ceci http://www.yotabanana.com/hiki/Ruby-gettext-howto-Rails.html
Rails 3 gère cela de manière robuste avec la considération CLDR et la variable d’interpolation de comptage. Voir 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
Il existe en réalité une alternative à la lourde approche i18n. La solution s'appelle Tr8n.
Votre code ci-dessus serait simplement:
<%= tr("You have {num || kid}", num: 1) %>
C'est tout. Pas besoin d'extraire vos clés de votre code et de les maintenir dans des ensembles de ressources, pas besoin d'implémenter des règles de pluralisation pour chaque langue. Tr8n est livré avec des règles de contexte numériques pour toutes les langues. Il est également livré avec des règles de genre, des règles de liste et des cas de langage.
La définition complète de la clé de traduction ci-dessus ressemblerait en réalité à ceci:
<%= tr("You have {num:number || one: kid, other: kids}", num: 1) %>
Mais comme nous voulons économiser de l'espace et du temps, num est automatiquement mappé aux règles numériques et il n'est pas nécessaire de fournir toutes les options pour les valeurs de règle. Tr8n est livré avec des pluralizers et des inflecteurs qui feront le travail pour vous à la volée.
La traduction de votre clé en russe serait simplement:
"У вас есть {num || ребенок, ребенка, детей}"
À propos, votre traduction serait inexacte dans des langues qui ont des règles spécifiques au genre. Par exemple, en hébreu, vous devrez spécifier au moins 2 traductions pour votre exemple, car "Vous" serait différent en fonction du sexe de l'utilisateur visualiseur. Tr8n le gère très bien. Voici une translittération des traductions en hébreu:
"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}}
Donc, votre clé anglaise unique, dans ce cas, nécessite 4 traductions. Toutes les traductions sont faites dans le contexte - vous n’avez pas à rompre la phrase. Tr8n dispose d'un mécanisme permettant d'associer une clé à plusieurs traductions en fonction de la langue et du contexte, le tout à la volée.
Une dernière chose. Et si vous deviez rendre la partie du compte audacieuse? Ce serait simplement:
<%= tr("You have [bold: {num || kid}]", num: 1, bold: "<strong>{$0}</strong>") %>
Juste au cas où vous voudriez redéfinir votre "gras" plus tard - ce serait très facile - vous n’aurez pas à parcourir tous vos fichiers YAML et à les modifier - vous le ferez au même endroit.
Pour en savoir plus, regardez ici:
https://github.com/tr8n/tr8n_Rails_clientsdk
Divulgation: Je suis le développeur et le responsable du framework Tr8n et de toutes ses bibliothèques.
C'est juste fonctionne hors de la boîte
en.yml:
en:
kid:
one: '1 kid'
other: '%{count} kids'
Utilisation (vous pouvez bien sûr ignorer I18n dans un fichier de vue):
> I18n.t :kid, count: 1
=> "1 kid"
> I18n.t :kid, count: 3
=> "3 kids"
Installez Rails-18n gem et ajoutez des traductions dans vos fichiers .yml
comme dans l'exemple exemple :
ru.yml:
ru:
kid:
zero: 'нет детей'
one: '%{count} ребенок'
few: '%{count} ребенка'
many: '%{count} детей'
other: 'дети'
Usage:
> 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: ''
=> "дети"
À propos de Redmine. Si vous copiez les règles de fichier de pluralisation dans config/locales/as plurals.rb et autres non identiques au nom de la locale (ru.rb, pl.rb .. etc.), celles-ci ne fonctionnent pas. Vous devez renommer les règles de fichier en 'locale'.rb ou changer de méthode dans le fichier /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
et si vous avez une vieille mine rouge, ajoutez
module Implementation
include ::I18n::Backend::Base
**include ::I18n::Backend::Pluralization**