globalize3 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +5 -0
- data/lib/globalize.rb +17 -1
- data/lib/globalize/active_record.rb +1 -41
- data/lib/globalize/active_record/act_macro.rb +18 -24
- data/lib/globalize/active_record/adapter.rb +3 -6
- data/lib/globalize/active_record/attributes.rb +1 -0
- data/lib/globalize/active_record/class_methods.rb +47 -34
- data/lib/globalize/active_record/instance_methods.rb +7 -17
- data/lib/globalize/active_record/migration.rb +5 -5
- data/lib/globalize/active_record/translation.rb +24 -0
- data/lib/globalize/version.rb +1 -1
- metadata +5 -4
data/README.textile
CHANGED
@@ -58,6 +58,11 @@ end
|
|
58
58
|
|
59
59
|
Note that the ActiveRecord model @Post@ must already exist and have a @translates@ directive listing the translated fields.
|
60
60
|
|
61
|
+
h2. Changes since Globalize2
|
62
|
+
|
63
|
+
* `translation_table_name` was renamed to `translations_table_name`
|
64
|
+
* `available_locales` has been removed. please use `translated_locales`
|
65
|
+
|
61
66
|
h2. Migration from Globalize for Rails (version 1)
|
62
67
|
|
63
68
|
See this script by Tomasz Stachewicz: http://gist.github.com/120867
|
data/lib/globalize.rb
CHANGED
@@ -4,11 +4,27 @@ module Globalize
|
|
4
4
|
autoload :ActiveRecord, 'globalize/active_record'
|
5
5
|
|
6
6
|
class << self
|
7
|
+
def locale
|
8
|
+
defined?(@@locale) && @@locale || I18n.locale
|
9
|
+
end
|
10
|
+
|
11
|
+
def locale=(locale)
|
12
|
+
@@locale = locale
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_locale(locale, &block)
|
16
|
+
previous_locale = defined?(@@locale) && @@locale || nil
|
17
|
+
self.locale = locale
|
18
|
+
result = yield
|
19
|
+
self.locale = previous_locale
|
20
|
+
result
|
21
|
+
end
|
22
|
+
|
7
23
|
def fallbacks?
|
8
24
|
I18n.respond_to?(:fallbacks)
|
9
25
|
end
|
10
26
|
|
11
|
-
def fallbacks(locale)
|
27
|
+
def fallbacks(locale = self.locale)
|
12
28
|
fallbacks? ? I18n.fallbacks[locale] : [locale.to_sym]
|
13
29
|
end
|
14
30
|
end
|
@@ -10,46 +10,6 @@ module Globalize
|
|
10
10
|
autoload :ClassMethods, 'globalize/active_record/class_methods'
|
11
11
|
autoload :InstanceMethods, 'globalize/active_record/instance_methods'
|
12
12
|
autoload :Migration, 'globalize/active_record/migration'
|
13
|
-
|
14
|
-
class << self
|
15
|
-
def build_translation_class(target, options)
|
16
|
-
options[:table_name] ||= "#{target.table_name.singularize}_translations"
|
17
|
-
|
18
|
-
klass = target.const_defined?(:Translation) ?
|
19
|
-
target.const_get(:Translation) :
|
20
|
-
target.const_set(:Translation, Class.new(::ActiveRecord::Base))
|
21
|
-
|
22
|
-
klass.class_eval do
|
23
|
-
set_table_name(options[:table_name])
|
24
|
-
|
25
|
-
belongs_to target.name.underscore.gsub('/', '_')
|
26
|
-
|
27
|
-
class << self
|
28
|
-
def by_locale(locale)
|
29
|
-
where(:locale => locale.to_s)
|
30
|
-
end
|
31
|
-
|
32
|
-
def by_locales(locales)
|
33
|
-
where(:locale => locales.map(&:to_s))
|
34
|
-
end
|
35
|
-
|
36
|
-
# TODO build is not defined here even when called through record.translations.find_or_initialize_by_locale(...)
|
37
|
-
# def find_or_initialize_by_locale(locale)
|
38
|
-
# by_locale(locale.to_s).first || build(:locale => locale.to_s)
|
39
|
-
# end
|
40
|
-
end
|
41
|
-
|
42
|
-
def locale
|
43
|
-
read_attribute(:locale).to_sym
|
44
|
-
end
|
45
|
-
|
46
|
-
def locale=(locale)
|
47
|
-
write_attribute(:locale, locale.to_s)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
klass
|
52
|
-
end
|
53
|
-
end
|
13
|
+
autoload :Translation, 'globalize/active_record/translation'
|
54
14
|
end
|
55
15
|
end
|
@@ -1,43 +1,31 @@
|
|
1
1
|
module Globalize
|
2
2
|
module ActiveRecord
|
3
3
|
module ActMacro
|
4
|
-
def locale
|
5
|
-
(defined?(@@locale) && @@locale)
|
6
|
-
end
|
7
|
-
|
8
|
-
def locale=(locale)
|
9
|
-
@@locale = locale
|
10
|
-
end
|
11
|
-
|
12
4
|
def translates(*attr_names)
|
13
5
|
return if translates?
|
14
|
-
options = attr_names.extract_options!
|
15
6
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
self.translation_class = ActiveRecord.build_translation_class(self, options)
|
20
|
-
self.translated_attribute_names = attr_names.map(&:to_sym)
|
7
|
+
options = attr_names.extract_options!
|
8
|
+
options[:table_name] ||= "#{table_name.singularize}_translations"
|
21
9
|
|
22
10
|
include InstanceMethods
|
23
11
|
extend ClassMethods, Migration
|
24
12
|
|
13
|
+
class_inheritable_accessor :translated_attribute_names, :translation_options
|
14
|
+
class_inheritable_writer :required_attributes
|
15
|
+
|
16
|
+
self.translated_attribute_names = attr_names.map(&:to_sym)
|
17
|
+
self.translation_options = options
|
18
|
+
|
25
19
|
after_save :save_translations!
|
20
|
+
|
26
21
|
has_many :translations, :class_name => translation_class.name,
|
27
22
|
:foreign_key => class_name.foreign_key,
|
28
|
-
:dependent => :delete_all
|
29
|
-
|
30
|
-
scope :with_translations, lambda { |locale|
|
31
|
-
conditions = required_attributes.map do |attribute|
|
32
|
-
"#{quoted_translation_table_name}.#{attribute} IS NOT NULL"
|
33
|
-
end
|
34
|
-
conditions << "#{quoted_translation_table_name}.locale = ?"
|
35
|
-
{ :include => :translations, :conditions => [conditions.join(' AND '), locale] }
|
36
|
-
}
|
23
|
+
:dependent => :delete_all,
|
24
|
+
:extend => HasManyExtensions
|
37
25
|
|
38
26
|
attr_names.each { |attr_name| translated_attr_accessor(attr_name) }
|
39
27
|
end
|
40
|
-
|
28
|
+
|
41
29
|
def class_name
|
42
30
|
class_name = table_name[table_name_prefix.length..-(table_name_suffix.length + 1)].camelize
|
43
31
|
pluralize_table_names ? class_name.singularize : class_name
|
@@ -47,5 +35,11 @@ module Globalize
|
|
47
35
|
included_modules.include?(InstanceMethods)
|
48
36
|
end
|
49
37
|
end
|
38
|
+
|
39
|
+
module HasManyExtensions
|
40
|
+
def find_or_initialize_by_locale(locale)
|
41
|
+
with_locale(locale.to_s).first || build(:locale => locale.to_s)
|
42
|
+
end
|
43
|
+
end
|
50
44
|
end
|
51
45
|
end
|
@@ -24,9 +24,7 @@ module Globalize
|
|
24
24
|
|
25
25
|
def save_translations!
|
26
26
|
stash.each do |locale, attrs|
|
27
|
-
|
28
|
-
translation = record.translations.by_locale(locale.to_s).first
|
29
|
-
translation ||= record.translations.build(:locale => locale.to_s)
|
27
|
+
translation = record.translations.find_or_initialize_by_locale(locale.to_s)
|
30
28
|
attrs.each { |attr_name, value| translation[attr_name] = value }
|
31
29
|
translation.save!
|
32
30
|
end
|
@@ -35,7 +33,6 @@ module Globalize
|
|
35
33
|
|
36
34
|
def reset
|
37
35
|
cache.clear
|
38
|
-
# stash.clear
|
39
36
|
end
|
40
37
|
|
41
38
|
protected
|
@@ -43,13 +40,13 @@ module Globalize
|
|
43
40
|
def fetch_translation(locale)
|
44
41
|
locale = locale.to_sym
|
45
42
|
record.translations.loaded? ? record.translations.detect { |t| t.locale == locale } :
|
46
|
-
record.translations.
|
43
|
+
record.translations.with_locales(locale)
|
47
44
|
end
|
48
45
|
|
49
46
|
def fetch_translations(locale)
|
50
47
|
# only query if not already included with :include => translations
|
51
48
|
record.translations.loaded? ? record.translations :
|
52
|
-
record.translations.
|
49
|
+
record.translations.with_locales(Globalize.fallbacks(locale))
|
53
50
|
end
|
54
51
|
|
55
52
|
def fetch_attribute(locale, attr_name)
|
@@ -1,27 +1,54 @@
|
|
1
1
|
module Globalize
|
2
2
|
module ActiveRecord
|
3
3
|
module ClassMethods
|
4
|
-
delegate :
|
4
|
+
delegate :translated_locales, :set_translations_table_name, :to => :translation_class
|
5
5
|
|
6
|
-
def
|
7
|
-
|
8
|
-
result = yield
|
9
|
-
self.locale = previous_locale
|
10
|
-
result
|
6
|
+
def with_locales(*locales)
|
7
|
+
scoped & translation_class.with_locales(*locales)
|
11
8
|
end
|
12
9
|
|
13
|
-
def
|
14
|
-
|
10
|
+
def with_translations(*locales)
|
11
|
+
locales = translated_locales if locales.empty?
|
12
|
+
includes(:translations).with_locales(locales).with_required_attributes
|
15
13
|
end
|
16
14
|
|
17
|
-
def
|
18
|
-
|
15
|
+
def with_required_attributes
|
16
|
+
required_translated_attributes.inject(scoped) do |scope, name|
|
17
|
+
scope.where("#{translated_column_name(name)} IS NOT NULL")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def with_translated_attribute(name, value, locales = nil)
|
22
|
+
locales ||= Globalize.fallbacks
|
23
|
+
with_translations.where(
|
24
|
+
translated_column_name(name) => value,
|
25
|
+
translated_column_name(:locale) => locales.map(&:to_s)
|
26
|
+
)
|
19
27
|
end
|
20
28
|
|
21
29
|
def required_attributes
|
22
|
-
|
23
|
-
|
24
|
-
|
30
|
+
validators.map { |v| v.attributes if v.is_a?(ActiveModel::Validations::PresenceValidator) }.flatten
|
31
|
+
end
|
32
|
+
|
33
|
+
def required_translated_attributes
|
34
|
+
translated_attribute_names & required_attributes
|
35
|
+
end
|
36
|
+
|
37
|
+
def translation_class
|
38
|
+
klass = const_get(:Translation) rescue const_set(:Translation, Class.new(Translation))
|
39
|
+
if klass.table_name == 'translations'
|
40
|
+
klass.set_table_name(translation_options[:table_name])
|
41
|
+
klass.belongs_to name.underscore.gsub('/', '_')
|
42
|
+
end
|
43
|
+
klass
|
44
|
+
end
|
45
|
+
|
46
|
+
def translations_table_name
|
47
|
+
translation_class.table_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def translated_column_name(name)
|
51
|
+
"#{translation_class.table_name}.#{name}"
|
25
52
|
end
|
26
53
|
|
27
54
|
def respond_to?(method, *args, &block)
|
@@ -29,8 +56,9 @@ module Globalize
|
|
29
56
|
end
|
30
57
|
|
31
58
|
def method_missing(method, *args)
|
32
|
-
if method.to_s =~ /^
|
33
|
-
|
59
|
+
if method.to_s =~ /^find_(first_|)by_(\w+)$/ && translated_attribute_names.include?($2.to_sym)
|
60
|
+
result = with_translated_attribute($2, args.first)
|
61
|
+
$1 == 'first_' ? result.first : result
|
34
62
|
else
|
35
63
|
super
|
36
64
|
end
|
@@ -38,30 +66,15 @@ module Globalize
|
|
38
66
|
|
39
67
|
protected
|
40
68
|
|
41
|
-
def find_first_by_translated_attr_and_locales(name, value)
|
42
|
-
query = "#{translated_attr_name(name)} = ? AND #{translated_attr_name('locale')} IN (?)"
|
43
|
-
locales = Globalize.fallbacks(locale || I18n.locale).map(&:to_s)
|
44
|
-
find(
|
45
|
-
:first,
|
46
|
-
:joins => :translations,
|
47
|
-
:conditions => [query, value, locales],
|
48
|
-
:readonly => false
|
49
|
-
)
|
50
|
-
end
|
51
|
-
|
52
69
|
def translated_attr_accessor(name)
|
53
|
-
define_method "#{name}=", lambda { |value|
|
54
|
-
globalize.write(
|
70
|
+
define_method :"#{name}=", lambda { |value|
|
71
|
+
globalize.write(Globalize.locale, name, value)
|
55
72
|
self[name] = value
|
56
73
|
}
|
57
74
|
define_method name, lambda { |*args|
|
58
|
-
globalize.fetch(args.first ||
|
75
|
+
globalize.fetch(args.first || Globalize.locale, name)
|
59
76
|
}
|
60
|
-
alias_method "#{name}_before_type_cast", name
|
61
|
-
end
|
62
|
-
|
63
|
-
def translated_attr_name(name)
|
64
|
-
"#{translation_class.table_name}.#{name}"
|
77
|
+
alias_method :"#{name}_before_type_cast", name
|
65
78
|
end
|
66
79
|
end
|
67
80
|
end
|
@@ -1,21 +1,19 @@
|
|
1
1
|
module Globalize
|
2
2
|
module ActiveRecord
|
3
3
|
module InstanceMethods
|
4
|
+
delegate :translated_locales, :to => :translations
|
5
|
+
|
4
6
|
def globalize
|
5
7
|
@globalize ||= Adapter.new self
|
6
8
|
end
|
7
9
|
|
8
10
|
def attributes
|
9
|
-
|
10
|
-
attrs[name] = read_attribute(name) ||
|
11
|
-
(globalize.fetch(I18n.locale, name) rescue nil)
|
12
|
-
attrs
|
13
|
-
end
|
11
|
+
super.merge(translated_attributes)
|
14
12
|
end
|
15
13
|
|
16
14
|
def attributes=(attributes, *args)
|
17
|
-
if
|
18
|
-
|
15
|
+
if locale = attributes.try(:delete, :locale)
|
16
|
+
Globalize.with_locale(locale) { super }
|
19
17
|
else
|
20
18
|
super
|
21
19
|
end
|
@@ -24,18 +22,10 @@ module Globalize
|
|
24
22
|
def attribute_names
|
25
23
|
translated_attribute_names.map(&:to_s) + super
|
26
24
|
end
|
27
|
-
|
28
|
-
def available_locales
|
29
|
-
translations.select('DISTINCT locale').map(&:locale)
|
30
|
-
end
|
31
|
-
|
32
|
-
def translated_locales
|
33
|
-
translations.map(&:locale)
|
34
|
-
end
|
35
|
-
|
25
|
+
|
36
26
|
def translated_attributes
|
37
27
|
translated_attribute_names.inject({}) do |attributes, name|
|
38
|
-
attributes.merge(name => send(name))
|
28
|
+
attributes.merge(name.to_s => send(name))
|
39
29
|
end
|
40
30
|
end
|
41
31
|
|
@@ -12,7 +12,7 @@ module Globalize
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
self.connection.create_table(
|
15
|
+
self.connection.create_table(translations_table_name) do |t|
|
16
16
|
t.references table_name.sub(/^#{table_name_prefix}/, "").singularize
|
17
17
|
t.string :locale
|
18
18
|
fields.each do |name, type|
|
@@ -22,7 +22,7 @@ module Globalize
|
|
22
22
|
end
|
23
23
|
|
24
24
|
self.connection.add_index(
|
25
|
-
|
25
|
+
translations_table_name,
|
26
26
|
"#{table_name.sub(/^#{table_name_prefix}/, "").singularize}_id",
|
27
27
|
:name => translation_index_name
|
28
28
|
)
|
@@ -31,13 +31,13 @@ module Globalize
|
|
31
31
|
def translation_index_name
|
32
32
|
require 'digest/sha1'
|
33
33
|
# FIXME what's the max size of an index name?
|
34
|
-
index_name = "index_#{
|
34
|
+
index_name = "index_#{translations_table_name}_on_#{self.table_name.singularize}_id"
|
35
35
|
index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}"
|
36
36
|
end
|
37
37
|
|
38
38
|
def drop_translation_table!
|
39
|
-
self.connection.remove_index(
|
40
|
-
self.connection.drop_table(
|
39
|
+
self.connection.remove_index(translations_table_name, :name => translation_index_name) rescue nil
|
40
|
+
self.connection.drop_table(translations_table_name)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Globalize
|
2
|
+
module ActiveRecord
|
3
|
+
class Translation < ::ActiveRecord::Base
|
4
|
+
class << self
|
5
|
+
def with_locales(*locales)
|
6
|
+
where(:locale => locales.flatten.map(&:to_s))
|
7
|
+
end
|
8
|
+
alias with_locale with_locales
|
9
|
+
|
10
|
+
def translated_locales
|
11
|
+
select('DISTINCT locale').map(&:locale)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def locale
|
16
|
+
read_attribute(:locale).to_sym
|
17
|
+
end
|
18
|
+
|
19
|
+
def locale=(locale)
|
20
|
+
write_attribute(:locale, locale.to_s)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/globalize/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: globalize3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sven Fuchs
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2010-07-
|
21
|
+
date: 2010-07-31 00:00:00 +02:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- lib/globalize/active_record/class_methods.rb
|
54
54
|
- lib/globalize/active_record/instance_methods.rb
|
55
55
|
- lib/globalize/active_record/migration.rb
|
56
|
+
- lib/globalize/active_record/translation.rb
|
56
57
|
- lib/globalize/active_record.rb
|
57
58
|
- lib/globalize/version.rb
|
58
59
|
- lib/globalize.rb
|