]> git.openstreetmap.org Git - rails.git/blob - vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb
Add Globalize2 so that we get some nice fall backs to other languages when a translat...
[rails.git] / vendor / plugins / globalize2 / lib / globalize / model / active_record / adapter.rb
1 module Globalize
2   module Model
3     class AttributeStash < Hash
4       def contains?(locale, attr_name)
5         locale = locale.to_sym
6         self[locale] ||= {}
7         self[locale].has_key? attr_name        
8       end
9       
10       def read(locale, attr_name)
11         locale = locale.to_sym
12         self[locale] ||= {}
13         self[locale][attr_name]
14       end
15       
16       def write(locale, attr_name, value)
17         locale = locale.to_sym
18         self[locale] ||= {}
19         self[locale][attr_name] = value
20       end
21     end
22     
23     class Adapter
24       def initialize(record)
25         @record = record
26         
27         # TODO what exactly are the roles of cache and stash
28         @cache = AttributeStash.new
29         @stash = AttributeStash.new
30       end
31       
32       def fetch(locale, attr_name)
33         # locale = I18n.locale
34         is_cached = @cache.contains?(locale, attr_name)
35         is_cached ? @cache.read(locale, attr_name) : begin
36           value = fetch_attribute locale, attr_name
37           @cache.write locale, attr_name, value if value && value.locale == locale
38           value
39         end
40       end
41       
42       def stash(locale, attr_name, value)
43         @stash.write locale, attr_name, value
44         @cache.write locale, attr_name, value
45       end
46       
47       def update_translations!
48         @stash.each do |locale, attrs|
49           translation = @record.globalize_translations.find_or_initialize_by_locale(locale.to_s)
50           attrs.each{|attr_name, value| translation[attr_name] = value }
51           translation.save!
52         end
53         @stash.clear
54       end
55       
56       # Clears the cache
57       def clear
58         @cache.clear
59         @stash.clear
60       end
61       
62       private
63       
64       def fetch_attribute(locale, attr_name)
65         fallbacks = I18n.fallbacks[locale].map{|tag| tag.to_s}.map(&:to_sym)
66         
67         # If the translations were included with 
68         # :include => globalize_translations
69         # there is no need to query them again.
70         unless @record.globalize_translations.loaded?
71           translations = @record.globalize_translations.by_locales(fallbacks) 
72         else
73           translations = @record.globalize_translations
74         end
75         result, requested_locale = nil, locale
76
77         # Walk through the fallbacks, starting with the current locale itself, and moving
78         # to the next best choice, until we find a match.
79         # Check the @globalize_set_translations cache first to see if we've just changed the 
80         # attribute and not saved yet.
81         fallbacks.each do |fallback|
82           # TODO should we be checking stash or just cache?
83           result = @stash.read(fallback, attr_name) || begin
84             translation = translations.detect {|tr| tr.locale == fallback }
85             translation && translation.send(attr_name)
86           end
87           if result
88             locale = fallback
89             break
90           end
91         end
92         result && Translation::Attribute.new(result, :locale => locale, :requested_locale => requested_locale)
93       end
94     end
95   end
96 end