i18n-js 2.1.2 → 3.0.11
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 +7 -0
- data/.editorconfig +24 -0
- data/.gitignore +5 -4
- data/.npmignore +27 -0
- data/.travis.yml +37 -0
- data/Appraisals +20 -0
- data/CHANGELOG.md +354 -0
- data/Gemfile +1 -1
- data/README.md +872 -0
- data/Rakefile +19 -7
- data/app/assets/javascripts/i18n/filtered.js.erb +23 -0
- data/app/assets/javascripts/i18n/shims.js +208 -0
- data/app/assets/javascripts/i18n/translations.js +3 -0
- data/app/assets/javascripts/i18n.js +1077 -0
- data/gemfiles/i18n_0_6.gemfile +7 -0
- data/gemfiles/i18n_0_7.gemfile +7 -0
- data/gemfiles/i18n_0_8.gemfile +7 -0
- data/gemfiles/i18n_0_9.gemfile +7 -0
- data/gemfiles/i18n_1_0.gemfile +7 -0
- data/i18n-js.gemspec +11 -9
- data/lib/i18n/js/dependencies.rb +59 -0
- data/lib/i18n/js/engine.rb +87 -0
- data/lib/i18n/js/fallback_locales.rb +70 -0
- data/lib/{i18n-js → i18n/js}/middleware.rb +32 -9
- data/lib/i18n/js/private/hash_with_symbol_keys.rb +36 -0
- data/lib/i18n/js/segment.rb +88 -0
- data/lib/i18n/js/utils.rb +52 -0
- data/lib/i18n/js/version.rb +7 -0
- data/lib/i18n/js.rb +242 -0
- data/lib/i18n-js.rb +1 -177
- data/lib/rails/generators/i18n/js/config/config_generator.rb +19 -0
- data/{config → lib/rails/generators/i18n/js/config/templates}/i18n-js.yml +11 -6
- data/lib/tasks/export.rake +8 -0
- data/package.json +25 -0
- data/spec/fixtures/custom_path.yml +5 -0
- data/spec/fixtures/default.yml +5 -0
- data/spec/fixtures/erb.yml +5 -0
- data/spec/fixtures/except_condition.yml +7 -0
- data/spec/fixtures/js_export_dir_custom.yml +7 -0
- data/spec/fixtures/js_export_dir_none.yml +6 -0
- data/spec/fixtures/js_extend_parent.yml +6 -0
- data/spec/fixtures/js_extend_segment.yml +6 -0
- data/spec/fixtures/js_file_per_locale.yml +7 -0
- data/spec/fixtures/js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml +4 -0
- data/spec/fixtures/js_file_per_locale_with_fallbacks_as_hash.yml +6 -0
- data/spec/fixtures/js_file_per_locale_with_fallbacks_as_locale.yml +4 -0
- data/spec/fixtures/js_file_per_locale_with_fallbacks_as_locale_without_fallback_translations.yml +4 -0
- data/spec/fixtures/js_file_per_locale_with_fallbacks_enabled.yml +4 -0
- data/spec/fixtures/js_file_per_locale_without_fallbacks.yml +4 -0
- data/spec/fixtures/js_file_with_namespace_and_pretty_print.yml +7 -0
- data/spec/fixtures/js_sort_translation_keys_false.yml +6 -0
- data/spec/fixtures/js_sort_translation_keys_true.yml +6 -0
- data/spec/{resources → fixtures}/locales.yml +13 -1
- data/spec/fixtures/multiple_conditions.yml +7 -0
- data/spec/fixtures/multiple_conditions_per_locale.yml +7 -0
- data/spec/fixtures/multiple_files.yml +7 -0
- data/spec/{resources → fixtures}/no_config.yml +0 -0
- data/spec/fixtures/no_scope.yml +4 -0
- data/spec/fixtures/simple_scope.yml +5 -0
- data/spec/js/currency.spec.js +62 -0
- data/spec/js/current_locale.spec.js +19 -0
- data/spec/js/dates.spec.js +265 -0
- data/spec/js/defaults.spec.js +31 -0
- data/spec/js/extend.spec.js +110 -0
- data/spec/js/interpolation.spec.js +124 -0
- data/spec/js/jasmine/MIT.LICENSE +20 -0
- data/spec/js/jasmine/jasmine-html.js +190 -0
- data/spec/js/jasmine/jasmine.css +166 -0
- data/spec/js/jasmine/jasmine.js +2476 -0
- data/spec/js/jasmine/jasmine_favicon.png +0 -0
- data/spec/js/locales.spec.js +31 -0
- data/spec/js/localization.spec.js +48 -0
- data/spec/js/numbers.spec.js +170 -0
- data/spec/js/placeholder.spec.js +24 -0
- data/spec/js/pluralization.spec.js +211 -0
- data/spec/js/prepare_options.spec.js +41 -0
- data/spec/js/require.js +2083 -0
- data/spec/js/specs.html +49 -0
- data/spec/js/specs_requirejs.html +72 -0
- data/spec/js/translate.spec.js +277 -0
- data/spec/js/translations.js +164 -0
- data/spec/js/utility_functions.spec.js +20 -0
- data/spec/ruby/i18n/js/fallback_locales_spec.rb +84 -0
- data/spec/ruby/i18n/js/segment_spec.rb +157 -0
- data/spec/ruby/i18n/js/utils_spec.rb +106 -0
- data/spec/ruby/i18n/js_spec.rb +627 -0
- data/spec/spec_helper.rb +55 -14
- data/yarn.lock +131 -0
- metadata +188 -96
- data/.rspec +0 -1
- data/Gemfile.lock +0 -51
- data/README.rdoc +0 -305
- data/lib/i18n-js/engine.rb +0 -62
- data/lib/i18n-js/railtie.rb +0 -13
- data/lib/i18n-js/rake.rb +0 -16
- data/lib/i18n-js/version.rb +0 -10
- data/spec/i18n_spec.js +0 -768
- data/spec/i18n_spec.rb +0 -205
- data/spec/resources/custom_path.yml +0 -4
- data/spec/resources/default.yml +0 -4
- data/spec/resources/js_file_per_locale.yml +0 -3
- data/spec/resources/multiple_conditions.yml +0 -6
- data/spec/resources/multiple_files.yml +0 -6
- data/spec/resources/no_scope.yml +0 -3
- data/spec/resources/simple_scope.yml +0 -4
- data/vendor/assets/javascripts/i18n/translations.js.erb +0 -7
- data/vendor/assets/javascripts/i18n.js +0 -450
@@ -0,0 +1,627 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe I18n::JS do
|
4
|
+
|
5
|
+
describe '.config_file_path' do
|
6
|
+
let(:default_path) { I18n::JS::DEFAULT_CONFIG_PATH }
|
7
|
+
let(:new_path) { File.join("tmp", default_path) }
|
8
|
+
|
9
|
+
subject { described_class.config_file_path }
|
10
|
+
|
11
|
+
context "when it is not set" do
|
12
|
+
it { should eq default_path }
|
13
|
+
end
|
14
|
+
context "when it is set already" do
|
15
|
+
before { described_class.config_file_path = new_path }
|
16
|
+
|
17
|
+
it { should eq new_path }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "exporting" do
|
22
|
+
before do
|
23
|
+
stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "exports messages to default path when configuration file doesn't exist" do
|
27
|
+
I18n::JS.export
|
28
|
+
file_should_exist "translations.js"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "exports messages using custom output path" do
|
32
|
+
set_config "custom_path.yml"
|
33
|
+
I18n::JS::Segment.should_receive(:new).with("tmp/i18n-js/all.js", translations, {js_extend: true, sort_translation_keys: true}).and_call_original
|
34
|
+
I18n::JS::Segment.any_instance.should_receive(:save!).with(no_args)
|
35
|
+
I18n::JS.export
|
36
|
+
end
|
37
|
+
|
38
|
+
it "sets default scope to * when not specified" do
|
39
|
+
set_config "no_scope.yml"
|
40
|
+
I18n::JS::Segment.should_receive(:new).with("tmp/i18n-js/no_scope.js", translations, {js_extend: true, sort_translation_keys: true}).and_call_original
|
41
|
+
I18n::JS::Segment.any_instance.should_receive(:save!).with(no_args)
|
42
|
+
I18n::JS.export
|
43
|
+
end
|
44
|
+
|
45
|
+
it "exports to multiple files" do
|
46
|
+
set_config "multiple_files.yml"
|
47
|
+
I18n::JS.export
|
48
|
+
|
49
|
+
file_should_exist "all.js"
|
50
|
+
file_should_exist "tudo.js"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "ignores an empty config file" do
|
54
|
+
set_config "no_config.yml"
|
55
|
+
I18n::JS.export
|
56
|
+
|
57
|
+
file_should_exist "translations.js"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "exports to a JS file per available locale" do
|
61
|
+
set_config "js_file_per_locale.yml"
|
62
|
+
I18n::JS.export
|
63
|
+
|
64
|
+
file_should_exist "en.js"
|
65
|
+
file_should_exist "fr.js"
|
66
|
+
|
67
|
+
en_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "en.js"))
|
68
|
+
expect(en_output).to eq(<<EOS
|
69
|
+
I18n.translations || (I18n.translations = {});
|
70
|
+
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), {"admin":{"edit":{"title":"Edit"},"show":{"note":"more details","title":"Show"}},"date":{"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"},"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"]}});
|
71
|
+
EOS
|
72
|
+
)
|
73
|
+
fr_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "fr.js"))
|
74
|
+
expect(fr_output).to eq(<<EOS
|
75
|
+
I18n.translations || (I18n.translations = {});
|
76
|
+
I18n.translations["fr"] = I18n.extend((I18n.translations["fr"] || {}), {"admin":{"edit":{"title":"Editer"},"show":{"note":"plus de détails","title":"Visualiser"}},"date":{"abbr_day_names":["dim","lun","mar","mer","jeu","ven","sam"],"abbr_month_names":[null,"jan.","fév.","mar.","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"day_names":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"formats":{"default":"%d/%m/%Y","long":"%e %B %Y","long_ordinal":"%e %B %Y","only_day":"%e","short":"%e %b"},"month_names":[null,"janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"]}});
|
77
|
+
EOS
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "exports with multiple conditions" do
|
82
|
+
set_config "multiple_conditions.yml"
|
83
|
+
I18n::JS.export
|
84
|
+
|
85
|
+
file_should_exist "bitsnpieces.js"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "exports with multiple conditions to a JS file per available locale" do
|
89
|
+
allow(::I18n).to receive(:available_locales){ [:en, :fr] }
|
90
|
+
|
91
|
+
set_config "multiple_conditions_per_locale.yml"
|
92
|
+
|
93
|
+
result = I18n::JS.translation_segments
|
94
|
+
result.map(&:file).should eql(["tmp/i18n-js/bits.%{locale}.js"])
|
95
|
+
|
96
|
+
result.map(&:save!)
|
97
|
+
|
98
|
+
en_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "bits.en.js"))
|
99
|
+
expect(en_output).to eq(<<EOS
|
100
|
+
I18n.translations || (I18n.translations = {});
|
101
|
+
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), {"date":{"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"}},"number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}}}});
|
102
|
+
EOS
|
103
|
+
)
|
104
|
+
fr_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "bits.fr.js"))
|
105
|
+
expect(fr_output).to eq(<<EOS
|
106
|
+
I18n.translations || (I18n.translations = {});
|
107
|
+
I18n.translations["fr"] = I18n.extend((I18n.translations["fr"] || {}), {"date":{"formats":{"default":"%d/%m/%Y","long":"%e %B %Y","long_ordinal":"%e %B %Y","only_day":"%e","short":"%e %b"}},"number":{"currency":{"format":{"format":"%n %u","precision":2,"unit":"€"}}}});
|
108
|
+
EOS
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "exports with :except condition" do
|
113
|
+
set_config "except_condition.yml"
|
114
|
+
I18n::JS.export
|
115
|
+
|
116
|
+
file_should_exist "trimmed.js"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "calls .export_i18n_js" do
|
120
|
+
allow(described_class).to receive(:export_i18n_js)
|
121
|
+
I18n::JS.export
|
122
|
+
expect(described_class).to have_received(:export_i18n_js).once
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "filters" do
|
127
|
+
it "filters translations using scope *.date.formats" do
|
128
|
+
result = I18n::JS.filter(translations, "*.date.formats")
|
129
|
+
result[:en][:date].keys.should eql([:formats])
|
130
|
+
result[:fr][:date].keys.should eql([:formats])
|
131
|
+
end
|
132
|
+
|
133
|
+
it "filters translations using scope [*.date.formats, *.number.currency.format]" do
|
134
|
+
result = I18n::JS.scoped_translations(["*.date.formats", "*.number.currency.format"])
|
135
|
+
result[:en].keys.collect(&:to_s).sort.should eql(%w[ date number ])
|
136
|
+
result[:fr].keys.collect(&:to_s).sort.should eql(%w[ date number ])
|
137
|
+
end
|
138
|
+
|
139
|
+
it "filters translations using multi-star scope" do
|
140
|
+
result = I18n::JS.scoped_translations("*.*.formats")
|
141
|
+
|
142
|
+
result[:en].keys.collect(&:to_s).sort.should eql(%w[ date time ])
|
143
|
+
result[:fr].keys.collect(&:to_s).sort.should eql(%w[ date time ])
|
144
|
+
|
145
|
+
result[:en][:date].keys.should eql([:formats])
|
146
|
+
result[:en][:time].keys.should eql([:formats])
|
147
|
+
|
148
|
+
result[:fr][:date].keys.should eql([:formats])
|
149
|
+
result[:fr][:time].keys.should eql([:formats])
|
150
|
+
end
|
151
|
+
|
152
|
+
it "filters translations using alternated stars" do
|
153
|
+
result = I18n::JS.scoped_translations("*.admin.*.title")
|
154
|
+
|
155
|
+
result[:en][:admin].keys.collect(&:to_s).sort.should eql(%w[ edit show ])
|
156
|
+
result[:fr][:admin].keys.collect(&:to_s).sort.should eql(%w[ edit show ])
|
157
|
+
|
158
|
+
result[:en][:admin][:show][:title].should eql("Show")
|
159
|
+
result[:fr][:admin][:show][:title].should eql("Visualiser")
|
160
|
+
|
161
|
+
result[:en][:admin][:edit][:title].should eql("Edit")
|
162
|
+
result[:fr][:admin][:edit][:title].should eql("Editer")
|
163
|
+
end
|
164
|
+
|
165
|
+
describe ".filtered_translations" do
|
166
|
+
subject do
|
167
|
+
I18n::JS.filtered_translations
|
168
|
+
end
|
169
|
+
|
170
|
+
let!(:old_sort_translation_keys) { I18n::JS.sort_translation_keys? }
|
171
|
+
before { I18n::JS.sort_translation_keys = sort_translation_keys_value }
|
172
|
+
after { I18n::JS.sort_translation_keys = old_sort_translation_keys }
|
173
|
+
before { expect(I18n::JS.sort_translation_keys?).to eq(sort_translation_keys_value) }
|
174
|
+
|
175
|
+
let(:sorted_hash) do
|
176
|
+
{sorted: :hash}
|
177
|
+
end
|
178
|
+
before do
|
179
|
+
allow(I18n::JS::Utils).
|
180
|
+
to receive(:deep_key_sort).
|
181
|
+
and_return(sorted_hash)
|
182
|
+
end
|
183
|
+
|
184
|
+
shared_examples_for ".filtered_translations" do
|
185
|
+
subject do
|
186
|
+
I18n::JS.filtered_translations
|
187
|
+
end
|
188
|
+
|
189
|
+
# This example is to prevent the regression from
|
190
|
+
# PR https://github.com/fnando/i18n-js/pull/318
|
191
|
+
it {should be_a(Hash)}
|
192
|
+
# Might need to test the keys... or not
|
193
|
+
end
|
194
|
+
|
195
|
+
context "when translation keys SHOULD be sorted" do
|
196
|
+
let(:sort_translation_keys_value) { true }
|
197
|
+
|
198
|
+
it_behaves_like ".filtered_translations"
|
199
|
+
it {should eq(sorted_hash)}
|
200
|
+
end
|
201
|
+
context "when translation keys should NOT be sorted" do
|
202
|
+
let(:sort_translation_keys_value) { false }
|
203
|
+
|
204
|
+
it_behaves_like ".filtered_translations"
|
205
|
+
it {should_not eq(sorted_hash)}
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context "exceptions" do
|
211
|
+
it "does not include scopes listed in the exceptions list" do
|
212
|
+
result = I18n::JS.scoped_translations("*", ['de.*', '*.admin', '*.*.currency'])
|
213
|
+
|
214
|
+
result[:de].should be_empty
|
215
|
+
|
216
|
+
result[:en][:admin].should be_nil
|
217
|
+
result[:fr][:admin].should be_nil
|
218
|
+
result[:ja][:admin].should be_nil
|
219
|
+
|
220
|
+
result[:en][:number][:currency].should be_nil
|
221
|
+
result[:fr][:number][:currency].should be_nil
|
222
|
+
end
|
223
|
+
|
224
|
+
it "does not include scopes listed in the exceptions list and respects the 'only' option" do
|
225
|
+
result = I18n::JS.scoped_translations("fr.*", ['*.admin', '*.*.currency'])
|
226
|
+
|
227
|
+
result[:en].should be_nil
|
228
|
+
result[:de].should be_nil
|
229
|
+
result[:ja].should be_nil
|
230
|
+
|
231
|
+
result[:fr][:admin].should be_nil
|
232
|
+
result[:fr][:number][:currency].should be_nil
|
233
|
+
|
234
|
+
result[:fr][:time][:am].should be_a(String)
|
235
|
+
end
|
236
|
+
|
237
|
+
it "does exclude absolute scopes listed in the exceptions list" do
|
238
|
+
result = I18n::JS.scoped_translations("*", ['de', 'en.admin', 'fr.number.currency'])
|
239
|
+
|
240
|
+
result[:de].should be_nil
|
241
|
+
|
242
|
+
result[:en].should be_a(Hash)
|
243
|
+
result[:en][:admin].should be_nil
|
244
|
+
|
245
|
+
result[:fr][:number].should be_a(Hash)
|
246
|
+
result[:fr][:number][:currency].should be_nil
|
247
|
+
end
|
248
|
+
|
249
|
+
it "does not exclude non-absolute scopes listed in the exceptions list" do
|
250
|
+
result = I18n::JS.scoped_translations("*", ['admin', 'currency'])
|
251
|
+
|
252
|
+
result[:en][:admin].should be_a(Hash)
|
253
|
+
result[:fr][:admin].should be_a(Hash)
|
254
|
+
result[:ja][:admin].should be_a(Hash)
|
255
|
+
|
256
|
+
result[:en][:number][:currency].should be_a(Hash)
|
257
|
+
result[:fr][:number][:currency].should be_a(Hash)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context "fallbacks" do
|
262
|
+
subject(:translations) do
|
263
|
+
I18n::JS.translation_segments.first.translations
|
264
|
+
end
|
265
|
+
|
266
|
+
it "exports without fallback when disabled" do
|
267
|
+
set_config "js_file_per_locale_without_fallbacks.yml"
|
268
|
+
subject[:fr][:fallback_test].should eql(nil)
|
269
|
+
subject[:fr][:null_test].should eql(nil)
|
270
|
+
subject[:de][:null_test].should eql(nil)
|
271
|
+
end
|
272
|
+
|
273
|
+
it "exports with default_locale as fallback when enabled" do
|
274
|
+
set_config "js_file_per_locale_with_fallbacks_enabled.yml"
|
275
|
+
subject[:fr][:fallback_test].should eql("Success")
|
276
|
+
subject[:fr][:null_test].should eql("fallback for null")
|
277
|
+
subject[:de][:null_test].should eql("fallback for null")
|
278
|
+
end
|
279
|
+
|
280
|
+
it "exports with default_locale as fallback when enabled with :default_locale" do
|
281
|
+
set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml"
|
282
|
+
subject[:fr][:fallback_test].should eql("Success")
|
283
|
+
subject[:fr][:null_test].should eql("fallback for null")
|
284
|
+
subject[:de][:null_test].should eql("fallback for null")
|
285
|
+
end
|
286
|
+
|
287
|
+
it "exports with given locale as fallback" do
|
288
|
+
set_config "js_file_per_locale_with_fallbacks_as_locale.yml"
|
289
|
+
subject[:fr][:fallback_test].should eql("Erfolg")
|
290
|
+
subject[:fr][:null_test].should eql(nil)
|
291
|
+
subject[:de][:null_test].should eql(nil)
|
292
|
+
end
|
293
|
+
|
294
|
+
context "when given locale is in `I18n.available_locales` but its translation is missing" do
|
295
|
+
subject { translations[:fr][:fallback_test] }
|
296
|
+
|
297
|
+
let(:new_locale) { :pirate }
|
298
|
+
let!(:old_available_locales) { I18n.config.available_locales }
|
299
|
+
let!(:new_available_locales) { I18n.config.available_locales + [new_locale] }
|
300
|
+
before do
|
301
|
+
I18n.config.available_locales = new_available_locales
|
302
|
+
set_config "js_file_per_locale_with_fallbacks_as_locale_without_fallback_translations.yml"
|
303
|
+
end
|
304
|
+
after do
|
305
|
+
I18n.config.available_locales = old_available_locales
|
306
|
+
end
|
307
|
+
|
308
|
+
it {should eql(nil)}
|
309
|
+
end
|
310
|
+
|
311
|
+
context "with I18n::Fallbacks enabled" do
|
312
|
+
let(:backend_with_fallbacks) { backend_class_with_fallbacks.new }
|
313
|
+
let!(:old_backebad) { I18n.backend }
|
314
|
+
|
315
|
+
before do
|
316
|
+
I18n.backend = backend_with_fallbacks
|
317
|
+
I18n.fallbacks[:fr] = [:de, :en]
|
318
|
+
end
|
319
|
+
after { I18n.backend = old_backebad }
|
320
|
+
|
321
|
+
it "exports with defined locale as fallback when enabled" do
|
322
|
+
set_config "js_file_per_locale_with_fallbacks_enabled.yml"
|
323
|
+
subject[:fr][:fallback_test].should eql("Erfolg")
|
324
|
+
end
|
325
|
+
|
326
|
+
it "exports with defined locale as fallback when enabled with :default_locale" do
|
327
|
+
set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml"
|
328
|
+
subject[:fr][:fallback_test].should eql("Success")
|
329
|
+
end
|
330
|
+
|
331
|
+
it "exports with Fallbacks as Hash" do
|
332
|
+
set_config "js_file_per_locale_with_fallbacks_as_hash.yml"
|
333
|
+
subject[:fr][:fallback_test].should eql("Erfolg")
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
context "namespace and pretty_print options" do
|
339
|
+
|
340
|
+
before do
|
341
|
+
stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
|
342
|
+
set_config "js_file_with_namespace_and_pretty_print.yml"
|
343
|
+
end
|
344
|
+
|
345
|
+
it "exports with defined locale as fallback when enabled" do
|
346
|
+
I18n::JS.export
|
347
|
+
file_should_exist "en.js"
|
348
|
+
output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "en.js"))
|
349
|
+
expect(output).to match(/^#{
|
350
|
+
<<EOS
|
351
|
+
Foo.translations || (Foo.translations = {});
|
352
|
+
Foo.translations["en"] = {
|
353
|
+
"number": {
|
354
|
+
"format": {
|
355
|
+
EOS
|
356
|
+
}.+#{
|
357
|
+
<<EOS
|
358
|
+
"edit": {
|
359
|
+
"title": "Edit"
|
360
|
+
}
|
361
|
+
},
|
362
|
+
"foo": "Foo",
|
363
|
+
"fallback_test": "Success"
|
364
|
+
};
|
365
|
+
EOS
|
366
|
+
}$/)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
context "I18n.available_locales" do
|
371
|
+
|
372
|
+
context "when I18n.available_locales is not set" do
|
373
|
+
it "should allow all locales" do
|
374
|
+
result = I18n::JS.scoped_translations("*.admin.*.title")
|
375
|
+
|
376
|
+
result[:en][:admin][:show][:title].should eql("Show")
|
377
|
+
result[:fr][:admin][:show][:title].should eql("Visualiser")
|
378
|
+
result[:ja][:admin][:show][:title].should eql("Ignore me")
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
context "when I18n.available_locales is set" do
|
383
|
+
before { allow(::I18n).to receive(:available_locales){ [:en, :fr] } }
|
384
|
+
|
385
|
+
it "should ignore non-valid locales" do
|
386
|
+
result = I18n::JS.scoped_translations("*.admin.*.title")
|
387
|
+
|
388
|
+
result[:en][:admin][:show][:title].should eql("Show")
|
389
|
+
result[:fr][:admin][:show][:title].should eql("Visualiser")
|
390
|
+
result.keys.include?(:ja).should eql(false)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
context "general" do
|
396
|
+
it "sets export directory" do
|
397
|
+
I18n::JS::DEFAULT_EXPORT_DIR_PATH.should eql("public/javascripts")
|
398
|
+
end
|
399
|
+
|
400
|
+
it "sets empty hash as configuration when no file is found" do
|
401
|
+
I18n::JS.config_file_exists?.should eql(false)
|
402
|
+
I18n::JS.config.should eql({})
|
403
|
+
end
|
404
|
+
|
405
|
+
it "executes erb in config file" do
|
406
|
+
set_config "erb.yml"
|
407
|
+
|
408
|
+
config_entry = I18n::JS.config[:translations].first
|
409
|
+
config_entry["only"].should eq("*.date.formats")
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
describe "i18n.js exporting" do
|
414
|
+
after { begin described_class.send(:remove_instance_variable, :@export_i18n_js_dir_path); rescue; end }
|
415
|
+
|
416
|
+
describe ".export_i18n_js with global variable" do
|
417
|
+
before do
|
418
|
+
allow(FileUtils).to receive(:mkdir_p).and_call_original
|
419
|
+
allow(FileUtils).to receive(:cp).and_call_original
|
420
|
+
|
421
|
+
described_class.stub(:export_i18n_js_dir_path).and_return(export_i18n_js_dir_path)
|
422
|
+
I18n::JS.export_i18n_js
|
423
|
+
end
|
424
|
+
|
425
|
+
context 'when .export_i18n_js_dir_path returns something' do
|
426
|
+
let(:export_i18n_js_dir_path) { temp_path }
|
427
|
+
|
428
|
+
it "does create the folder before copying" do
|
429
|
+
expect(FileUtils).to have_received(:mkdir_p).with(export_i18n_js_dir_path).once
|
430
|
+
end
|
431
|
+
it "does copy the file with FileUtils.cp" do
|
432
|
+
expect(FileUtils).to have_received(:cp).once
|
433
|
+
end
|
434
|
+
it "exports the file" do
|
435
|
+
File.should be_file(File.join(I18n::JS.export_i18n_js_dir_path, "i18n.js"))
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
context 'when .export_i18n_js_dir_path is set to nil' do
|
440
|
+
let(:export_i18n_js_dir_path) { nil }
|
441
|
+
|
442
|
+
it "does NOT create the folder before copying" do
|
443
|
+
expect(FileUtils).to_not have_received(:mkdir_p)
|
444
|
+
end
|
445
|
+
it "does NOT copy the file with FileUtils.cp" do
|
446
|
+
expect(FileUtils).to_not have_received(:cp)
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
describe ".export_i18n_js with config" do
|
452
|
+
|
453
|
+
let(:export_action) do
|
454
|
+
allow(FileUtils).to receive(:mkdir_p).and_call_original
|
455
|
+
allow(FileUtils).to receive(:cp).and_call_original
|
456
|
+
I18n::JS.export_i18n_js
|
457
|
+
end
|
458
|
+
|
459
|
+
context 'when :export_i18n_js set in config' do
|
460
|
+
before { set_config "js_export_dir_custom.yml"; export_action }
|
461
|
+
let(:export_i18n_js_dir_path) { temp_path }
|
462
|
+
let(:config_export_path) { "tmp/i18n-js/foo" }
|
463
|
+
|
464
|
+
it "does create the folder before copying" do
|
465
|
+
expect(FileUtils).to have_received(:mkdir_p).with(config_export_path).once
|
466
|
+
end
|
467
|
+
it "does copy the file with FileUtils.cp" do
|
468
|
+
expect(FileUtils).to have_received(:cp).once
|
469
|
+
end
|
470
|
+
it "exports the file" do
|
471
|
+
File.should be_file(File.join(config_export_path, "i18n.js"))
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
context 'when .export_i18n_js_dir_path is set to false' do
|
476
|
+
before { set_config "js_export_dir_none.yml"; export_action }
|
477
|
+
|
478
|
+
it "does NOT create the folder before copying" do
|
479
|
+
expect(FileUtils).to_not have_received(:mkdir_p)
|
480
|
+
end
|
481
|
+
|
482
|
+
it "does NOT copy the file with FileUtils.cp" do
|
483
|
+
expect(FileUtils).to_not have_received(:cp)
|
484
|
+
end
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
describe '.export_i18n_js_dir_path' do
|
489
|
+
let(:default_path) { I18n::JS::DEFAULT_EXPORT_DIR_PATH }
|
490
|
+
let(:new_path) { File.join("tmp", default_path) }
|
491
|
+
after { described_class.send(:remove_instance_variable, :@export_i18n_js_dir_path) }
|
492
|
+
|
493
|
+
subject { described_class.export_i18n_js_dir_path }
|
494
|
+
|
495
|
+
context "when it is not set" do
|
496
|
+
it { should eq default_path }
|
497
|
+
end
|
498
|
+
context "when it is set to another path already" do
|
499
|
+
before { described_class.export_i18n_js_dir_path = new_path }
|
500
|
+
|
501
|
+
it { should eq new_path }
|
502
|
+
end
|
503
|
+
context "when it is set to nil already" do
|
504
|
+
before { described_class.export_i18n_js_dir_path = nil }
|
505
|
+
|
506
|
+
it { should eq :none }
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
describe "translation key sorting" do
|
512
|
+
|
513
|
+
describe ".sort_translation_keys?" do
|
514
|
+
after { described_class.send(:remove_instance_variable, :@sort_translation_keys) }
|
515
|
+
subject { described_class.sort_translation_keys? }
|
516
|
+
|
517
|
+
|
518
|
+
context "set with config" do
|
519
|
+
|
520
|
+
context 'when :sort_translation_keys is not set in config' do
|
521
|
+
before :each do
|
522
|
+
set_config "default.yml"
|
523
|
+
end
|
524
|
+
|
525
|
+
it { should eq true }
|
526
|
+
end
|
527
|
+
|
528
|
+
context 'when :sort_translation_keys set to true in config' do
|
529
|
+
before :each do
|
530
|
+
set_config "js_sort_translation_keys_true.yml"
|
531
|
+
end
|
532
|
+
|
533
|
+
it { should eq true }
|
534
|
+
end
|
535
|
+
|
536
|
+
context 'when :sort_translation_keys set to false in config' do
|
537
|
+
before :each do
|
538
|
+
set_config "js_sort_translation_keys_false.yml"
|
539
|
+
end
|
540
|
+
|
541
|
+
it { should eq false }
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
context 'set by .sort_translation_keys' do
|
546
|
+
|
547
|
+
context "when it is not set" do
|
548
|
+
it { should eq true }
|
549
|
+
end
|
550
|
+
|
551
|
+
context "when it is set to true" do
|
552
|
+
before { described_class.sort_translation_keys = true }
|
553
|
+
|
554
|
+
it { should eq true }
|
555
|
+
end
|
556
|
+
|
557
|
+
context "when it is set to false" do
|
558
|
+
before { described_class.sort_translation_keys = false }
|
559
|
+
|
560
|
+
it { should eq false }
|
561
|
+
end
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
context "exporting" do
|
566
|
+
subject do
|
567
|
+
I18n::JS.export
|
568
|
+
file_should_exist "en.js"
|
569
|
+
File.read(File.join(I18n::JS.export_i18n_js_dir_path, "en.js"))
|
570
|
+
end
|
571
|
+
|
572
|
+
before do
|
573
|
+
stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
|
574
|
+
end
|
575
|
+
|
576
|
+
context 'sort_translation_keys is true' do
|
577
|
+
before :each do
|
578
|
+
set_config "js_sort_translation_keys_true.yml"
|
579
|
+
end
|
580
|
+
|
581
|
+
it "exports with the keys sorted" do
|
582
|
+
expect(subject).to eq(<<EOS
|
583
|
+
I18n.translations || (I18n.translations = {});
|
584
|
+
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), {"admin":{"edit":{"title":"Edit"},"show":{"note":"more details","title":"Show"}},"date":{"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"},"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"]},"fallback_test":"Success","foo":"Foo","null_test":"fallback for null","number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}},"format":{"delimiter":",","precision":3,"separator":"."}},"time":{"am":"am","formats":{"default":"%a, %d %b %Y %H:%M:%S %z","long":"%B %d, %Y %H:%M","short":"%d %b %H:%M"},"pm":"pm"}});
|
585
|
+
EOS
|
586
|
+
)
|
587
|
+
end
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
describe "js_extend option" do
|
593
|
+
before do
|
594
|
+
stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
|
595
|
+
end
|
596
|
+
|
597
|
+
it "exports with js_extend option at parent level" do
|
598
|
+
set_config "js_extend_parent.yml"
|
599
|
+
I18n::JS.export
|
600
|
+
|
601
|
+
file_should_exist "js_extend_parent.js"
|
602
|
+
|
603
|
+
output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "js_extend_parent.js"))
|
604
|
+
expect(output).to eq(<<EOS
|
605
|
+
I18n.translations || (I18n.translations = {});
|
606
|
+
I18n.translations[\"en\"] = {\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}};
|
607
|
+
I18n.translations[\"fr\"] = {\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}};
|
608
|
+
EOS
|
609
|
+
)
|
610
|
+
end
|
611
|
+
|
612
|
+
it "exports with js_extend option at segment level" do
|
613
|
+
set_config "js_extend_segment.yml"
|
614
|
+
I18n::JS.export
|
615
|
+
|
616
|
+
file_should_exist "js_extend_segment.js"
|
617
|
+
|
618
|
+
output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "js_extend_segment.js"))
|
619
|
+
expect(output).to eq(<<EOS
|
620
|
+
I18n.translations || (I18n.translations = {});
|
621
|
+
I18n.translations[\"en\"] = {\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}};
|
622
|
+
I18n.translations[\"fr\"] = {\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}};
|
623
|
+
EOS
|
624
|
+
)
|
625
|
+
end
|
626
|
+
end
|
627
|
+
end
|