globalize 5.0.1 → 5.2.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 +5 -5
- data/Appraisals +33 -0
- data/CHANGELOG.md +12 -0
- data/CONTRIBUTING.md +15 -0
- data/Gemfile +0 -9
- data/Gemfile.lock +59 -241
- data/{readme.md → README.md} +124 -36
- data/Rakefile +33 -0
- data/lib/globalize/active_record/act_macro.rb +27 -1
- data/lib/globalize/active_record/adapter.rb +13 -5
- data/lib/globalize/active_record/adapter_dirty.rb +56 -0
- data/lib/globalize/active_record/class_methods.rb +23 -9
- data/lib/globalize/active_record/exceptions.rb +1 -7
- data/lib/globalize/active_record/instance_methods.rb +89 -41
- data/lib/globalize/active_record/migration.rb +58 -31
- data/lib/globalize/active_record/translated_attributes_query.rb +181 -0
- data/lib/globalize/active_record.rb +10 -9
- data/lib/globalize/version.rb +1 -1
- data/lib/globalize.rb +20 -6
- data/lib/patches/active_record/persistence.rb +6 -15
- data/lib/patches/active_record/query_method.rb +2 -34
- data/lib/patches/active_record/rails4/query_method.rb +35 -0
- data/lib/patches/active_record/rails4/serialization.rb +22 -0
- data/lib/patches/active_record/rails4/uniqueness_validator.rb +42 -0
- data/lib/patches/active_record/rails5/uniqueness_validator.rb +47 -0
- data/lib/patches/active_record/rails5_1/serialization.rb +22 -0
- data/lib/patches/active_record/rails5_1/uniqueness_validator.rb +45 -0
- data/lib/patches/active_record/relation.rb +12 -0
- data/lib/patches/active_record/serialization.rb +5 -24
- data/lib/patches/active_record/uniqueness_validator.rb +7 -39
- data/lib/patches/active_record/xml_attribute_serializer.rb +19 -9
- metadata +85 -22
- data/globalize.gemspec +0 -29
- data/lib/globalize/active_record/query_methods.rb +0 -98
data/Rakefile
CHANGED
|
@@ -20,3 +20,36 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
|
20
20
|
rdoc.rdoc_files.include('README')
|
|
21
21
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
task :load_path do
|
|
25
|
+
%w(lib test).each do |path|
|
|
26
|
+
$LOAD_PATH.unshift(File.expand_path("../#{path}", __FILE__))
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
namespace :db do
|
|
31
|
+
desc 'Create the database'
|
|
32
|
+
task :create => :load_path do
|
|
33
|
+
require 'support/database'
|
|
34
|
+
|
|
35
|
+
Globalize::Test::Database.create!
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
desc "Drop the database"
|
|
39
|
+
task :drop => :load_path do
|
|
40
|
+
require 'support/database'
|
|
41
|
+
|
|
42
|
+
Globalize::Test::Database.drop!
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
desc "Set up the database schema"
|
|
46
|
+
task :migrate => :load_path do
|
|
47
|
+
require 'support/database'
|
|
48
|
+
|
|
49
|
+
Globalize::Test::Database.migrate!
|
|
50
|
+
# ActiveRecord::Schema.migrate :up
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
desc "Drop and recreate the database schema"
|
|
54
|
+
task :reset => [:drop, :create]
|
|
55
|
+
end
|
|
@@ -5,6 +5,7 @@ module Globalize
|
|
|
5
5
|
options = attr_names.extract_options!
|
|
6
6
|
# Bypass setup_translates! if the initial bootstrapping is done already.
|
|
7
7
|
setup_translates!(options) unless translates?
|
|
8
|
+
check_columns!(attr_names)
|
|
8
9
|
|
|
9
10
|
# Add any extra translatable attributes.
|
|
10
11
|
attr_names = attr_names.map(&:to_sym)
|
|
@@ -38,6 +39,30 @@ module Globalize
|
|
|
38
39
|
# Add attribute to the list.
|
|
39
40
|
self.translated_attribute_names << attr_name
|
|
40
41
|
end
|
|
42
|
+
|
|
43
|
+
begin
|
|
44
|
+
if ::ActiveRecord::VERSION::STRING > "5.0" && table_exists? && translation_class.table_exists?
|
|
45
|
+
self.ignored_columns += translated_attribute_names.map(&:to_s)
|
|
46
|
+
reset_column_information
|
|
47
|
+
end
|
|
48
|
+
rescue ::ActiveRecord::NoDatabaseError
|
|
49
|
+
warn 'Unable to connect to a database. Globalize skipped ignoring columns of translated attributes.'
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def check_columns!(attr_names)
|
|
54
|
+
# If tables do not exist or Rails version is greater than 5, do not warn about conflicting columns
|
|
55
|
+
return unless ::ActiveRecord::VERSION::STRING < "5.0" && table_exists? && translation_class.table_exists?
|
|
56
|
+
if (overlap = attr_names.map(&:to_s) & column_names).present?
|
|
57
|
+
ActiveSupport::Deprecation.warn(
|
|
58
|
+
["You have defined one or more translated attributes with names that conflict with column(s) on the model table. ",
|
|
59
|
+
"Globalize does not support this configuration anymore, remove or rename column(s) on the model table.\n",
|
|
60
|
+
"Model name (table name): #{model_name} (#{table_name})\n",
|
|
61
|
+
"Attribute name(s): #{overlap.join(', ')}\n"].join
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
rescue ::ActiveRecord::NoDatabaseError
|
|
65
|
+
warn 'Unable to connect to a database. Globalize skipped checking attributes with conflicting column names.'
|
|
41
66
|
end
|
|
42
67
|
|
|
43
68
|
def apply_globalize_options(options)
|
|
@@ -74,7 +99,8 @@ module Globalize
|
|
|
74
99
|
:foreign_key => options[:foreign_key],
|
|
75
100
|
:dependent => :destroy,
|
|
76
101
|
:extend => HasManyExtensions,
|
|
77
|
-
:autosave => false
|
|
102
|
+
:autosave => false,
|
|
103
|
+
:inverse_of => :globalized_model
|
|
78
104
|
|
|
79
105
|
after_create :save_translations!
|
|
80
106
|
after_update :save_translations!
|
|
@@ -3,7 +3,7 @@ module Globalize
|
|
|
3
3
|
class Adapter
|
|
4
4
|
# The cache caches attributes that already were looked up for read access.
|
|
5
5
|
# The stash keeps track of new or changed values that need to be saved.
|
|
6
|
-
attr_accessor :record, :stash
|
|
6
|
+
attr_accessor :record, :stash
|
|
7
7
|
private :record=, :stash=
|
|
8
8
|
|
|
9
9
|
delegate :translation_class, :to => :'record.class'
|
|
@@ -34,14 +34,16 @@ module Globalize
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def save_translations!
|
|
37
|
-
stash.
|
|
37
|
+
stash.each do |locale, attrs|
|
|
38
|
+
next if attrs.empty?
|
|
39
|
+
|
|
38
40
|
translation = record.translations_by_locale[locale] ||
|
|
39
41
|
record.translations.build(locale: locale.to_s)
|
|
40
|
-
|
|
41
42
|
attrs.each do |name, value|
|
|
42
43
|
value = value.val if value.is_a?(Arel::Nodes::Casted)
|
|
43
44
|
translation[name] = value
|
|
44
45
|
end
|
|
46
|
+
|
|
45
47
|
ensure_foreign_key_for(translation)
|
|
46
48
|
translation.save!
|
|
47
49
|
end
|
|
@@ -57,7 +59,8 @@ module Globalize
|
|
|
57
59
|
|
|
58
60
|
# Sometimes the translation is initialised before a foreign key can be set.
|
|
59
61
|
def ensure_foreign_key_for(translation)
|
|
60
|
-
|
|
62
|
+
# AR >= 4.1 reflections renamed to _reflections
|
|
63
|
+
translation[translation.class.reflections.stringify_keys["globalized_model"].foreign_key] = record.id
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
def type_cast(name, value)
|
|
@@ -76,7 +79,11 @@ module Globalize
|
|
|
76
79
|
|
|
77
80
|
def fetch_attribute(locale, name)
|
|
78
81
|
translation = record.translation_for(locale, false)
|
|
79
|
-
|
|
82
|
+
if translation
|
|
83
|
+
translation.send(name)
|
|
84
|
+
else
|
|
85
|
+
record.class.translation_class.new.send(name)
|
|
86
|
+
end
|
|
80
87
|
end
|
|
81
88
|
|
|
82
89
|
def set_metadata(object, metadata)
|
|
@@ -95,6 +102,7 @@ module Globalize
|
|
|
95
102
|
end
|
|
96
103
|
|
|
97
104
|
delegate :fallbacks_for_empty_translations?, :to => :record, :prefix => false
|
|
105
|
+
prepend AdapterDirty
|
|
98
106
|
end
|
|
99
107
|
end
|
|
100
108
|
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Globalize
|
|
2
|
+
module ActiveRecord
|
|
3
|
+
module AdapterDirty
|
|
4
|
+
def write locale, name, value
|
|
5
|
+
# Dirty tracking, paraphrased from
|
|
6
|
+
# ActiveRecord::AttributeMethods::Dirty#write_attribute.
|
|
7
|
+
name = name.to_s
|
|
8
|
+
store_old_value name, locale
|
|
9
|
+
old_values = dirty[name]
|
|
10
|
+
old_value = old_values[locale]
|
|
11
|
+
is_changed = record.send :attribute_changed?, name
|
|
12
|
+
if is_changed && value == old_value
|
|
13
|
+
# If there's already a change, delete it if this undoes the change.
|
|
14
|
+
old_values.delete locale
|
|
15
|
+
if old_values.empty?
|
|
16
|
+
_reset_attribute name
|
|
17
|
+
end
|
|
18
|
+
elsif !is_changed
|
|
19
|
+
# If there's not a change yet, record it.
|
|
20
|
+
record.send(:attribute_will_change!, name) if old_value != value
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
super locale, name, value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
attr_writer :dirty
|
|
27
|
+
def dirty
|
|
28
|
+
@dirty ||= {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def store_old_value name, locale
|
|
32
|
+
dirty[name] ||= {}
|
|
33
|
+
unless dirty[name].key? locale
|
|
34
|
+
old = fetch(locale, name)
|
|
35
|
+
old = old.dup if old.duplicable?
|
|
36
|
+
dirty[name][locale] = old
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def clear_dirty
|
|
41
|
+
self.dirty = {}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def _reset_attribute name
|
|
45
|
+
record.send("#{name}=", record.changed_attributes[name])
|
|
46
|
+
record.send(:clear_attribute_changes, [name])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def reset
|
|
50
|
+
clear_dirty
|
|
51
|
+
super
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -3,13 +3,21 @@ module Globalize
|
|
|
3
3
|
module ClassMethods
|
|
4
4
|
delegate :translated_locales, :set_translations_table_name, :to => :translation_class
|
|
5
5
|
|
|
6
|
+
if ::ActiveRecord::VERSION::STRING < "5.0.0"
|
|
7
|
+
def columns_hash
|
|
8
|
+
super.except(*translated_attribute_names.map(&:to_s))
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
6
12
|
def with_locales(*locales)
|
|
7
13
|
all.merge translation_class.with_locales(*locales)
|
|
8
14
|
end
|
|
9
15
|
|
|
10
16
|
def with_translations(*locales)
|
|
11
17
|
locales = translated_locales if locales.empty?
|
|
12
|
-
preload(:translations).joins(:translations).readonly(false).with_locales(locales)
|
|
18
|
+
preload(:translations).joins(:translations).readonly(false).with_locales(locales).tap do |query|
|
|
19
|
+
query.distinct! unless locales.flatten.one?
|
|
20
|
+
end
|
|
13
21
|
end
|
|
14
22
|
|
|
15
23
|
def with_required_attributes
|
|
@@ -42,12 +50,17 @@ module Globalize
|
|
|
42
50
|
|
|
43
51
|
def translation_class
|
|
44
52
|
@translation_class ||= begin
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
if self.const_defined?(:Translation, false)
|
|
54
|
+
klass = self.const_get(:Translation, false)
|
|
55
|
+
else
|
|
47
56
|
klass = self.const_set(:Translation, Class.new(Globalize::ActiveRecord::Translation))
|
|
48
57
|
end
|
|
49
58
|
|
|
50
|
-
klass.belongs_to :globalized_model,
|
|
59
|
+
klass.belongs_to :globalized_model,
|
|
60
|
+
class_name: self.name,
|
|
61
|
+
foreign_key: translation_options[:foreign_key],
|
|
62
|
+
inverse_of: :translations,
|
|
63
|
+
touch: translation_options.fetch(:touch, false)
|
|
51
64
|
klass
|
|
52
65
|
end
|
|
53
66
|
end
|
|
@@ -63,10 +76,10 @@ module Globalize
|
|
|
63
76
|
private
|
|
64
77
|
|
|
65
78
|
# Override the default relation method in order to return a subclass
|
|
66
|
-
# of ActiveRecord::Relation with custom finder
|
|
67
|
-
# attributes.
|
|
79
|
+
# of ActiveRecord::Relation with custom finder and calculation methods
|
|
80
|
+
# for translated attributes.
|
|
68
81
|
def relation
|
|
69
|
-
super.extending!(
|
|
82
|
+
super.extending!(TranslatedAttributesQuery)
|
|
70
83
|
end
|
|
71
84
|
|
|
72
85
|
protected
|
|
@@ -85,6 +98,7 @@ module Globalize
|
|
|
85
98
|
end
|
|
86
99
|
|
|
87
100
|
def define_translated_attr_accessor(name)
|
|
101
|
+
attribute(name, ::ActiveRecord::Type::Value.new)
|
|
88
102
|
define_translated_attr_reader(name)
|
|
89
103
|
define_translated_attr_writer(name)
|
|
90
104
|
end
|
|
@@ -100,8 +114,8 @@ module Globalize
|
|
|
100
114
|
|
|
101
115
|
def define_translations_writer(name)
|
|
102
116
|
define_method(:"#{name}_translations=") do |value|
|
|
103
|
-
value.each do |(locale,
|
|
104
|
-
write_attribute name,
|
|
117
|
+
value.each do |(locale, _value)|
|
|
118
|
+
write_attribute name, _value, :locale => locale
|
|
105
119
|
end
|
|
106
120
|
end
|
|
107
121
|
end
|
|
@@ -8,12 +8,6 @@ module Globalize
|
|
|
8
8
|
super("Missing translated field #{field.inspect}")
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
|
-
|
|
12
|
-
class BadFieldType < MigrationError
|
|
13
|
-
def initialize(name, type)
|
|
14
|
-
super("Bad field type for field #{name.inspect} (#{type.inspect}), should be :string or :text")
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
11
|
end
|
|
18
12
|
end
|
|
19
|
-
end
|
|
13
|
+
end
|
|
@@ -11,51 +11,65 @@ module Globalize
|
|
|
11
11
|
super.merge(translated_attributes)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def attributes=(
|
|
15
|
-
|
|
14
|
+
def attributes=(new_attributes, *options)
|
|
15
|
+
super unless new_attributes.respond_to?(:stringify_keys) && new_attributes.present?
|
|
16
|
+
attributes = new_attributes.stringify_keys
|
|
17
|
+
with_given_locale(attributes) { super(attributes.except("locale"), *options) }
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
with_given_locale(attributes) { super }
|
|
20
|
-
end
|
|
20
|
+
if Globalize.rails_52?
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
# In Rails 5.2 we need to override *_assign_attributes* as it's called earlier
|
|
23
|
+
# in the stack (before *assign_attributes*)
|
|
24
|
+
# See https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment.rb#L11
|
|
25
|
+
def _assign_attributes(new_attributes)
|
|
26
|
+
attributes = new_attributes.stringify_keys
|
|
27
|
+
with_given_locale(attributes) { super(attributes.except("locale")) }
|
|
28
|
+
end
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
else
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# If there's already a change, delete it if this undoes the change.
|
|
32
|
-
old = changed_attributes[name_str]
|
|
33
|
-
@changed_attributes.delete(name_str) if value == old
|
|
34
|
-
else
|
|
35
|
-
# If there's not a change yet, record it.
|
|
36
|
-
old = globalize.fetch(options[:locale], name)
|
|
37
|
-
old = old.dup if old.duplicable?
|
|
38
|
-
@changed_attributes[name_str] = old if value != old
|
|
32
|
+
def assign_attributes(new_attributes, *options)
|
|
33
|
+
super unless new_attributes.respond_to?(:stringify_keys) && new_attributes.present?
|
|
34
|
+
attributes = new_attributes.stringify_keys
|
|
35
|
+
with_given_locale(attributes) { super(attributes.except("locale"), *options) }
|
|
39
36
|
end
|
|
40
37
|
|
|
41
|
-
globalize.write(options[:locale], name, value)
|
|
42
38
|
end
|
|
43
39
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
return super(name) unless options[:translated]
|
|
40
|
+
def write_attribute(name, value, *args, &block)
|
|
41
|
+
return super(name, value, *args, &block) unless translated?(name)
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
options = {:locale => Globalize.locale}.merge(args.first || {})
|
|
44
|
+
|
|
45
|
+
globalize.write(options[:locale], name, value)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def [](attr_name)
|
|
49
|
+
if translated?(attr_name)
|
|
50
|
+
read_attribute(attr_name)
|
|
54
51
|
else
|
|
55
|
-
|
|
52
|
+
read_attribute(attr_name) { |n| missing_attribute(n, caller) }
|
|
56
53
|
end
|
|
57
54
|
end
|
|
58
55
|
|
|
56
|
+
def read_attribute(attr_name, options = {}, &block)
|
|
57
|
+
name = if self.class.attribute_alias?(attr_name)
|
|
58
|
+
self.class.attribute_alias(attr_name).to_s
|
|
59
|
+
else
|
|
60
|
+
attr_name.to_s
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
name = self.class.primary_key if name == "id".freeze && self.class.primary_key
|
|
64
|
+
|
|
65
|
+
_read_attribute(name, options, &block)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def _read_attribute(attr_name, options = {}, &block)
|
|
69
|
+
translated_value = read_translated_attribute(attr_name, options, &block)
|
|
70
|
+
translated_value.nil? ? super(attr_name, &block) : translated_value
|
|
71
|
+
end
|
|
72
|
+
|
|
59
73
|
def attribute_names
|
|
60
74
|
translated_attribute_names.map(&:to_s) + super
|
|
61
75
|
end
|
|
@@ -83,8 +97,9 @@ module Globalize
|
|
|
83
97
|
|
|
84
98
|
options[locale].each do |key, value|
|
|
85
99
|
translation.send :"#{key}=", value
|
|
100
|
+
translation.globalized_model.send :"#{key}=", value
|
|
86
101
|
end
|
|
87
|
-
translation.save
|
|
102
|
+
translation.save if persisted?
|
|
88
103
|
end
|
|
89
104
|
globalize.reset
|
|
90
105
|
end
|
|
@@ -143,14 +158,17 @@ module Globalize
|
|
|
143
158
|
Globalize.fallbacks(locale)
|
|
144
159
|
end
|
|
145
160
|
|
|
146
|
-
def rollback
|
|
147
|
-
translation_caches[::Globalize.locale] = translation.previous_version
|
|
148
|
-
end
|
|
149
|
-
|
|
150
161
|
def save(*)
|
|
151
|
-
Globalize.with_locale(translation.locale || I18n.default_locale) do
|
|
152
|
-
|
|
162
|
+
result = Globalize.with_locale(translation.locale || I18n.default_locale) do
|
|
163
|
+
without_fallbacks do
|
|
164
|
+
super
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
if result
|
|
168
|
+
globalize.clear_dirty
|
|
153
169
|
end
|
|
170
|
+
|
|
171
|
+
result
|
|
154
172
|
end
|
|
155
173
|
|
|
156
174
|
def column_for_attribute name
|
|
@@ -163,6 +181,16 @@ module Globalize
|
|
|
163
181
|
[super, translation.cache_key].join("/")
|
|
164
182
|
end
|
|
165
183
|
|
|
184
|
+
def changed?
|
|
185
|
+
changed_attributes.present? || translations.any?(&:changed?)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# need to access instance variable directly since changed_attributes
|
|
189
|
+
# is frozen as of Rails 4.2
|
|
190
|
+
def original_changed_attributes
|
|
191
|
+
@changed_attributes
|
|
192
|
+
end
|
|
193
|
+
|
|
166
194
|
protected
|
|
167
195
|
|
|
168
196
|
def each_locale_and_translated_attribute
|
|
@@ -184,15 +212,35 @@ module Globalize
|
|
|
184
212
|
translation_caches.clear
|
|
185
213
|
end
|
|
186
214
|
|
|
187
|
-
def with_given_locale(
|
|
188
|
-
attributes
|
|
215
|
+
def with_given_locale(_attributes, &block)
|
|
216
|
+
attributes = _attributes.stringify_keys
|
|
189
217
|
|
|
190
|
-
if locale = attributes.try(:delete,
|
|
218
|
+
if locale = attributes.try(:delete, "locale")
|
|
191
219
|
Globalize.with_locale(locale, &block)
|
|
192
220
|
else
|
|
193
221
|
yield
|
|
194
222
|
end
|
|
195
223
|
end
|
|
224
|
+
|
|
225
|
+
def without_fallbacks
|
|
226
|
+
before = self.fallbacks_for_empty_translations
|
|
227
|
+
self.fallbacks_for_empty_translations = false
|
|
228
|
+
yield
|
|
229
|
+
ensure
|
|
230
|
+
self.fallbacks_for_empty_translations = before
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# nil or value
|
|
234
|
+
def read_translated_attribute(name, options)
|
|
235
|
+
options = {:translated => true, :locale => nil}.merge(options)
|
|
236
|
+
return nil unless options[:translated]
|
|
237
|
+
return nil unless translated?(name)
|
|
238
|
+
|
|
239
|
+
value = globalize.fetch(options[:locale] || Globalize.locale, name)
|
|
240
|
+
return nil if value.nil?
|
|
241
|
+
|
|
242
|
+
block_given? ? yield(value) : value
|
|
243
|
+
end
|
|
196
244
|
end
|
|
197
245
|
end
|
|
198
246
|
end
|