babylonia 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e5e07171440e9ebac6b51d3f768b68471dcbd5cd
4
- data.tar.gz: 7c0141cd5353cfe4e8e4fa10abdad68675388466
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzYzMTcwNjBhNThmMTUxYzVkZWE3ZTcwMzM4ZjhmM2MxZWMxMmVlNg==
5
+ data.tar.gz: !binary |-
6
+ YzkxZTg3YTc2YmY2NTFjMzdjMDIwYjg0OWQ3N2M0ZDA3OGE2MTkyMw==
5
7
  SHA512:
6
- metadata.gz: bc939cba85b5aadb2bf909dcccafff796137489ee22956aaf91c000f347e21b3fc3db967f2736c871b78848f56b8f4b77ec65af1cc2c172da6548a056952b30d
7
- data.tar.gz: df443e957bc998fb312d3f483f9fb38c68e8bfd817abf897db36f200ea7804811268cf1655a2b38a8f6508aefb76b836caa1e384c1d873120f3ec266bddab4e9
8
+ metadata.gz: !binary |-
9
+ ZTUxYjJhYTJjY2Q4Nzg3NmIzMGY1YzYxZjJjYTA0NTJjNWM5ZjAwODUxMWUx
10
+ NzE4YjdlN2RjZGRlYWMzNjlhN2Q1ZjJiZGEyZDhmMGU2NTlhMzQyODk2YjQ3
11
+ ZWI5M2UwYmQwNDI5YzIxY2I1MzE0NGNjMGFkYWU1YzIzMWEwZWE=
12
+ data.tar.gz: !binary |-
13
+ NTZmMzRhYzIwYjg0MTA3YTAyOWY3NWIwNjgzYTY1Y2UxOWY1MmUzNTY2YTdj
14
+ ZmNiODU0NmY5MTNkNzU2ZDFmZTQxNzA5MmY5MGIzNjY1N2RiNDk0ZmM3ZDg1
15
+ MzA3YmI1NTM2MWFlMTllYWIyMTFjMDYxNzMxNzFlMTQ4ZTY4MDM=
@@ -3,164 +3,203 @@ require 'i18n'
3
3
 
4
4
  # Let your users translate their content into their languages without additional tables or columns in your tables
5
5
  # @author Beat Richartz
6
- # @version 0.0.2
6
+ # @version 0.2.0
7
7
  # @since 0.0.1
8
8
  #
9
9
  module Babylonia
10
10
 
11
- # Class methods to extend a class with in order to make it able to handle translatable attributes
11
+ # Helper Methods for locales
12
+ # @author Beat Richartz
13
+ # @version 0.0.2
14
+ # @since 0.0.1
12
15
  #
13
- module ClassMethods
14
- # Main class method ob Babylonia. Use to make attributes translatable
15
- # @param [Symbol] fields the attributes to translate
16
- # @param [Hash] options The options for translation
17
- # @option [Symbol, Proc, String] locale The current locale - can be either a symbol that will be sent to the instance, a locale symbol that is included in available_locales or a proc that will get called with the instance. Defaults to I18n.locale at the time of use
18
- # @option [Symbol, Proc, String] default_locale The fallback / default locale - can be either a symbol that will be sent to the instance, a locale symbol that is included in available_locales, a proc that will get called with the instance
19
- # @option [Symbol, Proc, Array] available_locales The available locales - can be either a symbol that will be sent to the instance, a proc that will get called with the instance, or an Array of symbols of available locales. Defaults to I18n.available_locales at the time of use.
20
- # @option [Boolean] fallback Wheter to fallback to the default locale or not
21
- # @option [String] placeholder The placeholder to use for missing translations
16
+ module HelperMethods
17
+ # Return the currently active locale for the object
18
+ # @return [Symbol] The currently active locale
22
19
  #
