i18n-js 3.7.1 → 4.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +4 -0
  3. data/.github/FUNDING.yml +3 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  6. data/.github/PULL_REQUEST_TEMPLATE.md +38 -0
  7. data/.github/dependabot.yml +15 -0
  8. data/.github/workflows/ruby-tests.yml +61 -0
  9. data/.gitignore +11 -7
  10. data/.rubocop.yml +12 -0
  11. data/CHANGELOG.md +12 -495
  12. data/CODE_OF_CONDUCT.md +74 -0
  13. data/CONTRIBUTING.md +79 -0
  14. data/Gemfile +3 -0
  15. data/LICENSE.md +20 -0
  16. data/README.md +89 -903
  17. data/Rakefile +10 -20
  18. data/exe/i18n +5 -0
  19. data/i18n-js.gemspec +47 -29
  20. data/lib/guard/i18n-js.rb +78 -0
  21. data/lib/guard/i18n-js/templates/Guardfile +10 -0
  22. data/lib/guard/i18n-js/version.rb +13 -0
  23. data/lib/i18n-js.rb +66 -1
  24. data/lib/i18n-js/cli.rb +47 -0
  25. data/lib/i18n-js/cli/command.rb +43 -0
  26. data/lib/i18n-js/cli/export_command.rb +108 -0
  27. data/lib/i18n-js/cli/init_command.rb +50 -0
  28. data/lib/i18n-js/cli/ui.rb +30 -0
  29. data/lib/i18n-js/cli/version_command.rb +18 -0
  30. data/lib/i18n-js/listen.rb +80 -0
  31. data/lib/i18n-js/schema.rb +92 -0
  32. data/lib/i18n-js/version.rb +5 -0
  33. metadata +123 -190
  34. data/.editorconfig +0 -24
  35. data/.npmignore +0 -27
  36. data/.travis.yml +0 -39
  37. data/Appraisals +0 -44
  38. data/app/assets/javascripts/i18n.js +0 -1092
  39. data/app/assets/javascripts/i18n/filtered.js.erb +0 -23
  40. data/app/assets/javascripts/i18n/shims.js +0 -240
  41. data/app/assets/javascripts/i18n/translations.js +0 -3
  42. data/gemfiles/i18n_0_6.gemfile +0 -7
  43. data/gemfiles/i18n_0_7.gemfile +0 -7
  44. data/gemfiles/i18n_0_8.gemfile +0 -7
  45. data/gemfiles/i18n_0_9.gemfile +0 -7
  46. data/gemfiles/i18n_1_0.gemfile +0 -7
  47. data/gemfiles/i18n_1_1.gemfile +0 -7
  48. data/gemfiles/i18n_1_2.gemfile +0 -7
  49. data/gemfiles/i18n_1_3.gemfile +0 -7
  50. data/gemfiles/i18n_1_4.gemfile +0 -7
  51. data/gemfiles/i18n_1_5.gemfile +0 -7
  52. data/gemfiles/i18n_1_6.gemfile +0 -7
  53. data/gemfiles/i18n_1_7.gemfile +0 -7
  54. data/gemfiles/i18n_1_8.gemfile +0 -7
  55. data/lib/i18n/js.rb +0 -259
  56. data/lib/i18n/js/dependencies.rb +0 -63
  57. data/lib/i18n/js/engine.rb +0 -87
  58. data/lib/i18n/js/fallback_locales.rb +0 -70
  59. data/lib/i18n/js/formatters/base.rb +0 -25
  60. data/lib/i18n/js/formatters/js.rb +0 -32
  61. data/lib/i18n/js/formatters/json.rb +0 -13
  62. data/lib/i18n/js/middleware.rb +0 -82
  63. data/lib/i18n/js/private/hash_with_symbol_keys.rb +0 -36
  64. data/lib/i18n/js/segment.rb +0 -80
  65. data/lib/i18n/js/utils.rb +0 -78
  66. data/lib/i18n/js/version.rb +0 -7
  67. data/lib/rails/generators/i18n/js/config/config_generator.rb +0 -19
  68. data/lib/rails/generators/i18n/js/config/templates/i18n-js.yml +0 -27
  69. data/lib/tasks/export.rake +0 -8
  70. data/package.json +0 -25
  71. data/spec/fixtures/custom_path.yml +0 -5
  72. data/spec/fixtures/default.yml +0 -5
  73. data/spec/fixtures/erb.yml +0 -5
  74. data/spec/fixtures/except_condition.yml +0 -7
  75. data/spec/fixtures/js_export_dir_custom.yml +0 -7
  76. data/spec/fixtures/js_export_dir_none.yml +0 -6
  77. data/spec/fixtures/js_extend_parent.yml +0 -6
  78. data/spec/fixtures/js_extend_segment.yml +0 -6
  79. data/spec/fixtures/js_file_per_locale.yml +0 -7
  80. data/spec/fixtures/js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml +0 -4
  81. data/spec/fixtures/js_file_per_locale_with_fallbacks_as_hash.yml +0 -6
  82. data/spec/fixtures/js_file_per_locale_with_fallbacks_as_locale.yml +0 -4
  83. data/spec/fixtures/js_file_per_locale_with_fallbacks_as_locale_without_fallback_translations.yml +0 -4
  84. data/spec/fixtures/js_file_per_locale_with_fallbacks_enabled.yml +0 -4
  85. data/spec/fixtures/js_file_per_locale_without_fallbacks.yml +0 -4
  86. data/spec/fixtures/js_file_with_namespace_prefix_and_pretty_print.yml +0 -9
  87. data/spec/fixtures/js_sort_translation_keys_false.yml +0 -6
  88. data/spec/fixtures/js_sort_translation_keys_true.yml +0 -6
  89. data/spec/fixtures/json_only.yml +0 -18
  90. data/spec/fixtures/locales.yml +0 -133
  91. data/spec/fixtures/merge_plurals.yml +0 -6
  92. data/spec/fixtures/merge_plurals_with_no_overrides.yml +0 -4
  93. data/spec/fixtures/merge_plurals_with_partial_overrides.yml +0 -4
  94. data/spec/fixtures/millions.yml +0 -4
  95. data/spec/fixtures/multiple_conditions.yml +0 -7
  96. data/spec/fixtures/multiple_conditions_per_locale.yml +0 -7
  97. data/spec/fixtures/multiple_files.yml +0 -7
  98. data/spec/fixtures/no_config.yml +0 -2
  99. data/spec/fixtures/no_scope.yml +0 -4
  100. data/spec/fixtures/simple_scope.yml +0 -5
  101. data/spec/js/currency.spec.js +0 -62
  102. data/spec/js/current_locale.spec.js +0 -19
  103. data/spec/js/dates.spec.js +0 -276
  104. data/spec/js/defaults.spec.js +0 -31
  105. data/spec/js/extend.spec.js +0 -110
  106. data/spec/js/interpolation.spec.js +0 -124
  107. data/spec/js/jasmine/MIT.LICENSE +0 -20
  108. data/spec/js/jasmine/jasmine-html.js +0 -190
  109. data/spec/js/jasmine/jasmine.css +0 -166
  110. data/spec/js/jasmine/jasmine.js +0 -2476
  111. data/spec/js/jasmine/jasmine_favicon.png +0 -0
  112. data/spec/js/locales.spec.js +0 -31
  113. data/spec/js/localization.spec.js +0 -78
  114. data/spec/js/numbers.spec.js +0 -170
  115. data/spec/js/placeholder.spec.js +0 -24
  116. data/spec/js/pluralization.spec.js +0 -219
  117. data/spec/js/prepare_options.spec.js +0 -41
  118. data/spec/js/require.js +0 -2083
  119. data/spec/js/specs.html +0 -49
  120. data/spec/js/specs_requirejs.html +0 -72
  121. data/spec/js/translate.spec.js +0 -299
  122. data/spec/js/translations.js +0 -172
  123. data/spec/js/utility_functions.spec.js +0 -20
  124. data/spec/ruby/i18n/js/fallback_locales_spec.rb +0 -84
  125. data/spec/ruby/i18n/js/segment_spec.rb +0 -219
  126. data/spec/ruby/i18n/js/utils_spec.rb +0 -106
  127. data/spec/ruby/i18n/js_spec.rb +0 -748
  128. data/spec/spec_helper.rb +0 -79
  129. data/yarn.lock +0 -131
