
== Configuring inflections

This data will be used in any further example:

=== YAML

  en:
    i18n:
      inflections:
        
        @person:
          i:          "i"
          u:          "you"
          he:         "he"
          she:        "she"
          it:         "it"
          you:        @u
        
        gender:
          m:          "male"
          f:          "female"
          n:          "neuter"
          default:    n
        
      
    welcome: "Dear @{f:Lady|m:Sir|n:You|All}!"  
    sayit:   "@person{i:I|u:You|he:He|she:She|it:It}{ }{i:am|u:are|he,she,it:is}"
    tobe:    "%{person} @person{i:am|u:are|he,she,it:is}"
  

=== Code

  I18n.backend.store_translations(:en, :i18n => { :inflections => {
    :gender => {
      :m          => 'male',
      :f          => 'female',
      :n          => 'neuter',
      :default    => :n
      },
    :@person => {
      :i          => 'i',
      :u          => 'you',
      :he         => 'he',
      :she        => 'she',
      :it         => 'it',
      :you        => :@u
      }
  }})
  
  I18n.backend.store_translations(:en, 'welcome' => 'Dear @{f:Lady|m:Sir|n:You|All}!')
  I18n.backend.store_translations(:en, 'sayit'   => '@person{i:I|u:You|he:He|she:She|it:It}{ }{i:am|u:are|he,she,it:is}')
  I18n.backend.store_translations(:en, 'tobe'    => '%{person} @person{i:am|u:are|he,she,it:is}')
  I18n.locale = :en

== Simple interpolation

When no option, it falls back to default token (n):

  I18n.translate('welcome')
  #=> "Dear You!"

When :m, it interpolates the m token's value:

  I18n.translate('welcome', :gender => :m)
  #=> "Dear Sir!"

When unknown, it falls back to default token (n):

  I18n.translate('welcome', :gender => :unknown)
  #=> "Dear You!"

When +nil+, it falls back to default token (n):

  I18n.translate('welcome', :gender => nil)
  #=> "Dear You!"

=== inflector_unknown_defaults

When :inflector_unknown_defaults is false, it falls back to free text:

  I18n.translate('welcome', :gender => :unknown, :inflector_unknown_defaults => false)
  #=> "Dear All!"

It also falls back when an inflection option is nil or empty:

  I18n.translate('welcome', :gender => nil, :inflector_unknown_defaults => false)
  #=> "Dear All!"

== Named pattern

Regular inflection option will be used if there is no strict inflection option:

  I18n.translate('sayit', :person => :i)
  #=> "I am"

Strict inflection option has precedence:

  I18n.translate('sayit', :person => :i, :@person => :u)
  #=> "You are"

Strict inflection option has precedence even if the option's value is messy:
 
  I18n.translate('sayit', :person => :i, :@person => :unknown)
  #=> " "
  
=== Using with interpolation argument

First part is interpolated using standard interpolation variable while
second part of the sentence comes from interpolation of inflection pattern.
The same option is feeding both engines.

  I18n.translate('tobe', :person => :i)
  #=> "i am"

Note funny thing. The interpolation variable +test+ takes value (+i+) from
+:person+ while option +:@person+ takes precedence when it comes to inflections.
Keep that in mind when combining regular interpolation variables with named patterns
while using the same variable for controlling both. Choose non-strict notation
for an option then.

  I18n.translate('tobe', :person => :i, :@person => :u)
  #=> "i are"

No free text in 'tobe' so the empty string is interpolated when strict kind is unknown:

  I18n.translate('tobe', :person => :i, :@person => :unknown)
  #=> "i "

== API

=== Getting kinds

Getting all known regular kinds:

  I18n.inflector.kinds
  #=> [:gender]

Getting all known strict kinds:

  I18n.inflector.strict.kinds
  #=> [:person]

Getting all known kinds for language 'pl':

  I18n.inflector.kinds(:pl)
  #=> []

=== Listing all known options

  I18n.inflector.options.known
  #=> [:inflector_cache_aware, :inflector_raises, :inflector_aliased_patterns,
  #    :inflector_unknown_defaults, :inflector_excluded_defaults]

== Real-life example for Polish language

Polish is highly inflected language. Additionally, position of a word in
a sentence is mutually coupled with meaning. That makes it extreemly
hard to create finite-state machine that would handle Polish grammar.
However, flection means that the same cores are combined with suffixes
and prefixes depending on many different kinds: gender, tense, form,
animation, declination and more. That makes Polish (and other Slavic
languages) alphabetically redundant. By interpolating common cores,
prefixes and suffixes of words we're able make our patterns compact.

=== YAML

  pl:
    are_you_sure: "@{m,f:Jesteś pew}{m:ien|f:na}{n:Na pewno}?"
    
    i18n:
      inflections:
        gender:
          f:          "rodzaj żeński"
          m:          "rodzaj męski"
          n:          "forma bezosobowa"
          masculine:  @m
          facet:      @m
          chłopak:    @m
          feminine:   @f
          pani:       @f
          kobieta:    @f
          k:          @f
          dziewczyna: @f
          impersonal: @n
          default:    n

