embedded_localization 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -50,25 +50,6 @@ g.name # => "공상 과학 소설"
50
50
 
51
51
  No extra tables needed for this!
52
52
 
53
- h3. Rails 3.0
54
-
55
- <pre><code>
56
- class CreateGenres < ActiveRecord::Migration
57
- def self.up
58
- create_table :genres do |t|
59
- t.string :name
60
- t.text :description
61
- t.timestamps
62
- end
63
- end
64
- def self.down
65
- drop_table :posts
66
- end
67
- end
68
- </code></pre>
69
-
70
- Note that the ActiveRecord model @Genre@ must already exist and have a @translates@ directive listing the translated fields.
71
-
72
53
  h3. Rails 3.0 + Embedded_Localization version < 0.2.0
73
54
 
74
55
  <pre><code>
@@ -87,19 +68,23 @@ end
87
68
 
88
69
  Please note, if you use Embedded_Localization with version < 0.2.0, that you should not define the translated attributes in the migrations -- instead define one text attribute with the name :i18n -- this will change in version 0.2.0
89
70
 
71
+ Note that the ActiveRecord model @Genre@ must already exist and have a @translates@ directive listing the translated fields.
72
+
73
+
90
74
  h2. I18n fallbacks for empty translations
91
75
 
92
- It is possible to enable fallbacks for empty translations. It will depend on the configuration setting you have set for I18n translations in your Rails config.
76
+ It is possible to enable fallbacks for empty translations. It will depend on the configuration setting you have set for I18n translations in your Rails config, or you can enable fallback when you define the translation fields. Currently we only support fallback to @I18n.default_locale@
93
77
 
94
78
  You can enable them by adding the next line to @config/application.rb@ (or only @config/environments/production.rb@ if you only want them in production)
95
79
 
96
- <pre><code>config.i18n.fallbacks = true</code></pre>
80
+ <pre><code>config.i18n.fallbacks = true # falls back to I18n.default_locale
81
+ </code></pre>
97
82
 
98
83
  By default, Embedded_Localization will only use fallbacks when the translation value for the item you've requested is @nil@.
99
84
 
100
85
  <pre><code>
101
86
  class Genre < ActiveRecord::Base
102
- translates :name, :description
87
+ translates :name, :description # , :fallbacks => true
103
88
  end
104
89
 
105
90
  I18n.locale = :en
@@ -129,7 +114,7 @@ Each class which uses Embedded_Localization will have these additional methods d
129
114
  <ul>
130
115
  <li>Klass.translated_attributes
131
116
  <li>Klass.translated?
132
- <li>Klass.fallback?
117
+ <li>Klass.fallbacks?
133
118
  </ul>
134
119
 
135
120
  e.g.:
@@ -137,7 +122,7 @@ e.g.:
137
122
  <pre><code>
138
123
  Genre.translated_attributes # => [:name,:description]
139
124
  Genre.translated? # => true
140
- Genre.fallback? # => false
125
+ Genre.fallbacks? # => false
141
126
 
142
127
  </code></pre>
143
128
 
@@ -188,10 +173,23 @@ e.g.:
188
173
 
189
174
  </code></pre>
190
175
 
176
+ h2. Motivation
177
+
178
+ A recent project needed some localization support for ActiveRecord model data, but I did not want to clutter the schema with one additional table for each translated model, as globalization3 requires. A second requirement was to allow SQL queries of the fields using the default locale.
179
+
180
+ The advantage of EmbeddedLocalization is that it does not need extra tables, and therefore no joins or additional table lookups to get to the translated data.
181
+
182
+ If your requirements are different, my approach might not work for you. In that case, I recommend to look at the alternative solutions listed below.
191
183
 
192
184
  h2. Changes
193
185
 
194
- This is the initial version.
186
+ h3. 0.1.4 (2012-01-31)
187
+ * fixed bug with dirty tracking of serialized i18n attribute
188
+ * renamed #fallback? to #fallbacks?
189
+
190
+
191
+ h3. 0.1.3 Initial Version (2012-01-27)
192
+
195
193
 
196
194
  h2. Alternative Solutions
197
195
 
@@ -9,9 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.email = ["tilo.sloboda@gmail.com"]
10
10
  s.homepage = "http://www.unixgods.org/~tilo/Ruby/embedded_localization"
11
11
  s.summary = %q{Rails I18n: library for embedded ActiveRecord 3 model/data translation}
