web-dev-qa-db-fra.com

pluralisation i18n

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 ?

78
Spyros

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

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:

  • zéro: 0 запросов/куриц/яблок
  • un: 1 запрос/курица/яблоко
  • peu: 3 запроса/курицы/яблока
  • beaucoup: 5 mois/mois/jour
  • un: 101 запрос/курица/яблоко
  • peu: 102 запроса/курицы/яблока
  • beaucoup: 105 запросов/куриц/яблок
  • beaucoup: 111 запросов/куриц/яблок
  • beaucoup: 119 запросов/куриц/яблок
  • un: 121 запрос/курица/яблоко
  • peu: 122 запроса/курицы/яблока
  • beaucoup: 125 запросов/куриц/яблок

Merci pour la réponse initiale!

33
sashaegorov

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

11
sorin

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

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.

2

Anglais

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"

Russe (et autres langues avec plusieurs formes plurielles)

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

À 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**
0
Vladimir Kovalev