clicrdv_easy_translatable 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 50704672bccd72c0179e2acd83114e675d7c2301c564ba81a011fa64ac6c3f8c
4
+ data.tar.gz: cf389801803b8822a553c465e9e0568dbbfb2b5a320626a600ced51181b94588
5
+ SHA512:
6
+ metadata.gz: 84a2c46f6ad7282664eaf750596f14a348e0a1a289fdac4dd0edb8deeed6af1d4b500a8b469f0614dd44492f4581818c01be9d96d12c1ab739414917078efed6
7
+ data.tar.gz: 7da00eed5cb246f1ace53df770e3887412c84854899a2189467d1c052467681239e883e7481227b07c4bebef643fbdce7776572853e12fa0cf35efc39f73c5a7
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2008, 2009, 2010 Sven Fuchs, Joshua Harvey, Clemens Kofler, John-Paul Bader, ClicRDV
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Translatable [![Gem Version](https://badge.fury.io/rb/easy_translatable.png)](http://badge.fury.io/rb/easy_translatable) [![Code Climate](https://codeclimate.com/github/clicrdv/translatable.png)](https://codeclimate.com/github/clicrdv/translatable) [![Build Status](https://travis-ci.org/clicrdv/translatable.png)](https://travis-ci.org/clicrdv/translatable) [![Coverage Status](https://coveralls.io/repos/clicrdv/translatable/badge.png)](https://coveralls.io/r/clicrdv/translatable)
2
+ ## Requirements
3
+
4
+ * ActiveRecord 3.2
5
+ * I18n
6
+
7
+ ## Installation
8
+
9
+ To install just use:
10
+
11
+ ```ruby
12
+ gem install easy_translatable
13
+ ```
14
+
15
+ When using bundler put this in your Gemfile:
16
+
17
+ ```ruby
18
+ gem 'easy_translatable', '~> 0.1.0'
19
+ ```
20
+
21
+ ## Todo
22
+
23
+ - cleanup
24
+ - doc
25
+ - migration/model for translation table
26
+
27
+
28
+ Copyright (c) 2008, 2009, 2010 Sven Fuchs, Joshua Harvey, Clemens Kofler, John-Paul Bader, ClicRDV
@@ -0,0 +1,67 @@
1
+ module Translatable
2
+ module ActiveRecord
3
+ class Adapter
4
+ # The cache caches attributes that already were looked up for read access.
5
+ # The stash keeps track of new or changed values that need to be saved.
6
+ attr_accessor :record, :stash, :translations
7
+ private :record=, :stash=
8
+
9
+ def initialize(record)
10
+ self.record = record
11
+ self.stash = Attributes.new
12
+ end
13
+
14
+ def fetch_stash(locale, name)
15
+ value = stash.read(locale, name)
16
+ return value if value
17
+ return nil
18
+ end
19
+
20
+ def stash_contains?(locale, name)
21
+ stash.contains?(locale, name)
22
+ end
23
+
24
+ def fetch(locale, name, value = nil)
25
+ value = stash_contains?(locale, name) ? fetch_stash(locale, name) : fetch_attribute(locale, name, value)
26
+
27
+ return value
28
+ end
29
+
30
+ def write(locale, name, value)
31
+ stash.write(locale, name, value)
32
+ end
33
+
34
+ def save_translations!
35
+ stash.reject {|locale, attrs| attrs.empty?}.each do |locale, attrs|
36
+ translations = record.translations_by_locale[locale]
37
+ attrs.each { |name, value|
38
+ translation = translations && translations[name] ||
39
+ record.translations.build(:locale => locale.to_s, :scope => record.class.table_name, :key => name)
40
+ translation['record_id'] = record.id
41
+ translation['value'] = value
42
+ translation.save!
43
+ }
44
+ end
45
+
46
+ reset
47
+ end
48
+
49
+ def reset
50
+ stash.clear
51
+ end
52
+
53
+ protected
54
+
55
+ def fetch_attribute(locale, name, value = nil)
56
+ if value.nil?
57
+ translation = record.translation_for(locale, name)
58
+ return translation && translation.send(:value)
59
+ else
60
+ translation = record.translation_for_serialized(locale, name, value)
61
+ return translation
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,27 @@
1
+ # Helper class for storing values per locale. Used by Globalize::Adapter
2
+ # to stash and cache attribute values.
3
+
4
+ module Translatable
5
+ module ActiveRecord
6
+ class Attributes < Hash # TODO: Think about using HashWithIndifferentAccess ?
7
+ def [](locale)
8
+ locale = locale.to_sym
9
+ self[locale] = {} unless has_key?(locale)
10
+ self.fetch(locale)
11
+ end
12
+
13
+ def contains?(locale, name)
14
+ self[locale].has_key?(name.to_s)
15
+ end
16
+
17
+ def read(locale, name)
18
+ self[locale][name.to_s]
19
+ end
20
+
21
+ def write(locale, name, value)
22
+ #raise 'z' if value.nil? # TODO
23
+ self[locale][name.to_s] = value
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,60 @@
1
+ module Translatable
2
+ module ActiveRecord
3
+ module ClassMethods
4
+ def translation_class
5
+ Translatable.translation_class
6
+ end
7
+
8
+ def translated?(name)
9
+ included = translated_attribute_names.detect { |attr| attr.is_a?(Hash) ? attr.keys.include?(name.to_sym) : attr == name.to_sym }
10
+ !included.nil?
11
+ end
12
+
13
+ protected
14
+
15
+ def translated_attr_accessor(name)
16
+ define_method(:"#{name}=") do |value|
17
+ write_attribute(name, value)
18
+ end
19
+ define_method(name) do |*args|
20
+ self.read_attribute(name, {:locale => args.detect {|a| !a.is_a? Hash }})
21
+ end
22
+ alias_method :"#{name}_before_type_cast", name
23
+ end
24
+
25
+ def locale_from(args)
26
+ args.detect {|a| !a.is_a? Hash }
27
+ end
28
+
29
+ def translations_accessor(name)
30
+ define_method(:"#{name}_translations") do
31
+ translations.each_with_object(HashWithIndifferentAccess.new) do |translation, result|
32
+ result[translation.locale] = translation.send(name)
33
+ end
34
+ end
35
+ define_method(:"#{name}_translations=") do |value|
36
+ value.each do |(locale, value)|
37
+ write_attribute name, value, :locale => locale
38
+ end
39
+ end
40
+ end
41
+
42
+ def condition_callback(attr_names, callback)
43
+ Proc.new { |rec|
44
+ attr_names.any? do |translatable_attr|
45
+ callback && rec.changes.keys.include?(translatable_attr.to_s)
46
+ end
47
+ }
48
+ end
49
+
50
+ %w(after_save before_save after_update before_update).each do |cb|
51
+ class_eval %{
52
+ def on_#{cb}_callback(attr_names, callback)
53
+ #{cb} callback, :if => condition_callback(attr_names, callback)
54
+ end
55
+ }
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,195 @@
1
+ module Translatable
2
+ module ActiveRecord
3
+ module InstanceMethods
4
+ delegate :translated_locales, :to => :translations
5
+
6
+ def translatable
7
+ @translatable ||= Adapter.new(self)
8
+ end
9
+
10
+ def self.included(base)
11
+ # Maintian Rails 3.0.x compatibility ..
12
+ if base.method_defined?(:assign_attributes)
13
+ base.class_eval %{
14
+ def assign_attributes(attributes, *options)
15
+ with_given_locale(attributes) { super }
16
+ end
17
+ }
18
+ else
19
+ base.class_eval %{
20
+ def attributes=(attributes, *args)
21
+ with_given_locale(attributes) { super }
22
+ end
23
+
24
+ def update_attributes!(attributes, *args)
25
+ with_given_locale(attributes) { super }
26
+ end
27
+
28
+ def update_attributes(attributes, *args)
29
+ with_given_locale(attributes) { super }
30
+ end
31
+ }
32
+ end
33
+ end
34
+
35
+ # Always call the super method, the attribute is translatable and we asked a translated model
36
+ def write_attribute(name, value, options = {}, &block)
37
+ if r_translated?(name) && translate?
38
+ options = {:locale => Translatable.locale}.merge(options)
39
+
40
+ # We don't want to track any changes, but save the new value in a translation hash
41
+
42
+ translatable.write(options[:locale], name, value)
43
+ else
44
+ super(name, value)
45
+ end
46
+ end
47
+
48
+ def translate
49
+ @translate_me = true
50
+ self
51
+ end
52
+
53
+ def end_translate
54
+ @translate_me = nil
55
+ self
56
+ end
57
+
58
+ def reload(options = nil)
59
+ @translate_me = false
60
+ translation_caches.clear
61
+ translated_attribute_names.each { |name| @attributes.reset(name.to_s) }
62
+ translatable.reset
63
+ super(options)
64
+ end
65
+
66
+ def save(*)
67
+ @translate_me = false
68
+ super
69
+ end
70
+
71
+ def translate?
72
+ !@translate_me.nil? && @translate_me
73
+ end
74
+
75
+ def read_attribute(name, options = {}, &block)
76
+ options = {:translated => true, :locale => Translatable.locale}.merge(options)
77
+ if r_translated?(name) and options[:translated]
78
+ serialized_value = super(name) if self.attributes.has_key?(name)
79
+ if translate? && (value = translatable.fetch(options[:locale] || Translatable.locale, name, serialized_value))
80
+ value
81
+ else
82
+ super(name)
83
+ end
84
+ else
85
+ super(name)
86
+ end
87
+ end
88
+
89
+ def r_translated?(name)
90
+ self.class.translated?(name)
91
+ end
92
+
93
+ def translated_attributes
94
+ translated_attribute_names.inject({}) do |attributes, name|
95
+ attributes.merge(name.to_s => translation.send(name))
96
+ end
97
+ end
98
+
99
+ # This method is basically the method built into Rails
100
+ # but we have to pass {:translated => false}
101
+ def untranslated_attributes
102
+ attrs = {}
103
+ attribute_names.each do |name|
104
+ attrs[name] = read_attribute(name, {:translated => false})
105
+ end
106
+ attrs
107
+ end
108
+
109
+ def translation_for(locale, name, build_if_missing = false)
110
+ unless translation_caches["#{locale}_#{name}"]
111
+ # Fetch translations from database as those in the translation collection may be incomplete
112
+ _translation = translations.detect{|t| t.locale.to_s == locale.to_s && t.key.to_s == name.to_s }
113
+ _translation ||= translations.build(:locale => locale) if build_if_missing
114
+ translation_caches["#{locale}_#{name}"] = _translation if _translation
115
+ end
116
+ translation_caches["#{locale}_#{name}"]
117
+ end
118
+
119
+ # Fetch translations per keys in the form
120
+ # model_attr_serialized_attribute
121
+ # E.G.1: ```Model``` has attribute ```config``` which has a key ```auto_save```
122
+ # will have a translation key ```config_auto_save```
123
+ # E.G.2: ```Model``` has attribute ```config``` which is an array of ```user_id => ([0-9]+)```
124
+ # will have translations key containing the index: ```config_user_id_0```, ```config_user_id_1```...
125
+ def translation_for_serialized(locale, name, value, build_if_missing = false)
126
+
127
+ unless translation_caches["#{locale}_#{name}"]
128
+ engine = self.attributes.has_key?(name) ? nil : JSON
129
+ deserialized_value = engine.nil? ? value : engine.load(value)
130
+
131
+ only = self.translated_serialized_attributes[name.to_sym].map(&:to_s)
132
+ if only.empty?
133
+ regex_keys = /\A#{name.to_s}_([a-z_]+[a-z])(?:_([0-9]*))?\Z/
134
+ else
135
+ regex_keys = /\A#{name.to_s}_(#{only.join('|')})(?:_([0-9]*))?\Z/
136
+ end
137
+ # Fetch translations from database as those in the translation collection may be incomplete
138
+ _translations = translations.select{|t| t.locale.to_s == locale.to_s && t.key.to_s =~ regex_keys }
139
+ _translations.each do |t|
140
+ matched = t.key.match regex_keys
141
+ unless matched.nil?
142
+ if matched.size == 3
143
+ sub_attr = matched[1]
144
+ index = matched[2].to_i
145
+ value[index][sub_attr] = t.value if value.size > index && value[index].has_key?(sub_attr)
146
+ elsif matched.size == 3
147
+ sub_attr = matched[1]
148
+ value[sub_attr] = t.value if value.has_key?(sub_attr)
149
+ end
150
+ end
151
+ end
152
+
153
+ translation_caches["#{locale}_#{name}"] = value
154
+ end
155
+ translation_caches["#{locale}_#{name}"]
156
+ end
157
+
158
+ def translation_caches
159
+ @translation_caches ||= {}
160
+ end
161
+
162
+
163
+ def with_given_locale(attributes, &block)
164
+ attributes.symbolize_keys! if attributes.respond_to?(:symbolize_keys!)
165
+
166
+ locale = respond_to?(:locale=) ? attributes.try(:[], :locale) :
167
+ attributes.try(:delete, :locale)
168
+
169
+ if locale && !respond_to?(:locale=)
170
+ already = translate?
171
+ translate unless translate?
172
+ Translatable.with_locale(locale, &block)
173
+ end_translate unless already
174
+ else
175
+ yield
176
+ end
177
+ end
178
+
179
+ def translations_by_locale(&block)
180
+ translations.each_with_object(HashWithIndifferentAccess.new) do |t, hash|
181
+ hash[t.locale] ||= HashWithIndifferentAccess.new
182
+ hash[t.locale][t.key] = block_given? ? block.call(t) : t
183
+ end
184
+ end
185
+
186
+ protected
187
+
188
+ def save_translations!
189
+ translatable.save_translations!
190
+ translation_caches.clear
191
+ end
192
+
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,96 @@
1
+ module Translatable
2
+ module ActiveRecord
3
+ module Macro
4
+
5
+ def translatable(*attr_names)
6
+
7
+ options = attr_names.extract_options!
8
+ setup_translatable!(options) unless translatable?
9
+
10
+ attr_names = attr_names.map(&:to_sym)
11
+ attr_names -= translated_attribute_names if defined?(translated_attribute_names)
12
+
13
+ if attr_names.present?
14
+
15
+ attr_names.each do |attr_name|
16
+ # Create accessors for the attribute.
17
+ translated_attr_accessor(attr_name)
18
+ translations_accessor(attr_name)
19
+
20
+ # Add attribute to the list.
21
+ self.translated_attribute_names << attr_name
22
+ if options[:only]
23
+ self.translated_serialized_attributes[attr_name] = options[:only] ? options[:only] : []
24
+ end
25
+ end
26
+
27
+ on_after_save_callback(attr_names, options[:after_save]) if options[:after_save]
28
+ on_before_save_callback(attr_names, options[:before_save]) if options[:before_save]
29
+ on_after_update_callback(attr_names, options[:after_update]) if options[:after_update]
30
+ on_before_update_callback(attr_names, options[:before_update]) if options[:before_update]
31
+
32
+ Translatable.add_translatable self
33
+
34
+ end
35
+ end
36
+
37
+ def class_name
38
+ @class_name ||= begin
39
+ class_name = table_name[table_name_prefix.length..-(table_name_suffix.length + 1)].downcase.camelize
40
+ pluralize_table_names ? class_name.singularize : class_name
41
+ end
42
+ end
43
+
44
+ def translatable?
45
+ included_modules.include?(InstanceMethods)
46
+ end
47
+
48
+ protected
49
+ def setup_translatable!(options)
50
+ options[:table_name] ||= Translatable.translation_class.table_name
51
+ options[:foreign_key] ||= 'record_id'
52
+ options[:conditions] ||= {}
53
+ options[:after_save] ||= false
54
+ options[:before_save] ||= false
55
+
56
+ class_attribute :translated_attribute_names, :translation_options, :fallbacks_for_empty_translations, :translated_serialized_attributes
57
+ self.translated_attribute_names = []
58
+ self.translation_options = options
59
+ self.fallbacks_for_empty_translations = options[:fallbacks_for_empty_translations]
60
+ self.translated_serialized_attributes = Hash.new
61
+
62
+ include InstanceMethods
63
+ extend ClassMethods
64
+
65
+ translation_class.table_name = options[:table_name]
66
+
67
+ has_many :translations, conditions(options), :class_name => translation_class.name,
68
+ :foreign_key => options[:foreign_key],
69
+ :dependent => :destroy,
70
+ :extend => HasManyExtensions,
71
+ :autosave => false
72
+
73
+ after_create :save_translations!
74
+ after_update :save_translations!
75
+ end
76
+
77
+ def conditions(options)
78
+ table_name = self.table_name
79
+ proc {
80
+ c = options[:conditions]
81
+ c = self.instance_eval(&c) if c.is_a?(Proc)
82
+ c.merge!(:scope => table_name, :locale => Translatable.locale)
83
+
84
+ where(c)
85
+ }
86
+ end
87
+
88
+ end
89
+
90
+ module HasManyExtensions
91
+ def find_or_initialize_by_locale(locale)
92
+ with_locale(locale.to_s).first || build(:locale => locale.to_s)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,31 @@
1
+ module Translatable
2
+ module ActiveRecord
3
+ module Relation
4
+ def exec_queries
5
+ queries = super
6
+
7
+ return queries.map(&:translate) if @translate_records
8
+
9
+ queries
10
+ end
11
+
12
+ private
13
+
14
+ def translate
15
+ @translate_records = true
16
+
17
+ self.eager_load(:translations)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ class Railtie < Rails::Railtie
24
+
25
+ initializer "easy_translatable.configure_rails_initialization" do
26
+ ActiveSupport.on_load(:active_record) do
27
+ ActiveRecord::Relation.send :prepend, Translatable::ActiveRecord::Relation
28
+ end
29
+ end
30
+
31
+ end if defined?(Rails)
@@ -0,0 +1,10 @@
1
+ module Translatable
2
+ module ActiveRecord
3
+ module Translate
4
+ def self.translate
5
+ self.scoped.translate
6
+ end
7
+
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ require File.expand_path '../active_record/class_methods.rb', __FILE__
2
+ require File.expand_path '../active_record/instance_methods.rb', __FILE__
3
+ require File.expand_path '../active_record/attributes.rb', __FILE__
4
+ require File.expand_path '../active_record/adapter.rb', __FILE__
5
+ require File.expand_path '../active_record/macro.rb', __FILE__
6
+ require File.expand_path '../active_record/translate.rb', __FILE__
7
+ require File.expand_path '../active_record/relation.rb', __FILE__
8
+
9
+ module Translatable
10
+ module ActiveRecord
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ require 'active_record'
2
+ require File.expand_path '../active_record.rb', __FILE__
3
+
4
+ ActiveRecord::Base.extend(Translatable::ActiveRecord::Translate)
5
+ ActiveRecord::Base.extend(Translatable::ActiveRecord::Macro)
@@ -0,0 +1,3 @@
1
+ module Translatable
2
+ VERSION = '0.4.0'
3
+ end
@@ -0,0 +1,68 @@
1
+ require File.join(File.dirname(__FILE__), 'translatable/default.rb')
2
+
3
+ module Translatable
4
+
5
+ @@translatable ||= Hash.new
6
+ @@translation_class ||= nil
7
+
8
+ class << self
9
+ def locale
10
+ read_locale || I18n.locale
11
+ end
12
+
13
+ def locale=(locale)
14
+ set_locale(locale)
15
+ end
16
+
17
+ def with_locale(locale, &block)
18
+ previous_locale = read_locale
19
+ begin
20
+ set_locale(locale)
21
+ result = yield(locale)
22
+ ensure
23
+ set_locale(previous_locale)
24
+ end
25
+ result
26
+ end
27
+
28
+ def translation_class_name=(klass)
29
+ @@translation_class = klass.constantize
30
+ end
31
+ def translation_class
32
+ @@translation_class ||= nil
33
+ end
34
+
35
+ # Hash of models that are translatable (values are the attrs)
36
+ def list
37
+ @@translatable ||= Hash.new
38
+ end
39
+
40
+ def add_translatable(klass)
41
+ if @@translatable.has_key? klass.name
42
+ klass.translated_attribute_names.each do |attr|
43
+ @@translatable[klass.name] << attr unless @@translatable[klass.name].include?(attr)
44
+ end
45
+ else
46
+ @@translatable[klass.name] = klass.translated_attribute_names
47
+ end
48
+
49
+ unless klass.translated_serialized_attributes.nil?
50
+ @@translatable[klass.name].map! do |attr|
51
+ serialized = klass.translated_serialized_attributes.reject{|k,v| k != attr}
52
+ serialized.empty? ? attr : serialized
53
+ end
54
+ end
55
+ end
56
+
57
+ protected
58
+
59
+ def read_locale
60
+ Thread.current[:translatable_locale]
61
+ end
62
+
63
+ def set_locale(locale)
64
+ Thread.current[:translatable_locale] = locale.try(:to_sym)
65
+ end
66
+ end
67
+
68
+ end
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clicrdv_easy_translatable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Paul Bonaud
8
+ - Charly Poly
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2022-03-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 6.1.3
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 6.1.3
28
+ - !ruby/object:Gem::Dependency
29
+ name: database_cleaner
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.6.0
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: 0.6.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - "~>"
43
+ - !ruby/object:Gem::Version
44
+ version: 0.6.0
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.6.0
48
+ - !ruby/object:Gem::Dependency
49
+ name: mocha
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: pathname_local
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: test_declarative
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ - !ruby/object:Gem::Dependency
91
+ name: friendly_id
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ type: :development
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ - !ruby/object:Gem::Dependency
105
+ name: sqlite3
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ - !ruby/object:Gem::Dependency
119
+ name: rake
120
+ requirement: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ - !ruby/object:Gem::Dependency
133
+ name: rdoc
134
+ requirement: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ type: :development
140
+ prerelease: false
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ - !ruby/object:Gem::Dependency
147
+ name: coveralls
148
+ requirement: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ type: :development
154
+ prerelease: false
155
+ version_requirements: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ description: Handle translations for AR models into a single table. And provide a
161
+ helper to select translated values.
162
+ email: paul.bonaud@clicrdv.com
163
+ executables: []
164
+ extensions: []
165
+ extra_rdoc_files: []
166
+ files:
167
+ - LICENSE
168
+ - README.md
169
+ - lib/translatable.rb
170
+ - lib/translatable/active_record.rb
171
+ - lib/translatable/active_record/adapter.rb
172
+ - lib/translatable/active_record/attributes.rb
173
+ - lib/translatable/active_record/class_methods.rb
174
+ - lib/translatable/active_record/instance_methods.rb
175
+ - lib/translatable/active_record/macro.rb
176
+ - lib/translatable/active_record/relation.rb
177
+ - lib/translatable/active_record/translate.rb
178
+ - lib/translatable/default.rb
179
+ - lib/translatable/version.rb
180
+ homepage: http://rubygems.org/gems/single_translatable
181
+ licenses:
182
+ - MIT
183
+ metadata: {}
184
+ post_install_message:
185
+ rdoc_options: []
186
+ require_paths:
187
+ - lib
188
+ required_ruby_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ required_rubygems_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ requirements: []
199
+ rubygems_version: 3.2.3
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: Handle translations for AR models into a single table
203
+ test_files: []