summaryrefslogtreecommitdiff
path: root/vendor/plugins/globalize2/lib
diff options
context:
space:
mode:
authorhukl <contact@smyck.org>2010-01-14 22:21:43 +0100
committerhukl <contact@smyck.org>2010-01-14 22:21:43 +0100
commit57d1382013c85a7b11ac8ce5e683f6006b12b328 (patch)
tree19646c4fa5952fa1cf0a2c874952affa346373f1 /vendor/plugins/globalize2/lib
parent1b86bf5f2e35d1820bfa32d979bcc2d9ff9a9a8e (diff)
Updated globalize2 to latest version. Modified existing code accoringly
Diffstat (limited to 'vendor/plugins/globalize2/lib')
-rw-r--r--vendor/plugins/globalize2/lib/globalize.rb15
-rw-r--r--vendor/plugins/globalize2/lib/globalize/active_record.rb194
-rw-r--r--vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb80
-rw-r--r--vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb25
-rw-r--r--vendor/plugins/globalize2/lib/globalize/active_record/migration.rb40
-rw-r--r--vendor/plugins/globalize2/lib/globalize/backend/chain.rb102
-rw-r--r--vendor/plugins/globalize2/lib/globalize/backend/pluralizing.rb37
-rw-r--r--vendor/plugins/globalize2/lib/globalize/backend/static.rb60
-rw-r--r--vendor/plugins/globalize2/lib/globalize/load_path.rb63
-rw-r--r--vendor/plugins/globalize2/lib/globalize/locale/fallbacks.rb63
-rw-r--r--vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb81
-rw-r--r--vendor/plugins/globalize2/lib/globalize/model/active_record.rb45
-rw-r--r--vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb96
-rw-r--r--vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb164
-rw-r--r--vendor/plugins/globalize2/lib/globalize/translation.rb32
-rw-r--r--vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb (renamed from vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb)16
-rw-r--r--vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb (renamed from vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb)8
-rw-r--r--vendor/plugins/globalize2/lib/locale/root.yml3
-rw-r--r--vendor/plugins/globalize2/lib/rails_edge_load_path_patch.rb40
19 files changed, 365 insertions, 799 deletions
diff --git a/vendor/plugins/globalize2/lib/globalize.rb b/vendor/plugins/globalize2/lib/globalize.rb
new file mode 100644
index 0000000..67c1878
--- /dev/null
+++ b/vendor/plugins/globalize2/lib/globalize.rb
@@ -0,0 +1,15 @@
1module Globalize
2 autoload :ActiveRecord, 'globalize/active_record'
3
4 class << self
5 def fallbacks?
6 I18n.respond_to?(:fallbacks)
7 end
8
9 def fallbacks(locale)
10 fallbacks? ? I18n.fallbacks[locale] : [locale.to_sym]
11 end
12 end
13end
14
15ActiveRecord::Base.send(:include, Globalize::ActiveRecord)
diff --git a/vendor/plugins/globalize2/lib/globalize/active_record.rb b/vendor/plugins/globalize2/lib/globalize/active_record.rb
new file mode 100644
index 0000000..d2a843f
--- /dev/null
+++ b/vendor/plugins/globalize2/lib/globalize/active_record.rb
@@ -0,0 +1,194 @@
1module Globalize
2 class MigrationError < StandardError; end
3 class MigrationMissingTranslatedField < MigrationError; end
4 class BadMigrationFieldType < MigrationError; end
5
6 module ActiveRecord
7 autoload :Adapter, 'globalize/active_record/adapter'
8 autoload :Attributes, 'globalize/active_record/attributes'
9 autoload :Migration, 'globalize/active_record/migration'
10
11 def self.included(base)
12 base.extend ActMacro
13 end
14
15 class << self
16 def build_translation_class(target, options)
17 options[:table_name] ||= "#{target.table_name.singularize}_translations"
18
19 klass = target.const_defined?(:Translation) ?
20 target.const_get(:Translation) :
21 target.const_set(:Translation, Class.new(::ActiveRecord::Base))
22
23 klass.class_eval do
24 set_table_name(options[:table_name])
25 belongs_to target.name.underscore.gsub('/', '_')
26 def locale; read_attribute(:locale).to_sym; end
27 def locale=(locale); write_attribute(:locale, locale.to_s); end
28 end
29
30 klass
31 end
32 end
33
34 module ActMacro
35 def locale
36 (defined?(@@locale) && @@locale)
37 end
38
39 def locale=(locale)
40 @@locale = locale
41 end
42
43 def translates(*attr_names)
44 return if translates?
45 options = attr_names.extract_options!
46
47 class_inheritable_accessor :translation_class, :translated_attribute_names
48 self.translation_class = ActiveRecord.build_translation_class(self, options)
49 self.translated_attribute_names = attr_names.map(&:to_sym)
50
51 include InstanceMethods
52 extend ClassMethods, Migration
53
54 after_save :save_translations!
55 has_many :translations, :class_name => translation_class.name,
56 :foreign_key => class_name.foreign_key,
57 :dependent => :delete_all,
58 :extend => HasManyExtensions
59
60 named_scope :with_translations, lambda { |locale|
61 conditions = required_attributes.map do |attribute|
62 "#{quoted_translation_table_name}.#{attribute} IS NOT NULL"
63 end
64 conditions << "#{quoted_translation_table_name}.locale = ?"
65 { :include => :translations, :conditions => [conditions.join(' AND '), locale] }
66 }
67
68 attr_names.each { |attr_name| translated_attr_accessor(attr_name) }
69 end
70
71 def translates?
72 included_modules.include?(InstanceMethods)
73 end
74 end
75
76 module HasManyExtensions
77 def by_locale(locale)
78 first(:conditions => { :locale => locale.to_s })
79 end
80
81 def by_locales(locales)
82 all(:conditions => { :locale => locales.map(&:to_s) })
83 end
84 end
85
86 module ClassMethods
87 delegate :set_translation_table_name, :to => :translation_class
88
89 def with_locale(locale)
90 previous_locale, self.locale = self.locale, locale
91 result = yield
92 self.locale = previous_locale
93 result
94 end
95
96 def translation_table_name
97 translation_class.table_name
98 end
99
100 def quoted_translation_table_name
101 translation_class.quoted_table_name
102 end
103
104 def required_attributes
105 validations = reflect_on_all_validations.select do |validation|
106 validation.macro == :validates_presence_of
107 end.map(&:name)
108 end
109
110 def respond_to?(method, *args, &block)
111 method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym) || super
112 end
113
114 def method_missing(method, *args)
115 if method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym)
116 find_first_by_translated_attr_and_locales($1, args.first)
117 else
118 super
119 end
120 end
121
122 protected
123
124 def find_first_by_translated_attr_and_locales(name, value)
125 query = "#{translated_attr_name(name)} = ? AND #{translated_attr_name('locale')} IN (?)"
126 locales = Globalize.fallbacks(locale || I18n.locale).map(&:to_s)
127 find(:first, :joins => :translations, :conditions => [query, value, locales])
128 end
129
130 def translated_attr_accessor(name)
131 define_method "#{name}=", lambda { |value|
132 globalize.write(self.class.locale || I18n.locale, name, value)
133 self[name] = value
134 }
135 define_method name, lambda { |*args|
136 globalize.fetch(args.first || self.class.locale || I18n.locale, name)
137 }
138 alias_method "#{name}_before_type_cast", name
139 end
140
141 def translated_attr_name(name)
142 "#{translation_class.table_name}.#{name}"
143 end
144 end
145
146 module InstanceMethods
147 def globalize
148 @globalize ||= Adapter.new self
149 end
150
151 def attributes=(attributes, *args)
152 if attributes.respond_to?(:delete) && locale = attributes.delete(:locale)
153 self.class.with_locale(locale) { super }
154 else
155 super
156 end
157 end
158
159 def available_locales
160 translations.scoped(:select => 'DISTINCT locale').map(&:locale)
161 end
162
163 def translated_locales
164 translations.map(&:locale)
165 end
166
167 def translated_attributes
168 translated_attribute_names.inject({}) do |attributes, name|
169 attributes.merge(name => send(name))
170 end
171 end
172
173 def set_translations(options)
174 options.keys.each do |locale|
175 translation = translations.find_by_locale(locale.to_s) ||
176 translations.build(:locale => locale.to_s)
177 translation.update_attributes!(options[locale])
178 end
179 end
180
181 def reload(options = nil)
182 translated_attribute_names.each { |name| @attributes.delete(name.to_s) }
183 globalize.reset
184 super(options)
185 end
186
187 protected
188
189 def save_translations!
190 globalize.save_translations!
191 end
192 end
193 end
194end
diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb b/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb
new file mode 100644
index 0000000..12f89ec
--- /dev/null
+++ b/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb
@@ -0,0 +1,80 @@
1module Globalize
2 module ActiveRecord
3 class Adapter
4 # The cache caches attributes that already were looked up for read access.
5 # The stash keeps track of new or changed values that need to be saved.
6 attr_reader :record, :cache, :stash
7
8 def initialize(record)
9 @record = record
10 @cache = Attributes.new
11 @stash = Attributes.new
12 end
13
14 def fetch(locale, attr_name)
15 cache.contains?(locale, attr_name) ?
16 cache.read(locale, attr_name) :
17 cache.write(locale, attr_name, fetch_attribute(locale, attr_name))
18 end
19
20 def write(locale, attr_name, value)
21 stash.write(locale, attr_name, value)
22 cache.write(locale, attr_name, value)
23 end
24
25 def save_translations!
26 stash.each do |locale, attrs|
27 translation = record.translations.find_or_initialize_by_locale(locale.to_s)
28 attrs.each { |attr_name, value| translation[attr_name] = value }
29 translation.save!
30 end
31 stash.clear
32 end
33
34 def reset
35 cache.clear
36 # stash.clear
37 end
38
39 protected
40
41 def fetch_translation(locale)
42 locale = locale.to_sym
43 record.translations.loaded? ? record.translations.detect { |t| t.locale == locale } :
44 record.translations.by_locale(locale)
45 end
46
47 def fetch_translations(locale)
48 # only query if not already included with :include => translations
49 record.translations.loaded? ? record.translations :
50 record.translations.by_locales(Globalize.fallbacks(locale))
51 end
52
53 def fetch_attribute(locale, attr_name)
54 translations = fetch_translations(locale)
55 value, requested_locale = nil, locale
56
57 Globalize.fallbacks(locale).each do |fallback|
58 translation = translations.detect { |t| t.locale == fallback }
59 value = translation && translation.send(attr_name)
60 locale = fallback && break if value
61 end
62
63 set_metadata(value, :locale => locale, :requested_locale => requested_locale)
64 value
65 end
66
67 def set_metadata(object, metadata)
68 if object.respond_to?(:translation_metadata)
69 object.translation_metadata.merge!(meta_data)
70 end
71 end
72
73 def translation_metadata_accessor(object)
74 return if obj.respond_to?(:translation_metadata)
75 class << object; attr_accessor :translation_metadata end
76 object.translation_metadata ||= {}
77 end
78 end
79 end
80end
diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb b/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb
new file mode 100644
index 0000000..7bd923c
--- /dev/null
+++ b/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb
@@ -0,0 +1,25 @@
1# Helper class for storing values per locale. Used by Globalize::Adapter
2# to stash and cache attribute values.
3module Globalize
4 module ActiveRecord
5 class Attributes < Hash
6 def [](locale)
7 locale = locale.to_sym
8 self[locale] = {} unless has_key?(locale)
9 self.fetch(locale)
10 end
11
12 def contains?(locale, attr_name)
13 self[locale].has_key?(attr_name)
14 end
15
16 def read(locale, attr_name)
17 self[locale][attr_name]
18 end
19
20 def write(locale, attr_name, value)
21 self[locale][attr_name] = value
22 end
23 end
24 end
25end
diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb b/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb
new file mode 100644
index 0000000..ebff3b6
--- /dev/null
+++ b/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb
@@ -0,0 +1,40 @@
1module Globalize
2 module ActiveRecord
3 module Migration
4 def create_translation_table!(fields)
5 translated_attribute_names.each do |f|
6 raise MigrationMissingTranslatedField, "Missing translated field #{f}" unless fields[f]
7 end
8
9 fields.each do |name, type|
10 if translated_attribute_names.include?(name) && ![:string, :text].include?(type)
11 raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text"
12 end
13 end
14
15 self.connection.create_table(translation_table_name) do |t|
16 t.references self.table_name.singularize
17 t.string :locale
18 fields.each do |name, type|
19 t.column name, type
20 end
21 t.timestamps
22 end
23
24 self.connection.add_index(translation_table_name, "#{self.table_name.singularize}_id", :name => translation_index_name)
25 end
26
27 def translation_index_name
28 require 'digest/sha1'
29 # FIXME what's the max size of an index name?
30 index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id"
31 index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}"
32 end
33
34 def drop_translation_table!
35 self.connection.remove_index(translation_table_name, :name => translation_index_name) rescue nil
36 self.connection.drop_table(translation_table_name)
37 end
38 end
39 end
40end
diff --git a/vendor/plugins/globalize2/lib/globalize/backend/chain.rb b/vendor/plugins/globalize2/lib/globalize/backend/chain.rb
deleted file mode 100644
index bb8679e..0000000
--- a/vendor/plugins/globalize2/lib/globalize/backend/chain.rb
+++ /dev/null
@@ -1,102 +0,0 @@
1module I18n
2 class << self
3 def chain_backends(*args)
4 self.backend = Globalize::Backend::Chain.new(*args)
5 end
6 end
7end
8
9module Globalize
10 module Backend
11 class Chain
12 def initialize(*args)
13 add(*args) unless args.empty?
14 end
15
16 # Change this to a) accept any number of backends and b) accept classes.
17 # When classes are passed instantiate them and add the instances as backends.
18 # Return the added backends from #add.
19 #
20 # Add an initialize method that accepts the same arguments and passes them
21 # to #add, so we could:
22 # I18n.backend = Globalize::Backend::Chain.new(Globalize::Backend::Foo, Globalize::Backend::Bar)
23 # Globalize::Backend::Chain.new(:foo, :bar)
24 # Globalize.chain_backends :foo, :bar
25 def add(*backends)
26 backends.each do |backend|
27 backend = Globalize::Backend.const_get(backend.to_s.capitalize) if backend.is_a? Symbol
28 backend = backend.new if backend.is_a? Class
29 self.backends << backend
30 end
31 end
32
33 def load_translations(*args)
34 backends.each{|backend| backend.load_translations(*args) }
35 end
36
37 # For defaults:
38 # Never pass any default option to the backends but instead implement our own default
39 # mechanism (e.g. symbols as defaults would need to be passed to the whole chain to
40 # be translated).
41 #
42 # For namespace lookup:
43 # Only return if the result is not a hash OR count is not present, otherwise merge them.
44 # So in effect the count variable would control whether we have a namespace lookup or a
45 # pluralization going on.
46 #
47 # Exceptions:
48 # Make sure that we catch MissingTranslationData exceptions and raise
49 # one in the end when no translation was found at all.
50 #
51 # For bulk translation:
52 # If the key is an array we need to call #translate for each of the
53 # keys and collect the results.
54
55 def translate(locale, key, options = {})
56 raise I18n::InvalidLocale.new(locale) if locale.nil?
57 return key.map{|k| translate locale, k, options } if key.is_a? Array
58
59 default = options.delete(:default)
60 result = backends.inject({}) do |namespace, backend|
61 begin
62 translation = backend.translate(locale.to_sym, key, options)
63 if namespace_lookup?(translation, options)
64 namespace.merge! translation
65 elsif translation
66 return translation
67 end
68 rescue I18n::MissingTranslationData
69 end
70 end
71 result || default(locale, default, options) || raise(I18n::MissingTranslationData.new(locale, key, options))
72 end
73
74 def localize(locale, object, format = :default)
75 backends.each do |backend|
76 result = backend.localize(locale, object, format) and return result
77 end
78 end
79
80 protected
81 def backends
82 @backends ||= []
83 end
84
85 def default(locale, default, options = {})
86 case default
87 when String then default
88 when Symbol then translate locale, default, options
89 when Array then default.each do |obj|
90 result = default(locale, obj, options.dup) and return result
91 end and nil
92 end
93 rescue I18n::MissingTranslationData
94 nil
95 end
96
97 def namespace_lookup?(result, options)
98 result.is_a?(Hash) and not options.has_key?(:count)
99 end
100 end
101 end
102end \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/globalize/backend/pluralizing.rb b/vendor/plugins/globalize2/lib/globalize/backend/pluralizing.rb
deleted file mode 100644
index 80016f2..0000000
--- a/vendor/plugins/globalize2/lib/globalize/backend/pluralizing.rb
+++ /dev/null
@@ -1,37 +0,0 @@
1require 'i18n/backend/simple'
2
3module Globalize
4 module Backend
5 class Pluralizing < I18n::Backend::Simple
6 def pluralize(locale, entry, count)
7 return entry unless entry.is_a?(Hash) and count
8 key = :zero if count == 0 && entry.has_key?(:zero)
9 key ||= pluralizer(locale).call(count)
10 raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key)
11 translation entry[key], :plural_key => key
12 end
13
14 def add_pluralizer(locale, pluralizer)
15 pluralizers[locale.to_sym] = pluralizer
16 end
17
18 def pluralizer(locale)
19 pluralizers[locale.to_sym] || default_pluralizer
20 end
21
22 protected
23 def default_pluralizer
24 pluralizers[:en]
25 end
26
27 def pluralizers
28 @pluralizers ||= { :en => lambda{|n| n == 1 ? :one : :other } }
29 end
30
31 # Overwrite this method to return something other than a String
32 def translation(string, attributes)
33 string
34 end
35 end
36 end
37end \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/globalize/backend/static.rb b/vendor/plugins/globalize2/lib/globalize/backend/static.rb
deleted file mode 100644
index fb9e1fe..0000000
--- a/vendor/plugins/globalize2/lib/globalize/backend/static.rb
+++ /dev/null
@@ -1,60 +0,0 @@
1require 'globalize/backend/pluralizing'
2require 'globalize/locale/fallbacks'
3require 'globalize/translation'
4
5module Globalize
6 module Backend
7 class Static < Pluralizing
8 def initialize(*args)
9 add(*args) unless args.empty?
10 end
11
12 def translate(locale, key, options = {})
13 result, default, fallback = nil, options.delete(:default), nil
14 I18n.fallbacks[locale].each do |fallback|
15 begin
16 result = super(fallback, key, options) and break
17 rescue I18n::MissingTranslationData
18 end
19 end
20 result ||= default locale, default, options
21
22 attrs = {:requested_locale => locale, :locale => fallback, :key => key, :options => options}
23 translation(result, attrs) || raise(I18n::MissingTranslationData.new(locale, key, options))
24 end
25
26 protected
27
28 alias :orig_interpolate :interpolate unless method_defined? :orig_interpolate
29 def interpolate(locale, string, values = {})
30 result = orig_interpolate(locale, string, values)
31 translation = translation(string)
32 translation.nil? ? result : translation.replace(result)
33 end
34
35 def translation(result, meta = nil)
36 return unless result
37
38 case result
39 when Numeric
40 result
41 when String
42 result = Translation::Static.new(result) unless result.is_a? Translation::Static
43 result.set_meta meta
44 result
45 when Hash
46 Hash[*result.map do |key, value|
47 [key, translation(value, meta)]
48 end.flatten]
49 when Array
50 result.map do |value|
51 translation(value, meta)
52 end
53 else
54 result
55 # raise "unexpected translation type: #{result.inspect}"
56 end
57 end
58 end
59 end
60end \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/globalize/load_path.rb b/vendor/plugins/globalize2/lib/globalize/load_path.rb
deleted file mode 100644
index a49825b..0000000
--- a/vendor/plugins/globalize2/lib/globalize/load_path.rb
+++ /dev/null
@@ -1,63 +0,0 @@
1# Locale load_path and Locale loading support.
2#
3# To use this include the Globalize::LoadPath::I18n module to I18n like this:
4#
5# I18n.send :include, Globalize::LoadPath::I18n
6#
7# Clients can add load_paths using:
8#
9# I18n.load_path.add load_path, 'rb', 'yml' # pass any number of extensions like this
10# I18n.load_path << 'path/to/dir' # usage without an extension, defaults to 'yml'
11#
12# And load locale data using either of:
13#
14# I18n.load_locales 'en-US', 'de-DE'
15# I18n.load_locale 'en-US'
16#
17# This will lookup all files named like:
18#
19# 'path/to/dir/all.yml'
20# 'path/to/dir/en-US.yml'
21# 'path/to/dir/en-US/*.yml'
22#
23# The filenames will be passed to I18n.load_translations which delegates to
24# the backend. So the actual behaviour depends on the implementation of the
25# backend. I18n::Backend::Simple will be able to read YAML and plain Ruby
26# files. See the documentation for I18n.load_translations for details.
27
28module Globalize
29 class LoadPath < Array
30 def extensions
31 @extensions ||= ['rb', 'yml']
32 end
33 attr_writer :extensions
34
35 def locales
36 @locales ||= ['*']
37 end
38 attr_writer :locales
39
40 def <<(path)
41 push path
42 end
43
44 def push(*paths)
45 super(*paths.map{|path| filenames(path) }.flatten.uniq.sort)
46 end
47
48 protected
49
50 def filenames(path)
51 return [path] if File.file? path
52 patterns(path).map{|pattern| Dir[pattern] }
53 end
54
55 def patterns(path)
56 locales.map do |locale|
57 extensions.map do |extension|
58 %W(#{path}/all.#{extension} #{path}/#{locale}.#{extension} #{path}/#{locale}/**/*.#{extension})
59 end
60 end.flatten.uniq
61 end
62 end
63end \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/globalize/locale/fallbacks.rb b/vendor/plugins/globalize2/lib/globalize/locale/fallbacks.rb
deleted file mode 100644
index c4acd57..0000000
--- a/vendor/plugins/globalize2/lib/globalize/locale/fallbacks.rb
+++ /dev/null
@@ -1,63 +0,0 @@
1require 'globalize/locale/language_tag'
2
3module I18n
4 @@fallbacks = nil
5
6 class << self
7 # Returns the current fallbacks. Defaults to +Globalize::Locale::Fallbacks+.
8 def fallbacks
9 @@fallbacks ||= Globalize::Locale::Fallbacks.new
10 end
11
12 # Sets the current fallbacks. Used to set a custom fallbacks instance.
13 def fallbacks=(fallbacks)
14 @@fallbacks = fallbacks
15 end
16 end
17end
18
19module Globalize
20 module Locale
21 class Fallbacks < Hash
22 def initialize(*defaults)
23 @map = {}
24 map defaults.pop if defaults.last.is_a?(Hash)
25
26 defaults = [I18n.default_locale.to_sym] if defaults.empty?
27 self.defaults = defaults
28 end
29
30 def defaults=(defaults)
31 @defaults = defaults.map{|default| compute(default, false) }.flatten << :root
32 end
33 attr_reader :defaults
34
35 def [](tag)
36 tag = tag.to_sym
37 has_key?(tag) ? fetch(tag) : store(tag, compute(tag))
38 end
39
40 def map(mappings)
41 mappings.each do |from, to|
42 from, to = from.to_sym, Array(to)
43 to.each do |to|
44 @map[from] ||= []
45 @map[from] << to.to_sym
46 end
47 end
48 end
49
50 protected
51
52 def compute(tags, include_defaults = true)
53 result = Array(tags).collect do |tag|
54 tags = LanguageTag::tag(tag.to_sym).parents(true).map! {|t| t.to_sym }
55 tags.each{|tag| tags += compute(@map[tag]) if @map[tag] }
56 tags
57 end.flatten
58 result.push *defaults if include_defaults
59 result.uniq
60 end
61 end
62 end
63end
diff --git a/vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb b/vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb
deleted file mode 100644
index d9aae54..0000000
--- a/vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb
+++ /dev/null
@@ -1,81 +0,0 @@
1# for specifications see http://en.wikipedia.org/wiki/IETF_language_tag
2#
3# SimpleParser does not implement advanced usages such as grandfathered tags
4
5module Globalize
6 module Locale
7 module Rfc4646
8 SUBTAGS = [:language, :script, :region, :variant, :extension, :privateuse, :grandfathered]
9 FORMATS = {:language => :downcase, :script => :capitalize, :region => :upcase, :variant => :downcase}
10 end
11
12 class LanguageTag < Struct.new(*Rfc4646::SUBTAGS)
13 class << self
14 def parser
15 @@parser ||= SimpleParser
16 end
17
18 def parser=(parser)
19 @@parser = parser
20 end
21
22 def tag(tag)
23 matches = parser.match(tag)
24 new *matches if matches
25 end
26 end
27
28 Rfc4646::FORMATS.each do |name, format|
29 define_method(name) { self[name].send(format) unless self[name].nil? }
30 end
31
32 def to_sym
33 to_s.to_sym
34 end
35
36 def to_s
37 @tag ||= to_a.compact.join("-")
38 end
39
40 def to_a
41 members.collect {|attr| self.send(attr) }
42 end
43
44 def parent
45 segs = to_a.compact
46 segs.length < 2 ? nil : LanguageTag.tag(segs[0..(segs.length-2)].join('-'))
47 end
48
49 def parents(include_self = true)
50 result, parent = [], self.dup
51 result << parent if include_self
52 while parent = parent.parent
53 result << parent
54 end
55 result
56 end
57
58 module SimpleParser
59 PATTERN = %r{\A(?:
60 ([a-z]{2,3}(?:(?:-[a-z]{3}){0,3})?|[a-z]{4}|[a-z]{5,8}) # language
61 (?:-([a-z]{4}))? # script
62 (?:-([a-z]{2}|\d{3}))? # region
63 (?:-([0-9a-z]{5,8}|\d[0-9a-z]{3}))* # variant
64 (?:-([0-9a-wyz](?:-[0-9a-z]{2,8})+))* # extension
65 (?:-(x(?:-[0-9a-z]{1,8})+))?| # privateuse subtag
66 (x(?:-[0-9a-z]{1,8})+)| # privateuse tag
67 /* ([a-z]{1,3}(?:-[0-9a-z]{2,8}){1,2}) */ # grandfathered
68 )\z}xi
69
70 class << self
71 def match(tag)
72 c = PATTERN.match(tag.to_s).captures
73 c[0..4] << (c[5].nil? ? c[6] : c[5]) << c[7] # TODO c[7] is grandfathered, throw a NotImplemented exception here?
74 rescue
75 false
76 end
77 end
78 end
79 end
80 end
81end
diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record.rb
deleted file mode 100644
index 9218054..0000000
--- a/vendor/plugins/globalize2/lib/globalize/model/active_record.rb
+++ /dev/null
@@ -1,45 +0,0 @@
1require 'globalize/translation'
2require 'globalize/locale/fallbacks'
3require 'globalize/model/active_record/adapter'
4require 'globalize/model/active_record/translated'
5
6module Globalize
7 module Model
8 module ActiveRecord
9 class << self
10 def create_proxy_class(klass)
11 module_names = klass.name.split('::')
12 klass_name = module_names.pop
13 target = module_names.empty? ? Object : module_names.join('::').constantize
14
15 target.const_set "#{klass_name}Translation", Class.new(::ActiveRecord::Base) {
16 belongs_to "#{klass.name.underscore.gsub('/', '_')}".intern
17
18 def locale
19 read_attribute(:locale).to_sym
20 end
21
22 def locale=(locale)
23 write_attribute(:locale, locale.to_s)
24 end
25 }
26 end
27
28 def define_accessors(klass, attr_names)
29 attr_names.each do |attr_name|
30 klass.send :define_method, attr_name, lambda {
31 globalize.fetch self.class.locale, attr_name
32 }
33 klass.send :define_method, "#{attr_name}_before_type_cast", lambda {
34 globalize.fetch self.class.locale, attr_name
35 }
36 klass.send :define_method, "#{attr_name}=", lambda {|val|
37 globalize.stash self.class.locale, attr_name, val
38 self[attr_name] = val
39 }
40 end
41 end
42 end
43 end
44 end
45end \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb
deleted file mode 100644
index 93355b8..0000000
--- a/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb
+++ /dev/null
@@ -1,96 +0,0 @@
1module 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
96end
diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb
deleted file mode 100644
index 4f75c8a..0000000
--- a/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb
+++ /dev/null
@@ -1,164 +0,0 @@
1require 'digest/sha1'
2
3module Globalize
4 module Model
5 class MigrationError < StandardError; end
6 class MigrationMissingTranslatedField < MigrationError; end
7 class BadMigrationFieldType < MigrationError; end
8
9 module ActiveRecord
10 module Translated
11 def self.included(base)
12 base.extend ActMethods
13 end
14
15 module ActMethods
16 def translates(*attr_names)
17 options = attr_names.extract_options!
18 options[:translated_attributes] = attr_names
19
20 # Only set up once per class
21 unless included_modules.include? InstanceMethods
22 class_inheritable_accessor :globalize_options, :globalize_proxy
23
24 include InstanceMethods
25 extend ClassMethods
26
27 self.globalize_proxy = Globalize::Model::ActiveRecord.create_proxy_class(self)
28 has_many(
29 :globalize_translations,
30 :class_name => globalize_proxy.name,
31 :extend => Extensions,
32 :dependent => :delete_all,
33 :foreign_key => class_name.foreign_key
34 )
35
36 after_save :update_globalize_record
37 end
38
39 self.globalize_options = options
40 Globalize::Model::ActiveRecord.define_accessors(self, attr_names)
41
42 # Import any callbacks that have been defined by extensions to Globalize2
43 # and run them.
44 extend Callbacks
45 Callbacks.instance_methods.each { |callback| send(callback) }
46 end
47
48 def locale=(locale)
49 @@locale = locale
50 end
51
52 def locale
53 (defined?(@@locale) && @@locale) || I18n.locale
54 end
55 end
56
57 # Dummy Callbacks module. Extensions to Globalize2 can insert methods into here
58 # and they'll be called at the end of the translates class method.
59 module Callbacks
60 end
61
62 # Extension to the has_many :globalize_translations association
63 module Extensions
64 def by_locales(locales)
65 find :all, :conditions => { :locale => locales.map(&:to_s) }
66 end
67 end
68
69 module ClassMethods
70 def method_missing(method, *args)
71 if method.to_s =~ /^find_by_(\w+)$/ && globalize_options[:translated_attributes].include?($1.to_sym)
72 find(:first, :joins => :globalize_translations,
73 :conditions => [ "#{i18n_attr($1)} = ? AND #{i18n_attr('locale')} IN (?)",
74 args.first,I18n.fallbacks[I18n.locale].map{|tag| tag.to_s}])
75 else
76 super
77 end
78 end
79
80 def create_translation_table!(fields)
81 translated_fields = self.globalize_options[:translated_attributes]
82 translated_fields.each do |f|
83 raise MigrationMissingTranslatedField, "Missing translated field #{f}" unless fields[f]
84 end
85
86 fields.each do |name, type|
87 if translated_fields.include?(name) && ![:string, :text].include?(type)
88 raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text"
89 end
90 end
91
92 self.connection.create_table(translation_table_name) do |t|
93 t.references self.table_name.singularize
94 t.string :locale
95 fields.each do |name, type|
96 t.column name, type
97 end
98 t.timestamps
99 end
100
101 self.connection.add_index(translation_table_name, "#{self.table_name.singularize}_id", :name => translation_index_name)
102 end
103
104 def translation_table_name
105 self.name.underscore.gsub('/', '_') + '_translations'
106 end
107
108 def translation_index_name
109 # FIXME what's the max size of an index name?
110 index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id"
111 index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}"
112 end
113
114 def drop_translation_table!
115 self.connection.remove_index(translation_table_name, :name => translation_index_name)
116 self.connection.drop_table translation_table_name
117 end
118
119 private
120
121 def i18n_attr(attribute_name)
122 self.base_class.name.underscore.gsub('/', '_') + "_translations.#{attribute_name}"
123 end
124 end
125
126 module InstanceMethods
127 def reload(options = nil)
128 globalize.clear
129
130 # clear all globalized attributes
131 # TODO what's the best way to handle this?
132 self.class.globalize_options[:translated_attributes].each do |attr|
133 @attributes.delete(attr.to_s)
134 end
135
136 super(options)
137 end
138
139 def globalize
140 @globalize ||= Adapter.new self
141 end
142
143 def update_globalize_record
144 globalize.update_translations!
145 end
146
147 def translated_locales
148 globalize_translations.scoped(:select => 'DISTINCT locale').map do |translation|
149 translation.locale.to_sym
150 end
151 end
152
153 def set_translations options
154 options.keys.each do |key|
155 translation = globalize_translations.find_by_locale(key.to_s) ||
156 globalize_translations.build(:locale => key.to_s)
157 translation.update_attributes!(options[key])
158 end
159 end
160 end
161 end
162 end
163 end
164end \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/globalize/translation.rb b/vendor/plugins/globalize2/lib/globalize/translation.rb
deleted file mode 100644
index a80afcd..0000000
--- a/vendor/plugins/globalize2/lib/globalize/translation.rb
+++ /dev/null
@@ -1,32 +0,0 @@
1module Globalize
2 # Translations are simple value objects that carry some context information
3 # alongside the actual translation string.
4
5 class Translation < String
6 class Attribute < Translation
7 attr_accessor :requested_locale, :locale, :key
8 end
9
10 class Static < Translation
11 attr_accessor :requested_locale, :locale, :key, :options, :plural_key, :original
12
13 def initialize(string, meta = nil)
14 self.original = string
15 super
16 end
17 end
18
19 def initialize(string, meta = nil)
20 set_meta meta
21 super string
22 end
23
24 def fallback?
25 locale.to_sym != requested_locale.to_sym
26 end
27
28 def set_meta(meta)
29 meta.each {|name, value| send :"#{name}=", value } if meta
30 end
31 end
32end \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb b/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb
index 3f06ac2..24c1089 100644
--- a/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb
+++ b/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb
@@ -2,10 +2,10 @@
2# but additionally logs missing translations to a given log. 2# but additionally logs missing translations to a given log.
3# 3#
4# Useful for identifying missing translations during testing. 4# Useful for identifying missing translations during testing.
5#
6# E.g.
7# 5#
8# require 'globalize/i18n/missing_translations_log_handler 6# E.g.
7#
8# require 'globalize/i18n/missing_translations_log_handler'
9# I18n.missing_translations_logger = RAILS_DEFAULT_LOGGER 9# I18n.missing_translations_logger = RAILS_DEFAULT_LOGGER
10# I18n.exception_handler = :missing_translations_log_handler 10# I18n.exception_handler = :missing_translations_log_handler
11# 11#
@@ -16,7 +16,7 @@
16 16
17module I18n 17module I18n
18 @@missing_translations_logger = nil 18 @@missing_translations_logger = nil
19 19
20 class << self 20 class << self
21 def missing_translations_logger 21 def missing_translations_logger
22 @@missing_translations_logger ||= begin 22 @@missing_translations_logger ||= begin
@@ -24,18 +24,18 @@ module I18n
24 Logger.new(STDOUT) 24 Logger.new(STDOUT)
25 end 25 end
26 end 26 end
27 27
28 def missing_translations_logger=(logger) 28 def missing_translations_logger=(logger)
29 @@missing_translations_logger = logger 29 @@missing_translations_logger = logger
30 end 30 end
31 31
32 def missing_translations_log_handler(exception, locale, key, options) 32 def missing_translations_log_handler(exception, locale, key, options)
33 if MissingTranslationData === exception 33 if MissingTranslationData === exception
34 missing_translations_logger.warn(exception.message) 34 missing_translations_logger.warn(exception.message)
35 return exception.message 35 return exception.message
36 else 36 else
37 raise exception 37 raise exception
38 end 38 end
39 end 39 end
40 end 40 end
41end \ No newline at end of file 41end
diff --git a/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb b/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb
index e32be28..18237b1 100644
--- a/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb
+++ b/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb
@@ -2,10 +2,10 @@
2# but also raises on missing translations. 2# but also raises on missing translations.
3# 3#
4# Useful for identifying missing translations during testing. 4# Useful for identifying missing translations during testing.
5#
6# E.g.
7# 5#
8# require 'globalize/i18n/missing_translations_raise_handler 6# E.g.
7#
8# require 'globalize/i18n/missing_translations_raise_handler'
9# I18n.exception_handler = :missing_translations_raise_handler 9# I18n.exception_handler = :missing_translations_raise_handler
10module I18n 10module I18n
11 class << self 11 class << self
@@ -13,8 +13,6 @@ module I18n
13 raise exception 13 raise exception
14 end 14 end
15 end 15 end
16
17# self.exception_handler = :missing_translations_raise_handler
18end 16end
19 17
20I18n.exception_handler = :missing_translations_raise_handler 18I18n.exception_handler = :missing_translations_raise_handler
diff --git a/vendor/plugins/globalize2/lib/locale/root.yml b/vendor/plugins/globalize2/lib/locale/root.yml
deleted file mode 100644
index 2ec2b3b..0000000
--- a/vendor/plugins/globalize2/lib/locale/root.yml
+++ /dev/null
@@ -1,3 +0,0 @@
1root:
2 bidi:
3 direction: left-to-right \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/rails_edge_load_path_patch.rb b/vendor/plugins/globalize2/lib/rails_edge_load_path_patch.rb
deleted file mode 100644
index e6f90d8..0000000
--- a/vendor/plugins/globalize2/lib/rails_edge_load_path_patch.rb
+++ /dev/null
@@ -1,40 +0,0 @@
1module I18n
2 @@load_path = nil
3 @@default_locale = :'en-US'
4
5 class << self
6 def load_path
7 @@load_path ||= []
8 end
9
10 def load_path=(load_path)
11 @@load_path = load_path
12 end
13 end
14end
15
16I18n::Backend::Simple.module_eval do
17 def initialized?
18 @initialized ||= false
19 end
20
21 protected
22
23 def init_translations
24 load_translations(*I18n.load_path)
25 @initialized = true
26 end
27
28 def lookup(locale, key, scope = [])
29 return unless key
30 init_translations unless initialized?
31 keys = I18n.send :normalize_translation_keys, locale, key, scope
32 keys.inject(translations){|result, k| result[k.to_sym] or return nil }
33 end
34end
35
36rails_dir = File.expand_path "#{File.dirname(__FILE__)}/../../../rails/"
37paths = %w(actionpack/lib/action_view/locale/en-US.yml
38 activerecord/lib/active_record/locale/en-US.yml
39 activesupport/lib/active_support/locale/en-US.yml)
40paths.each{|path| I18n.load_path << "#{rails_dir}/#{path}" }