class TwitterCldr::Formatters::PluralFormatter

Constants

PLURALIZATION_REGEXP

Attributes

locale[R]

Public Class Methods

for_locale(locale) click to toggle source
# File lib/twitter_cldr/formatters/plurals/plural_formatter.rb, line 18
def for_locale(locale)
  formatter_cache[locale] ||= PluralFormatter.new(locale)
end
new(locale = TwitterCldr.locale) click to toggle source
# File lib/twitter_cldr/formatters/plurals/plural_formatter.rb, line 31
def initialize(locale = TwitterCldr.locale)
  @locale = TwitterCldr.convert_locale(locale)
end

Protected Class Methods

formatter_cache() click to toggle source
# File lib/twitter_cldr/formatters/plurals/plural_formatter.rb, line 24
def formatter_cache
  @formatter_cache ||= {}
end

Public Instance Methods

format(string, replacements) click to toggle source

Replaces every pluralization token in the string with a phrase formed using a number and a pluralization pattern from the replacements hash.

Two types of formatting are supported for pluralization.

  • Regular pluralization:

    Format of a pluralization group is '%{number:objects}'. When pluralization group like that is encountered in the string, replacements hash is expected to contain a number and pluralization patterns at keys :number and :objects respectively (note, keys of the replacements hash should be symbols).

    Pluralization patterns are specified as a hash containing a pattern for every plural category of the language. Keys of this hash should be symbols. If necessary, pluralization pattern can contain placeholder for the number. Syntax for the placeholder is similar to the hash-based string interpolation: '%{number}.

  • Inline pluralization:

    Pluralization group if formatted as '%<{ “number”: { “one”: “one horse” } }>'. Content inside '%<…>' is expected to be a valid string representation of a JSON object with a single key-value pair (JSON property), where key matches key in the replacements hash (e.g., in this example replacements hash can be something like { :number => 3 }), and value is a hash (JSON object) of pluralization rules to be used with this number. No space is allowed inside opening '%<{' and closing '}>' sequences. As pluralization group is parsed as JSON all keys and string values inside it should be enclosed in double quotes.

Examples:

f.format('%{count:horses}', :count => 1, :horses => { :one => 'one horse', :other => '%{count} horses' })
# => "one horse"

f.format('%{count:horses}', :count => 2, :horses => { :one => 'one horse', :other => '%{count} horses' })
# => "2 horses"

f.format('%<{ "count": {"one": "one horse", "other": "%{count} horses"} }>', :count => 2)
# => "2 horses"

Multiple pluralization groups can be present in the same string.

Examples:

f.format(
    '%{ponies_count:ponies} and %{unicorns_count:unicorns}',
    :ponies_count   => 2, :ponies   => { :one => 'one pony',    :other => '%{ponies_count} ponies' },
    :unicorns_count => 1, :unicorns => { :one => 'one unicorn', :other => '%{unicorns_count} unicorns' }
)
# => "2 ponies and one unicorn"

The same applies to inline pluralization.

Mixed styles of pluralization (both regular and inline) can be used in the same string, but it's better to avoid that as it might bring more confusion than real benefit.

If a number or required pluralization pattern is missing in the replacements hash, corresponding pluralization token is ignored.

Examples:

f.format('%{count:horses}', :horses => { :one => 'one horse', :other => '%{count} horses' })
# => "%{count:horses}"

f.format('%<{"count": {"one": "one horse", "other": "%{count} horses"}}>', {})
# => '%<{"count": {"one": "one horse", "other": "%{count} horses"}}>'

f.format('%{count:horses}', :count => 10, :horses => { :one => 'one horse' })
# => "%{count:horses}"

f.format('%<{"count": {"one": "one horse"}}>', :count => 2)
# => '%<{"count": {"one": "one horse"}}>'

f.format('%{count:horses}', {})
# => "%{count:horses}"
# File lib/twitter_cldr/formatters/plurals/plural_formatter.rb, line 106
def format(string, replacements)
  string.gsub(PLURALIZATION_REGEXP) do |match|
    number_placeholder, patterns = if $3
      parse_inline_pluralization($3)
    else
      [$1, replacements[$2.to_sym]]
    end

    number  = replacements[number_placeholder.to_sym]
    pattern = pluralization_pattern(patterns, number)

    pattern && interpolate_pattern(pattern, number_placeholder, number) || match
  end
end

Private Instance Methods

interpolate_pattern(pattern, placeholder, number) click to toggle source
# File lib/twitter_cldr/formatters/plurals/plural_formatter.rb, line 147
def interpolate_pattern(pattern, placeholder, number)
  pattern.gsub("%{#{placeholder}}", number.to_s)
end
parse_inline_pluralization(captured_group) click to toggle source
# File lib/twitter_cldr/formatters/plurals/plural_formatter.rb, line 123
def parse_inline_pluralization(captured_group)
  pluralization_hash = JSON.parse(captured_group)

  if pluralization_hash.is_a?(Hash) && pluralization_hash.size == 1
    pluralization_hash.first
  else
    raise ArgumentError.new('expected a Hash with a single key')
  end
end
pluralization_pattern(patterns, number) click to toggle source
# File lib/twitter_cldr/formatters/plurals/plural_formatter.rb, line 137
def pluralization_pattern(patterns, number)
  return unless number && patterns

  if patterns.is_a?(Hash)
    TwitterCldr::Utils.deep_symbolize_keys(patterns)[pluralization_rule(number)]
  else
    raise ArgumentError.new('expected patterns to be a Hash')
  end
end
pluralization_rule(number) click to toggle source
# File lib/twitter_cldr/formatters/plurals/plural_formatter.rb, line 133
def pluralization_rule(number)
  TwitterCldr::Formatters::Plurals::Rules.rule_for(number, locale)
end