lost_in_translations 1.2.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
+ SHA1:
3
+ metadata.gz: bcda78e45d1191420fb5863127b77c5315fa7b46
4
+ data.tar.gz: 6cdf234915545512aac5e751a692986454fcfe27
5
+ SHA512:
6
+ metadata.gz: 55dd44bafc0005398321643ca0b44cef0ede2dd18365735809aceeeb06acec6e0a0b8201eba40380d2fe0b552738d317633ae9a3d8f6699fd667ba1e817f0bc2
7
+ data.tar.gz: c73c4f621cf6dc45e67fe3ba2901319604dbdb12ff481c01a8600edced13100a8c0d55d4e8e9a97aa1f7df8a3fd1d83851e1271d04a953251f1c0a3e56c050f8
data/.gitignore ADDED
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalization:
25
+ /.bundle/
26
+ /vendor/bundle
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ # Gemfile.lock
32
+ # .ruby-version
33
+ .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
37
+
38
+ *.bundle
39
+ *.so
40
+ *.o
41
+ *.a
42
+ mkmf.log
43
+
44
+ .DS_Store
45
+
46
+ # Jetbrains Idea files
47
+ .idea/
48
+ api.iml
49
+
50
+ db/schema.rb
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --tty
2
+ --color
3
+ --format documentation
4
+ --format html -o "tmp/rspec_result.html"
data/.rubocop.yml ADDED
@@ -0,0 +1,15 @@
1
+ Style/EmptyLinesAroundClassBody:
2
+ Enabled: false
3
+
4
+ Style/EmptyLinesAroundModuleBody:
5
+ Enabled: false
6
+
7
+ AllCops:
8
+ DisplayCopNames: true
9
+ Exclude:
10
+ - 'spec/**/*'
11
+ - 'Gemfile*'
12
+ - '*.gemspec'
13
+
14
+ Documentation:
15
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.0
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.1.0
5
+ - 2.3.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,97 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lost_in_translations (1.2.0)
5
+ i18n (~> 0.7)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (4.2.6)
11
+ activesupport (= 4.2.6)
12
+ builder (~> 3.1)
13
+ activerecord (4.2.6)
14
+ activemodel (= 4.2.6)
15
+ activesupport (= 4.2.6)
16
+ arel (~> 6.0)
17
+ activesupport (4.2.6)
18
+ i18n (~> 0.7)
19
+ json (~> 1.7, >= 1.7.7)
20
+ minitest (~> 5.1)
21
+ thread_safe (~> 0.3, >= 0.3.4)
22
+ tzinfo (~> 1.1)
23
+ arel (6.0.3)
24
+ ast (2.2.0)
25
+ builder (3.2.2)
26
+ byebug (8.2.5)
27
+ codeclimate-test-reporter (0.4.8)
28
+ simplecov (>= 0.7.1, < 1.0.0)
29
+ coderay (1.1.1)
30
+ diff-lcs (1.2.5)
31
+ docile (1.1.5)
32
+ i18n (0.7.0)
33
+ json (1.8.3)
34
+ method_source (0.8.2)
35
+ minitest (5.9.0)
36
+ parser (2.3.0.6)
37
+ ast (~> 2.2)
38
+ powerpack (0.1.1)
39
+ pry (0.10.3)
40
+ coderay (~> 1.1.0)
41
+ method_source (~> 0.8.1)
42
+ slop (~> 3.4)
43
+ pry-byebug (3.3.0)
44
+ byebug (~> 8.0)
45
+ pry (~> 0.10)
46
+ rainbow (2.1.0)
47
+ rspec (3.4.0)
48
+ rspec-core (~> 3.4.0)
49
+ rspec-expectations (~> 3.4.0)
50
+ rspec-mocks (~> 3.4.0)
51
+ rspec-core (3.4.4)
52
+ rspec-support (~> 3.4.0)
53
+ rspec-expectations (3.4.0)
54
+ diff-lcs (>= 1.2.0, < 2.0)
55
+ rspec-support (~> 3.4.0)
56
+ rspec-mocks (3.4.1)
57
+ diff-lcs (>= 1.2.0, < 2.0)
58
+ rspec-support (~> 3.4.0)
59
+ rspec-support (3.4.1)
60
+ rubocop (0.37.2)
61
+ parser (>= 2.3.0.4, < 3.0)
62
+ powerpack (~> 0.1)
63
+ rainbow (>= 1.99.1, < 3.0)
64
+ ruby-progressbar (~> 1.7)
65
+ unicode-display_width (~> 0.3)
66
+ ruby-progressbar (1.7.5)
67
+ simplecov (0.11.2)
68
+ docile (~> 1.1.0)
69
+ json (~> 1.8)
70
+ simplecov-html (~> 0.10.0)
71
+ simplecov-html (0.10.0)
72
+ slop (3.6.0)
73
+ sqlite3 (1.3.11)
74
+ thread_safe (0.3.5)
75
+ tzinfo (1.2.2)
76
+ thread_safe (~> 0.1)
77
+ unicode-display_width (0.3.1)
78
+
79
+ PLATFORMS
80
+ ruby
81
+
82
+ DEPENDENCIES
83
+ activerecord (= 4.2.6)
84
+ byebug (= 8.2.5)
85
+ codeclimate-test-reporter (= 0.4.8)
86
+ lost_in_translations!
87
+ pry-byebug (= 3.3.0)
88
+ rspec (= 3.4.0)
89
+ rubocop (= 0.37.2)
90
+ simplecov (= 0.11.2)
91
+ sqlite3 (= 1.3.11)
92
+
93
+ RUBY VERSION
94
+ ruby 2.3.0p0
95
+
96
+ BUNDLED WITH
97
+ 1.12.5
data/README.md ADDED
@@ -0,0 +1,203 @@
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
+
8
+ ## 1. Basic Usage
9
+ ```ruby
10
+ class User < Struct.new(:title, :first_name, :last_name)
11
+ include LostInTranslations
12
+
13
+ translate :title, :first_name
14
+
15
+ def translation_data
16
+ {
17
+ en: { first_name: 'Jon', last_name: 'Snow' },
18
+ fr: { first_name: 'Jean', last_name: 'Neige' }
19
+ }
20
+ end
21
+ end
22
+ ```
23
+ 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**, otherwise calls the original redefined method.
24
+
25
+ ```ruby
26
+ @user = User.new('Cavaleiro', 'Joao', 'Neve')
27
+
28
+ I18n.locale = :fr
29
+
30
+ @user.first_name # returns 'Jean'
31
+ @user.last_name # returns 'Neve'
32
+ @user.title # returns 'Cavaleiro'
33
+
34
+ I18n.with_locale(:en) do
35
+ @user.first_name # returns 'Jon'
36
+ @user.last_name # returns 'Neve'
37
+ @user.title # returns 'Cavaleiro'
38
+ end
39
+
40
+ I18n.with_locale(:de) do
41
+ @user.first_name # returns 'Joao'
42
+ @user.last_name # returns 'Neve'
43
+ @user.title # returns 'Cavaleiro'
44
+ end
45
+ ```
46
+
47
+ Instance method **#translate** is also available:
48
+ ```ruby
49
+ @user.translate(:first_name, :fr) # returns 'Jean'
50
+ @user.translate(:first_name, :en) # returns 'Jon'
51
+ @user.translate(:first_name, :de) # returns 'Joao'
52
+ ```
53
+
54
+ ## 2. Ideal usage
55
+ If your ActiveRecord Model has a json attribute called **translation_data**.
56
+ ```ruby
57
+ class CreateUsers < ActiveRecord::Migration
58
+ def up
59
+ create_table :users do |t|
60
+ t.string :title
61
+ t.string :first_name
62
+ t.string :last_name
63
+ t.json :translation_data
64
+ t.timestamps
65
+ end
66
+
67
+ User.create \
68
+ title: 'Cavaleiro',
69
+ first_name: 'Joao',
70
+ last_name: 'Neve'
71
+ translation_data: {
72
+ en: { first_name: 'Jon', last_name: 'Snow' },
73
+ fr: { first_name: 'Jean', last_name: 'Neige' }
74
+ }
75
+ end
76
+ end
77
+ ```
78
+
79
+ The usage becomes quite simple.
80
+ ```ruby
81
+ class User < ActiveRecord::Base
82
+ include LostInTranslations
83
+
84
+ translate :title, :first_name
85
+ end
86
+
87
+ @user = User.find(1)
88
+
89
+ I18n.locale = :fr
90
+
91
+ @user.first_name # returns 'Jean'
92
+ @user.last_name # returns 'Neve'
93
+ @user.title # returns 'Cavaleiro'
94
+ ```
95
+
96
+ ## 3. Configuration
97
+
98
+ ### 3.1 Your "translation_data" method (in all of your objects) is not called "translation_data"
99
+ ```ruby
100
+ LostInTranslations.configure do |config|
101
+ config.translation_data_field = 'my_translation_data_field'
102
+ end
103
+ ```
104
+
105
+ ```ruby
106
+ class User < ActiveRecord::Base
107
+ include LostInTranslations
108
+
109
+ translate :first_name
110
+
111
+ def my_translation_data_field
112
+ {
113
+ en: { first_name: 'Jon', last_name: 'Snow' },
114
+ fr: { first_name: 'Jean', last_name: 'Neige' }
115
+ }
116
+ end
117
+ end
118
+
119
+ I18n.locale = :fr
120
+
121
+ User.find(1).first_name # returns 'Jean'
122
+ ```
123
+
124
+ ### 3.2 Your "translation_data" method (in a particular object) is not called "translation_data"
125
+ ```ruby
126
+ class User < ActiveRecord::Base
127
+ include LostInTranslations
128
+
129
+ translate :first_name
130
+
131
+ self.translation_data_field = :my_translation_data_field
132
+
133
+ def my_translation_data_field
134
+ {
135
+ en: { first_name: 'Jon', last_name: 'Snow' },
136
+ fr: { first_name: 'Jean', last_name: 'Neige' }
137
+ }
138
+ end
139
+ end
140
+
141
+ I18n.locale = :fr
142
+
143
+ User.find(1).first_name # returns 'Jean'
144
+ ```
145
+
146
+ ### 3.3 Custom translation mechanism
147
+ ```ruby
148
+ class MyTranslator
149
+ def self.translate(object, field, locale)
150
+ translations = #get_data_from_redis_or_yaml_file(object)
151
+
152
+ (translations[locale] || {})[field]
153
+ end
154
+ end
155
+ ```
156
+
157
+ ```ruby
158
+ LostInTranslations.configure do |config|
159
+ config.translator = MyTranslator
160
+ end
161
+ ```
162
+
163
+ ```ruby
164
+ class User < ActiveRecord::Base
165
+ include LostInTranslations
166
+
167
+ translate :first_name
168
+ end
169
+
170
+ I18n.locale = :fr
171
+
172
+ User.find(1).first_name # returns 'Jean' from redis or yaml file
173
+ ```
174
+
175
+ Don't forget that you can do the same at the object level
176
+ ```ruby
177
+ class User < ActiveRecord::Base
178
+ include LostInTranslations
179
+
180
+ translate :first_name
181
+
182
+ def translation_data
183
+ # get_data_from_redis_or_yaml_file(self)
184
+ end
185
+ end
186
+
187
+ I18n.locale = :fr
188
+
189
+ User.find(1).first_name # returns 'Jean' from redis or yaml file
190
+ ```
191
+
192
+ ## 4 Instalation
193
+
194
+ Add your application's Gemfile:
195
+ ```
196
+ gem 'lost_in_translations'
197
+ ```
198
+
199
+ And then execute:
200
+
201
+ ```
202
+ $> bundle install
203
+ ```
@@ -0,0 +1,41 @@
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/translator'
6
+ require 'lost_in_translations/active_record'
7
+
8
+ module LostInTranslations
9
+
10
+ def self.included(base_class)
11
+ if defined?(::ActiveRecord::Base) &&
12
+ base_class.ancestors.include?(::ActiveRecord::Base)
13
+ base_class.include LostInTranslations::ActiveRecord
14
+ else
15
+ base_class.include Ruby
16
+ end
17
+ end
18
+
19
+ def self.config
20
+ @config ||= Config.new('translation_data', Translator)
21
+ end
22
+
23
+ def self.translate(*args)
24
+ config.translator.translate(*args)
25
+ end
26
+
27
+ def self.define_translation_methods(object, *fields)
28
+ fields.each do |field|
29
+ object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
30
+ def #{field}
31
+ translate(:#{field}, I18n.locale)
32
+ end
33
+ RUBY
34
+ end
35
+ end
36
+
37
+ def self.configure
38
+ yield(config)
39
+ end
40
+
41
+ end
@@ -0,0 +1,27 @@
1
+ module LostInTranslations
2
+ module ActiveRecord
3
+
4
+ module ClassMethods
5
+
6
+ def translate(*fields)
7
+ LostInTranslations.define_translation_methods(self, *fields)
8
+ end
9
+
10
+ end
11
+
12
+ def self.included(base_class)
13
+ base_class.include Base
14
+ base_class.extend ClassMethods
15
+ end
16
+
17
+ def translate(field, locale = I18n.locale)
18
+ LostInTranslations.translate(self, field, locale) ||
19
+ ActiveRecord.call_original_field(self, field)
20
+ end
21
+
22
+ def self.call_original_field(object, field)
23
+ object.read_attribute(field)
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module LostInTranslations
2
+ module Base
3
+
4
+ def self.included(base_class)
5
+ base_class.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ attr_writer :translation_data_field
11
+
12
+ def translation_data_field
13
+ @translation_data_field ||
14
+ LostInTranslations.config.translation_data_field
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module LostInTranslations
2
+
3
+ Config = Struct.new(:translation_data_field, :translator)
4
+
5
+ end
@@ -0,0 +1,39 @@
1
+ module LostInTranslations
2
+ module Ruby
3
+
4
+ module ClassMethods
5
+
6
+ def translate(*fields)
7
+ fields.each do |field|
8
+ alias_method Ruby.original_field_name(field), field.to_sym
9
+ end
10
+
11
+ LostInTranslations.define_translation_methods(self, *fields)
12
+ end
13
+
14
+ end
15
+
16
+ def self.included(base_class)
17
+ base_class.include Base
18
+ base_class.extend ClassMethods
19
+ end
20
+
21
+ def translate(field, locale = I18n.locale)
22
+ LostInTranslations.translate(self, field, locale) ||
23
+ Ruby.call_original_field(self, field)
24
+ end
25
+
26
+ def self.call_original_field(object, field)
27
+ method_name = Ruby.original_field_name(field)
28
+
29
+ return object.send(field) unless object.respond_to?(method_name)
30
+
31
+ object.send(method_name)
32
+ end
33
+
34
+ def self.original_field_name(field)
35
+ "original_field_#{field}".to_sym
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ module LostInTranslations
2
+ class Translator
3
+
4
+ def self.translate(object, field, locale)
5
+ translations = translations_for(object, locale) || {}
6
+
7
+ translations[field.to_sym] || translations[field.to_s]
8
+ end
9
+
10
+ def self.translations_for(object, locale)
11
+ translations = translation_data(object) || {}
12
+
13
+ translations[locale.to_sym] || translations[locale.to_s]
14
+ end
15
+
16
+ def self.translation_data(object)
17
+ translation_data_field = object.class.translation_data_field
18
+
19
+ unless object.respond_to?(translation_data_field)
20
+ raise \
21
+ NotImplementedError,
22
+ "#{object.class.name} does not respond to .#{translation_data_field}"
23
+ end
24
+
25
+ object.send(translation_data_field)
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ module LostInTranslations
2
+
3
+ VERSION = '1.2.0'.freeze
4
+
5
+ end
@@ -0,0 +1,32 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'lost_in_translations/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'lost_in_translations'
9
+ gem.version = LostInTranslations::VERSION
10
+ gem.license = 'MIT'
11
+ gem.authors = ['StreetBees Dev Team']
12
+ gem.email = 'dev@streetbees.com'
13
+ gem.summary = 'Ruby Translation Gem'
14
+ gem.description = 'Super light Translation Ruby Gem agnostic to your framework and source data'
15
+ gem.homepage = 'https://github.com/streetbees/lost_in_translations'
16
+
17
+ gem.files = `git ls-files`.split($/)
18
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ['lib']
21
+
22
+ gem.add_development_dependency 'rspec', '3.4.0'
23
+ gem.add_development_dependency 'byebug', '8.2.5'
24
+ gem.add_development_dependency 'sqlite3', '1.3.11'
25
+ gem.add_development_dependency 'rubocop', '0.37.2'
26
+ gem.add_development_dependency 'simplecov', '0.11.2'
27
+ gem.add_development_dependency 'pry-byebug', '3.3.0'
28
+ gem.add_development_dependency 'activerecord', '4.2.6'
29
+ gem.add_development_dependency 'codeclimate-test-reporter', '0.4.8'
30
+
31
+ gem.add_dependency 'i18n', '~> 0.7'
32
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe LostInTranslations::ActiveRecord do
4
+
5
+ describe '.translate' do
6
+
7
+ context "when translating a field" do
8
+ before do
9
+ @user_class = Class.new(ActiveRecord::Base) do
10
+ self.table_name = 'users'
11
+
12
+ include LostInTranslations::ActiveRecord
13
+
14
+ translate :title, :first_name
15
+
16
+ def translation_data
17
+ {
18
+ en: { first_name: 'Jon', last_name: 'Snow' },
19
+ fr: { first_name: 'Jean', last_name: 'Neige' }
20
+ }
21
+ end
22
+ end
23
+
24
+ @user_class.create title: 'Cavaleiro', first_name: 'Joao', last_name: 'Neve'
25
+ @user = @user_class.first
26
+ end
27
+ after { @user.destroy }
28
+
29
+ it_behaves_like "a proper translator"
30
+ end
31
+
32
+ context "when a particular field is not translated" do
33
+ before do
34
+ @user_class = Class.new(ActiveRecord::Base) do
35
+ self.table_name = 'users'
36
+
37
+ include LostInTranslations::ActiveRecord
38
+
39
+ translate :title, :first_name
40
+
41
+ def translation_data
42
+ {
43
+ en: { first_name: 'Jon', last_name: 'Snow' },
44
+ fr: { first_name: 'Jean', last_name: 'Neige' }
45
+ }
46
+ end
47
+ end
48
+
49
+ @user = @user_class.new title: 'Cavaleiro', first_name: 'Joao', last_name: 'Neve'
50
+ end
51
+
52
+ it "#field must return the original data" do
53
+ I18n.with_locale(:en) do
54
+ expect(@user.last_name).to eq 'Neve'
55
+ end
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe LostInTranslations::Base do
4
+
5
+ describe '.translation_data_field =' do
6
+
7
+ context "when it points to a real method" do
8
+ before do
9
+ @user_class = Struct.new(:first_name, :last_name) do
10
+ include LostInTranslations::Base
11
+
12
+ self.translation_data_field = :translation_json
13
+
14
+ def translation_json
15
+ {
16
+ en: { first_name: 'Jon', last_name: 'Snow' },
17
+ fr: { first_name: 'Jean', last_name: 'Neige' }
18
+ }
19
+ end
20
+ end
21
+
22
+ LostInTranslations.define_translation_methods(@user_class, :first_name)
23
+
24
+ @user = @user_class.new('Joao', 'Neve')
25
+ end
26
+
27
+ it "LostInTranslations.translate must return a translation" do
28
+ expect(LostInTranslations.translate(@user, :first_name, :en)).to eq 'Jon'
29
+ end
30
+
31
+ it "calling a field not translated, must return the original data" do
32
+ I18n.with_locale(:en) do
33
+ expect(@user.last_name).to eq 'Neve'
34
+ end
35
+ end
36
+
37
+ context "and the translation data doesn't contain results" do
38
+ it "LostInTranslations.translate must return nil" do
39
+ expect(LostInTranslations.translate(@user, :first_name, :de)).to be_nil
40
+ end
41
+ end
42
+ end
43
+
44
+ context "when it DOENS't point to a real method" do
45
+ before do
46
+ @user_class = Struct.new(:first_name, :last_name) do
47
+ include LostInTranslations::Base
48
+
49
+ self.translation_data_field = :translation_json
50
+ end
51
+
52
+ LostInTranslations.define_translation_methods(@user_class, :first_name)
53
+
54
+ @user = @user_class.new('Joao', 'Neve')
55
+ end
56
+
57
+ it "LostInTranslations.translate must raise an error" do
58
+ expect { LostInTranslations.translate(@user, :first_name, :en) }.to raise_error(NotImplementedError)
59
+ end
60
+
61
+ it "calling a field not translated, must return the original data" do
62
+ I18n.with_locale(:en) do
63
+ expect(@user.last_name).to eq 'Neve'
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ describe LostInTranslations do
4
+
5
+ describe "#included" do
6
+ context "when the object inherits from ActiveRecord" do
7
+ before do
8
+ @user_class = Class.new(ActiveRecord::Base) do
9
+ self.table_name = 'users'
10
+
11
+ include LostInTranslations
12
+ end
13
+ end
14
+
15
+ it "LostInTranslations::ActiveRecord must be included" do
16
+ expect(@user_class.ancestors.include?(LostInTranslations::ActiveRecord)).to be true
17
+ end
18
+ end
19
+
20
+ context "when the object DOES NOT inherit from ActiveRecord" do
21
+ before do
22
+ @user_class = Class.new { include LostInTranslations }
23
+ end
24
+
25
+ it "LostInTranslations::Ruby must be included" do
26
+ expect(@user_class.ancestors.include?(LostInTranslations::Ruby)).to be true
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "#config.translation_data_field" do
32
+
33
+ context "when setting the 'translation_data_field' to a known method" do
34
+ before do
35
+ LostInTranslations.configure do |config|
36
+ config.translation_data_field = 'translation_json'
37
+ end
38
+
39
+ @user_class = Struct.new(:first_name, :last_name) do
40
+ include LostInTranslations
41
+
42
+ translate :first_name
43
+
44
+ def translation_json
45
+ { en: { first_name: 'Jon', last_name: 'Snow' } }
46
+ end
47
+ end
48
+
49
+ @user = @user_class.new('joao', 'neve')
50
+ end
51
+ after { LostInTranslations.config.translation_data_field = 'translation_data' }
52
+
53
+ it "calling a translated field must return a translation" do
54
+ I18n.with_locale(:en) do
55
+ expect(@user.first_name).to eq 'Jon'
56
+ end
57
+ end
58
+ end
59
+
60
+ context "when setting the 'translation_data_field' to an unknown method" do
61
+ before do
62
+ LostInTranslations.configure do |config|
63
+ config.translation_data_field = 'translation_json'
64
+ end
65
+
66
+ @user_class = Struct.new(:first_name, :last_name) do
67
+ include LostInTranslations
68
+
69
+ translate :first_name
70
+ end
71
+
72
+ @user = @user_class.new('joao', 'neve')
73
+ end
74
+ after { LostInTranslations.config.translation_data_field = 'translation_data' }
75
+
76
+ it "calling a translated field, must raise an error" do
77
+ I18n.with_locale(:en) do
78
+ expect { @user.first_name }.to raise_error(NotImplementedError)
79
+ end
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ describe "#config.translator" do
86
+
87
+ context "changing the source of the translation_data" do
88
+ before do
89
+ LostInTranslations.configure do |config|
90
+ config.translator = Class.new(LostInTranslations::Translator) do
91
+ def self.translation_data(object)
92
+ { en: { first_name: 'Jon', last_name: 'Snow' } }
93
+ end
94
+ end
95
+ end
96
+
97
+ @user_class = Struct.new(:first_name, :last_name) do
98
+ include LostInTranslations
99
+
100
+ translate :first_name
101
+ end
102
+
103
+ @user = @user_class.new('joao', 'neve')
104
+ end
105
+ after { LostInTranslations.config.translator = LostInTranslations::Translator }
106
+
107
+ it "calling a translated field must return a translation" do
108
+ I18n.with_locale(:en) do
109
+ expect(@user.first_name).to eq 'Jon'
110
+ end
111
+ end
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe LostInTranslations::Ruby do
4
+
5
+ describe '.translate' do
6
+
7
+ context "when translating a field" do
8
+ before do
9
+ @user_class = Struct.new(:title, :first_name, :last_name) do
10
+ include LostInTranslations
11
+
12
+ translate :title, :first_name
13
+
14
+ def translation_data
15
+ {
16
+ en: { first_name: 'Jon', last_name: 'Snow' },
17
+ fr: { first_name: 'Jean', last_name: 'Neige' }
18
+ }
19
+ end
20
+ end
21
+
22
+ @user = @user_class.new('Cavaleiro', 'Joao', 'Neve')
23
+ end
24
+
25
+ it_behaves_like "a proper translator"
26
+ end
27
+
28
+ context "when a particular field is not translated" do
29
+ before do
30
+ @user_class = Struct.new(:title, :first_name, :last_name) do
31
+ include LostInTranslations
32
+
33
+ translate :title, :first_name
34
+
35
+ def translation_data
36
+ {
37
+ en: { first_name: 'Jon', last_name: 'Snow' },
38
+ fr: { first_name: 'Jean', last_name: 'Neige' }
39
+ }
40
+ end
41
+ end
42
+
43
+ @user = @user_class.new('Cavaleiro', 'Joao', 'Neve')
44
+ end
45
+
46
+ it "#field must return the original data" do
47
+ I18n.with_locale(:en) do
48
+ expect(@user.last_name).to eq 'Neve'
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,35 @@
1
+ require "codeclimate-test-reporter"
2
+
3
+ CodeClimate::TestReporter.start
4
+
5
+ require "simplecov"
6
+
7
+ SimpleCov.start do
8
+ root("lib/")
9
+ coverage_dir("../tmp/coverage/")
10
+ end
11
+
12
+ $: << File.expand_path('../', File.dirname(__FILE__))
13
+
14
+ require 'pry-byebug'
15
+ require 'active_record'
16
+ require 'lost_in_translations'
17
+
18
+ I18n.available_locales = [:en, :pt, :fr, :de]
19
+ I18n.default_locale = :pt
20
+
21
+ ActiveRecord::Base.establish_connection \
22
+ pool: 5,
23
+ timeout: 5000,
24
+ adapter: 'sqlite3',
25
+ database: File.expand_path('../spec/support/db/test.sqlite3', File.dirname(__FILE__))
26
+
27
+ Dir["./spec/**/support/**/*.rb"].each do |file|
28
+ require file
29
+ end
30
+
31
+ RSpec.configure do |config|
32
+ config.run_all_when_everything_filtered = true
33
+
34
+ config.order = 'random'
35
+ end
Binary file
@@ -0,0 +1,23 @@
1
+ shared_examples_for "a proper translator" do
2
+ it "#field must return a translation" do
3
+ I18n.with_locale(:en) do
4
+ expect(@user.first_name).to eq 'Jon'
5
+ end
6
+ end
7
+
8
+ context "when the translation data doesn't contain the desired language" do
9
+ it "#field must return the original data" do
10
+ I18n.with_locale(:de) do
11
+ expect(@user.first_name).to eq 'Joao'
12
+ end
13
+ end
14
+ end
15
+
16
+ context "when the translation data doesn't contain the desired field" do
17
+ it "#field must return the original data" do
18
+ I18n.with_locale(:en) do
19
+ expect(@user.title).to eq 'Cavaleiro'
20
+ end
21
+ end
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,200 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lost_in_translations
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
+ platform: ruby
6
+ authors:
7
+ - StreetBees Dev Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.4.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.4.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 8.2.5
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 8.2.5
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.3.11
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.11
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.37.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.37.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.11.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.11.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 3.3.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 3.3.0
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
+ - ".gitignore"
147
+ - ".rspec"
148
+ - ".rubocop.yml"
149
+ - ".ruby-version"
150
+ - ".travis.yml"
151
+ - Gemfile
152
+ - Gemfile.lock
153
+ - README.md
154
+ - lib/lost_in_translations.rb
155
+ - lib/lost_in_translations/active_record.rb
156
+ - lib/lost_in_translations/base.rb
157
+ - lib/lost_in_translations/config.rb
158
+ - lib/lost_in_translations/ruby.rb
159
+ - lib/lost_in_translations/translator.rb
160
+ - lib/lost_in_translations/version.rb
161
+ - lost_in_translations.gemspec
162
+ - spec/lost_in_translations/active_record_spec.rb
163
+ - spec/lost_in_translations/base_spec.rb
164
+ - spec/lost_in_translations/lost_in_translations_spec.rb
165
+ - spec/lost_in_translations/ruby_spec.rb
166
+ - spec/spec_helper.rb
167
+ - spec/support/db/test.sqlite3
168
+ - spec/support/shared_examples/proper_translator.rb
169
+ homepage: https://github.com/streetbees/lost_in_translations
170
+ licenses:
171
+ - MIT
172
+ metadata: {}
173
+ post_install_message:
174
+ rdoc_options: []
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubyforge_project:
189
+ rubygems_version: 2.5.1
190
+ signing_key:
191
+ specification_version: 4
192
+ summary: Ruby Translation Gem
193
+ test_files:
194
+ - spec/lost_in_translations/active_record_spec.rb
195
+ - spec/lost_in_translations/base_spec.rb
196
+ - spec/lost_in_translations/lost_in_translations_spec.rb
197
+ - spec/lost_in_translations/ruby_spec.rb
198
+ - spec/spec_helper.rb
199
+ - spec/support/db/test.sqlite3
200
+ - spec/support/shared_examples/proper_translator.rb