i18n-js 3.8.0 → 3.8.4

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.
data/i18njs.png ADDED
Binary file
data/lib/i18n/js.rb CHANGED
@@ -4,6 +4,7 @@ require "i18n"
4
4
 
5
5
  require "i18n/js/utils"
6
6
  require "i18n/js/private/hash_with_symbol_keys"
7
+ require "i18n/js/private/config_store"
7
8
 
8
9
  module I18n
9
10
  module JS
@@ -26,6 +27,8 @@ module I18n
26
27
 
27
28
  def self.config_file_path=(new_path)
28
29
  @config_file_path = new_path
30
+ # new config file path = need to re-read config from new file
31
+ Private::ConfigStore.instance.flush_cache
29
32
  end
30
33
 
31
34
  # Allow using a different backend than the one globally configured
@@ -108,14 +111,16 @@ module I18n
108
111
  # Load configuration file for partial exporting and
109
112
  # custom output directory
110
113
  def self.config
111
- if config_file_exists?
112
- erb_result_from_yaml_file = ERB.new(File.read(config_file_path)).result
113
- Private::HashWithSymbolKeys.new(
114
- (::YAML.load(erb_result_from_yaml_file) || {})
115
- )
116
- else
117
- Private::HashWithSymbolKeys.new({})
118
- end.freeze
114
+ Private::ConfigStore.instance.fetch do
115
+ if config_file_exists?
116
+ erb_result_from_yaml_file = ERB.new(File.read(config_file_path)).result
117
+ Private::HashWithSymbolKeys.new(
118
+ (::YAML.load(erb_result_from_yaml_file) || {})
119
+ )
120
+ else
121
+ Private::HashWithSymbolKeys.new({})
122
+ end.freeze
123
+ end
119
124
  end
120
125
 
121
126
  # @api private
@@ -4,6 +4,12 @@ module I18n
4
4
  module JS
5
5
  module Formatters
6
6
  class JS < Base
7
+ JSON_ESCAPE_MAP = {
8
+ "'" => "\\'",
9
+ "\\" => "\\\\"
10
+ }.freeze
11
+ private_constant :JSON_ESCAPE_MAP
12
+
7
13
  def format(translations)
8
14
  contents = header
9
15
  translations.each do |locale, translations_for_locale|
@@ -20,10 +26,11 @@ module I18n
20
26
  end
21
27
 
22
28
  def line(locale, translations)
29
+ json_literal = @pretty_print ? translations : %(JSON.parse('#{translations.gsub(/#{Regexp.union(JSON_ESCAPE_MAP.keys)}/){|match| JSON_ESCAPE_MAP.fetch(match) }}'))
23
30
  if @js_extend
