releaf-i18n_database 0.2.1 → 1.0.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +19 -21
  3. data/app/assets/javascripts/{releaf/controllers → controllers}/releaf/i18n_database/translations.js +0 -0
  4. data/app/assets/stylesheets/{releaf/controllers → controllers}/releaf/i18n_database/translations.scss +0 -0
  5. data/app/builders/releaf/i18n_database/translations/builders_common.rb +1 -1
  6. data/app/builders/releaf/i18n_database/translations/index_builder.rb +1 -1
  7. data/app/controllers/releaf/i18n_database/translations_controller.rb +121 -127
  8. data/app/lib/releaf/i18n_database/parse_spreadsheet_translations.rb +62 -0
  9. data/app/lib/releaf/i18n_database/translations_store.rb +149 -0
  10. data/app/lib/releaf/i18n_database/translations_utilities.rb +6 -6
  11. data/app/models/releaf/i18n_database/i18n_entry.rb +21 -0
  12. data/app/models/releaf/i18n_database/i18n_entry_translation.rb +11 -0
  13. data/app/views/releaf/i18n_database/translations/_form_fields.haml +2 -2
  14. data/lib/releaf-i18n_database.rb +14 -3
  15. data/lib/releaf/i18n_database/backend.rb +56 -131
  16. data/lib/releaf/i18n_database/configuration.rb +8 -0
  17. data/lib/releaf/i18n_database/engine.rb +1 -30
  18. data/lib/releaf/i18n_database/humanize_missing_translations.rb +1 -1
  19. data/misc/translations.xlsx +0 -0
  20. data/spec/builders/translations/builder_common_spec.rb +1 -1
  21. data/spec/builders/translations/edit_builder_spec.rb +2 -2
  22. data/spec/builders/translations/table_builder_spec.rb +1 -1
  23. data/spec/controllers/i18n_backend/translations_controller_spec.rb +10 -19
  24. data/spec/features/translations_spec.rb +235 -16
  25. data/spec/fixtures/invalid.xls +3 -0
  26. data/spec/fixtures/invalid.xlsx +3 -0
  27. data/spec/lib/releaf/i18n_database/backend_spec.rb +192 -0
  28. data/spec/lib/releaf/i18n_database/configuration_spec.rb +13 -0
  29. data/spec/lib/{i18n_database → releaf/i18n_database}/humanize_missing_translations_spec.rb +7 -1
  30. data/spec/lib/releaf/i18n_database/parse_spreadsheet_translations_spec.rb +151 -0
  31. data/spec/lib/releaf/i18n_database/translations_store_spec.rb +548 -0
  32. data/spec/lib/{i18n_database → releaf/i18n_database}/translations_utilities_spec.rb +39 -39
  33. data/spec/models/i18n_database/i18n_entry_spec.rb +50 -0
  34. data/spec/models/i18n_database/i18n_entry_translation_spec.rb +9 -0
  35. metadata +45 -30
  36. data/app/lib/releaf/i18n_database/translations_importer.rb +0 -72
  37. data/app/models/releaf/i18n_database/translation.rb +0 -17
  38. data/app/models/releaf/i18n_database/translation_data.rb +0 -11
  39. data/lib/releaf/i18n_database/builders_autoload.rb +0 -10
  40. data/releaf-i18n_database.gemspec +0 -21
  41. data/spec/lib/i18n_database/backend_spec.rb +0 -337
  42. data/spec/lib/i18n_database/translations_importer_spec.rb +0 -17
  43. data/spec/models/i18n_database/translation_data_spec.rb +0 -13
  44. data/spec/models/i18n_database/translation_spec.rb +0 -49
@@ -1,19 +1,19 @@
1
1
  require 'rails_helper'
2
2
  feature "Translations" do
3
- background do
3
+ background(create_translations: true) do
4
4
  auth_as_user
5
5
 