=== Code

  # Using shorter form than listed as YAML
  
  I18n.backend.store_translations(:pl, :i18n => { :inflections => { :gender =>
                                  { :f => 'f', :m=>'m', :n=>'n', :kobieta=>:@f, :facet => :@m, :default=>:n }}})
  
  # Making use of commas makes it easy to implement DRY
  # and re-use some parts of the words that are the same in two or more phrases
  
  I18n.backend.store_translations(:pl, :are_you_sure => "@{m,f:Jesteś pew}@{m:ien|f:na}@{n:Na pewno}?")
    
  I18n.locale = :pl
  
  I18n.translate('are_you_sure', :gender => :kobieta)
  #=> "Jesteś pewna?"
    
  I18n.translate('are_you_sure', :gender => :facet)
  #=> "Jesteś pewien?"  
  
  I18n.translate('are_you_sure')
  #=> "Na pewno?"

  # It would look like that without commas:
  I18n.backend.store_translations(:pl, :are_you_sure => "@{m:Jesteś pewien|f:Jesteś pewna|n:Na pewno}?")

  # That would also work but it's less readable.
  # PS: Have you ever configured Sendmail? ;-)
  I18n.backend.store_translations(:pl, :are_you_sure => "@{n:Na|m,f:Jesteś}{ pew}{m:ie}{n}{f:a|n:o}?")

=== Complex pattern usage

  # Store needed translations
  I18n.backend.store_translations(:pl,
    :i18n => { :inflections => {
      :@gender =>
          { :f       => 'f', :m     => 'm', :n       => 'n',
            :kobieta => :@f, :facet => :@m, :default => :n },
      :@tense =>
          { :t     => 'teraz', :w       => 'przeszły', :j     => 'przyszły',
            :teraz => :@t,     :wczoraj => :@w,        :jutro => :@j,
            :default => :t }
      }})
  
  I18n.backend.store_translations(:pl,
    :msg_receive => "@gender+tense{n+w:Otrzymano|Dosta}{*+t:jesz|*+j:niesz|f+w:łaś|m+w:łeś} wiadomość")

  I18n.locale = :pl

  p I18n.translate('msg_receive', :gender => :kobieta)
  #=> "Dostajesz wiadomość"

  p I18n.translate('msg_receive', :gender => :facet)
  #=> "Dostajesz wiadomość"

  p I18n.translate('msg_receive')
  #=> "Dostajesz wiadomość"

  p I18n.translate('msg_receive', :gender => :kobieta, :tense => :wczoraj)
  #=> "Dostałaś wiadomość"

  p I18n.translate('msg_receive', :gender => :facet, :tense => :wczoraj)
  #=> "Dostałeś wiadomość"
  
  p I18n.translate('msg_receive', :tense => :jutro)
  #=> "Dostaniesz wiadomość"
  
  p I18n.translate('msg_receive', :tense => :wczoraj)
  #=> "Otrzymano wiadomość"

==== YAML for the example above

The example above may use this YAML content instead of +store_translations+:

  pl:
    msg_receive: "@gender+tense{n+w:Otrzymano|Dosta}{*+t:jesz|*+j:niesz|f+w:łaś|m+w:łeś} wiadomość"
    
    i18n:
      inflections:
        @gender:
          m:  'male'
          f:  'female'
          n:  'neuter'
          kobieta:  @f
          facet:    @m
          default:  n
        @tense:
          t:        'teraźniejszy'
          w:        'przeszły'
          j:        'przyszły'
          teraz:    @t
          wczoraj:  @w
          jutro:    @j
          default:  @t

===== Alternative for +msg_receive+ key

The +msg_receive+ might also be expressed using two infleciton keys:

  pl:
    @msg_receive_1:
      @kind:    gender+tense
      @free:    'Dosta'
      n+w:      'Otrzymano'
  
    @msg_receive_2:
      @kind:    gender+tense
      @suffix:  " wiadomość"
      m,f,n+t:  "jesz"
      m,f,n+j:  "niesz"
      f+w:      "łaś"
      m+w:      "łeś"

But then you have to change the translation call too, e.g.:

  p I18n.translate(['@msg_receive_1','@msg_receive_2'], :gender => :kobieta).join
  #=> "Dostajesz wiadomość"

The split is necessary because we have two patterns here and no way to express them
as one inflection key.

== To be or not to be

Here is the example pattern that inflects English to be by tense,
person and grammatical number:

  en:
    i18n:
        inflections:
          @person:
              1: first
              2: second
              3: third
              i:    :@1
              you:  :@2
              He:   :@3
              She:  :@3
              it:   :@3
          @tense:
            past:      past
            present:   present
            now:       @present
            default:   present
          @num:
            s: singular
            p: plural
            default: s
    
    to_be: >
            @num+person{s+1:I|*+2:You|s+3:%{person}|p+3:They|p+1:We}
            @num+person+tense{s+1+present:am|s+2+present:are|s+3+present:is|
            p+*+present:are|s+1,3+past:was|p+*+past:were|s+2+past:were}

And the code that prints all possible combinations:

  [:i, :you, :He, :She, :It].each do |person|
    puts  I18n.translate(:to_be, :num => :s, :person => person, :tense => :now) + "\t| " +
          I18n.translate(:to_be, :num => :s, :person => person, :tense => :past)
  end
  
  puts
  
  (1..3).each do |person|
    puts  I18n.translate(:to_be, :num => :p, :person => person, :tense => :now) + " | " +
          I18n.translate(:to_be, :num => :p, :person => person, :tense => :past)
  end

to be continued…