24
- %(#{@namespace}.translations["#{locale}"] = I18n.extend((#{@namespace}.translations["#{locale}"] || {}), #{translations});\n)
31
+ %(#{@namespace}.translations["#{locale}"] = I18n.extend((#{@namespace}.translations["#{locale}"] || {}), #{json_literal});\n)
25
32
  else
26
- %(#{@namespace}.translations["#{locale}"] = #{translations};\n)
33
+ %(#{@namespace}.translations["#{locale}"] = #{json_literal};\n)
27
34
  end
28
35
  end
29
36
  end
@@ -45,7 +45,7 @@ module I18n
45
45
 
46
46
  def save_cache(new_cache)
47
47
  # path could be a symbolic link
48
- FileUtils.mkdir_p(cache_dir) unless File.exists?(cache_dir)
48
+ FileUtils.mkdir_p(cache_dir) unless File.exist?(cache_dir)
49
49
  File.open(cache_path, "w+") do |file|
50
50
  file << new_cache.to_yaml
51
51
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module I18n
6
+ module JS
7
+ # @api private
8
+ module Private
9
+ # Caching implementation for I18n::JS.config
10
+ #
11
+ # @api private
12
+ class ConfigStore
13
+ include Singleton
14
+
15
+ def fetch
16
+ return @config if @config
17
+
18
+ yield.tap do |obj|
19
+ raise ArgumentError, "unexpected falsy object from block" unless obj
20
+
21
+ @config = obj
22
+ end
23
+ end
24
+
25
+ def flush_cache
26
+ @config = nil
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -50,6 +50,7 @@ module I18n
50
50
  def write_file(_file = @file, _translations = @translations)
51
51
  FileUtils.mkdir_p File.dirname(_file)
52
52
  _translations = Utils.deep_key_sort(_translations) if @sort_translation_keys
53
+ _translations = Utils.deep_remove_procs(_translations)
53
54
  contents = formatter.format(_translations)
54
55
 
55
56
  return if File.exist?(_file) && File.read(_file) == contents
data/lib/i18n/js/utils.rb CHANGED
@@ -73,6 +73,19 @@ module I18n
73
73
  seed[key] = value.is_a?(Hash) ? deep_key_sort(value) : value
74
74
  end
75
75
  end
76
+
77
+ def self.deep_remove_procs(hash)
78
+ # procs exist in `i18n.plural.rule` as pluralizer
79
+ # But having it in translation causes the exported JS/JSON changes every time
80
+ # https://github.com/ruby-i18n/i18n/blob/v1.8.7/lib/i18n/backend/pluralization.rb#L51
81
+ hash.keys.
82
+ each_with_object({}) do |key, seed|
83
+ value = hash[key]
84
+ next if value.is_a?(Proc)
85
+
86
+ seed[key] = value.is_a?(Hash) ? deep_remove_procs(value) : value
87
+ end
88
+ end
76
89
  end
77
90
  end
78
91
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module I18n
4
4
  module JS
5
- VERSION = "3.8.0"
5
+ VERSION = "3.8.4"
6
6
  end
7
7
  end
data/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "i18n"
9
9
  ],
10
10
  "devDependencies": {
11
- "jasmine-node": "^1.14.5"
11
+ "jasmine-node": "^3.0.0"
12
12
  },
13
13
  "main": "app/assets/javascripts/i18n.js",
14
14
  "scripts": {
@@ -0,0 +1,14 @@
1
+ describe("JSON.parse", function () {
2
+ it('should parse', function () {
3
+ expect(JSON.parse('{"a":"Test\'s"}')).toEqual({
4
+ a: "Test's"
5
+ })
6
+
7
+ expect(JSON.parse('{"a":"say \\"hello\\""}')).toEqual({
8
+ a: 'say "hello"'
9
+ });
10
+ expect(JSON.parse('{"double-backslash-in-double-quote":"\\"\\\\\\\\\\""}')).toEqual({
11
+ 'double-backslash-in-double-quote': '"\\\\"'
12
+ });
13
+ })
14
+ })
@@ -131,8 +131,8 @@ EOS
131
131
 
132
132
  expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
133
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"});
134
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"test":"Test"}'));
135
+ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), JSON.parse('{"test":"Test2"}'));
136
136
  EOF
137
137
  end
138
138
  end
@@ -146,12 +146,54 @@ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] ||
146
146
 
147
147
  expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
148
148
  MyNamespace.translations || (MyNamespace.translations = {});
149
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"test":"Test"});
149
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"test":"Test"}'));
150
150
  EOF
151
151
 
152
152
  expect(File.open(File.join(temp_path, "fr.js")){|f| f.read}).to eql <<-EOF
153
153
  MyNamespace.translations || (MyNamespace.translations = {});