23
- def build_babylonian_tower_on(*fields)
24
- options = fields.last.is_a?(Hash) ? fields.pop : {}
25
- options[:locale] ||= lambda { |r| I18n.locale }
26
- options[:default_locale] ||= lambda { |r| I18n.default_locale }
27
- options[:available_locales] ||= lambda { |r| I18n.available_locales }
28
- options[:fallback] = true if options[:fallback].nil?
29
-
30
- fields.each do |field|
31
- # Alias method chain the field to a translated value
32
- # @param [Symbol] locale Pass a locale to get the field translation in this specific locale
33
- # @param [Boolean] fallback Whether a fallback should be used, defaults to true
34
- # @return [String, NilClass] Either the string with the translation, the fallback, the placeholder or nil
35
- # @example Call a field in italian
36
- # your_instance.field(:it) #=> "Translation"
37
- #
38
- define_method :"#{field}_translated" do |l=nil, options={fallback: true}|
39
- field_hash = send(:"#{field}_hash")
40
- translation = field_hash[l || locale]
41
- translation = field_hash[default_locale] if translation.nil? or translation.empty? and options[:fallback] and locale_fallback?
42
- (translation.nil? or translation.empty?) ? missing_translation_placeholder(field) : translation
43
- end
44
- alias_method :"#{field}_raw", field
45
- alias_method field, :"#{field}_translated"
46
-
47
- # Return the translated values as a hash
48
- # @return [Hash] The hash with all the translations stored in the field
49
- #
50
- define_method :"#{field}_hash" do
51
- field_content = send(:"#{field}_raw")
52
- field_content.is_a?(String) ? YAML.load(field_content) : {}
53
- end
54
-
55
- # Set the field to a value. This either takes a string or a hash
56
- # If given a String, the current locale is set to this value
57
- # If given a Hash, the hash is merged into the current translation hash, and empty values are purged
58
- # @param [String, Hash] data The data to set either the current language translation or all translations to
59
- # @example Set the translation for the current locale
60
- # your_object.field = "TRANSLATION"
61
- # @example Set the translation and delete italian
62
- # your_object.field = {de: 'DEUTSCH', it: ''}
63
- #
64
- define_method :"#{field}_translated=" do |data|
65
- current_hash = send(:"#{field}_hash")
66
-
67
- if data.is_a?(String)
68
- current_hash.merge! locale => data
69
- elsif data.is_a?(Hash)
70
- data.delete_if{|k,v| !has_available_locale?(k) }
71
- current_hash.merge! data
72
- end
73
-
74
- send(:"#{field}_raw=", YAML.dump(current_hash.delete_if{|k,v| v.nil? or v.empty? }))
75
- end
76
- alias_method :"#{field}_raw=", :"#{field}="
77
- alias_method :"#{field}=", :"#{field}_translated="
78
- end
79
-
80
- # Return the currently active locale for the object
81
- # @return [Symbol] The currently active locale
82
- #
83
- define_method :locale do
84
- evaluate_localization_option!(:locale)
85
- end
86
-
87
- # Return the default locale for the object
88
- # @return [Symbol] The currently active locale
89
- #
90
- define_method :default_locale do
91
- evaluate_localization_option!(:default_locale)
20
+ def locale
21
+ evaluate_localization_option!(:locale)
22
+ end
23
+
24
+ # Return the default locale for the object
25
+ # @return [Symbol] The currently active locale
26
+ #
27
+ def default_locale
28
+ evaluate_localization_option!(:default_locale)
29
+ end
30
+
31
+ # Return if the object falls back on translations
32
+ # @return [Boolean] if the translations fall back to the default locale
33
+ #
34
+ def locale_fallback?
35
+ evaluate_localization_option!(:fallback)
36
+ end
37
+
38
+ # Return the missing translation placeholder
39
+ # @return [String] The missing translation placeholder
40
+ #
41
+ def missing_translation_placeholder field
42
+ evaluate_localization_option!(:placeholder, field)
43
+ end
44
+
45
+ # Return if a translation in the language is stored in all translated fields
46
+ # @return [Boolean] True if a translation is stored
47
+ #
48
+ def has_locale? locale
49
+ locales.include?(locale.to_sym)
50
+ end
51
+
52
+ # Return all the available locales
53
+ # @return [Array] An array of symbols of all available locales
54
+ #
55
+ def available_locales
56
+ evaluate_localization_option!(:available_locales)
57
+ end
58
+
59
+ # Return if a locale is theoretically available in all translated fields
60
+ # @return [Boolean] True if the language is available
61
+ #
62
+ def has_available_locale? locale
63
+ available_locales.include?(locale.to_sym)
64
+ end
65
+
66
+ protected
67
+
68
+ def translation_nil_or_empty? translation
69
+ translation.nil? or translation.empty?
70
+ end
71
+
72
+ def dump_translation_locale_hash hash
73
+ YAML.dump(hash.delete_if{|k,v| translation_nil_or_empty?(v) })
74
+ end
75
+
76
+ def fallback_to_default_locale!(hash, translation, options)
77
+ if translation_nil_or_empty?(translation) and options[:fallback] and locale_fallback?
78
+ hash[default_locale]
79
+ else
80
+ translation
92
81
  end
