i18n-js 3.8.0 → 3.8.4

Sign up to get free protection for your applications and to get access to all the features.
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