6
- t1 = create(:translation, key: 'test.key1')
7
- t2 = create(:translation, key: 'great.stuff')
8
- t3 = create(:translation, key: 'geek.stuff')
9
- create(:translation_data, lang: 'en', localization: 'testa atslēga', translation_id: t1.id)
10
- create(:translation_data, lang: 'en', localization: 'awesome stuff', translation_id: t2.id)
11
- create(:translation_data, lang: 'lv', localization: 'lieliska manta', translation_id: t2.id)
12
- create(:translation_data, lang: 'en', localization: 'geek stuff', translation_id: t3.id)
13
- create(:translation_data, lang: 'lv', localization: 'nūģu lieta', translation_id: t3.id)
6
+ translation_1 = Releaf::I18nDatabase::I18nEntry.create(key: 'test.key1')
7
+ translation_2 = Releaf::I18nDatabase::I18nEntry.create(key: 'great.stuff')
8
+ translation_3 = Releaf::I18nDatabase::I18nEntry.create(key: 'geek.stuff')
9
+ translation_1.i18n_entry_translation.create(locale: 'en', text: 'testa atslēga')
10
+ translation_2.i18n_entry_translation.create(locale: 'en', text: 'awesome stuff')
11
+ translation_2.i18n_entry_translation.create(locale: 'lv', text: 'lieliska manta')
12
+ translation_3.i18n_entry_translation.create(locale: 'en', text: 'geek stuff')
13
+ translation_3.i18n_entry_translation.create(locale: 'lv', text: 'nūģu lieta')
14
14
  end
15
15
 
16
- scenario "blank only filtering", js: true do
16
+ scenario "blank only filtering", js: true, create_translations: true do
17
17
  visit releaf_i18n_database_translations_path
18
18
  expect(page).to have_number_of_resources(3)
19
19
 
@@ -46,7 +46,7 @@ feature "Translations" do
46
46
  expect(page).to have_number_of_resources(3)
47
47
  end
48
48
 
49
- scenario "index" do
49
+ scenario "index", create_translations: true do
50
50
  visit releaf_i18n_database_translations_path
51
51
  expect( page ).to have_content 'test.key1'
52
52
  expect( page ).to have_content 'great.stuff'
@@ -59,7 +59,7 @@ feature "Translations" do
59
59
  expect( page ).to have_content 'nūģu lieta'
60
60
  end
61
61
 
62
- scenario "Editing", js: true do
62
+ scenario "Editing", js: true, create_translations: true do
63
63
  visit releaf_i18n_database_translations_path
64
64
 
65
65
  fill_in 'search', with: "stuff"
@@ -77,7 +77,7 @@ feature "Translations" do
77
77
  expect(page).to have_notification("Update failed", :error)
78
78
 
79
79
  within ".table tr.item:last-child" do
80
- click_button "Remove item"
80
+ click_button "Remove"
81
81
  end
82
82
  expect(page).to have_css(".table tr.item", count: 1) # wait for fade out to complete
83
83
 
@@ -101,7 +101,15 @@ feature "Translations" do
101
101
  expect(page).to have_content 'en translation'
102
102
  end
103
103
 
104
- scenario "Import excel file with translations", js: true do
104
+ scenario "Do not save empty translations", create_translations: true do
105
+ visit releaf_i18n_database_translations_path
106
+ click_link "Edit"
107
+ click_button "Save"
108
+
109
+ expect(Releaf::I18nDatabase::I18nEntryTranslation.where(text: "").count).to eq(0)
110
+ end
111
+
112
+ scenario "Import excel file with translations", js: true, create_translations: true do
105
113
  visit releaf_i18n_database_translations_path
106
114
  expect(page).to have_no_css(".table td span", text: "Eksports")
107
115
  expect(page).to have_no_css(".table td span", text: "Export")
@@ -129,7 +137,7 @@ feature "Translations" do
129
137
  expect(page).to have_css(".table td span", text: "jauns")
130
138
  end
131
139
 