93
-
94
- # Return if the object falls back on translations
95
- # @return [Boolean] if the translations fall back to the default locale
96
- #
97
- define_method :locale_fallback? do
98
- evaluate_localization_option!(:fallback)
82
+ end
83
+ end
84
+
85
+ # Method missing implementation for virtual attributes
86
+ # @author Beat Richartz
87
+ # @version 0.0.2
88
+ # @since 0.0.1
89
+ #
90
+ module VirtualAttributes
91
+ # Define method missing to be able to access a language directly
92
+ # Enables to call a language virtual attribute directly
93
+ # @note Since the virtual attribute is called directly, there is no fallback on this unless you set it to true
94
+ # @example Call a getter directly
95
+ # object.field_de #=> 'DEUTSCH'
96
+ # @example Call a setter directly
97
+ # object.field_de = 'DEUTSCH'
98
+ # @example Call an untranslated field
99
+ # object.field_it #=> nil
100
+ #
101
+ # @example Call a field with fallback
102
+ # object.field_it(fallback: true)
103
+ def method_missing meth, *args, &block
104
+ if parts = extract_locale_method_parts(meth)
105
+ parts[2] ? send(parts[0] + parts[2].to_s, { parts[1].to_sym => args.first }) : send(parts[0], parts[1].to_sym, args.first || {})
106
+ else
107
+ super(meth, *args, &block)
99
108
  end
100
-
101
- # Return the missing translation placeholder
102
- # @return [String] The missing translation placeholder
103
- #
104
- define_method :missing_translation_placeholder do |field|
105
- evaluate_localization_option!(:placeholder, field)
109
+ end
110
+
111
+ private
112
+
113
+ def extract_locale_method_parts meth
114
+ if (parts = meth.to_s.match(/\A([^_]+)_(\w+)(=)?\z/).to_a[1..3]) && localized?(parts[0]) && has_available_locale?(parts[1])
115
+ parts
106
116
  end
107
-
108
- # Return languages stored in all translated fields
109
- # @return [Array] An array containing all languages stored
117
+ end
118
+ end
119
+
120
+ # Class methods to extend a class with in order to make it able to handle translatable attributes
121
+ #
122
+ module ClassMethods
123
+ private
124
+
125
+ def install_locale_field_getter_for(field)
126
+ # Alias method chain the field to a translated value
127
+ # @param [Symbol] locale Pass a locale to get the field translation in this specific locale
128
+ # @param [Boolean] fallback Whether a fallback should be used, defaults to true
129
+ # @return [String, NilClass] Either the string with the translation, the fallback, the placeholder or nil
130
+ # @example Call a field in italian
131
+ # your_instance.field(:it) #=> "Translation"
110
132
  #