154
- MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), {"test":"Test2"});
154
+ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), JSON.parse('{"test":"Test2"}'));
155
+ EOF
156
+ end
157
+ end
158
+
159
+ context "when file includes single quote" do
160
+ let(:file){ "tmp/i18n-js/%{locale}.js" }
161
+ let(:translations){ { en: { "a" => "Test's" } } }
162
+
163
+ it "should write files" do
164
+ file_should_exist "en.js"
165
+
166
+ expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
167
+ MyNamespace.translations || (MyNamespace.translations = {});
168
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"a":"Test\\'s"}'));
169
+ EOF
170
+ end
171
+ end
172
+
173
+ context "when file includes escaped double quote" do
174
+ let(:file){ "tmp/i18n-js/%{locale}.js" }
175
+ let(:translations){ { en: { "a" => 'say "hello"' } } }
176
+
177
+ it "should escape double quote" do
178
+ file_should_exist "en.js"
179
+
180
+ expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
181
+ MyNamespace.translations || (MyNamespace.translations = {});
182
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"a":"say \\\\"hello\\\\""}'));
183
+ EOF
184
+ end
185
+ end
186
+
187
+ context "when file includes backslash in double quote" do
188
+ let(:file){ "tmp/i18n-js/%{locale}.js" }
189
+ let(:translations){ { en: { "double-backslash-in-double-quote" => '"\\\\"' } } }
190
+
191
+ it "should escape backslash" do
192
+ file_should_exist "en.js"
193
+
194
+ expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
195
+ MyNamespace.translations || (MyNamespace.translations = {});
196
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"double-backslash-in-double-quote":"\\\\"\\\\\\\\\\\\\\\\\\\\""}'));
155
197
  EOF
156
198
  end
157
199
  end
@@ -166,7 +208,7 @@ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] ||
166
208
 
167
209
  expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
168
210
  MyNamespace.translations || (MyNamespace.translations = {});
169
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"a":"Test","b":"Test"});
211
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"a":"Test","b":"Test"}'));
170
212
  EOF
171
213
  end
172
214
  end
@@ -181,7 +223,7 @@ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] ||
181
223
 
182
224
  expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
183
225
  MyNamespace.translations || (MyNamespace.translations = {});
184
- MyNamespace.translations["en"] = {"a":"Test","b":"Test"};
226
+ MyNamespace.translations["en"] = JSON.parse('{"a":"Test","b":"Test"}');
185
227
  EOF
186
228
  end
187
229
  end
@@ -196,7 +238,7 @@ MyNamespace.translations["en"] = {"a":"Test","b":"Test"};
196
238
 
197
239
  expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
198
240
  MyNamespace.translations || (MyNamespace.translations = {});
199
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"a":"Test","b":"Test"});
241
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"a":"Test","b":"Test"}'));
200
242
  EOF
201
243
  end
202
244
  end
@@ -211,7 +253,32 @@ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] ||
211
253
 
212
254
  expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
213
255
  MyNamespace.translations || (MyNamespace.translations = {});
214
- MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"b":"Test","a":"Test"});
256
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"b":"Test","a":"Test"}'));
257
+ EOF
258
+ end
259
+ end
260
+
261
+ context "when translation entries contain procs" do
262
+ let(:translations) do
263
+ {
264
+ en: {
265
+ "test" => "Test",
266
+ "i18n" => {"plural" => {"rule" => proc {} }},
267
+ },
268
+ fr: {
269
+ "test" => "Test2",
270
+ "i18n" => {"plural" => {"rule" => proc {} }},
271
+ },
272
+ }
273
+ end
274
+
275
+ it "should write files without procs or their string representations" do
276
+ file_should_exist "segment.js"
277
+
278
+ expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
279
+ MyNamespace.translations || (MyNamespace.translations = {});
280
+ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"i18n":{"plural":{}},"test":"Test"}'));
281
+ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), JSON.parse('{"i18n":{"plural":{}},"test":"Test2"}'));
215
282
  EOF
216
283
  end
217
284
  end
@@ -103,4 +103,36 @@ describe I18n::JS::Utils do
103
103
  expect(described_class.scopes_match?([:a, :b, :c], [:a, '*', '*'])).to eql true
104
104
  end
105
105
  end
106
+
107
+ describe ".deep_remove_procs" do
108
+ let(:proc_obj) { proc {} }
109
+ let(:hash_with_proc) do
110
+ {
111
+ :a => :b,
112
+ :c => proc_obj,
113
+ :d => {
114
+ :e => proc_obj,
115
+ :f => :g,
116
+ }
117
+ }
118
+ end
119
+ subject { described_class.deep_remove_procs(hash_with_proc) }
120
+
121
+ it "performs a deep keys sort without changing the original hash" do
122
+ should eql({
123
+ :a => :b,
124
+ :d => {
125
+ :f => :g,
126
+ }
127
+ })
128
+ expect(hash_with_proc).to eql({
129
+ :a => :b,
130
+ :c => proc_obj,
131
+ :d => {
132
+ :e => proc_obj,
133
+ :f => :g,
134
+ }
135
+ })
136
+ end
137
+ end
106
138
  end
