i18n 복수화


88

레일에서 i18n의 복수 문자열을 번역하고 싶습니다. 문자열은 다음과 같을 수 있습니다.

You have 2 kids

또는

You have 1 kid

pluralize helper 메서드를 사용할 수 있다는 것을 알고 있지만, 미래의 어느 시점에서든 내 견해를 엉망으로 만들 필요가 없도록 i18n 번역에 이것을 포함하고 싶습니다. 나는 그것이 :count어떻게 든 복수형 번역에 사용되는 것을 읽었 지만 그것이 어떻게 구현되는지에 대한 실제 자원을 찾을 수 없습니다.

번역 문자열에 변수를 전달할 수 있다는 것을 알고 있습니다. 나는 또한 다음과 같은 것을 시도했다.

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

잘 작동하지만 동일한 아이디어의 근본적인 문제가 있습니다. 'kid'복수형 도우미에 문자열을 지정해야합니다 . 그렇게하고 싶지 않다. 왜냐하면 미래에 문제를 보게 될 것이기 때문이다. 대신 번역에 모든 것을 유지하고 뷰에는 아무것도 남기지 않습니다.

어떻게 할 수 있습니까?


2
"#{....}"위 코드에서 "보간 자"와 따옴표 는 필요하지 않습니다.
Zabba

1
다른 언어의 복수형이 영어처럼 작동한다고 가정하기 때문에 잘못된 접근 방식을 사용합니다. 올바른 접근 방식에 대해서는 내 대답 을 참조하십시오 .
sorin

Sorin, 답변 해주셔서 감사합니다.이 질문에 gettext를 사용하고 싶지 않습니다. 나는 Zabba의 솔루션이 i18n에 대한 내 요구에 적합하다고 생각합니다.
SPYROS

Rails 3는 CLDR 및 'count'보간 변수를 사용하여보다 강력하게 처리합니다. guides.rubyonrails.org/i18n.html#pluralization
Luke W

몇 년 후 'kid'문자열에 대한 번역을 사용할 수도 있습니다 <%= t 'misc.kids', :kids_num => pluralize(1, t('kid')) %>. 어쩌면이 2011 년에 작동하지 않았다 그러나 그것은 확실히 레일 5.2.2 지금 않는 (!)
자비스 존슨

답변:


176

이 시도:

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! 

미안하지만 이것은 많은 언어에서 작동하지 않습니다. 복수화는 정말 복잡합니다. translate.sourceforge.net/wiki/l10n/pluralforms 참조이 때문에 내 대답이 더 적절하다고 생각합니다.
sorin

1
@sorin, 여러 복수화 규칙을 사용하도록 내 대답을 업데이트했습니다.
Zabba

5
괜찮습니다.하지만 이제 복수형 사전을 유지하기 위해 새로운 정규직이 생겼습니다!.
sorin

이것은 대단합니다! 일하기 위해 %{count}전체 블록 즉, 따옴표를 사용해야했습니다. one: "%{count} kid"
firedev

1
@ThePablick, 예, '/ initializer'디렉토리의 파일은 http 서버 시작시 한 번만로드되기 때문입니다.
Zabba 2013 년

37

러시아어를 사용하는 Ruby on Rails 프로그래머가 이것을 찾을 수 있기를 바랍니다. 내 자신의 매우 정확한 러시아어 복수화 공식을 공유하고 싶습니다. 유니 코드 사양을 기반으로 합니다. 여기에 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
        } 
      } 
    } 
  } 
}

원어민과 같은 경우를 즐길 수 111121. 그리고 여기 테스트 결과 :

  • 0 : 0 запросов / куриц / яблок
  • 하나 : 1 запрос / курица / яблоко
  • 소수 : 3 запроса / курицы / яблока
  • 많은 : 5 запросов / куриц / яблок
  • 하나 : 101 запрос / курица / яблоко
  • 소수 : 102 запроса / курицы / яблока
  • 많은 : 105 запросов / куриц / яблок
  • 다수 : 111 запросов / куриц / яблок
  • 다수 : 119 запросов / куриц / яблок
  • 하나 : 121 запрос / курица / яблоко
  • 소수 : 122 запроса / курицы / яблока
  • 많은 : 125 запросов / куриц / яблок

초기 답변에 감사드립니다!


1
당신이 언급 한 다른 대답은 이것을 다른 파일에 넣었습니다. 그래서 접근 방식으로 콘텐츠를 이동해야 config/locales/plurals.rb보다는config/initializers/pluralization.rb
silverdr

@silverdr 대답에서 파일 이름을 수정했습니다. 팁 고마워!
sashaegorov

11

첫째, 복수형의 수는 언어에 따라 다릅니다. 영어에는 2 개, 루마니아어에는 3 개, 아랍어에는 6 개가 있습니다!

복수형을 제대로 사용하려면을 사용해야 gettext합니다.

Ruby 및 rails의 경우 http://www.yotabanana.com/hiki/ruby-gettext-howto-rails.html을 확인해야합니다 .


4
Sorin, 이것이 제가 생각했던 것입니다. 그러나 이것은 CLDR 형식 ( unicode.org/repos/cldr-tmp/trunk/diff/supplemental/… )을 따르면 해결되는 것 같습니다 . 내가 잘못?
Nikos D

1 일, 2 일, 3 일, 4 일, 11 일, 12 일, 13 일도 있지만 21 일, 22 일, 23 일 등이 있습니다.
gnasher729


5

영어

상자에서 바로 작동 합니다.

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

4

실제로 번거로운 i18n 접근 방식에 대한 대안이 있습니다. 해결책은 Tr8n이라고합니다.

위의 코드는 다음과 같습니다.

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

그게 다야. 코드에서 키를 추출하여 리소스 번들로 유지할 필요가 없으며 각 언어에 대한 복수화 규칙을 구현할 필요가 없습니다. Tr8n은 모든 언어에 대한 숫자 컨텍스트 규칙과 함께 제공됩니다. 성별 규칙, 목록 규칙 및 언어 케이스도 함께 제공됩니다.

위 번역 키의 전체 정의는 실제로 다음과 같습니다.

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

그러나 공간과 시간을 절약하기 위해 num은 자동으로 숫자 규칙에 매핑되며 규칙 값에 대한 모든 옵션을 제공 할 필요가 없습니다. Tr8n에는 즉석에서 작업을 수행 할 복수형 및 인플 렉터가 함께 제공됩니다.

러시아어로 된 키의 번역은 다음과 같습니다.

 "У вас есть {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에는 언어와 문맥에 따라 하나의 키를 여러 번역에 매핑하는 메커니즘이 있습니다.

마지막 한가지. 카운트 부분을 굵게 만들어야한다면 어떨까요? 단순히 다음과 같습니다.

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

나중에 "굵게"를 재정의하려는 경우-매우 쉬울 것입니다. 모든 YAML 파일을 검토하고 변경할 필요가 없습니다. 한곳에서 수행하면됩니다.

자세한 내용은 여기를 참조하십시오.

https://github.com/tr8n/tr8n_rails_clientsdk

공개 : 저는 Tr8n 프레임 워크와 모든 라이브러리의 개발자이자 유지 관리자입니다.


1
반대표가 무엇인지 알았 으면 좋겠습니다. 대답은 괜찮은 것 같습니다.
doug65536

0

Redmine에 대해. config / locales /의 복수화 파일 규칙을 plurals.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**
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.