111
- define_method :locales do
112
- first_field_locales = send(:"#{fields.first}_hash").keys
113
- fields.inject(first_field_locales){|o, f| o & send(:"#{f}_hash").keys }
133
+ define_method :"#{field}_translated" do |l=nil, options={fallback: true}|
134
+ field_hash = send(:"#{field}_hash")
135
+ translation = field_hash[l || locale]
136
+ translation = fallback_to_default_locale!(field_hash, translation, options)
137
+ translation_nil_or_empty?(translation) ? missing_translation_placeholder(field) : translation
114
138
  end
115
-
116
- # Return if a translation in the language is stored in all translated fields
117
- # @return [Boolean] True if a translation is stored
139
+ alias_method :"#{field}_raw", field
140
+ alias_method field, :"#{field}_translated"
141
+ end
142
+
143
+ def install_locale_field_hash_for(field)
144
+ # Return the translated values as a hash
145
+ # @return [Hash] The hash with all the translations stored in the field
118
146
  #
119
- define_method :has_locale? do |locale|
120
- locales.include?(locale.to_sym)
121
- end
122
-
123
- # Return all the available locales
124
- # @return [Array] An array of symbols of all available locales
125
- #
126
- define_method :available_locales do
127
- evaluate_localization_option!(:available_locales)
147
+ define_method :"#{field}_hash" do
148
+ field_content = send(:"#{field}_raw")
149
+ field_content.is_a?(String) ? YAML.load(field_content) : {}
128
150
  end
129
-
130
- # Return if a locale is theoretically available in all translated fields
131
- # @return [Boolean] True if the language is available
151
+ end
152
+
153
+ def install_locale_field_setter_for(field)
154
+ # Set the field to a value. This either takes a string or a hash
155
+ # If given a String, the current locale is set to this value
156
+ # If given a Hash, the hash is merged into the current translation hash, and empty values are purged
157
+ # @param [String, Hash] data The data to set either the current language translation or all translations to
158
+ # @example Set the translation for the current locale
159
+ # your_object.field = "TRANSLATION"
160
+ # @example Set the translation and delete italian
161
+ # your_object.field = {de: 'DEUTSCH', it: ''}
132
162
  #
133
- define_method :has_available_locale? do |locale|
134
- available_locales.include?(locale.to_sym)
163
+ define_method :"#{field}_translated=" do |data|
164
+ current_hash = send(:"#{field}_hash")
165
+
166
+ if data.is_a?(String)
167
+ current_hash.merge! locale => data
168
+ elsif data.is_a?(Hash)
169
+ data.delete_if{|k,v| !has_available_locale?(k) }
170
+ current_hash.merge! data
171
+ end
172
+
173
+ send(:"#{field}_raw=", dump_translation_locale_hash(current_hash))
135
174
  end
136
-
175
+ alias_method :"#{field}_raw=", :"#{field}="
176
+ alias_method :"#{field}=", :"#{field}_translated="
177
+ end
178
+
179
+ def install_virtual_locale_attributes_via_method_missing
180
+
181
+ end
182
+
183
+ def install_localized_helper_for(fields)
137
184
  # Return if an attribute is localized
138
185
  # @return [Boolean] True if the attribute is localized
139
186
  #
140
187
  define_method :localized? do |attr|
141
188
  fields.include?(attr.to_sym)
142
189
  end
143
-
144
- # Define method missing to be able to access a language directly
145
- # Enables to call a language virtual attribute directly
146
- # @note Since the virtual attribute is called directly, there is no fallback on this unless you set it to true
147
- # @example Call a getter directly
148
- # object.field_de #=> 'DEUTSCH'
149
- # @example Call a setter directly
150
- # object.field_de = 'DEUTSCH'
151
- # @example Call an untranslated field
152
- # object.field_it #=> nil
190
+ end
191
+
192
+ def install_locales_helper_for(fields)
193
+ # Return languages stored in all translated fields
194
+ # @return [Array] An array containing all languages stored
153
195
  #