132
- scenario "Import unsupported file", js: true do
140
+ scenario "Import unsupported file", js: true, create_translations: true do
133
141
  visit releaf_i18n_database_translations_path
134
142
 
135
143
  script = "$('form.import').css({display: 'block'});"
@@ -144,7 +152,39 @@ feature "Translations" do
144
152
  expect(page).to have_notification("Unsupported file format", "error")
145
153
  end
146
154
 
147
- scenario "Export translations" do
155
+ scenario "Import corrupt xls file", js: true, create_translations: true do
156
+ visit releaf_i18n_database_translations_path
157
+
158
+ script = "$('form.import').css({display: 'block'});"
159
+ page.execute_script(script)
160
+
161
+ fixture_path = File.expand_path('../fixtures/invalid.xls', __dir__)
162
+
163
+ within('form.import') do
164
+ attach_file(:import_file, fixture_path)
165
+ end
166
+
167
+ expect(page).to have_notification("Unsupported file format", "error")
168
+ end
169
+
170
+
171
+ scenario "Import corrupt xlsx file", js: true, create_translations: true do
172
+ visit releaf_i18n_database_translations_path
173
+
174
+ script = "$('form.import').css({display: 'block'});"
175
+ page.execute_script(script)
176
+
177
+ fixture_path = File.expand_path('../fixtures/invalid.xlsx', __dir__)
178
+
179
+ within('form.import') do
180
+ attach_file(:import_file, fixture_path)
181
+ end
182
+
183
+ expect(page).to have_notification("Unsupported file format", "error")
184
+ end
185
+
186
+
187
+ scenario "Export translations", create_translations: true do
148
188
  visit releaf_i18n_database_translations_path
149
189
  click_link "Export"
150
190
 
@@ -159,4 +199,183 @@ feature "Translations" do
159
199
 
160
200
  File.delete(tmp_file)
161
201
  end