@@ -1,20 +0,0 @@
1
- var I18n = require("../../app/assets/javascripts/i18n");
2
-
3
- describe("Utility Functions", function(){
4
- beforeEach(function(){
5
- I18n.reset();
6
- });
7
-
8
- describe("I18n.lookup", function() {
9
- it("does not change locale on failed lookup", function(){
10
- var fallback_locales = ['fallback1', 'fallback2'];
11
-
12
- I18n.locales['lang'] = fallback_locales.slice();
13
- expect(I18n.locales.lang).toEqual(fallback_locales);
14
-
15
- I18n.lookup('anything', {locale: 'lang'})
16
- expect(I18n.locales.lang).toEqual(fallback_locales);
17
- });
18
-
19
- })
20
- });
@@ -1,84 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe I18n::JS::FallbackLocales do
4
- let(:locale) { :fr }
5
- let(:default_locale) { :en }
6
-
7
- describe "#locales" do
8
- let(:fallbacks_locales) { described_class.new(fallbacks, locale) }
9
- subject { fallbacks_locales.locales }
10
-
11
- let(:fetching_locales) { proc do fallbacks_locales.locales end }
12
-
13
- context "when given true as fallbacks" do
14
- let(:fallbacks) { true }
15
- it { should eq([default_locale]) }
16
- end
17
-
18
- context "when given false as fallbacks" do
19
- let(:fallbacks) { false }
20
- it { expect(fetching_locales).to raise_error(ArgumentError) }
21
- end
22
-
23
- context "when given a valid locale as fallbacks" do
24
- let(:fallbacks) { :de }
25
- it { should eq([:de]) }
26
- end
27
-
28
- context "when given a valid Array as fallbacks" do
29
- let(:fallbacks) { [:de, :en] }
30
- it { should eq([:de, :en]) }
31
- end
32
-
33
- context "when given a valid Hash with current locale as key as fallbacks" do
34
- let(:fallbacks) do { :fr => [:de, :en] } end
35
- it { should eq([:de, :en]) }
36
- end
37
-
38
- context "when given a valid Hash without current locale as key as fallbacks" do
39
- let(:fallbacks) do { :de => [:fr, :en] } end
40
- it { should eq([default_locale]) }
41
- end
42
-
43
- context "when given a invalid locale as fallbacks" do
44
- let(:fallbacks) { :invalid_locale }
45
- it { should eq([:invalid_locale]) }
46
- end
47
-
48
- context "when given a invalid type as fallbacks" do
49
- let(:fallbacks) { 42 }
50
- it { expect(fetching_locales).to raise_error(ArgumentError) }
51
- end
52
-
53
- # I18n::Backend::Fallbacks
54
- context "when I18n::Backend::Fallbacks is used" do
55
- let(:backend_with_fallbacks) { backend_class_with_fallbacks.new }
56
-
57
- before do
58
- I18n::JS.backend = backend_with_fallbacks
59
- I18n.fallbacks[:fr] = [:de, :en]
60
- end
61
- after { I18n::JS.backend = I18n::Backend::Simple.new }
62
-
63
- context "given true as fallbacks" do
64
- let(:fallbacks) { true }
65
- it { should eq([:de, :en]) }
66
- end
67
-
68
- context "given :default_locale as fallbacks" do
69
- let(:fallbacks) { :default_locale }
70
- it { should eq([:en]) }
71
- end
72
-
73
- context "given a Hash with current locale as fallbacks" do
74
- let(:fallbacks) do { :fr => [:en] } end
75
- it { should eq([:en]) }
76
- end
77
-
78
- context "given a Hash without current locale as fallbacks" do
79
- let(:fallbacks) do { :de => [:en] } end
80
- it { should eq([:de, :en]) }
81
- end
82
- end
83
- end
84
- end
@@ -1,219 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe I18n::JS::Segment do
4
-
5
- let(:file) { "tmp/i18n-js/segment.js" }
6
- let(:translations){ { en: { "test" => "Test" }, fr: { "test" => "Test2" } } }
7
- let(:namespace) { "MyNamespace" }
8
- let(:pretty_print){ nil }
9
- let(:json_only) { nil }
10
- let(:js_extend) { nil }
11
- let(:sort_translation_keys){ nil }
12
- let(:options) { { namespace: namespace,
13
- pretty_print: pretty_print,
14
- json_only: json_only,
15
- js_extend: js_extend,
16
- sort_translation_keys: sort_translation_keys }.delete_if{|k,v| v.nil?} }
17
- subject { I18n::JS::Segment.new(file, translations, options) }
18
-
19
- describe ".new" do
20
-
21
- it "should persist the file path variable" do
22
- expect(subject.file).to eql("tmp/i18n-js/segment.js")
23
- end
24
-
25
- it "should persist the translations variable" do
26
- expect(subject.translations).to eql(translations)
27
- end
28
-
29
- it "should persist the namespace variable" do
30
- expect(subject.namespace).to eql("MyNamespace")
31
- end
32
-
33
- context "when namespace is nil" do
34
- let(:namespace){ nil }
35
-
36
- it "should default namespace to `I18n`" do
37
- expect(subject.namespace).to eql("I18n")
38
- end
39
- end
40
-
41
- context "when namespace is not set" do
42
- subject { I18n::JS::Segment.new(file, translations) }
43
-
44
- it "should default namespace to `I18n`" do
45
- expect(subject.namespace).to eql("I18n")
46
- end
47
- end
48
-
49
- context "when pretty_print is nil" do
50
- it "should set pretty_print to false" do
51
- expect(subject.pretty_print).to be false
52
- end
53
- end
54
-
55
- context "when pretty_print is truthy" do
56
- let(:pretty_print){ 1 }
57
-
58
- it "should set pretty_print to true" do
59
- expect(subject.pretty_print).to be true
60
- end
61
- end
62
- end
63
-
64
- describe "#saving!" do
65
- before { allow(I18n::JS).to receive(:export_i18n_js_dir_path).and_return(temp_path) }
66
-
67
- context "when json_only is true with locale" do
68
- let(:file){ "tmp/i18n-js/%{locale}.js" }
69
- let(:json_only){ true }
70
-
71
- it 'should output JSON files per locale' do
72
- subject.save!
73
- file_should_exist "en.js"
74
- file_should_exist "fr.js"
75
-
76
- expect(File.read(File.join(temp_path, "en.js"))).to eql(
77
- %Q({"en":{"test":"Test"}})
78
- )
79
-
80
- expect(File.read(File.join(temp_path, "fr.js"))).to eql(
81
- %Q({"fr":{"test":"Test2"}})
82
- )
83
- end
84
- end
85
-
86
- context "when json_only is true without locale" do
87
- let(:file){ "tmp/i18n-js/segment.js" }
88
- let(:json_only){ true }
89
-
90
- it 'should output one JSON file for all locales' do
91
- subject.save!
92
- file_should_exist "segment.js"
93
-
94
- expect(File.read(File.join(temp_path, "segment.js"))).to eql(
95
- %Q({"en":{"test":"Test"},"fr":{"test":"Test2"}})
96
- )
97
- end
98
- end
99
-
100
- context "when json_only and pretty print are true" do
101
- let(:file){ "tmp/i18n-js/segment.js" }
102
- let(:json_only){ true }
103
- let(:pretty_print){ true }
104
-
105
- it 'should output one JSON file for all locales' do
106
- subject.save!
107
- file_should_exist "segment.js"
108
-
109
- expect(File.read(File.join(temp_path, "segment.js"))).to eql <<-EOS
110
- {
111
- "en": {
112
- "test": "Test"
113
- },
114
- "fr": {
115
- "test": "Test2"
116
- }
117
- }
118
- EOS
119
- .chomp
120
- end
121
- end
122
- end
123
-
124
- describe "#save!" do
125
- before { allow(I18n::JS).to receive(:export_i18n_js_dir_path).and_return(temp_path) }
126
- before { subject.save! }
127
-
128
- context "when file does not include %{locale}" do
129
- it "should write the file" do
130
- file_should_exist "segment.js"
131
-
132
- expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
133
- MyNamespace.translations || (MyNamespace.translations = {});
134
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"test":"Test"});
135
- MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), {"test":"Test2"});
136
- EOF
137
- end
138
- end
139
-
140
- context "when file includes %{locale}" do
141
- let(:file){ "tmp/i18n-js/%{locale}.js" }
142
-
143
- it "should write files" do
144
- file_should_exist "en.js"
145
- file_should_exist "fr.js"
146
-
147
- expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
148
- MyNamespace.translations || (MyNamespace.translations = {});
149
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"test":"Test"});
150
- EOF
151
-
152
- expect(File.open(File.join(temp_path, "fr.js")){|f| f.read}).to eql <<-EOF
153
- MyNamespace.translations || (MyNamespace.translations = {});
154
- MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), {"test":"Test2"});
155
- EOF
156
- end
157
- end
158
-
159
- context "when js_extend is true" do
160
- let(:js_extend){ true }
161
-
162
- let(:translations){ { en: { "b" => "Test", "a" => "Test" } } }
163
-
164
- it 'should output the keys as sorted' do
165
- file_should_exist "segment.js"
166
-
167
- expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
168
- MyNamespace.translations || (MyNamespace.translations = {});
169
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"a":"Test","b":"Test"});
170
- EOF
171
- end
172
- end
173
-
174
- context "when js_extend is false" do
175
- let(:js_extend){ false }
176
-
177
- let(:translations){ { en: { "b" => "Test", "a" => "Test" } } }
178
-
179
- it 'should output the keys as sorted' do
180
- file_should_exist "segment.js"
181
-
182
- expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
183
- MyNamespace.translations || (MyNamespace.translations = {});
184
- MyNamespace.translations["en"] = {"a":"Test","b":"Test"};
185
- EOF
186
- end
187
- end
188
-
189
- context "when sort_translation_keys is true" do
190
- let(:sort_translation_keys){ true }
191
-
192
- let(:translations){ { en: { "b" => "Test", "a" => "Test" } } }
193
-
194
- it 'should output the keys as sorted' do
195
- file_should_exist "segment.js"
196
-
197
- expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
198
- MyNamespace.translations || (MyNamespace.translations = {});
199
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"a":"Test","b":"Test"});
200
- EOF
201
- end
202
- end
203
-
204
- context "when sort_translation_keys is false" do
205
- let(:sort_translation_keys){ false }
206
-
207
- let(:translations){ { en: { "b" => "Test", "a" => "Test" } } }
208
-
209
- it 'should output the keys as sorted' do
210
- file_should_exist "segment.js"
211
-
212
- expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
213
- MyNamespace.translations || (MyNamespace.translations = {});
214
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"b":"Test","a":"Test"});
215
- EOF
216
- end
217
- end
218
- end
219
- end
@@ -1,106 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe I18n::JS::Utils do
4
-
5
- describe ".strip_keys_with_nil_values" do
6
- subject { described_class.strip_keys_with_nil_values(input_hash) }
7
-
8
- context 'when input_hash does NOT contain nil value' do
9
- let(:input_hash) { {a: 1, b: { c: 2 }} }
10
- let(:expected_hash) { input_hash }
11
-
12
- it 'returns the original input' do
13
- is_expected.to eq expected_hash
14
- end
15
- end
16
- context 'when input_hash does contain nil value' do
17
- let(:input_hash) { {a: 1, b: { c: 2, d: nil }, e: { f: nil }} }
18
- let(:expected_hash) { {a: 1, b: { c: 2 }, e: {}} }
19
-
20
- it 'returns the original input with nil values removed' do
21
- is_expected.to eq expected_hash
22
- end
23
- end
24
- end
25
-
26
- context "hash merging" do
27
- it "performs a deep merge" do
28
- target = {:a => {:b => 1}}
29
- result = described_class.deep_merge(target, {:a => {:c => 2}})
30
-
31
- expect(result[:a]).to eql({:b => 1, :c => 2})
32
- end
33
-
34
- it "performs a banged deep merge" do
35
- target = {:a => {:b => 1}}
36
- described_class.deep_merge!(target, {:a => {:c => 2}})
37
-
38
- expect(target[:a]).to eql({:b => 1, :c => 2})
39
- end
40
- end
41
-
42
- describe ".deep_reject" do
43
- it "performs a deep keys rejection" do
44
- hash = {:a => {:b => 1}}
45
-
46
- result = described_class.deep_reject(hash) { |k, v| k == :b }
47
-
48
- expect(result).to eql({:a => {}})
49
- end
50
-
51
- it "performs a deep keys rejection prunning the whole tree if necessary" do
52
- hash = {:a => {:b => {:c => {:d => 1, :e => 2}}}}
53
-
54
- result = described_class.deep_reject(hash) { |k, v| k == :b }
55
-
56
- expect(result).to eql({:a => {}})
57
- end
58
-
59
-
60
- it "performs a deep keys rejection without changing the original hash" do
61
- hash = {:a => {:b => 1, :c => 2}}
62
-
63
- result = described_class.deep_reject(hash) { |k, v| k == :b }
64
-
65
- expect(result).to eql({:a => {:c => 2}})
66
- expect(hash).to eql({:a => {:b => 1, :c => 2}})
67
- end
68
- end
69
-
70
- describe ".deep_key_sort" do
71
- let(:unsorted_hash) { {:z => {:b => 1, :a => 2}, :y => 3} }
72
- subject(:sorting) { described_class.deep_key_sort(unsorted_hash) }
73
-
74
- it "performs a deep keys sort without changing the original hash" do
75
- should eql({:y => 3, :z => {:a => 2, :b => 1}})
76
- expect(unsorted_hash).to eql({:z => {:b => 1, :a => 2}, :y => 3})
77
- end
78
-
79
- # Idea from gem `rails_admin`
80
- context "when hash contain non-Symbol as key" do
81
- let(:unsorted_hash) { {:z => {1 => 1, true => 2}, :y => 3} }
82
-
83
- it "performs a deep keys sort without error" do
84
- expect{ sorting }.to_not raise_error
85
- end
86
- it "converts keys to symbols" do
87
- should eql({:y => 3, :z => {1 => 1, true => 2}})
88
- end
89
- end
90
- end
91
-
92
- describe ".scopes_match?" do
93
- it "performs a comparison of literal scopes" do
94
- expect(described_class.scopes_match?([:a, :b], [:a, :b, :c])).to_not eql true
95
- expect(described_class.scopes_match?([:a, :b, :c], [:a, :b, :c])).to eql true
96
- expect(described_class.scopes_match?([:a, :b, :c], [:a, :b, :d])).to_not eql true
97
- end
98
-
99
- it "performs a comparison of wildcard scopes" do
100
- expect(described_class.scopes_match?([:a, '*'], [:a, :b, :c])).to_not eql true
101
- expect(described_class.scopes_match?([:a, '*', :c], [:a, :b, :c])).to eql true
102
- expect(described_class.scopes_match?([:a, :b, :c], [:a, '*', :c])).to eql true
103
- expect(described_class.scopes_match?([:a, :b, :c], [:a, '*', '*'])).to eql true
104
- end
105
- end
106
- end
@@ -1,748 +0,0 @@
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
- allow(I18n::JS::Segment).to receive(:new).with("tmp/i18n-js/all.js", translations, {js_extend: true, sort_translation_keys: true, json_only: false}).and_call_original
34
- allow_any_instance_of(I18n::JS::Segment).to 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
- allow(I18n::JS::Segment).to receive(:new).with("tmp/i18n-js/no_scope.js", translations, {js_extend: true, sort_translation_keys: true, json_only: false}).and_call_original
41
- allow_any_instance_of(I18n::JS::Segment).to 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
- expect(result.map(&:file)).to 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 as json only" do
113
- set_config "json_only.yml"
114
- I18n::JS.export
115
- en_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "json_only.en.js"))
116
- fr_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "json_only.fr.js"))
117
- expect(en_output).to eq (<<EOS
118
- {"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":"$"}}}}}
119
- EOS
120
- ).chop
121
- expect(fr_output).to eq (<<EOS
122
- {"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":"€"}}}}}
123
- EOS
124
- ).chop
125
- expect(JSON.parse(en_output).keys.first).to eq 'en'
126
- end
127
-
128
- it "exports with :except condition" do
129
- set_config "except_condition.yml"
130
- I18n::JS.export
131
-
132
- file_should_exist "trimmed.js"
133
- end
134
-
135
- it "calls .export_i18n_js" do
136
- allow(described_class).to receive(:export_i18n_js)
137
- I18n::JS.export
138
- expect(described_class).to have_received(:export_i18n_js).once
139
- end
140
- end
141
-
142
- context "filters" do
143
- it "filters translations using scope *.date.formats" do
144
- result = I18n::JS.filter(translations, "*.date.formats")
145
- expect(result[:en][:date].keys).to eql([:formats])
146
- expect(result[:fr][:date].keys).to eql([:formats])
147
- end
148
-
149
- it "filters translations using scope [*.date.formats, *.number.currency.format]" do
150
- result = I18n::JS.scoped_translations(["*.date.formats", "*.number.currency.format"])
151
- expect(result[:en].keys.collect(&:to_s).sort).to eql(%w[ date number ])
152
- expect(result[:fr].keys.collect(&:to_s).sort).to eql(%w[ date number ])
153
- end
154
-
155
- it "filters translations using multi-star scope" do
156
- result = I18n::JS.scoped_translations("*.*.formats")
157
-
158
- expect(result[:en].keys.collect(&:to_s).sort).to eql(%w[ date time ])
159
- expect(result[:fr].keys.collect(&:to_s).sort).to eql(%w[ date time ])
160
-
161
- expect(result[:en][:date].keys).to eql([:formats])
162
- expect(result[:en][:time].keys).to eql([:formats])
163
-
164
- expect(result[:fr][:date].keys).to eql([:formats])
165
- expect(result[:fr][:time].keys).to eql([:formats])
166
- end
167
-
168
- it "filters translations using alternated stars" do
169
- result = I18n::JS.scoped_translations("*.admin.*.title")
170
-
171
- expect(result[:en][:admin].keys.collect(&:to_s).sort).to eql(%w[ edit show ])
172
- expect(result[:fr][:admin].keys.collect(&:to_s).sort).to eql(%w[ edit show ])
173
-
174
- expect(result[:en][:admin][:show][:title]).to eql("Show")
175
- expect(result[:fr][:admin][:show][:title]).to eql("Visualiser")
176
-
177
- expect(result[:en][:admin][:edit][:title]).to eql("Edit")
178
- expect(result[:fr][:admin][:edit][:title]).to eql("Editer")
179
- end
180
-
181
- describe ".filtered_translations" do
182
- subject do
183
- I18n::JS.filtered_translations
184
- end
185
-
186
- let!(:old_sort_translation_keys) { I18n::JS.sort_translation_keys? }
187
- before { I18n::JS.sort_translation_keys = sort_translation_keys_value }
188
- after { I18n::JS.sort_translation_keys = old_sort_translation_keys }
189
- before { expect(I18n::JS.sort_translation_keys?).to eq(sort_translation_keys_value) }
190
-
191
- let(:sorted_hash) do
192
- {sorted: :hash}
193
- end
194
- before do
195
- allow(I18n::JS::Utils).
196
- to receive(:deep_key_sort).
197
- and_return(sorted_hash)
198
- end
199
-
200
- shared_examples_for ".filtered_translations" do
201
- subject do
202
- I18n::JS.filtered_translations
203
- end
204
-
205
- # This example is to prevent the regression from
206
- # PR https://github.com/fnando/i18n-js/pull/318
207
- it {should be_a(Hash)}
208
- # Might need to test the keys... or not
209
- end
210
-
211
- context "when translation keys SHOULD be sorted" do
212
- let(:sort_translation_keys_value) { true }
213
-
214
- it_behaves_like ".filtered_translations"
215
- it {should eq(sorted_hash)}
216
- end
217
- context "when translation keys should NOT be sorted" do
218
- let(:sort_translation_keys_value) { false }
219
-
220
- it_behaves_like ".filtered_translations"
221
- it {should_not eq(sorted_hash)}
222
- end
223
- end
224
- end
225
-
226
- context "exceptions" do
227
- it "does not include scopes listed in the exceptions list" do
228
- result = I18n::JS.scoped_translations("*", ['de.*', '*.admin', '*.*.currency'])
229
-
230
- expect(result[:de]).to be_empty
231
-
232
- expect(result[:en][:admin]).to be_nil
233
- expect(result[:fr][:admin]).to be_nil
234
- expect(result[:ja][:admin]).to be_nil
235
-
236
- expect(result[:en][:number][:currency]).to be_nil
237
- expect(result[:fr][:number][:currency]).to be_nil
238
- end
239
-
240
- it "does not include scopes listed in the exceptions list and respects the 'only' option" do
241
- result = I18n::JS.scoped_translations("fr.*", ['*.admin', '*.*.currency'])
242
-
243
- expect(result[:en]).to be_nil
244
- expect(result[:de]).to be_nil
245
- expect(result[:ja]).to be_nil
246
-
247
- expect(result[:fr][:admin]).to be_nil
248
- expect(result[:fr][:number][:currency]).to be_nil
249
-
250
- expect(result[:fr][:time][:am]).to be_a(String)
251
- end
252
-
253
- it "does exclude absolute scopes listed in the exceptions list" do
254
- result = I18n::JS.scoped_translations("*", ['de', 'en.admin', 'fr.number.currency'])
255
-
256
- expect(result[:de]).to be_nil
257
-
258
- expect(result[:en]).to be_a(Hash)
259
- expect(result[:en][:admin]).to be_nil
260
-
261
- expect(result[:fr][:number]).to be_a(Hash)
262
- expect(result[:fr][:number][:currency]).to be_nil
263
- end
264
-
265
- it "does not exclude non-absolute scopes listed in the exceptions list" do
266
- result = I18n::JS.scoped_translations("*", ['admin', 'currency'])
267
-
268
- expect(result[:en][:admin]).to be_a(Hash)
269
- expect(result[:fr][:admin]).to be_a(Hash)
270
- expect(result[:ja][:admin]).to be_a(Hash)
271
-
272
- expect(result[:en][:number][:currency]).to be_a(Hash)
273
- expect(result[:fr][:number][:currency]).to be_a(Hash)
274
- end
275
- end
276
-
277
- context "fallbacks" do
278
- subject(:translations) do
279
- I18n::JS.translation_segments.first.translations
280
- end
281
-
282
- it "exports without fallback when disabled" do
283
- set_config "js_file_per_locale_without_fallbacks.yml"
284
- expect(subject[:fr][:fallback_test]).to eql(nil)
285
- expect(subject[:fr][:null_test]).to eql(nil)
286
- expect(subject[:de][:null_test]).to eql(nil)
287
- end
288
-
289
- it "exports with default_locale as fallback when enabled" do
290
- set_config "js_file_per_locale_with_fallbacks_enabled.yml"
291
- expect(subject[:fr][:fallback_test]).to eql("Success")
292
- expect(subject[:fr][:null_test]).to eql("fallback for null")
293
- expect(subject[:de][:null_test]).to eql("fallback for null")
294
- end
295
-
296
- it "exports with default_locale as fallback when enabled with :default_locale" do
297
- set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml"
298
- expect(subject[:fr][:fallback_test]).to eql("Success")
299
- expect(subject[:fr][:null_test]).to eql("fallback for null")
300
- expect(subject[:de][:null_test]).to eql("fallback for null")
301
- end
302
-
303
- it "exports with given locale as fallback" do
304
- set_config "js_file_per_locale_with_fallbacks_as_locale.yml"
305
- expect(subject[:fr][:fallback_test]).to eql("Erfolg")
306
- expect(subject[:fr][:null_test]).to eql(nil)
307
- expect(subject[:de][:null_test]).to eql(nil)
308
- end
309
-
310
- context "when given locale is in `I18n.available_locales` but its translation is missing" do
311
- subject { translations[:fr][:fallback_test] }
312
-
313
- let(:new_locale) { :pirate }
314
- let!(:old_available_locales) { I18n.config.available_locales }
315
- let!(:new_available_locales) { I18n.config.available_locales + [new_locale] }
316
- before do
317
- I18n.config.available_locales = new_available_locales
318
- set_config "js_file_per_locale_with_fallbacks_as_locale_without_fallback_translations.yml"
319
- end
320
- after do
321
- I18n.config.available_locales = old_available_locales
322
- end
323
-
324
- it {should eql(nil)}
325
- end
326
-
327
- context "with I18n::Fallbacks enabled" do
328
- let(:backend_with_fallbacks) { backend_class_with_fallbacks.new }
329
- let!(:old_backebad) { I18n.backend }
330
-
331
- before do
332
- I18n::JS.backend = backend_with_fallbacks
333
- I18n.fallbacks[:fr] = [:de, :en]
334
- end
335
- after { I18n::JS.backend = old_backebad }
336
-
337
- it "exports with defined locale as fallback when enabled" do
338
- set_config "js_file_per_locale_with_fallbacks_enabled.yml"
339
- expect(subject[:fr][:fallback_test]).to eql("Erfolg")
340
- end
341
-
342
- it "exports with defined locale as fallback when enabled with :default_locale" do
343
- set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml"
344
- expect(subject[:fr][:fallback_test]).to eql("Success")
345
- end
346
-
347
- it "exports with Fallbacks as Hash" do
348
- set_config "js_file_per_locale_with_fallbacks_as_hash.yml"
349
- expect(subject[:fr][:fallback_test]).to eql("Erfolg")
350
- end
351
- end
352
- end
353
-
354
- context "namespace, prefix, suffix, and pretty_print options" do
355
-
356
- before do
357
- stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
358
- set_config "js_file_with_namespace_prefix_and_pretty_print.yml"
359
- end
360
-
361
- it "exports with defined locale as fallback when enabled" do
362
- I18n::JS.export
363
- file_should_exist "en.js"
364
- output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "en.js"))
365
- expect(output).to match(/^#{
366
- <<EOS
367
- import random from 'random-library';
368
- Foo.translations || (Foo.translations = {});
369
- Foo.translations["en"] = {
370
- "number": {
371
- "format": {
372
- EOS
373
- }.+#{
374
- <<EOS
375
- "edit": {
376
- "title": "Edit"
377
- }
378
- },
379
- "foo": "Foo",
380
- "fallback_test": "Success"
381
- };
382
- //test
383
- EOS
384
- }$/)
385
- end
386
- end
387
-
388
- context "I18n.available_locales" do
389
-
390
- context "when I18n.available_locales is not set" do
391
- it "should allow all locales" do
392
- result = I18n::JS.scoped_translations("*.admin.*.title")
393
-
394
- expect(result[:en][:admin][:show][:title]).to eql("Show")
395
- expect(result[:fr][:admin][:show][:title]).to eql("Visualiser")
396
- expect(result[:ja][:admin][:show][:title]).to eql("Ignore me")
397
- end
398
- end
399
-
400
- context "when I18n.available_locales is set" do
401
- before { allow(::I18n).to receive(:available_locales){ [:en, :fr] } }
402
-
403
- it "should ignore non-valid locales" do
404
- result = I18n::JS.scoped_translations("*.admin.*.title")
405
-
406
- expect(result[:en][:admin][:show][:title]).to eql("Show")
407
- expect(result[:fr][:admin][:show][:title]).to eql("Visualiser")
408
- expect(result.keys.include?(:ja)).to eql(false)
409
- end
410
- end
411
- end
412
-
413
- context "general" do
414
- it "sets export directory" do
415
- expect(I18n::JS::DEFAULT_EXPORT_DIR_PATH).to eql("public/javascripts")
416
- end
417
-
418
- it "sets empty hash as configuration when no file is found" do
419
- expect(I18n::JS.config_file_exists?).to eql(false)
420
- expect(I18n::JS.config).to eql({})
421
- end
422
-
423
- it "executes erb in config file" do
424
- set_config "erb.yml"
425
-
426
- config_entry = I18n::JS.config[:translations].first
427
- expect(config_entry["only"]).to eq("*.date.formats")
428
- end
429
- end
430
-
431
- describe "i18n.js exporting" do
432
- after { begin described_class.send(:remove_instance_variable, :@export_i18n_js_dir_path); rescue; end }
433
-
434
- describe ".export_i18n_js with global variable" do
435
- before do
436
- allow(FileUtils).to receive(:mkdir_p).and_call_original
437
- allow(FileUtils).to receive(:cp).and_call_original
438
-
439
- allow(described_class).to receive(:export_i18n_js_dir_path).and_return(export_i18n_js_dir_path)
440
- I18n::JS.export_i18n_js
441
- end
442
-
443
- context 'when .export_i18n_js_dir_path returns something' do
444
- let(:export_i18n_js_dir_path) { temp_path }
445
-
446
- it "does create the folder before copying" do
447
- expect(FileUtils).to have_received(:mkdir_p).with(export_i18n_js_dir_path).once
448
- end
449
- it "does copy the file with FileUtils.cp" do
450
- expect(FileUtils).to have_received(:cp).once
451
- end
452
- it "exports the file" do
453
- expect(File).to be_file(File.join(I18n::JS.export_i18n_js_dir_path, "i18n.js"))
454
- end
455
- end
456
-
457
- context 'when .export_i18n_js_dir_path is set to nil' do
458
- let(:export_i18n_js_dir_path) { nil }
459
-
460
- it "does NOT create the folder before copying" do
461
- expect(FileUtils).to_not have_received(:mkdir_p)
462
- end
463
- it "does NOT copy the file with FileUtils.cp" do
464
- expect(FileUtils).to_not have_received(:cp)
465
- end
466
- end
467
- end
468
-
469
- describe ".export_i18n_js with config" do
470
-
471
- let(:export_action) do
472
- allow(FileUtils).to receive(:mkdir_p).and_call_original
473
- allow(FileUtils).to receive(:cp).and_call_original
474
- I18n::JS.export_i18n_js
475
- end
476
-
477
- context 'when :export_i18n_js set in config' do
478
- before { set_config "js_export_dir_custom.yml"; export_action }
479
- let(:export_i18n_js_dir_path) { temp_path }
480
- let(:config_export_path) { "tmp/i18n-js/foo" }
481
-
482
- it "does create the folder before copying" do
483
- expect(FileUtils).to have_received(:mkdir_p).with(config_export_path).once
484
- end
485
- it "does copy the file with FileUtils.cp" do
486
- expect(FileUtils).to have_received(:cp).once
487
- end
488
- it "exports the file" do
489
- expect(File).to be_file(File.join(config_export_path, "i18n.js"))
490
- end
491
- end
492
-
493
- context 'when .export_i18n_js_dir_path is set to false' do
494
- before { set_config "js_export_dir_none.yml"; export_action }
495
-
496
- it "does NOT create the folder before copying" do
497
- expect(FileUtils).to_not have_received(:mkdir_p)
498
- end
499
-
500
- it "does NOT copy the file with FileUtils.cp" do
501
- expect(FileUtils).to_not have_received(:cp)
502
- end
503
- end
504
- end
505
-
506
- describe '.export_i18n_js_dir_path' do
507
- let(:default_path) { I18n::JS::DEFAULT_EXPORT_DIR_PATH }
508
- let(:new_path) { File.join("tmp", default_path) }
509
- after { described_class.send(:remove_instance_variable, :@export_i18n_js_dir_path) }
510
-
511
- subject { described_class.export_i18n_js_dir_path }
512
-
513
- context "when it is not set" do
514
- it { should eq default_path }
515
- end
516
- context "when it is set to another path already" do
517
- before { described_class.export_i18n_js_dir_path = new_path }
518
-
519
- it { should eq new_path }
520
- end
521
- context "when it is set to nil already" do
522
- before { described_class.export_i18n_js_dir_path = nil }
523
-
524
- it { should eq :none }
525
- end
526
- end
527
- end
528
-
529
- describe "translation key sorting" do
530
-
531
- describe ".sort_translation_keys?" do
532
- after { described_class.send(:remove_instance_variable, :@sort_translation_keys) }
533
- subject { described_class.sort_translation_keys? }
534
-
535
-
536
- context "set with config" do
537
-
538
- context 'when :sort_translation_keys is not set in config' do
539
- before :each do
540
- set_config "default.yml"
541
- end
542
-
543
- it { should eq true }
544
- end
545
-
546
- context 'when :sort_translation_keys set to true in config' do
547
- before :each do
548
- set_config "js_sort_translation_keys_true.yml"
549
- end
550
-
551
- it { should eq true }
552
- end
553
-
554
- context 'when :sort_translation_keys set to false in config' do
555
- before :each do
556
- set_config "js_sort_translation_keys_false.yml"
557
- end
558
-
559
- it { should eq false }
560
- end
561
- end
562
-
563
- context 'set by .sort_translation_keys' do
564
-
565
- context "when it is not set" do
566
- it { should eq true }
567
- end
568
-
569
- context "when it is set to true" do
570
- before { described_class.sort_translation_keys = true }
571
-
572
- it { should eq true }
573
- end
574
-
575
- context "when it is set to false" do
576
- before { described_class.sort_translation_keys = false }
577
-
578
- it { should eq false }
579
- end
580
- end
581
- end
582
-
583
- context "exporting" do
584
- subject do
585
- I18n::JS.export
586
- file_should_exist "en.js"
587
- File.read(File.join(I18n::JS.export_i18n_js_dir_path, "en.js"))
588
- end
589
-
590
- before do
591
- stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
592
- end
593
-
594
- context 'sort_translation_keys is true' do
595
- before :each do
596
- set_config "js_sort_translation_keys_true.yml"
597
- end
598
-
599
- it "exports with the keys sorted" do
600
- expect(subject).to eq <<EOS
601
- I18n.translations || (I18n.translations = {});
602
- 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","merge_plurals":{"one":"Apple","other":"Apples"},"merge_plurals_with_no_overrides":{"one":"Apple","other":"Apples","zero":"No Apple"},"merge_plurals_with_partial_overrides":{"one":"Cat","other":"Cats"},"null_test":"fallback for null","number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}},"format":{"delimiter":",","precision":3,"separator":"."},"human":{"decimal_units":{"units":{"million":"Million"}}}},"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"}});
603
- EOS
604
- end
605
- end
606
- end
607
- end
608
-
609
- describe "js_extend option" do
610
- before do
611
- stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
612
- end
613
-
614
- # https://github.com/fnando/i18n-js/issues/553
615
- describe "millions" do
616
- before do
617
- stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
618
- end
619
-
620
- subject do
621
- File.read(File.join(I18n::JS.export_i18n_js_dir_path, "millions.js"))
622
- end
623
-
624
- it "should correctly export millions" do
625
- set_config "millions.yml"
626
- I18n::JS.export
627
- file_should_exist "millions.js"
628
-
629
- expect(subject).to eq <<EOS
630
- I18n.translations || (I18n.translations = {});
631
- I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
632
- I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
633
- I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
634
- I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":{\"one\":\"millón\",\"other\":\"millones\"}}}}}});
635
- I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
636
- I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
637
- I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
638
- EOS
639
- end
640
- end
641
-
642
- it "exports with js_extend option at parent level" do
643
- set_config "js_extend_parent.yml"
644
- I18n::JS.export
645
-
646
- file_should_exist "js_extend_parent.js"
647
-
648
- output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "js_extend_parent.js"))
649
- expect(output).to eq(<<EOS
650
- I18n.translations || (I18n.translations = {});
651
- I18n.translations[\"en\"] = {\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}};
652
- I18n.translations[\"fr\"] = {\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}};
653
- EOS
654
- )
655
- end
656
-
657
- it "exports with js_extend option at segment level" do
658
- set_config "js_extend_segment.yml"
659
- I18n::JS.export
660
-
661
- file_should_exist "js_extend_segment.js"
662
-
663
- output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "js_extend_segment.js"))
664
- expect(output).to eq(<<EOS
665
- I18n.translations || (I18n.translations = {});
666
- I18n.translations[\"en\"] = {\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}};
667
- I18n.translations[\"fr\"] = {\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}};
668
- EOS
669
- )
670
- end
671
- end
672
-
673
- describe "merging plural keys" do
674
- before do
675
- stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
676
- end
677
-
678
- subject do
679
- File.read(File.join(I18n::JS.export_i18n_js_dir_path, "merge_plurals.js"))
680
- end
681
-
682
- it "should correctly merge the plural keys" do
683
- set_config "merge_plurals.yml"
684
- I18n::JS.export
685
- file_should_exist "merge_plurals.js"
686
-
687
- expect(subject).to eq <<EOS
688
- I18n.translations || (I18n.translations = {});
689
- I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), {\"merge_plurals\":{\"one\":\"Apple\",\"other\":\"Apples\"}});\nI18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), {\"merge_plurals\":{\"one\":\"Pomme\",\"other\":\"Pommes\",\"zero\":\"Pomme\"}});
690
- EOS
691
- end
692
- end
693
-
694
- describe "merging plural keys, with fallbacks" do
695
- before do
696
- stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
697
- end
698
-
699
- subject do
700
- File.read(File.join(I18n::JS.export_i18n_js_dir_path, "merge_plurals_with_no_overrides.js"))
701
- end
702
-
703
- it "should correctly merge the plural keys" do
704
- set_config "merge_plurals_with_no_overrides.yml"
705
- I18n::JS.export
706
- file_should_exist "merge_plurals_with_no_overrides.js"
707
-
708
- expect(subject).to eq <<EOS
709
- I18n.translations || (I18n.translations = {});
710
- I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
711
- I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
712
- I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
713
- I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
714
- I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
715
- I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
716
- I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), {\"merge_plurals_with_no_overrides\":{\"few\":\"кошек\",\"many\":\"кошка\",\"one\":\"кот\",\"other\":\"кошек\"}});
717
- EOS
718
- end
719
- end
720
-
721
- # see discussion @ https://github.com/fnando/i18n-js/pull/551#issuecomment-543205767
722
- describe "merging plural keys, with fallbacks, with partial overrides" do
723
- before do
724
- stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
725
- end
726
-
727
- subject do
728
- File.read(File.join(I18n::JS.export_i18n_js_dir_path, "merge_plurals_with_partial_overrides.js"))
729
- end
730
-
731
- it "should correctly merge the plural keys" do
732
- set_config "merge_plurals_with_partial_overrides.yml"
733
- I18n::JS.export
734
- file_should_exist "merge_plurals_with_partial_overrides.js"
735
-
736
- expect(subject).to eq <<EOS
737
- I18n.translations || (I18n.translations = {});
738
- I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
739
- I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
740
- I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"few\":null,\"many\":null,\"one\":\"Cat\",\"other\":\"Cats\"}});
741
- I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
742
- I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
743
- I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
744
- I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
745
- EOS
746
- end
747
- end
748
- end