154
- # @example Call a field with fallback
155
- # object.field_it(fallback: true)
156
- define_method :method_missing do |meth, *args, &block|
157
- if (m = meth.to_s.match(/\A([^_]+)_(\w+)(=)?\z/).to_a[1..3]) && localized?(m[0]) && has_available_locale?(m[1])
158
- m[2] ? send(m[0] + m[2].to_s, {m[1].to_sym => args.first}) : send(m[0], m[1].to_sym, args.first || {})
159
- else
160
- super(meth, *args, &block)
161
- end
196
+ define_method :locales do
197
+ first_field_locales = send(:"#{fields.first}_hash").keys
198
+ fields.inject(first_field_locales){|o, f| o & send(:"#{f}_hash").keys }
162
199
  end
163
-
200
+ end
201
+
202
+ def install_locale_options_evaluation(options)
164
203
  # Evaluate a localization option
165
204
  #
166
205
  define_method :evaluate_localization_option! do |option, field=nil, recursion=false|
@@ -176,5 +215,42 @@ module Babylonia
176
215
  end
177
216
  end
178
217
  end
218
+
219
+ def evaluate_locale_options_for(fields)
220
+ options = fields.last.is_a?(Hash) ? fields.pop : {}
221
+ options[:locale] ||= lambda { |r| I18n.locale }
222
+ options[:default_locale] ||= lambda { |r| I18n.default_locale }
223
+ options[:available_locales] ||= lambda { |r| I18n.available_locales }
224
+ options[:fallback] = true if options[:fallback].nil?
225
+ options
226
+ end
227
+
228
+ # Main class method ob Babylonia. Use to make attributes translatable
229
+ # @param [Symbol] fields the attributes to translate
230
+ # @param [Hash] options The options for translation
231
+ # @option [Symbol, Proc, String] locale The current locale - can be either a symbol that will be sent to the instance, a locale symbol that is included in available_locales or a proc that will get called with the instance. Defaults to I18n.locale at the time of use
232
+ # @option [Symbol, Proc, String] default_locale The fallback / default locale - can be either a symbol that will be sent to the instance, a locale symbol that is included in available_locales, a proc that will get called with the instance
233
+ # @option [Symbol, Proc, Array] available_locales The available locales - can be either a symbol that will be sent to the instance, a proc that will get called with the instance, or an Array of symbols of available locales. Defaults to I18n.available_locales at the time of use.
234
+ # @option [Boolean] fallback Wheter to fallback to the default locale or not
235
+ # @option [String] placeholder The placeholder to use for missing translations
236
+ #
237
+ public
238
+
239
+ def build_babylonian_tower_on(*fields)
240
+ options = evaluate_locale_options_for(fields)
241
+
242
+ fields.each do |field|
243
+ install_locale_field_getter_for(field)
244
+ install_locale_field_setter_for(field)
245
+ install_locale_field_hash_for(field)
246
+ end
247
+
248
+ include HelperMethods
249
+ install_localized_helper_for(fields)
250
+ install_locales_helper_for(fields)
251
+
252
+ include VirtualAttributes
253
+ install_locale_options_evaluation(options)
254
+ end
179
255
  end
180
256
  end
@@ -1,5 +1,5 @@
1
1
  module Babylonia
2
2
  # The current gem version
3
3
  #
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: babylonia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Beat Richartz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-20 00:00:00.000000000 Z
11
+ date: 2013-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.5.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.5.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.0.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ! '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.0.0
41
41
  description: Let your users translate their content into their languages without additional
@@ -70,21 +70,20 @@ require_paths:
70
70
  - lib
71
71
  required_ruby_version: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ! '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  required_rubygems_version: !ruby/object:Gem::Requirement
77
77
  requirements:
78
- - - '>='
78
+ - - ! '>='
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0'
81
81
  requirements: []
82
82
  rubyforge_project:
83
- rubygems_version: 2.0.7
83
+ rubygems_version: 2.1.11
84
84
  signing_key:
85
85
  specification_version: 4
86
86
  summary: Let there be languages!
87
87
  test_files:
88
88
  - spec/babylonia/class_methods_spec.rb
89
89
  - spec/spec_helper.rb
90
- has_rdoc: