lost_in_translations_temp 1.4.3

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e5fd582680517c1d790b2eb872fc08781540be63
4
+ data.tar.gz: ab6661e9fe1fdf23c944234506d35f66c579d9d4
5
+ SHA512:
6
+ metadata.gz: cde2d1caded6e0c4d2bcb2877d60d0c35400c8d3ef2000b5dfeae5a9d7639371b4b8bc43dc99f91f536814a156e2ef0c75efbd8cb0e4714fd44b389307ff9ed9
7
+ data.tar.gz: 3e5680d8bf25ed39fbb0b90f502ff440578e0e1b70bc4ff28daaa9e7dd699ff4ee851d34e7f54c79ff4bdb9b9c51e20a85b7d5dd24127d244965f9e94d276b83
data/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # Lost In Translations
2
+ Super light Translation Ruby Gem agnostic to your framework and source data
3
+
4
+ [![Code Climate](https://codeclimate.com/github/Streetbees/lost-in-translations/badges/gpa.svg)](https://codeclimate.com/github/Streetbees/lost-in-translations)
5
+ [![Test Coverage](https://codeclimate.com/github/Streetbees/lost-in-translations/badges/coverage.svg)](https://codeclimate.com/github/Streetbees/lost-in-translations/coverage)
6
+ [![Build Status](https://travis-ci.org/Streetbees/lost-in-translations.svg?branch=master)](https://travis-ci.org/Streetbees/lost-in-translations)
7
+ [![Gem Version](https://badge.fury.io/rb/lost_in_translations.svg)](https://badge.fury.io/rb/lost_in_translations)
8
+
9
+ ## 1) Basic Usage
10
+ ```ruby
11
+ class User < Struct.new(:title, :first_name, :last_name)
12
+ include LostInTranslations
13
+
14
+ translate :title, :first_name
15
+
16
+ def translation_data
17
+ @translation_data ||= {
18
+ en: { first_name: 'Jon', last_name: 'Snow' },
19
+ fr: { first_name: 'Jean', last_name: 'Neige' }
20
+ }
21
+ end
22
+ end
23
+ ```
24
+ Class method ```.translate``` will redefine ```#title``` and ```#first_name``` instance methods in order to return the values that match the ```I18n.locale``` and the ```attribute name``` from the Hash returned by ```#translation_data```.
25
+
26
+ ```ruby
27
+ @user = User.new('Cavaleiro', 'Joao', 'Neve')
28
+
29
+ I18n.default_locale = :pt
30
+ I18n.locale = :fr
31
+
32
+ @user.first_name # returns 'Jean'
33
+ @user.last_name # returns 'Neve'
34
+ @user.title # returns nil
35
+
36
+ I18n.with_locale(:en) do
37
+ @user.first_name # returns 'Jon'
38
+ @user.last_name # returns 'Neve'
39
+ @user.title # returns nil
40
+ end
41
+
42
+ I18n.with_locale(:pt) do
43
+ # there is no translation present but since locale
44
+ # matches the default_locale, the original value is returned
45
+
46
+ @user.first_name # returns 'Joao'
47
+ @user.last_name # returns 'Neve'
48
+ @user.title # returns 'Cavaleiro'
49
+ end
50
+
51
+ I18n.with_locale(:de) do
52
+ @user.first_name # returns nil
53
+ @user.last_name # returns 'Neve'
54
+ @user.title # returns nil
55
+ end
56
+ ```
57
+
58
+ The following instance methods are also available:
59
+ #### 1.1) ```#translate```
60
+ ```ruby
61
+ @user.translate(:first_name, :fr) # returns 'Jean'
62
+ @user.translate(:first_name, :en) # returns 'Jon'
63
+ @user.translate(:first_name, :pt) # returns 'Joao'
64
+ @user.translate(:first_name, :de) # returns nil
65
+ ```
66
+
67
+ #### 1.2) ```#<I18n.available_locales>_<translated_field>```
68
+ ```ruby
69
+ @user.fr_first_name # returns 'Jean'
70
+ @user.en_first_name # returns 'Jon'
71
+ @user.pt_first_name # returns 'Joao'
72
+ @user.de_first_name # returns nil
73
+ ```
74
+
75
+ #### 1.3) ```#<I18n.available_locales>_<translated_field>=```
76
+ ```ruby
77
+ @user.pt_first_name = 'João'
78
+ @user.de_first_name = 'Hans'
79
+
80
+ @user.translation_data # will contain
81
+ # {
82
+ # en: { first_name: 'Jon', last_name: 'Snow' },
83
+ # pt: { first_name: 'João' },
84
+ # de: { first_name: 'Hans' },
85
+ # fr: { first_name: 'Jean', last_name: 'Neige' }
86
+ # }
87
+ ```
88
+
89
+ ## 2) Ideal usage
90
+ If your ActiveRecord Model has a json attribute called ```translation_data```.
91
+ ```ruby
92
+ class CreateUsers < ActiveRecord::Migration
93
+ def up
94
+ create_table :users do |t|
95
+ t.string :title
96
+ t.string :first_name
97
+ t.string :last_name
98
+ t.jsonb :translation_data
99
+ t.timestamps
100
+ end
101
+
102
+ User.create \
103
+ title: 'Cavaleiro',
104
+ first_name: 'Joao',
105
+ last_name: 'Neve',
106
+ translation_data: {
107
+ en: { first_name: 'Jon', last_name: 'Snow' },
108
+ fr: { first_name: 'Jean', last_name: 'Neige' }
109
+ }
110
+ end
111
+ end
112
+ ```
113
+
114
+ The usage becomes quite simple.
115
+ ```ruby
116
+ class User < ActiveRecord::Base
117
+ include LostInTranslations
118
+
119
+ translate :title, :first_name
120
+ end
121
+
122
+ @user = User.find(1)
123
+
124
+ I18n.locale = :fr
125
+
126
+ @user.first_name # returns 'Jean'
127
+ @user.last_name # returns 'Neve'
128
+ @user.title # returns nil
129
+ ```
130
+
131
+ ## 3) Forcing locales
132
+
133
+ There are many cases when you'll need to translate only a part of your data,
134
+ specially if this part is returned in a list of translated data.
135
+
136
+ For those cases you only have to define the field (virtual or persisted)
137
+ `force_locale` with one valid locale:
138
+
139
+ ```ruby
140
+ class User < ActiveRecord::Base
141
+ include LostInTranslations
142
+
143
+ translate :title, :first_name
144
+ end
145
+
146
+ User.create(
147
+ title: 'Cavaleiro',
148
+ first_name: 'Joao',
149
+ last_name: 'Neve',
150
+ force_locale: nil,
151
+ translation_data: {
152
+ en: { first_name: 'Jon', last_name: 'Snow' },
153
+ fr: { first_name: 'Jean', last_name: 'Neige' }
154
+ }
155
+ )
156
+
157
+ User.create(
158
+ title: 'Cavaleiro',
159
+ first_name: 'Joao',
160
+ last_name: 'Neve',
161
+ force_locale: 'fr'
162
+ translation_data: {
163
+ en: { first_name: 'Jon', last_name: 'Snow' },
164
+ fr: { first_name: 'Jean', last_name: 'Neige' }
165
+ }
166
+ )
167
+
168
+ User.create(
169
+ title: 'Cavaleiro',
170
+ first_name: 'Joao',
171
+ last_name: 'Neve',
172
+ force_locale: 'en'
173
+ translation_data: {
174
+ en: { first_name: 'Jon', last_name: 'Snow' },
175
+ fr: { first_name: 'Jean', last_name: 'Neige' }
176
+ }
177
+ )
178
+
179
+ I18n.locale = :pt
180
+
181
+ User.all.each do |user|
182
+ puts user.name
183
+ end
184
+
185
+ # It'll automatically output:
186
+ # Joao
187
+ # Jean
188
+ # Jon
189
+
190
+ ```
191
+
192
+
193
+ ## 4) Instalation
194
+
195
+ Add this to your Gemfile:
196
+ ```
197
+ gem 'lost_in_translations'
198
+ ```
199
+
200
+ And then execute:
201
+
202
+ ```
203
+ $> bundle install
204
+ ```
205
+
206
+ In Rails, create the file **config/initializers/lost_in_translations.rb** with:
207
+ ```ruby
208
+ LostInTranslations.reload
209
+ ```
210
+ Because Rails starts with a set of **I18n.available_locales** different from when it finished loading and **LostInTranslations** needs to redefine new methods for those new locales in your classes.
211
+
212
+ ## 5) F.A.Q.
213
+
214
+ - [I18n.available_locales as changed, how do I recreate the new translation methods?](https://github.com/Streetbees/lost-in-translations/wiki/Redefining-translation-methods)
215
+ - [Your "translation_data" method (in all of your objects) is not called "translation_data"](https://github.com/Streetbees/lost-in-translations/wiki/translation_data-configuration-version-1)
216
+ - [Your "translation_data" method (in a particular object) is not called "translation_data"](https://github.com/Streetbees/lost-in-translations/wiki/translation_data-configuration-version-2)
217
+ - [Custom translation mechanism](https://github.com/Streetbees/lost-in-translations/wiki/Custom-translation-mechanism)
@@ -0,0 +1,85 @@
1
+ require 'i18n'
2
+ require 'lost_in_translations/base'
3
+ require 'lost_in_translations/ruby'
4
+ require 'lost_in_translations/config'
5
+ require 'lost_in_translations/active_record'
6
+ require 'lost_in_translations/translator/base'
7
+
8
+ module LostInTranslations
9
+ def self.included(base_class)
10
+ if defined?(::ActiveRecord::Base) &&
11
+ base_class.ancestors.include?(::ActiveRecord::Base)
12
+ base_class.send(:include, LostInTranslations::ActiveRecord)
13
+ else
14
+ base_class.send(:include, Ruby)
15
+ end
16
+ end
17
+
18
+ def self.config
19
+ @config ||= Config.new(
20
+ 'translation_data',
21
+ Translator::Base,
22
+ nil,
23
+ 'force_locale'
24
+ )
25
+ end
26
+
27
+ def self.translate(*args)
28
+ config.translator.translate(*args)
29
+ end
30
+
31
+ def self.assign_translation(*args)
32
+ config.translator.assign_translation(*args)
33
+ end
34
+
35
+ def self.translation_data(object)
36
+ config.translator.translation_data(object)
37
+ end
38
+
39
+ def self.define_translation_methods(object, *fields)
40
+ fields.each do |field|
41
+ define_dynamic_translation_method(object, field)
42
+ define_particular_translation_methods(object, field)
43
+ end
44
+ end
45
+
46
+ def self.define_dynamic_translation_method(object, method_name)
47
+ object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
48
+ def #{method_name}
49
+ translate(:#{method_name}, I18n.locale)
50
+ end
51
+ RUBY
52
+ end
53
+
54
+ def self.define_particular_translation_methods(object, attribute)
55
+ I18n.available_locales.each do |locale|
56
+ method_name = "#{locale.to_s.downcase.tr('-', '_')}_#{attribute}"
57
+
58
+ define_translation_method(object, method_name, attribute, locale)
59
+ end
60
+ end
61
+
62
+ def self.define_translation_method(object, method_name, attribute, locale)
63
+ object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
64
+ def #{method_name}
65
+ translate(:#{attribute}, :'#{locale}')
66
+ end
67
+
68
+ def #{method_name}=(value)
69
+ assign_translation(:#{attribute}, value, :'#{locale}')
70
+ end
71
+ RUBY
72
+ end
73
+
74
+ def self.configure
75
+ yield(config)
76
+ end
77
+
78
+ def self.infected_classes
79
+ @infected_classes ||= []
80
+ end
81
+
82
+ def self.reload
83
+ infected_classes.each(&:define_translation_methods)
84
+ end
85
+ end
@@ -0,0 +1,18 @@
1
+ module LostInTranslations
2
+ module ActiveRecord
3
+ def self.included(base_class)
4
+ base_class.send(:include, Base)
5
+ base_class.extend ClassMethods
6
+ end
7
+
8
+ def call_original_field(object, field)
9
+ object.read_attribute(field)
10
+ end
11
+
12
+ module ClassMethods
13
+ def define_translation_methods
14
+ LostInTranslations.define_translation_methods self, *translation_fields
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,53 @@
1
+ module LostInTranslations
2
+ module Base
3
+ def self.included(base_class)
4
+ LostInTranslations.infected_classes.push(base_class)
5
+
6
+ base_class.extend ClassMethods
7
+ end
8
+
9
+ def translate(field, locale = I18n.locale)
10
+ translation = LostInTranslations.translate(self, field, locale)
11
+
12
+ if translation.nil? && fallback_to_default_locale(locale)
13
+ translation = call_original_field(self, field)
14
+ end
15
+
16
+ translation
17
+ end
18
+
19
+ def assign_translation(field, value, locale = I18n.locale)
20
+ LostInTranslations.assign_translation(self, field, value, locale)
21
+ end
22
+
23
+ def fallback_to_default_locale(locale)
24
+ LostInTranslations.config.fallback_to_default_locale ||
25
+ locale.to_sym == I18n.default_locale.to_sym
26
+ end
27
+
28
+ module ClassMethods
29
+ attr_writer :translation_data_field
30
+ attr_writer :force_locale_field
31
+
32
+ def translation_data_field
33
+ @translation_data_field ||
34
+ LostInTranslations.config.translation_data_field
35
+ end
36
+
37
+ def force_locale_field
38
+ @force_locale_field ||
39
+ LostInTranslations.config.force_locale_field
40
+ end
41
+
42
+ def translation_fields
43
+ @translation_fields ||= []
44
+ end
45
+
46
+ def translate(*fields)
47
+ translation_fields.concat(fields)
48
+
49
+ define_translation_methods
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ module LostInTranslations
2
+ Config = Struct.new \
3
+ :translation_data_field, :translator, :fallback_to_default_locale,
4
+ :force_locale_field
5
+ end
@@ -0,0 +1,34 @@
1
+ module LostInTranslations
2
+ module Ruby
3
+ def self.included(base_class)
4
+ base_class.send(:include, Base)
5
+ base_class.extend ClassMethods
6
+ end
7
+
8
+ def call_original_field(object, field)
9
+ method_name = Ruby.original_field_name(field)
10
+
11
+ return object.send(field) unless object.respond_to?(method_name)
12
+
13
+ object.send(method_name)
14
+ end
15
+
16
+ def self.original_field_name(field)
17
+ "original_field_#{field}".to_sym
18
+ end
19
+
20
+ module ClassMethods
21
+ def define_translation_methods
22
+ translation_fields.each do |field|
23
+ next if instance_methods.include?(Ruby.original_field_name(field))
24
+
25
+ class_eval do
26
+ alias_method Ruby.original_field_name(field), field.to_sym
27
+ end
28
+ end
29
+
30
+ LostInTranslations.define_translation_methods self, *translation_fields
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,61 @@
1
+ module LostInTranslations
2
+ module Translator
3
+ class Base
4
+ def self.translate(object, field, original_locale)
5
+ locale = check_forcing_locale(object, original_locale)
6
+
7
+ data = translation_data(object)
8
+
9
+ translations = data[locale.to_sym] || data[locale.to_s] || {}
10
+
11
+ translations[field.to_sym] || translations[field.to_s]
12
+ end
13
+
14
+ def self.assign_translation(object, field, value, locale)
15
+ data = translation_data(object)
16
+
17
+ translations = data[locale.to_sym] || data[locale.to_s]
18
+
19
+ translations ||= data[locale.to_sym] = {}
20
+
21
+ translations[field.to_sym] = value
22
+ end
23
+
24
+ def self.translation_data(object)
25
+ translation_data_field = translation_data_field(object)
26
+
27
+ data = object.send(translation_data_field)
28
+
29
+ if data.nil? && object.respond_to?("#{translation_data_field}=")
30
+ data = object.send("#{translation_data_field}=", {})
31
+ end
32
+
33
+ data
34
+ end
35
+
36
+ def self.translation_data_field(object)
37
+ translation_data_field = object.class.translation_data_field
38
+
39
+ unless object.respond_to?(translation_data_field)
40
+ raise \
41
+ NotImplementedError,
42
+ "#{object.class.name} does not implement .#{translation_data_field}"
43
+ end
44
+
45
+ translation_data_field
46
+ end
47
+
48
+ def self.check_forcing_locale(object, locale)
49
+ force_locale_field = object.class.force_locale_field
50
+
51
+ if object.respond_to?(force_locale_field)
52
+ force_locale = object.send(force_locale_field)
53
+
54
+ return force_locale unless force_locale.to_s.length < 2
55
+ end
56
+
57
+ locale
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ module LostInTranslations
2
+ VERSION = '1.4.3'.freeze
3
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lost_in_translations_temp
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.4.3
5
+ platform: ruby
6
+ authors:
7
+ - StreetBees Dev Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-09-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.3
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 11.2.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 11.2.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 3.4.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 3.4.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.3.11
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.11
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.37.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.37.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 0.11.2
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 0.11.2
97
+ - !ruby/object:Gem::Dependency
98
+ name: activerecord
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 4.2.6
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 4.2.6
111
+ - !ruby/object:Gem::Dependency
112
+ name: codeclimate-test-reporter
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 0.4.8
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '='
123
+ - !ruby/object:Gem::Version
124
+ version: 0.4.8
125
+ - !ruby/object:Gem::Dependency
126
+ name: i18n
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.7'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.7'
139
+ description: Super light Translation Ruby Gem agnostic to your framework and source
140
+ data
141
+ email: dev@streetbees.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - README.md
147
+ - lib/lost_in_translations.rb
148
+ - lib/lost_in_translations/active_record.rb
149
+ - lib/lost_in_translations/base.rb
150
+ - lib/lost_in_translations/config.rb
151
+ - lib/lost_in_translations/ruby.rb
152
+ - lib/lost_in_translations/translator/base.rb
153
+ - lib/lost_in_translations/version.rb
154
+ homepage: https://github.com/streetbees/lost-in-translations
155
+ licenses:
156
+ - MIT
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 2.6.12
175
+ signing_key:
176
+ specification_version: 4
177
+ summary: Ruby Translation Gem
178
+ test_files: []