globalize 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +87 -0
- data/LICENSE +21 -0
- data/Rakefile +22 -0
- data/lib/globalize.rb +80 -0
- data/lib/globalize/active_record.rb +12 -0
- data/lib/globalize/active_record/act_macro.rb +96 -0
- data/lib/globalize/active_record/adapter.rb +111 -0
- data/lib/globalize/active_record/attributes.rb +27 -0
- data/lib/globalize/active_record/class_methods.rb +173 -0
- data/lib/globalize/active_record/exceptions.rb +19 -0
- data/lib/globalize/active_record/instance_methods.rb +224 -0
- data/lib/globalize/active_record/migration.rb +191 -0
- data/lib/globalize/active_record/translation.rb +46 -0
- data/lib/globalize/interpolation.rb +28 -0
- data/lib/globalize/version.rb +3 -0
- data/lib/globalize/versioning.rb +5 -0
- data/lib/globalize/versioning/paper_trail.rb +41 -0
- data/lib/i18n/missing_translations_log_handler.rb +41 -0
- data/lib/i18n/missing_translations_raise_handler.rb +25 -0
- data/lib/patches/active_record/query_method.rb +35 -0
- data/lib/patches/active_record/relation.rb +15 -0
- data/lib/patches/active_record/uniqueness_validator.rb +55 -0
- data/lib/patches/active_record/xml_attribute_serializer.rb +13 -0
- metadata +186 -0
@@ -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,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:
|