202
+
203
+ describe "Lookup" do
204
+ background do
205
+ Releaf::I18nDatabase::Backend.reset_cache
206
+ allow( Releaf.application.config.i18n_database ).to receive(:translation_auto_creation).and_return(true)
207
+ end
208
+
209
+ context "when translation exists within higher level key (instead of being scope)" do
210
+ it "returns nil (Humanize key)" do
211
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "some.food")
212
+ translation.i18n_entry_translation.create(locale: "lv", text: "suņi")
213
+
214
+ expect(I18n.t("some.food", locale: "lv")).to eq("suņi")
215
+ expect(I18n.t("some.food.asd", locale: "lv")).to eq("Asd")
216
+ end
217
+ end
218
+
219
+ context "when pluralized translation requested" do
220
+ context "when valid pluralized data matched" do
221
+ it "returns pluralized translation" do
222
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "dog.other")
223
+ translation.i18n_entry_translation.create(locale: "lv", text: "suņi")
224
+
225
+ expect(I18n.t("dog", locale: "lv", count: 2)).to eq("suņi")
226
+ end
227
+ end
228
+
229
+ context "when invalid pluralized data matched" do
230
+ it "returns nil (Humanize key)" do
231
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "dog.food")
232
+ translation.i18n_entry_translation.create(locale: "lv", text: "suņi")
233
+
234
+ expect(I18n.t("dog", locale: "lv", count: 2)).to eq("Dog")
235
+ end
236
+ end
237
+ end
238
+
239
+ context "when same translations with different cases exists" do
240
+ it "returns case sensitive translation" do
241
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "Save")
242
+ translation.i18n_entry_translation.create(locale: "lv", text: "Saglabāt")
243
+
244
+ expect(I18n.t("save", locale: "lv")).to eq("Save")
245
+ expect(I18n.t("Save", locale: "lv")).to eq("Saglabāt")
246
+ end
247
+ end
248
+
249
+ context "existing translation" do
250
+ context "when translations hash exists in parent scope" do
251
+ before do
252
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "dog.other")
253
+ translation.i18n_entry_translation.create(locale: "en", text: "dogs")
254
+ end
255
+
256
+ context "when pluralized translation requested" do
257
+ it "returns pluralized translation" do
258
+ expect(I18n.t("admin.controller.dog", count: 2)).to eq("dogs")
259
+ end
260
+ end
261
+
262
+ context "when non pluralized translation requested" do
263
+ it "returns nil" do
264
+ expect(I18n.t("admin.controller.dog")).to eq("Dog")
265
+ end
266
+ end
267
+ end
268
+
269
+ context "when ignorable pattern" do
270
+ it "does not auto create missing translation" do
271
+ expect{ I18n.t("attributes.title") }.to_not change{ Releaf::I18nDatabase::I18nEntry.count }
272
+ end
273
+ end
274
+
275
+ context "in parent scope" do
276
+ context "nonexistent translation in given scope" do
277
+ it "uses parent scope" do
278
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "validation.admin.blank")
279
+ translation.i18n_entry_translation.create(locale: "lv", text: "Tukšs")
280
+ expect(I18n.t("blank", scope: "validation.admin.roles", locale: "lv")).to eq("Tukšs")
281
+ end
282
+
283
+ context "when `inherit_scopes` option is `false`" do
284
+ it "does not lookup upon higher level scopes" do
285
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "validation.admin.blank")
286
+ translation.i18n_entry_translation.create(locale: "lv", text: "Tukšs")
287
+ expect(I18n.t("blank", scope: "validation.admin.roles", locale: "lv", inherit_scopes: false)).to eq("Blank")
288
+ end
289
+ end
290
+ end
291
+
292
+ context "and empty translation value in given scope" do
293
+ it "uses parent scope" do
294
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "validation.admin.roles.blank")
295
+ translation.i18n_entry_translation.create(locale: "lv", text: "")
296
+
297
+ parent_translation = Releaf::I18nDatabase::I18nEntry.create(key: "validation.admin.blank")
298
+ parent_translation.i18n_entry_translation.create(locale: "lv", text: "Tukšs")
299
+
300
+ expect(I18n.t("blank", scope: "validation.admin.roles", locale: "lv")).to eq("Tukšs")
301
+ end
302
+ end
303
+
304
+ context "and existing translation value in given scope" do
305
+ it "uses given scope" do
306
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "validation.admin.roles.blank")
307
+ translation.i18n_entry_translation.create(locale: "lv", text: "Tukša vērtība")
308
+
309
+ parent_translation = Releaf::I18nDatabase::I18nEntry.create(key: "validation.admin.blank")
310
+ parent_translation.i18n_entry_translation.create(locale: "lv", text: "Tukšs")
311
+
312
+ expect(I18n.t("blank", scope: "validation.admin.roles", locale: "lv")).to eq("Tukša vērtība")
313
+ end
314
+ end
315
+ end
316
+
317
+ context "when scope defined" do
318
+ it "uses given scope" do
319
+ translation = Releaf::I18nDatabase::I18nEntry.create(key: "admin.content.cancel")
320
+ translation.i18n_entry_translation.create(locale: "lv", text: "Atlikt")
321
+ expect(I18n.t("cancel", scope: "admin.content", locale: "lv")).to eq("Atlikt")
322
+ end
323
+ end
324
+ end
325
+
326
+ context "nonexistent translation" do
327
+ context "loading multiple times" do
328
+ it "queries db only for the first time" do
329
+ I18n.t("save", scope: "admin.xx")
330
+ expect(Releaf::I18nDatabase::I18nEntry).not_to receive(:where)
331
+ I18n.t("save", scope: "admin.xx")
332
+ end
333
+ end
334
+
335
+ context "with nonexistent translation" do
336
+ before do
337
+ allow(Releaf.application.config).to receive(:all_locales).and_return(["ru", "lv"])
338
+ end
339
+
340
+ it "creates empty translation" do
341
+ expect { I18n.t("save") }.to change { Releaf::I18nDatabase::I18nEntry.where(key: "save").count }.by(1)
342
+ end
343
+
344
+ context "when count option passed" do
345
+ context "when create_plurals option not passed" do
346
+ it "creates empty translation" do
347
+ expect { I18n.t("animals.horse", count: 1) }.to change { Releaf::I18nDatabase::I18nEntry.where(key: "animals.horse").count }.by(1)
348
+ end
349
+ end
350
+
351
+ context "when negative create_plurals option passed" do
352
+ it "creates empty translation" do
353
+ expect { I18n.t("animals.horse", create_plurals: false, count: 1) }.to change { Releaf::I18nDatabase::I18nEntry.where(key: "animals.horse").count }.by(1)
354
+ end
355
+ end
356
+
357
+ context "when positive create_plurals option passed" do
358
+ it "creates pluralized translations for all Releaf locales" do
359
+ result = ["animals.horse.few", "animals.horse.many", "animals.horse.one", "animals.horse.other", "animals.horse.zero"]
360
+ expect{ I18n.t("animals.horse", count: 1, create_plurals: true) }.to change{ Releaf::I18nDatabase::I18nEntry.pluck(:key).sort }.
361
+ from([]).to(result.sort)
362
+ end
363
+ end
364
+ end
365
+ end
366
+ end
367
+
368
+ context "when scope requested" do
369
+ it "returns all scope translations" do
370
+ translation_1 = Releaf::I18nDatabase::I18nEntry.create(key: "admin.content.cancel")
371
+ translation_1.i18n_entry_translation.create(locale: "lv", text: "Atlikt")
372
+
373
+ translation_2 = Releaf::I18nDatabase::I18nEntry.create(key: "admin.content.save")
374
+ translation_2.i18n_entry_translation.create(locale: "lv", text: "Saglabāt")
375
+
376
+ expect(I18n.t("admin.content", locale: "lv")).to eq(cancel: "Atlikt", save: "Saglabāt")
377
+ expect(I18n.t("admin.content", locale: "en")).to eq(cancel: nil, save: nil)
378
+ end
379
+ end
380
+ end
162
381
  end
@@ -0,0 +1,3 @@
1
+ NOT REALLY
2
+ A SPREADSHEET
3
+ FILE
@@ -0,0 +1,3 @@
1
+ NOT REALLY
2
+ A SPREADSHEET
3
+ FILE
@@ -0,0 +1,192 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::I18nDatabase::Backend do
4
+ let(:translations_store){ Releaf::I18nDatabase::TranslationsStore.new }
5
+
6
+ describe ".configure_component" do
7
+ it "adds new `Releaf::I18nDatabase::Configuration` configuration with default config" do
8
+ stub_const("Releaf::I18nDatabase::Backend::DEFAULT_CONFIG", a: :b)
9
+ allow(Releaf::I18nDatabase::Configuration).to receive(:new)
10
+ .with(a: :b).and_return("_new")
11
+ expect(Releaf.application.config).to receive(:add_configuration).with("_new")
12
+ described_class.configure_component
13
+ end
14
+ end
15
+
16
+ describe ".reset_cache" do
17
+ it "reset translations cache to backend instance" do
18
+ subject.translations_cache = :x
19
+ allow(described_class).to receive(:backend_instance).and_return(subject)
20
+ expect{ described_class.reset_cache }.to change{ subject.translations_cache }.to(nil)
21
+ end
22
+ end
23
+
24
+ describe ".backend_instance" do
25
+ context "when I18n backend has chained backends" do
26
+ it "returns Releaf::I18nDatabase::Backend instance" do
27
+ backends = I18n::Backend::Chain.new(subject, I18n::Backend::Simple.new)
28
+ allow(I18n).to receive(:backend).and_return(backends)
29
+ expect(described_class.backend_instance).to eq(subject)
30
+ end
31
+
32
+ it "returns nil when chain hasn't Releaf::I18nDatabase::Backend instance" do
33
+ backends = I18n::Backend::Chain.new(I18n::Backend::Simple.new)
34
+ allow(I18n).to receive(:backend).and_return(backends)
35
+ expect(described_class.backend_instance).to be nil
36
+ end
37
+ end
38
+
39
+ context "when I18n backend has single backend and it is instance of Releaf::I18nDatabase::Backend" do
40
+ it "returns Releaf::I18nDatabase::Backend instance" do
41
+ allow(I18n).to receive(:backend).and_return(subject)
42
+ expect(described_class.backend_instance).to eq(subject)
43
+ end
44
+ end
45
+
46
+ context "when I18n backend has single backend and it is not instance of Releaf::I18nDatabase::Backend" do
47
+ it "returns nil" do
48
+ allow(I18n).to receive(:backend).and_return(I18n::Backend::Simple.new)
49
+ expect(described_class.backend_instance).to be nil
50
+ end
51
+ end
52
+ end
53
+
54
+ describe ".initialize_component" do
55
+ it "adds itself as i18n backend as primary backend while keeping Rails default simple backend as secondary" do
56
+ allow(I18n).to receive(:backend).and_return(:current_backend)
57
+ allow(I18n::Backend::Chain).to receive(:new).with(:new_backend, :current_backend).and_return(:x)
58
+ allow(described_class).to receive(:new).and_return(:new_backend)
59
+ expect(I18n).to receive(:backend=).with(:x)
60
+ described_class.initialize_component
61
+ end
62
+ end
63
+
64
+ describe ".locales_pluralizations" do
65
+ it "returns array all pluralization forms for releaf locales" do
66
+ allow(Releaf.application.config).to receive(:all_locales).and_return([:de, :ru, :aasdsd])
67
+
68
+ allow(TwitterCldr).to receive(:supported_locale?).with(:de).and_return(true)
69
+ allow(TwitterCldr::Formatters::Plurals::Rules).to receive(:all_for).with(:de).and_return([:one, :other, :many])
70
+
71
+ allow(TwitterCldr).to receive(:supported_locale?).with(:ru).and_return(true)
72
+ allow(TwitterCldr::Formatters::Plurals::Rules).to receive(:all_for).with(:ru).and_return([:one, :other, :few, :zero])
73
+
74
+ allow(TwitterCldr).to receive(:supported_locale?).with(:aasdsd).and_return(false)
75
+
76
+ expect(described_class.locales_pluralizations).to eq([:one, :other, :many, :few, :zero])
77
+ end
78
+ end
79
+
80
+ describe "#translations" do
81
+ let(:another_translations_store){ Releaf::I18nDatabase::TranslationsStore.new }
82
+
83
+ context "when translations has been loaded and is not expired" do
84
+ it "returns assigned translations hash instance" do
85
+ subject.translations_cache = translations_store
86
+ allow(translations_store).to receive(:expired?).and_return(false)
87
+ expect(Releaf::I18nDatabase::TranslationsStore).to_not receive(:new)
88
+ expect(subject.translations).to eq(translations_store)
89
+ end
90
+ end
91
+
92
+ context "when translations has been loaded and is expired" do
93
+ it "initializes new `TranslationsStore`, cache and return it" do
94
+ subject.translations_cache = translations_store
95
+ allow(translations_store).to receive(:expired?).and_return(true)
96
+ expect(Releaf::I18nDatabase::TranslationsStore).to receive(:new).and_return(another_translations_store)
97
+ expect(subject.translations).to eq(another_translations_store)
98
+ end
99
+ end
100
+
101
+ context "when translations has not been loaded" do
102
+ it "initializes new `TranslationsStore`, cache and return it" do
103
+ subject.translations_cache = nil
104
+ expect(Releaf::I18nDatabase::TranslationsStore).to receive(:new).and_return(another_translations_store)
105
+ expect(subject.translations).to eq(another_translations_store)
106
+ end
107
+ end
108
+ end
109
+
110
+ describe "#store_translations" do
111
+ it "pass given translations to simple translation backend" do
112
+ simple_backend = I18n.backend.backends.last
113
+ expect(simple_backend).to receive(:store_translations).with(:lv, {a: "x"}, {c: "d"})
114
+ subject.store_translations(:lv, {a: "x"}, {c: "d"})
115
+ end
116
+ end
117
+
118
+ describe ".translations_updated_at" do
119
+ it "returns translations updated_at from cached settings" do
120
+ allow(Releaf::Settings).to receive(:[]).with(described_class::UPDATED_AT_KEY).and_return("x")
121
+ expect(described_class.translations_updated_at).to eq("x")
122
+ end
123
+ end
124
+
125
+ describe ".translations_updated_at=" do
126
+ it "stores translations updated_at to cached settings" do
127
+ expect(Releaf::Settings).to receive(:[]=).with(described_class::UPDATED_AT_KEY, "xx")
128
+ described_class.translations_updated_at = "xx"
129
+ end
130
+ end
131
+
132
+ describe "#lookup" do
133
+ before do
134
+ allow(subject).to receive(:translations).and_return(translations_store)
135
+ allow(subject).to receive(:normalize_flat_keys).with(:lv, "some.localization", "_scope_", ":")
136
+ .and_return("xx.s.loc")
137
+ end
138
+
139
+ it "flattens key before passing further" do
140
+ expect(translations_store).to receive(:missing?).with(:lv, "xx.s.loc")
141
+ expect(translations_store).to receive(:lookup).with(:lv, "xx.s.loc", separator: ":", a: "b")
142
+ expect(translations_store).to receive(:missing).with(:lv, "xx.s.loc", separator: ":", a: "b")
143
+
144
+ subject.lookup(:lv, "some.localization", "_scope_", separator: ":", a: "b")
145
+ end
146
+
147
+ context "when translation is known as missing" do
148
+ it "does not make lookup in translation hash, does not mark it as missing and return nil" do
149
+ allow(translations_store).to receive(:missing?).with(:lv, "xx.s.loc").and_return(true)
150
+ expect(translations_store).to_not receive(:lookup)
151
+ expect(translations_store).to_not receive(:missing)
152
+ expect(subject.lookup(:lv, "some.localization", "_scope_", separator: ":", a: "b")).to be nil
153
+ end
154
+ end
155
+
156
+ context "when translation is not known as missing" do
157
+ before do
158
+ allow(translations_store).to receive(:missing?).with(:lv, "xx.s.loc").and_return(false)
159
+ end
160
+
161
+ context "when lookup result is not nil" do
162
+ before do
163
+ allow(translations_store).to receive(:lookup).with(:lv, "xx.s.loc", separator: ":", a: "b").and_return("x")
164
+ end
165
+
166
+ it "returns lookup result" do
167
+ expect(subject.lookup(:lv, "some.localization", "_scope_", separator: ":", a: "b")).to eq("x")
168
+ end
169
+
170
+ it "does not mark translation as missing" do
171
+ expect(translations_store).to_not receive(:missing).with(:lv, "xx.s.loc", separator: ":", a: "b")
172
+ subject.lookup(:lv, "some.localization", "_scope_", separator: ":", a: "b")
173
+ end
174
+ end
175
+
176
+ context "when lookup result is nil" do
177
+ before do
178
+ allow(translations_store).to receive(:lookup).with(:lv, "xx.s.loc", separator: ":", a: "b").and_return(nil)
179
+ end
180
+
181
+ it "returns nil" do
182
+ expect(subject.lookup(:lv, "some.localization", "_scope_", separator: ":", a: "b")).to be nil
183
+ end
184
+
185
+ it "marks translation as missing" do
186
+ expect(translations_store).to receive(:missing).with(:lv, "xx.s.loc", separator: ":", a: "b")
187
+ subject.lookup(:lv, "some.localization", "_scope_", separator: ":", a: "b")
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end