i18n Pluralisierung


86

Ich möchte in der Lage sein, pluralisierte Zeichenfolgen in i18n in Schienen zu übersetzen. Eine Zeichenfolge kann sein:

You have 2 kids

oder

You have 1 kid

Ich weiß, dass ich die Pluralisierungs-Hilfsmethode verwenden kann, aber ich möchte dies in i18n-Übersetzungen einbetten, damit ich zu keinem Zeitpunkt in der Zukunft meine Ansichten durcheinander bringen muss. Ich habe gelesen, dass dies :countirgendwie in Übersetzungen für den Plural verwendet wird, aber ich kann keine wirklichen Ressourcen dafür finden, wie es implementiert wird.

Beachten Sie, dass ich weiß, dass ich eine Variable in einer Übersetzungszeichenfolge übergeben kann. Ich habe auch etwas versucht wie:

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

Was gut funktioniert, aber ein grundlegendes Problem der gleichen Idee hat. Ich muss die Zeichenfolge 'kid'im Pluralisierungshelfer angeben . Ich möchte das nicht tun, weil es in Zukunft zu Problemen führen wird. Stattdessen möchte ich alles in der Übersetzung und nichts in der Ansicht behalten.

Wie kann ich das machen ?


2
Beachten Sie, dass der "Interpolator" und die Anführungszeichen "#{....}"im obigen Code nicht erforderlich sind.
Zabba

1
Sie haben einen falschen Ansatz, weil Sie davon ausgehen, dass die Pluralformen für andere Sprachen wie in Englisch funktionieren. Siehe meine Antwort für einen korrekten Ansatz.
Sorin

Sorin, danke für deine Antwort, ich möchte gettext einfach nicht für diese verwenden. Ich denke, die Lösung von Zabba ist großartig für meine Anforderungen mit i18n.
Spyros


Jahre später können Sie aber auch eine Übersetzung für den String 'kid' verwenden - also haben Sie : <%= t 'misc.kids', :kids_num => pluralize(1, t('kid')) %>. Vielleicht hat das 2011 (!) Nicht funktioniert, aber jetzt auf Rails 5.2.2
Jarvis Johnson

Antworten:


174

Versuche dies:

en.yml ::

en:
  misc:
    kids:
      zero: no kids
      one: 1 kid
      other: %{count} kids

In einer Ansicht:

You have <%= t('misc.kids', :count => 4) %>

Aktualisierte Antwort für Sprachen mit mehrfacher Pluralisierung (getestet mit Rails 3.0.7):

Datei config/initializers/pluralization.rb :

require "i18n/backend/pluralization" 
I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)