12
- s.description = %q{Rails I18n: Embedded_Localization for ActiveRecord 3 is very lightweight, and allows you to \
13
- transparently store translations of attributes right inside each record -- no extra database tables needed to store \
14
- the localization data!}
12
+ s.description = %q{Rails I18n: Embedded_Localization for ActiveRecord 3 is very lightweight, and allows you to transparently store translations of attributes right inside each record -- no extra database tables needed to store the localization data!}
15
13
 
16
14
  # s.rubyforge_project = "embedded_localization"
17
15
  s.rubyforge_project = "[none]"
@@ -4,8 +4,12 @@ module EmbeddedLocalization
4
4
  def translates(*attr_names)
5
5
  return if translates? # cludge to make sure we don't set this up twice..
6
6
 
7
+ # for details about I18n fallbacks, check the source:
8
+ # i18n-0.6.0/lib/i18n/backend/fallbacks.rb
9
+ # i18n-0.6.0/lib/i18n/locale/fallbacks.rb
10
+
11
+ # options[:fallbacks] => true or false # not used at this time
7
12
  options = attr_names.extract_options!
8
- # options[:fallback] => true or false
9
13
 
10
14
  class_attribute :translated_attribute_names, :translation_options
11
15
  self.translated_attribute_names = attr_names.map(&:to_sym).sort.uniq
@@ -14,10 +18,17 @@ module EmbeddedLocalization
14
18
  include InstanceMethods
15
19
  extend ClassMethods
16
20
 
21
+ #-
17
22
  # if ActiveRecord::Base is in the parent-chain of the class where we are included into:
23
+ # ::Rails::Railtie.subclasses.map(&:to_s).include?("ActiveRecord::Railtie")
24
+ #+
25
+
18
26
  serialize :i18n # we should also protect it from direct assignment by the user
19
27
 
28
+ #-
20
29
  # if Mongoid::Document is in the list of classes which extends the class we are included into:
30
+ # ::Rails::Railtie.subclasses.map(&:to_s).include?("Rails::Mongoid::Railtie")
31
+
21
32
  # field :i18n, type: Hash
22
33
  # but on the other hand, Mongoid now supports "localized fields" -- so we don't need to re-implement this.
23
34
  # Yay! Durran Jordan is awesome! :-) See: http://mongoid.org/docs/documents/localized.html
@@ -30,32 +41,40 @@ module EmbeddedLocalization
30
41
  # - we can easily hide the internal hash by re-defining the attr-accessors for doing the I18n
31
42
  # - we can better add the per-attribute versioning, which is planned
32
43
  # -
44
+ #+
33
45
 
34
46
  after_initialize :initialize_i18n_hashes
35
47
 
36
-
37
48
  # dynamically define the accessors for the translated attributes:
38
49
 
39
50
  translated_attribute_names.each do |attr_name|
40
51
  class_eval do
41
52
  # define the getter method
53
+ #
42
54
  define_method(attr_name) do |locale = I18n.locale|
43
- if ! self.i18n.has_key?(locale)
44
- return self.i18n[ I18n.default_locale ][attr_name] if ActsAsI18n.fallback?
45
- return nil
55
+ if self.i18n.has_key?(locale)
56
+ self.i18n[ locale ][attr_name]
57
+ else
58
+ # fallback to the I18n.default_locale if we do fallbacks:
59
+ if self.class.fallbacks? && self.i18n[ I18n.default_locale ]
60
+ return self.i18n[ I18n.default_locale ][attr_name]
61
+ else
62
+ return nil
63
+ end
46
64
  end
47
- self.i18n[ locale ][attr_name]
48
65
  end
49
66
 
50
- # define the setter method
67
+ # define the setter method
68
+ #
51
69
  define_method(attr_name.to_s+ '=') do |new_translation|
70
+ self.i18n_will_change! # for ActiveModel Dirty tracking
52
71
  self.i18n[I18n.locale] ||= HashWithIndifferentAccess.new
53
72
  self.i18n[I18n.locale][attr_name] = new_translation
54
73
  end
55
74
  end
56
75
  end
57
76
  end
58
-
77
+
59
78
  def translates?
60
79
  included_modules.include?(InstanceMethods)
61
80
  end
@@ -16,9 +16,18 @@ module EmbeddedLocalization
16
16
  translated_attribute_names.include?(name.to_sym)
17
17
  end
18
18
 
19
- def fallback?
20
- translation_options[:fallback]
19
+ # # determine if we are using fallbacks
20
+ def fallbacks?
21
+ i18n_fallbacks = I18n.backend.class.included_modules.map(&:to_s).include?('I18n::Backend::Fallbacks') # will be true if config.i18n.fallbacks => true in config
22
+ i18n_fallbacks || translation_options[:fallbacks] == true
21
23
  end
