1 # encoding: utf-8
2
3 module I18n
4 module Backend
5 # Backend that chains multiple other backends and checks each of them when
6 # a translation needs to be looked up. This is useful when you want to use
7 # standard translations with a Simple backend but store custom application
8 # translations in a database or other backends.
9 #
10 # To use the Chain backend instantiate it and set it to the I18n module.
11 # You can add chained backends through the initializer or backends
12 # accessor:
13 #
14 # # preserves the existing Simple backend set to I18n.backend
15 # I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)
16 #
17 # The implementation assumes that all backends added to the Chain implement
18 # a lookup method with the same API as Simple backend does.
19 class Chain
20 include Base
21
22 attr_accessor :backends
23
24 def initialize(*backends)
25 self.backends = backends
26 end
27
28 def reload!
29 backends.each { |backend| backend.reload! }
30 end
31
32 def store_translations(locale, data, options = {})
33 backends.first.store_translations(locale, data, options = {})
34 end
35
36 def available_locales
37 backends.map { |backend| backend.available_locales }.flatten.uniq
38 end
39
40 def translate(locale, key, options = {})
41 return key.map { |k| translate(locale, k, options) } if key.is_a?(Array)
42
43 default = options.delete(:default)
44 namespace = {}
45 backends.each do |backend|
46 begin
47 options.update(:default => default) if default and backend == backends.last
48 translation = backend.translate(locale, key, options)
49 if namespace_lookup?(translation, options)
50 namespace.update(translation)
51 elsif !translation.nil?
52 return translation
53 end
54 rescue MissingTranslationData
55 end
56 end
57 return namespace unless namespace.empty?
58 raise(I18n::MissingTranslationData.new(locale, key, options))
59 end
60
61 def localize(locale, object, format = :default, options = {})
62 backends.each do |backend|
63 begin
64 result = backend.localize(locale, object, format, options) and return result
65 rescue MissingTranslationData
66 end
67 end
68 raise(I18n::MissingTranslationData.new(locale, format, options))
69 end
70
71 protected
72 def namespace_lookup?(result, options)
73 result.is_a?(Hash) and not options.has_key?(:count)
74 end
75 end
76 end
77 end