@@ -67,13 +67,13 @@ describe I18n::JS do
67
67
  en_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "en.js"))
68
68
  expect(en_output).to eq(<<EOS
69
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"]}});
70
+ I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), JSON.parse('{"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
71
  EOS
72
72
  )
73
73
  fr_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "fr.js"))
74
74
  expect(fr_output).to eq(<<EOS
75
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"]}});
76
+ I18n.translations["fr"] = I18n.extend((I18n.translations["fr"] || {}), JSON.parse('{"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
77
  EOS
78
78
  )
79
79
  end
@@ -98,13 +98,13 @@ EOS
98
98
  en_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "bits.en.js"))
99
99
  expect(en_output).to eq(<<EOS
100
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":"$"}}}});
101
+ I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), JSON.parse('{"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
102
  EOS
103
103
  )
104
104
  fr_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "bits.fr.js"))
105
105
  expect(fr_output).to eq(<<EOS
106
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":"€"}}}});
107
+ I18n.translations["fr"] = I18n.extend((I18n.translations["fr"] || {}), JSON.parse('{"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
108
  EOS
109
109
  )
110
110
  end
@@ -599,7 +599,7 @@ EOS
599
599
  it "exports with the keys sorted" do
600
600
  expect(subject).to eq <<EOS
601
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"}});
602
+ I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), JSON.parse('{"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
603
  EOS
604
604
  end
605
605
  end
@@ -628,13 +628,13 @@ EOS
628
628
 
629
629
  expect(subject).to eq <<EOS
630
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\"}}}}});
631
+ I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
632
+ I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
633
+ I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
634
+ I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":{\"one\":\"millón\",\"other\":\"millones\"}}}}}}'));
635
+ I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
636
+ I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
637
+ I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
638
638
  EOS
639
639
  end
640
640
  end
@@ -648,8 +648,8 @@ EOS
648
648
  output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "js_extend_parent.js"))
649
649
  expect(output).to eq(<<EOS
650
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\"}}};
651
+ I18n.translations[\"en\"] = JSON.parse('{\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}}');
652
+ I18n.translations[\"fr\"] = JSON.parse('{\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}}');
653
653
  EOS
654
654
  )
655
655
  end
@@ -663,8 +663,8 @@ EOS
663
663
  output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "js_extend_segment.js"))
664
664
  expect(output).to eq(<<EOS
665
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\"}}};
666
+ I18n.translations[\"en\"] = JSON.parse('{\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}}');
667
+ I18n.translations[\"fr\"] = JSON.parse('{\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}}');
668
668
  EOS
669
669
  )
670
670
  end
@@ -686,7 +686,7 @@ EOS
686
686
 
687
687
  expect(subject).to eq <<EOS
688
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\"}});
689
+ I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), JSON.parse('{\"merge_plurals\":{\"one\":\"Apple\",\"other\":\"Apples\"}}'));\nI18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), JSON.parse('{\"merge_plurals\":{\"one\":\"Pomme\",\"other\":\"Pommes\",\"zero\":\"Pomme\"}}'));
690
690
  EOS
691
691
  end
692
692
  end
@@ -707,13 +707,13 @@ EOS
707
707
 
708
708
  expect(subject).to eq <<EOS
709
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\":\"кошек\"}});
710
+ I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
711
+ I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
712
+ I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
713
+ I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
714
+ I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
715
+ I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
716
+ I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"few\":\"кошек\",\"many\":\"кошка\",\"one\":\"кот\",\"other\":\"кошек\"}}'));
717
717
  EOS
718
718
  end
719
719
  end
@@ -735,13 +735,13 @@ EOS
735
735
 
736
736
  expect(subject).to eq <<EOS
737
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\"}});
738
+ I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
739
+ I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
740
+ I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"few\":null,\"many\":null,\"one\":\"Cat\",\"other\":\"Cats\"}}'));
741
+ I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
742
+ I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
743
+ I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
744
+ I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
745
745
  EOS
746
746
  end
747
747
  end