24
+
25
+ #-
26
+ # # fetch the fallbacks from the i18n backend
27
+ # def fallbacks
28
+ # fallbacks? ? I18n.fallbacks : nil
29
+ # end
30
+
22
31
  end
23
32
  end
24
33
  end
@@ -2,19 +2,22 @@ module EmbeddedLocalization
2
2
  module ActiveRecord
3
3
  module InstanceMethods
4
4
 
5
- # maybe a better way to do this is to use a special class LocalizedAttribute < HashWithIndifferentAccess
6
- # and use the [] , []= operators... hmm... thinking...
7
-
5
+ # we only support fallbacks to I18n.default_locale for now
6
+ #
8
7
  def get_localized_attribute(attr_name, locale)
9
- if ! self.i18n.has_key?(locale)
10
- return self.i18n[ I18n.default_locale ][attr_name] if ActsAsI18n.fallback?
11
- return nil
12
- else
8
+ if self.i18n.has_key?(locale)
13
9
  self.i18n[locale][attr_name]
10
+ else
11
+ if self.class.fallbacks? && self.i18n[ I18n.default_locale ]
12
+ return self.i18n[ I18n.default_locale ][attr_name]
13
+ else
14
+ return nil
15
+ end
14
16
  end
15
17
  end
16
-
18
+
17
19
  def set_localized_attribute(attr_name, locale, new_translation)
20
+ self.i18n_will_change! # for ActiveModel Dirty tracking
18
21
  self.i18n[locale] ||= HashWithIndifferentAccess.new
19
22
  self.i18n[locale][attr_name] = new_translation
20
23
  end
@@ -1,3 +1,3 @@
1
1
  module EmbeddedLocalization
2
- VERSION = '0.1.3'
2
+ VERSION = '0.1.4'
3
3
  end
@@ -3,15 +3,30 @@ require 'extensions/hash'
3
3
 
4
4
  module EmbeddedLocalization
5
5
  autoload :ActiveRecord, 'embedded_localization/active_record'
6
-
7
- class << self
8
- class_attribute :fallback
9
-
10
- def fallback?
11
- fallback == true
12
- end
13
- end
14
6
  end
15
7
 
16
8
  # we're assuming for now only to be used with ActiveRecord 3, which is auto-required above
17
9
  ActiveRecord::Base.extend(EmbeddedLocalization::ActiveRecord::ActMacro)
10
+
11
+ #-
12
+ # ------------------------------------------------------------------------------------------------------
13
+ # probably a good idea to keep our own implementation of fallbacks,
14
+ # because we only want to fallback to I18n.default_locale .. nothing more complicated for now.
15
+ # ------------------------------------------------------------------------------------------------------
16
+ #
17
+ # Fallbacks: https://github.com/svenfuchs/i18n/wiki/Fallbacks
18
+ #
19
+ # The problem is that the I18n backends are meant for static strings in the views, helpers, etc.; not for model data.
20
+ # Switching on the current I18n backend's fallbacks will allow us to use that backend's mappings from one locale to the fallbacks,
21
+ # but we still need to search for the translated module data in our serialized i18n attribute hash ourselves.
22
+
23
+ # to enable I18n fallbacks:
24
+ # require "i18n/backend/fallbacks"
25
+ # I18n.backend.class.send(:include, I18n::Backend::Fallbacks)
26
+
27
+ # Thread.current[:i18n_config].backend
28
+ # ?? I18n.fallbacks.map('es' => 'en') ?? doesn't seem to work as expected..
29
+
30
+ # not as general:
31
+ # I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
32
+
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: embedded_localization
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.3
5
+ version: 0.1.4
6
6
  platform: ruby
7
7
  authors:
8
8
  - Tilo Sloboda
@@ -10,13 +10,10 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-01-27 00:00:00 Z
13
+ date: 2012-01-31 00:00:00 Z
14
14
  dependencies: []
15
15
 
16
- description: |-
17
- Rails I18n: Embedded_Localization for ActiveRecord 3 is very lightweight, and allows you to \
18
- transparently store translations of attributes right inside each record -- no extra database tables needed to store \
19
- the localization data!
16
+ description: "Rails I18n: Embedded_Localization for ActiveRecord 3 is very lightweight, and allows you to transparently store translations of attributes right inside each record -- no extra database tables needed to store the localization data!"
20
17
  email:
21
18
  - tilo.sloboda@gmail.com
22
19
  executables: []