08bf6f5508f2011a2ec2c9e1b8ce41b87842ed00
[packages/precise/mcollective.git] / lib / mcollective / vendor / i18n / lib / i18n / locale / fallbacks.rb
1 # Locale Fallbacks
2 #
3 # Extends the I18n module to hold a fallbacks instance which is set to an
4 # instance of I18n::Locale::Fallbacks by default but can be swapped with a
5 # different implementation.
6 #
7 # Locale fallbacks will compute a number of fallback locales for a given locale.
8 # For example:
9 #
10 # <pre><code>
11 # I18n.fallbacks[:"es-MX"] # => [:"es-MX", :es, :en] </code></pre>
12 #
13 # Locale fallbacks always fall back to
14 #
15 #   * all parent locales of a given locale (e.g. :es for :"es-MX") first,
16 #   * the current default locales and all of their parents second
17 #
18 # The default locales are set to [I18n.default_locale] by default but can be
19 # set to something else.
20 #
21 # One can additionally add any number of additional fallback locales manually.
22 # These will be added before the default locales to the fallback chain. For
23 # example:
24 #
25 #   # using the default locale as default fallback locale
26 #
27 #   I18n.default_locale = :"en-US"
28 #   I18n.fallbacks = I18n::Locale::Fallbacks.new(:"de-AT" => :"de-DE")
29 #   I18n.fallbacks[:"de-AT"] # => [:"de-AT", :"de-DE", :de, :"en-US", :en]
30 #
31 #   # using a custom locale as default fallback locale
32 #
33 #   I18n.fallbacks = I18n::Locale::Fallbacks.new(:"en-GB", :"de-AT" => :de, :"de-CH" => :de)
34 #   I18n.fallbacks[:"de-AT"] # => [:"de-AT", :de, :"en-GB", :en]
35 #   I18n.fallbacks[:"de-CH"] # => [:"de-CH", :de, :"en-GB", :en]
36 #
37 #   # mapping fallbacks to an existing instance
38 #
39 #   # people speaking Catalan also speak Spanish as spoken in Spain
40 #   fallbacks = I18n.fallbacks
41 #   fallbacks.map(:ca => :"es-ES")
42 #   fallbacks[:ca] # => [:ca, :"es-ES", :es, :"en-US", :en]
43 #
44 #   # people speaking Arabian as spoken in Palestine also speak Hebrew as spoken in Israel
45 #   fallbacks.map(:"ar-PS" => :"he-IL")
46 #   fallbacks[:"ar-PS"] # => [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en]
47 #   fallbacks[:"ar-EG"] # => [:"ar-EG", :ar, :"en-US", :en]
48 #
49 #   # people speaking Sami as spoken in Finnland also speak Swedish and Finnish as spoken in Finnland
50 #   fallbacks.map(:sms => [:"se-FI", :"fi-FI"])
51 #   fallbacks[:sms] # => [:sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en]
52
53 module I18n
54   module Locale
55     class Fallbacks < Hash
56       def initialize(*mappings)
57         @map = {}
58         map(mappings.pop) if mappings.last.is_a?(Hash)
59         self.defaults = mappings.empty? ? [I18n.default_locale.to_sym] : mappings
60       end
61
62       def defaults=(defaults)
63         @defaults = defaults.map { |default| compute(default, false) }.flatten
64       end
65       attr_reader :defaults
66
67       def [](locale)
68         raise InvalidLocale.new(locale) if locale.nil?
69         locale = locale.to_sym
70         super || store(locale, compute(locale))
71       end
72
73       def map(mappings)
74         mappings.each do |from, to|
75           from, to = from.to_sym, Array(to)
76           to.each do |_to|
77             @map[from] ||= []
78             @map[from] << _to.to_sym
79           end
80         end
81       end
82
83       protected
84
85       def compute(tags, include_defaults = true, exclude = [])
86         result = Array(tags).collect do |tag|
87           tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym } - exclude
88           tags.each { |_tag| tags += compute(@map[_tag], false, exclude + tags) if @map[_tag] }
89           tags
90         end.flatten
91         result.push(*defaults) if include_defaults
92         result.uniq.compact
93       end
94     end
95   end
96 end