Datei 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`)

Datei config/locales/en.yml :

en:
  kids:
    zero: en_zero
    one: en_one
    other: en_other

Datei 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! 

Entschuldigung, aber das funktioniert einfach nicht mit vielen Sprachen. Die Pluralisierung ist sehr komplex, siehe translate.sourceforge.net/wiki/l10n/pluralforms. Aus diesem Grund halte ich meine Antwort für angemessener.
Sorin

1
@ Sorin, hat meine Antwort aktualisiert, um mehrere Pluralisierungsregeln zu verwenden.
Zabba

5
Es ist in Ordnung, aber jetzt haben Sie einen neuen Vollzeitjob, um das Pluralisierungswörterbuch zu pflegen!.
Sorin

Das ist toll! Um %{count}zur Arbeit zu kommen, musste ich Anführungszeichen um den gesamten Block verwenden, dh. one: "%{count} kid"
Firedev

1
@ThePablick, ja, da die Dateien im Verzeichnis '/ initializer' nur einmal geladen werden - beim Start des http-Servers.
Zabba

37

Ich hoffe, dass russischsprachige Ruby on Rails-Programmierer dies finden konnten. Ich möchte nur meine eigene sehr genaue russische Pluralisierungsformel teilen. Es basiert auf Unicode-Spezifikationen . Hier ist nur der Inhalt der config/locales/plurals.rbDatei, alles andere sollte genauso gemacht werden wie in der obigen Antwort.

{: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
        } 
      } 
    } 
  } 
}

Muttersprachler können Fälle wie 111und genießen 121. Und hier die Testergebnisse:

  • Null: 0 запросов / куриц / яблок
  • eins: 1 запрос / курица / яблоко
  • wenige: 3 запроса / курицы / яблока
  • viele: 5 запросов / куриц / яблок
  • eins: 101 запрос / курица / яблоко
  • wenige: 102 запроса / курицы / яблока
  • viele: 105 запросов / куриц / яблок
  • viele: 111 запросов / куриц / яблок
  • viele: 119 запросов / куриц / яблок
  • eins: 121 запрос / курица / яблоко
  • wenige: 122 запроса / курицы / яблока
  • viele: 125 запросов / куриц / яблок

Danke für die erste Antwort!


1
Die andere Antwort, auf die Sie sich bezogen haben, hat dies in einer anderen Datei abgelegt. Also mit diesem Ansatz sollte Ihr Inhalt config/locales/plurals.rbeher zu gehen alsconfig/initializers/pluralization.rb
silverdr

@silverdr Ich habe den Dateinamen als Antwort festgelegt. Danke für den Tipp!
Sashaegorov

11

Denken Sie zunächst daran, dass die Anzahl der Pluralformen von der Sprache abhängt . Für Englisch gibt es zwei, für Rumänisch 3 und für Arabisch 6!

Wenn Sie mehrere Formen richtig verwenden möchten, müssen Sie sie verwenden gettext.

Für Ruby und Rails sollten Sie diese http://www.yotabanana.com/hiki/ruby-gettext-howto-rails.html überprüfen


4
Sorin, das habe ich auch gedacht, aber dies scheint gelöst zu werden, indem man dem CLDR-Format folgt ( unicode.org/repos/cldr-tmp/trunk/diff/supplemental/… ). Liege ich falsch?
Nikos D

Es gibt auch 1., 2., 3., 4., 11., 12. und 13., aber 21., 22., 23. und so weiter.
Gnasher729


4

Englisch

Es funktioniert einfach sofort

en.yml :

en:
  kid:
    one: '1 kid'
    other: '%{count} kids'

Verwendung (Sie können I18n natürlich in einer Ansichtsdatei überspringen):

> I18n.t :kid, count: 1
 => "1 kid"

> I18n.t :kid, count: 3
 => "3 kids"

Russisch (und andere Sprachen mit mehreren Pluralformen)

Installieren Sie Rails-18n Gem und fügen Sie Ihren .ymlDateien Übersetzungen hinzu, wie im Beispiel :

ru.yml :

ru:
  kid:
    zero: 'нет детей'
    one: '%{count} ребенок'
    few: '%{count} ребенка'
    many: '%{count} детей'
    other: 'дети'

Verwendung:

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

3

Es gibt tatsächlich eine Alternative zum umständlichen i18n-Ansatz. Die Lösung heißt Tr8n.

Ihr obiger Code wäre einfach:

 <%= tr("You have {num || kid}", num: 1) %>

Das ist es. Sie müssen Ihre Schlüssel nicht aus Ihrem Code extrahieren und in Ressourcenpaketen verwalten. Sie müssen keine Pluralisierungsregeln für jede Sprache implementieren. Tr8n enthält numerische Kontextregeln für alle Sprachen. Es kommt auch mit Geschlechterregeln, Listenregeln und Sprachfällen.

Die vollständige Definition des obigen Übersetzungsschlüssels würde tatsächlich so aussehen:

 <%= tr("You have {num:number || one: kid, other: kids}", num: 1) %>

Da wir jedoch Platz und Zeit sparen möchten, wird num automatisch numerischen Regeln zugeordnet, und es müssen nicht alle Optionen für die Regelwerte angegeben werden. Tr8n wird mit Pluralisierern und Inflektoren geliefert, die die Arbeit im laufenden Betrieb für Sie erledigen.

Die Übersetzung für Ihren Schlüssel auf Russisch wäre einfach:

 "У вас есть {num || ребенок, ребенка, детей}"

Übrigens wäre Ihre Übersetzung in Sprachen mit geschlechtsspezifischen Regeln ungenau. Auf Hebräisch müssten Sie beispielsweise mindestens zwei Übersetzungen für Ihr Beispiel angeben, da "Sie" je nach Geschlecht des angezeigten Benutzers unterschiedlich wären. Tr8n handhabt es sehr gut. Hier ist eine Transliteration hebräischer Übersetzungen:

 "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}}

In diesem Fall benötigt Ihr einzelner englischer Schlüssel 4 Übersetzungen. Alle Übersetzungen erfolgen im Kontext - Sie müssen den Satz nicht brechen. Tr8n verfügt über einen Mechanismus, mit dem ein Schlüssel basierend auf Sprache und Kontext mehreren Übersetzungen zugeordnet werden kann - alles im laufenden Betrieb.

Eine letzte Sache. Was wäre, wenn Sie den Zählteil fett machen müssten? Es wäre einfach:

<%= tr("You have [bold: {num || kid}]", num: 1, bold: "<strong>{$0}</strong>") %>

Nur für den Fall, dass Sie Ihr "Fett" später neu definieren möchten - es wäre sehr einfach - müssen Sie nicht alle Ihre YAML-Dateien durchgehen und ändern - Sie tun es einfach an einem Ort.

Um mehr zu erfahren, schauen Sie bitte hier:

https://github.com/tr8n/tr8n_rails_clientsdk

Offenlegung: Ich bin der Entwickler und Betreuer des Tr8n-Frameworks und aller seiner Bibliotheken.


1
Ich wünschte, ich wüsste, wofür die Abstimmungen waren, die Antwort scheint in Ordnung zu sein.
Doug65536

0

Über Redmine. Wenn Sie Regeln für Pluralisierungsdateien in config / locales / als plurals.rb und andere Regeln kopieren, die nicht mit dem Namen des Gebietsschemas übereinstimmen (ru.rb, pl.rb .. usw.), funktionieren diese nicht. Sie müssen die Dateiregeln in 'locale'.rb umbenennen oder die Methode in der Datei /lib/redmine/i18n.rb ändern

def init_translations(locale)
  locale = locale.to_s
  paths = ::I18n.load_path.select {|path| File.basename(path, '.*') == locale}
  load_translations(paths)
  translations[locale] ||= {}
end

und wenn Sie ältere Redmine haben, fügen Sie hinzu

module Implementation
        include ::I18n::Backend::Base
        **include ::I18n::Backend::Pluralization**
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.