globalize 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ module Globalize
2
+ module ActiveRecord
3
+ class Translation < ::ActiveRecord::Base
4
+
5
+ attr_accessible :locale
6
+ validates :locale, :presence => true
7
+
8
+ class << self
9
+ # Sometimes ActiveRecord queries .table_exists? before the table name
10
+ # has even been set which results in catastrophic failure.
11
+ def table_exists?
12
+ table_name.present? && super
13
+ end
14
+
15
+ def with_locales(*locales)
16
+ # Avoid using "IN" with SQL queries when only using one locale.
17
+ locales = locales.flatten.map(&:to_s)
18
+ locales = locales.first if locales.one?
19
+ where :locale => locales
20
+ end
21
+ alias with_locale with_locales
22
+
23
+ def translated_locales
24
+ select('DISTINCT locale').order(:locale).map(&:locale)
25
+ end
26
+ end
27
+
28
+ def locale
29
+ _locale = read_attribute :locale
30
+ _locale.present? ? _locale.to_sym : _locale
31
+ end
32
+
33
+ def locale=(locale)
34
+ write_attribute :locale, locale.to_s
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ # Setting this will force polymorphic associations to subclassed objects
41
+ # to use their table_name rather than the parent object's table name,
42
+ # which will allow you to get their models back in a more appropriate
43
+ # format.
44
+ #
45
+ # See http://www.ruby-forum.com/topic/159894 for details.
46
+ Globalize::ActiveRecord::Translation.abstract_class = true
@@ -0,0 +1,28 @@
1
+ module Globalize
2
+ module Interpolation
3
+ def interpolate(name, model, args)
4
+ translation = model.read_attribute(name, {:locale => locale_from(args)})
5
+ try_interpolation translation, interpolation_args_from(args)
6
+ end
7
+
8
+ private
9
+
10
+ def interpolation_args_from(args)
11
+ args.detect {|a| a.is_a? Hash }
12
+ end
13
+
14
+ def locale_from(args)
15
+ args.detect {|a| !a.is_a? Hash }
16
+ end
17
+
18
+ def try_interpolation(translation,args)
19
+ if args
20
+ I18n.interpolate(translation,args)
21
+ else
22
+ translation
23
+ end
24
+ end
25
+
26
+ extend self
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Globalize
2
+ Version = '3.0.0'
3
+ end
@@ -0,0 +1,5 @@
1
+ module Globalize
2
+ module Versioning
3
+ autoload :PaperTrail, 'globalize/versioning/paper_trail'
4
+ end
5
+ end
@@ -0,0 +1,41 @@
1
+ require 'paper_trail'
2
+
3
+ module Globalize
4
+ module Versioning
5
+ module PaperTrail
6
+ # At present this isn't used but we may use something similar in paper trail
7
+ # shortly, so leaving it around to reference easily.
8
+ #def versioned_columns
9
+ #super + self.class.translated_attribute_names
10
+ #end
11
+ end
12
+ end
13
+ end
14
+
15
+ ActiveRecord::Base.class_eval do
16
+ class << self
17
+ def has_paper_trail_with_globalize(*args)
18
+ has_paper_trail_without_globalize(*args)
19
+ include Globalize::Versioning::PaperTrail
20
+ end
21
+ alias_method_chain :has_paper_trail, :globalize
22
+ end
23
+ end
24
+
25
+ Version.class_eval do
26
+
27
+ before_save do |version|
28
+ version.locale = Globalize.locale.to_s
29
+ end
30
+
31
+ def self.locale_conditions_to_sql
32
+ "locale = '#{Globalize.locale.to_s}'"
33
+ end
34
+
35
+ scope :for_this_locale, lambda{ { :conditions => locale_conditions_to_sql } }
36
+
37
+ def sibling_versions_with_locales
38
+ sibling_versions_without_locales.for_this_locale
39
+ end
40
+ alias_method_chain :sibling_versions, :locales
41
+ end
@@ -0,0 +1,41 @@
1
+ # A simple exception handler that behaves like the default exception handler
2
+ # but additionally logs missing translations to a given log.
3
+ #
4
+ # Useful for identifying missing translations during testing.
5
+ #
6
+ # E.g.
7
+ #
8
+ # require 'globalize/i18n/missing_translations_log_handler'
9
+ # I18n.missing_translations_logger = RAILS_DEFAULT_LOGGER
10
+ # I18n.exception_handler = :missing_translations_log_handler
11
+ #
12
+ # To set up a different log file:
13
+ #
14
+ # logger = Logger.new("#{RAILS_ROOT}/log/missing_translations.log")
15
+ # I18n.missing_translations_logger = logger
16
+
17
+ module I18n
18
+ @@missing_translations_logger = nil
19
+
20
+ class << self
21
+ def missing_translations_logger
22
+ @@missing_translations_logger ||= begin
23
+ require 'logger' unless defined?(Logger)
24
+ Logger.new(STDOUT)
25
+ end
26
+ end
27
+
28
+ def missing_translations_logger=(logger)
29
+ @@missing_translations_logger = logger
30
+ end
31
+
32
+ def missing_translations_log_handler(exception, locale, key, options)
33
+ if MissingTranslationData === exception
34
+ missing_translations_logger.warn(exception.message)
35
+ return exception.message
36
+ else
37
+ raise exception
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,25 @@
1
+ # A simple exception handler that behaves like the default exception handler
2
+ # but also raises on missing translations.
3
+ #
4
+ # Useful for identifying missing translations during testing.
5
+ #
6
+ # E.g.
7
+ #
8
+ # require 'globalize/i18n/missing_translations_raise_handler'
9
+ # I18n.exception_handler = :missing_translations_raise_handler
10
+ module I18n
11
+ class << self
12
+ def missing_translations_raise_handler(exception, locale, key, options)
13
+ raise exception
14
+ end
15
+ end
16
+ end
17
+
18
+ I18n.exception_handler = :missing_translations_raise_handler
19
+
20
+ ActionView::Helpers::TranslationHelper.module_eval do
21
+ def translate(key, options = {})
22
+ I18n.translate(key, options)
23
+ end
24
+ alias :t :translate
25
+ end
@@ -0,0 +1,35 @@
1
+ require 'active_record/attribute_methods/query'
2
+
3
+ module ActiveRecord
4
+ module AttributeMethods
5
+ module Query
6
+ def query_attribute(attr_name)
7
+ unless value = read_attribute(attr_name)
8
+ false
9
+ else
10
+ column = self.class.columns_hash[attr_name]
11
+ if column.nil?
12
+
13
+ # TODO submit a rails patch
14
+
15
+ # not sure what active_record tests say but i guess this should mean:
16
+ # call to_i and check zero? if the value is a Numeric or starts with
17
+ # a digit, so it can meaningfully be typecasted by to_i
18
+
19
+ # if Numeric === value || value !~ /[^0-9]/
20
+ if Numeric === value || value.to_s =~ /^[0-9]/
21
+ !value.to_i.zero?
22
+ else
23
+ return false if ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value)
24
+ !value.blank?
25
+ end
26
+ elsif column.number?
27
+ !value.zero?
28
+ else
29
+ !value.blank?
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ module ActiveRecord
2
+ class Relation
3
+ if ::ActiveRecord::VERSION::STRING >= "3.2.1"
4
+ def where_values_hash
5
+ _translations_table_name = klass.respond_to?(:translations_table_name) ? klass.translations_table_name : nil
6
+
7
+ equalities = with_default_scope.where_values.grep(Arel::Nodes::Equality).find_all { |node|
8
+ [table_name, _translations_table_name].compact.include? node.left.relation.name
9
+ }
10
+
11
+ Hash[equalities.map { |where| [where.left.name, where.right] }].with_indifferent_access
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ require 'active_record/validations/uniqueness.rb'
2
+
3
+ ActiveRecord::Validations::UniquenessValidator.class_eval do
4
+ def validate_each_with_translations(record, attribute, value)
5
+ klass = record.class
6
+ if klass.translates? && klass.translated?(attribute)
7
+ if methods.include?(:build_relation) || respond_to?(:build_relation)
8
+ finder_class = klass.translation_class
9
+ table = finder_class.arel_table
10
+
11
+ relation = build_relation(finder_class, table, attribute, value).and(table[:locale].eq(Globalize.locale))
12
+ relation = relation.and(table[klass.reflect_on_association(:translations).foreign_key].not_eq(record.send(:id))) if record.persisted?
13
+
14
+ # TODO: add scope with translated attributes
15
+ if options[:scope]
16
+ ActiveRecord::Base.logger.warn("WARNING: Globalize does not currently support `scope` option on uniqueness validation for translated attributes.")
17
+ end
18
+
19
+ if finder_class.unscoped.where(relation).exists?
20
+ record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
21
+ end
22
+ else
23
+ finder_class = klass.translation_class
24
+ table = finder_class.unscoped
25
+
26
+ table_name = finder_class.quoted_table_name
27
+
28
+ if value && klass.serialized_attributes.key?(attribute.to_s)
29
+ value = YAML.dump value
30
+ end
31
+
32
+ sql, params = mount_sql_and_params(finder_class, table_name, attribute, value)
33
+
34
+ relation = table.where(sql, *params).where(:locale => Globalize.locale)
35
+
36
+ Array.wrap(options[:scope]).each do |scope_item|
37
+ scope_value = record.send(scope_item)
38
+ relation = relation.where(scope_item => scope_value)
39
+ end
40
+
41
+ if record.persisted?
42
+ fk = klass.reflect_on_association(:translations).options[:foreign_key]
43
+ relation = relation.where(finder_class.arel_table[fk].not_eq(record.send(:id)))
44
+ end
45
+
46
+ if relation.exists?
47
+ record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
48
+ end
49
+ end
50
+ else
51
+ validate_each_without_translations(record, attribute, value)
52
+ end
53
+ end
54
+ alias_method_chain :validate_each, :translations
55
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_record/serializers/xml_serializer'
2
+
3
+ ActiveRecord::XmlSerializer::Attribute.class_eval do
4
+ def compute_type_with_translations
5
+ klass = @serializable.class
6
+ if klass.translates? && klass.translated_attribute_names.include?(name.to_sym)
7
+ :string
8
+ else
9
+ compute_type_without_translations
10
+ end
11
+ end
12
+ alias_method_chain :compute_type, :translations
13
+ end
metadata ADDED
@@ -0,0 +1,186 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: globalize
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Sven Fuchs
8
+ - Joshua Harvey
9
+ - Clemens Kofler
10
+ - John-Paul Bader
11
+ - Tomasz Stachewicz
12
+ - Philip Arndt
13
+ - Chris Salzberg
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+ date: 2013-10-24 00:00:00.000000000 Z
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: activerecord
21
+ requirement: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - '>='
24
+ - !ruby/object:Gem::Version
25
+ version: 3.0.0
26
+ type: :runtime
27
+ prerelease: false
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: activemodel
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '>='
38
+ - !ruby/object:Gem::Version
39
+ version: 3.0.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 3.0.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: paper_trail
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: '2'
61
+ - !ruby/object:Gem::Dependency
62
+ name: database_cleaner
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 0.6.0
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ version: 0.6.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: mocha
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: pathname_local
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: test_declarative
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: sqlite3
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ description: Rails I18n de-facto standard library for ActiveRecord model/data translation.
132
+ email: nobody@globalize-rails.org
133
+ executables: []
134
+ extensions: []
135
+ extra_rdoc_files: []
136
+ files:
137
+ - lib/globalize/active_record/act_macro.rb
138
+ - lib/globalize/active_record/adapter.rb
139
+ - lib/globalize/active_record/attributes.rb
140
+ - lib/globalize/active_record/class_methods.rb
141
+ - lib/globalize/active_record/exceptions.rb
142
+ - lib/globalize/active_record/instance_methods.rb
143
+ - lib/globalize/active_record/migration.rb
144
+ - lib/globalize/active_record/translation.rb
145
+ - lib/globalize/active_record.rb
146
+ - lib/globalize/interpolation.rb
147
+ - lib/globalize/version.rb
148
+ - lib/globalize/versioning/paper_trail.rb
149
+ - lib/globalize/versioning.rb
150
+ - lib/globalize.rb
151
+ - lib/i18n/missing_translations_log_handler.rb
152
+ - lib/i18n/missing_translations_raise_handler.rb
153
+ - lib/patches/active_record/query_method.rb
154
+ - lib/patches/active_record/relation.rb
155
+ - lib/patches/active_record/uniqueness_validator.rb
156
+ - lib/patches/active_record/xml_attribute_serializer.rb
157
+ - Gemfile
158
+ - Gemfile.lock
159
+ - LICENSE
160
+ - Rakefile
161
+ homepage: https://github.com/globalize/globalize
162
+ licenses:
163
+ - MIT
164
+ metadata: {}
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - '>='
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubyforge_project:
181
+ rubygems_version: 2.1.0
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Rails I18n de-facto standard library for ActiveRecord model/data translation
185
+ test_files: []
186
+ has_rdoc: