From 7db0b073fec6bc3e6f213b58c76e7f43fcc2ab97 Mon Sep 17 00:00:00 2001 From: David Celis Date: Sun, 29 Jul 2012 15:31:53 -0700 Subject: Make ActiveSupport::Inflector locale aware and multilingual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Inflector is currently not very supportive of internationalized websites. If a user wants to singularize and/or pluralize words based on any locale other than English, they must define each case in locale files. Rather than create large locale files with mappings between singular and plural words, why not allow the Inflector to accept a locale? This patch makes ActiveSupport::Inflector locale aware and uses `:en`` unless otherwise specified. Users will still be provided a list of English (:en) inflections, but they may additionally define inflection rules for other locales. Each list is kept separately and permanently. There is no reason to limit users to one list of inflections: ActiveSupport::Inflector.inflections(:es) do |inflect| inflect.plural(/$/, 's') inflect.plural(/([^aeéiou])$/i, '\1es') inflect.plural(/([aeiou]s)$/i, '\1') inflect.plural(/z$/i, 'ces') inflect.plural(/á([sn])$/i, 'a\1es') inflect.plural(/é([sn])$/i, 'e\1es') inflect.plural(/í([sn])$/i, 'i\1es') inflect.plural(/ó([sn])$/i, 'o\1es') inflect.plural(/ú([sn])$/i, 'u\1es') inflect.singular(/s$/, '') inflect.singular(/es$/, '') inflect.irregular('el', 'los') end 'ley'.pluralize(:es) # => "leyes" 'ley'.pluralize(:en) # => "leys" 'avión'.pluralize(:es) # => "aviones" 'avión'.pluralize(:en) # => "avións" A multilingual Inflector should be of use to anybody that is tasked with internationalizing their Rails application. Signed-off-by: David Celis --- .../active_support/core_ext/string/inflections.rb | 22 +++++++++++++++++---- activesupport/lib/active_support/inflections.rb | 2 +- .../lib/active_support/inflector/inflections.rb | 23 +++++++++++++--------- .../lib/active_support/inflector/methods.rb | 22 +++++++++++++++------ 4 files changed, 49 insertions(+), 20 deletions(-) (limited to 'activesupport/lib/active_support') diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb index efa2d43f20..6edfcd7493 100644 --- a/activesupport/lib/active_support/core_ext/string/inflections.rb +++ b/activesupport/lib/active_support/core_ext/string/inflections.rb @@ -13,6 +13,11 @@ class String # the singular form will be returned if count == 1. # For any other value of +count+ the plural will be returned. # + # If the optional parameter +locale+ is specified, + # the word will be pluralized as a word of that language. + # By default, this parameter is set to :en. + # You must define your own inflection rules for languages other than English. + # # 'post'.pluralize # => "posts" # 'octopus'.pluralize # => "octopi" # 'sheep'.pluralize # => "sheep" @@ -21,15 +26,23 @@ class String # 'CamelOctopus'.pluralize # => "CamelOctopi" # 'apple'.pluralize(1) # => "apple" # 'apple'.pluralize(2) # => "apples" - def pluralize(count = nil) + # 'ley'.pluralize(:es) # => "leyes" + # 'ley'.pluralize(1, :es) # => "ley" + def pluralize(count = nil, locale = :en) + locale = count if count.is_a?(Symbol) if count == 1 self else - ActiveSupport::Inflector.pluralize(self) + ActiveSupport::Inflector.pluralize(self, locale) end end # The reverse of +pluralize+, returns the singular form of a word in a string. + # + # If the optional parameter +locale+ is specified, + # the word will be singularized as a word of that language. + # By default, this paramter is set to :en. + # You must define your own inflection rules for languages other than English. # # 'posts'.singularize # => "post" # 'octopi'.singularize # => "octopus" @@ -37,8 +50,9 @@ class String # 'word'.singularize # => "word" # 'the blue mailmen'.singularize # => "the blue mailman" # 'CamelOctopi'.singularize # => "CamelOctopus" - def singularize - ActiveSupport::Inflector.singularize(self) + # 'leyes'.singularize(:es) # => "ley" + def singularize(locale = :en) + ActiveSupport::Inflector.singularize(self, locale) end # +constantize+ tries to find a declared constant with the name specified diff --git a/activesupport/lib/active_support/inflections.rb b/activesupport/lib/active_support/inflections.rb index ca2d8cb270..ef882ebd09 100644 --- a/activesupport/lib/active_support/inflections.rb +++ b/activesupport/lib/active_support/inflections.rb @@ -1,7 +1,7 @@ require 'active_support/inflector/inflections' module ActiveSupport - Inflector.inflections do |inflect| + Inflector.inflections(:en) do |inflect| inflect.plural(/$/, 's') inflect.plural(/s$/i, 's') inflect.plural(/^(ax|test)is$/i, '\1es') diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb index c9e50a9462..091692e5a4 100644 --- a/activesupport/lib/active_support/inflector/inflections.rb +++ b/activesupport/lib/active_support/inflector/inflections.rb @@ -1,13 +1,15 @@ require 'active_support/core_ext/array/prepend_and_append' +require 'active_support/i18n' module ActiveSupport module Inflector extend self # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional - # inflection rules. + # inflection rules. If passed an optional locale, rules for other languages can be specified. The default locale is + # :en. Only rules for English are provided. # - # ActiveSupport::Inflector.inflections do |inflect| + # ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.plural /^(ox)$/i, '\1\2en' # inflect.singular /^(ox)en/i, '\1' # @@ -20,8 +22,9 @@ module ActiveSupport # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may # already have been loaded. class Inflections - def self.instance - @__instance__ ||= new + def self.instance(locale = :en) + @__instance__ ||= Hash.new { |h, k| h[k] = new } + @__instance__[locale] end attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms, :acronym_regex @@ -160,16 +163,18 @@ module ActiveSupport end # Yields a singleton instance of Inflector::Inflections so you can specify additional - # inflector rules. + # inflector rules. If passed an optional locale, rules for other languages can be specified. + # If not specified, defaults to :en. Only rules for English are provided. + # # - # ActiveSupport::Inflector.inflections do |inflect| + # ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.uncountable "rails" # end - def inflections + def inflections(locale = :en) if block_given? - yield Inflections.instance + yield Inflections.instance(locale) else - Inflections.instance + Inflections.instance(locale) end end end diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index c14a43de0d..44214d16fa 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -10,31 +10,41 @@ module ActiveSupport # # The Rails core team has stated patches for the inflections library will not be accepted # in order to avoid breaking legacy applications which may be relying on errant inflections. - # If you discover an incorrect inflection and require it for your application, you'll need - # to correct it yourself (explained below). + # If you discover an incorrect inflection and require it for your application or wish to + # define rules for languages other than English, please correct or add them yourself (explained below). module Inflector extend self # Returns the plural form of the word in the string. # + # If passed an optional +locale+ parameter, the word will be + # pluralized using rules defined for that language. By default, + # this parameter is set to :en. + # # "post".pluralize # => "posts" # "octopus".pluralize # => "octopi" # "sheep".pluralize # => "sheep" # "words".pluralize # => "words" # "CamelOctopus".pluralize # => "CamelOctopi" - def pluralize(word) - apply_inflections(word, inflections.plurals) + # "ley".pluralize(:es) # => "leyes" + def pluralize(word, locale = :en) + apply_inflections(word, inflections(locale).plurals) end # The reverse of +pluralize+, returns the singular form of a word in a string. # + # If passed an optional +locale+ parameter, the word will be + # pluralized using rules defined for that language. By default, + # this parameter is set to :en. + # # "posts".singularize # => "post" # "octopi".singularize # => "octopus" # "sheep".singularize # => "sheep" # "word".singularize # => "word" # "CamelOctopi".singularize # => "CamelOctopus" - def singularize(word) - apply_inflections(word, inflections.singulars) + # "leyes".singularize(:es) # => "ley" + def singularize(word, locale = :en) + apply_inflections(word, inflections(locale).singulars) end # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+ -- cgit v1.2.3