i18n-js 3.0.0.rc14 → 3.0.0.rc15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 10a07ab318e610dfc7102d3d88015d8a55c42a76
4
- data.tar.gz: 21fa8daa428b711f6d592c3b14bad7183e5af2f8
3
+ metadata.gz: 3cb04a52e869d4da0331db74c65512cae5c19abc
4
+ data.tar.gz: 6522e5f84e73ca868c2054a2d67946c3d798a672
5
5
  SHA512:
6
- metadata.gz: cef3f6f68e7ca327e96902093069c47df6897074d35db121700076e3e7137d1ae68a9222e76ded1bea5e8d3145597cc0f37c9651d12a3b62ccbf766ce8374186
7
- data.tar.gz: 6940d5acc297f6482cb74caa56f64c85b2be20065a069fd26267956ee157ce139b2f92b425c9e2e55ce983c285bd66dcdae861454bc4371aa4e478687613da4d
6
+ metadata.gz: a500c069fd37898516080b518c313f8cb3cc7e0d3acc8cf9cd0a0f0b82f6f2c5f751ea777868d6de14f88fda66797f60e37246aedfbfc73942558ca648149dad
7
+ data.tar.gz: ce0941d24100dd6c414f4699de4db0fac4725c2f995129cc19cec35847e7693503570e5ca8262aa7cda7da93e8ac5712bdd94c82db58271fcbc5687c3d89128a
data/CHANGELOG.md CHANGED
@@ -2,6 +2,7 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+
5
6
  ## [Unreleased]
6
7
 
7
8
  ### Added
@@ -17,6 +18,34 @@ This project adheres to [Semantic Versioning](http://semver.org/).
17
18
  - Nothing
18
19
 
19
20
 
21
+ ## [3.0.0.rc15] - 2016-12-07
22
+
23
+ ### Added
24
+
25
+ - Nothing
26
+
27
+ ### Changed
28
+
29
+ - [JS] Allow `defaultValue` to work in pluralization
30
+ (PR: https://github.com/fnando/i18n-js/pull/433)
31
+ - [Ruby] Stop validating the fallback locales against `I18n.available_locales`
32
+ This allows some locales to be used as fallback locales, but not to be generated in JS.
33
+ (PR: https://github.com/fnando/i18n-js/pull/425)
34
+ - [Ruby] Remove dependency on gem `activesupport`
35
+
36
+ ### Fixed
37
+
38
+ - [JS] Stop converting numeric & boolean values into objects
39
+ when merging objects with `I18n.extend`
40
+ (PR: https://github.com/fnando/i18n-js/pull/420)
41
+ - [JS] Fix I18n pluralization fallback when tree is empty
42
+ (PR: https://github.com/fnando/i18n-js/pull/435)
43
+ - [Ruby] Use old syntax to define lambda for compatibility with older Rubies
44
+ (Issue: https://github.com/fnando/i18n-js/issues/419)
45
+ - [Ruby] Fix error raised in middleware cache cleaning in parallel test
46
+ (Issue: https://github.com/fnando/i18n-js/issues/436)
47
+
48
+
20
49
  ## [3.0.0.rc14] - 2016-08-29
21
50
 
22
51
  ### Changed
@@ -188,7 +217,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
188
217
 
189
218
 
190
219
 
191
- [Unreleased]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc14...HEAD
220
+ [Unreleased]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc15...HEAD
221
+ [3.0.0.rc15]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc14...v3.0.0.rc15
192
222
  [3.0.0.rc14]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc13...v3.0.0.rc14
193
223
  [3.0.0.rc13]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc12...v3.0.0.rc13
194
224
  [3.0.0.rc12]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc11...v3.0.0.rc12
data/README.md CHANGED
@@ -742,6 +742,7 @@ I18n.translations["pt-BR"] = {
742
742
  }
743
743
  ```
744
744
 
745
+
745
746
  ## Known Issues
746
747
 
747
748
  ### Missing translations in precompiled file(s) after adding any new locale file
@@ -774,6 +775,16 @@ This means that new locale files will not be detected, and so they will not trig
774
775
 
775
776
  **Note:** See issue [#213](https://github.com/fnando/i18n-js/issues/213) for more details and discussion of this issue.
776
777
 
778
+ ### Translations in JS are not updated when Sprockets not loaded before this gem
779
+
780
+ The "rails engine" declaration will try to detect existence of "sprockets" before adding the initailizer
781
+ If sprockets is loaded after this gem, the preprocessor for
782
+ making JS translations file cache to depend on content of locale files will not be hooked.
783
+ So ensure sprockets is loaded before this gem like moving entry of sprockets in Gemfile or adding "require" statements for sprockets somewhere.
784
+
785
+ **Note:** See issue [#404](https://github.com/fnando/i18n-js/issues/404) for more details and discussion of this issue.
786
+
787
+
777
788
  ## Maintainer
778
789
 
779
790
  - Nando Vieira - <http://nandovieira.com.br>
@@ -53,11 +53,23 @@
53
53
 
54
54
  // Is a given value an array?
55
55
  // Borrowed from Underscore.js
56
- var isArray = function(obj) {
56
+ var isArray = function(val) {
57
57
  if (Array.isArray) {
58
- return Array.isArray(obj);
58
+ return Array.isArray(val);
59
59
  };
60
- return Object.prototype.toString.call(obj) === '[object Array]';
60
+ return Object.prototype.toString.call(val) === '[object Array]';
61
+ };
62
+
63
+ var isString = function(val) {
64
+ return typeof value == 'string' || Object.prototype.toString.call(val) === '[object String]';
65
+ };
66
+
67
+ var isNumber = function(val) {
68
+ return typeof val == 'number' || Object.prototype.toString.call(val) === '[object Number]';
69
+ };
70
+
71
+ var isBoolean = function(val) {
72
+ return val === true || val === false;
61
73
  };
62
74
 
63
75
  var decimalAdjust = function(type, value, exp) {
@@ -83,7 +95,7 @@
83
95
  var key, value;
84
96
  for (key in obj) if (obj.hasOwnProperty(key)) {
85
97
  value = obj[key];
86
- if (Object.prototype.toString.call(value) === '[object String]') {
98
+ if (isString(value) || isNumber(value) || isBoolean(value)) {
87
99
  dest[key] = value;
88
100
  } else {
89
101
  if (dest[key] == null) dest[key] = {};
@@ -347,7 +359,6 @@
347
359
  if (!translations) {
348
360
  continue;
349
361
  }
350
-
351
362
  while (scopes.length) {
352
363
  translations = translations[scopes.shift()];
353
364
 
@@ -366,6 +377,75 @@
366
377
  }
367
378
  };
368
379
 
380
+ // lookup pluralization rule key into translations
381
+ I18n.pluralizationLookupWithoutFallback = function(count, locale, translations) {
382
+ var pluralizer = this.pluralization.get(locale)
383
+ , pluralizerKeys = pluralizer(count)
384
+ , pluralizerKey
385
+ , message;
386
+
387
+ if (isObject(translations)) {
388
+ while (pluralizerKeys.length) {
389
+ pluralizerKey = pluralizerKeys.shift();
390
+ if (this.isSet(translations[pluralizerKey])) {
391
+ message = translations[pluralizerKey];
392
+ break;
393
+ }
394
+ }
395
+ }
396
+
397
+ return message;
398
+ };
399
+
400
+ // Lookup dedicated to pluralization
401
+ I18n.pluralizationLookup = function(count, scope, options) {
402
+ options = this.prepareOptions(options);
403
+ var locales = this.locales.get(options.locale).slice()
404
+ , requestedLocale = locales[0]
405
+ , locale
406
+ , scopes
407
+ , translations
408
+ , message
409
+ ;
410
+ scope = this.getFullScope(scope, options);
411
+
412
+ while (locales.length) {
413
+ locale = locales.shift();
414
+ scopes = scope.split(this.defaultSeparator);
415
+ translations = this.translations[locale];
416
+
417
+ if (!translations) {
418
+ continue;
419
+ }
420
+
421
+ while (scopes.length) {
422
+ translations = translations[scopes.shift()];
423
+ if (!isObject(translations)) {
424
+ break;
425
+ }
426
+ if (scopes.length == 0) {
427
+ message = this.pluralizationLookupWithoutFallback(count, locale, translations);
428
+ }
429
+ }
430
+ if (message != null && message != undefined) {
431
+ break;
432
+ }
433
+ }
434
+
435
+ if (message == null || message == undefined) {
436
+ if (this.isSet(options.defaultValue)) {
437
+ if (isObject(options.defaultValue)) {
438
+ message = this.pluralizationLookupWithoutFallback(count, options.locale, options.defaultValue);
439
+ } else {
440
+ message = options.defaultValue;
441
+ }
442
+ translations = options.defaultValue;
443
+ }
444
+ }
445
+
446
+ return { message: message, translations: translations };
447
+ };
448
+
369
449
  // Rails changed the way the meridian is stored.
370
450
  // It started with `date.meridian` returning an array,
371
451
  // then it switched to `time.am` and `time.pm`.
@@ -470,7 +550,7 @@
470
550
  if (typeof(translation) === "string") {
471
551
  translation = this.interpolate(translation, options);
472
552
  } else if (isObject(translation) && this.isSet(options.count)) {
473
- translation = this.pluralize(options.count, translation, options);
553
+ translation = this.pluralize(options.count, scope, options);
474
554
  }
475
555
 
476
556
  return translation;
@@ -516,32 +596,22 @@
516
596
  // which will be retrieved from `options`.
517
597
  I18n.pluralize = function(count, scope, options) {
518
598
  options = this.prepareOptions(options);
519
- var translations, pluralizer, keys, key, message;
599
+ var pluralizer, message, result;
520
600
 
521
- if (isObject(scope)) {
522
- translations = scope;
523
- } else {
524
- translations = this.lookup(scope, options);
525
- }
526
-
527
- if (!translations) {
601
+ result = this.pluralizationLookup(count, scope, options);
602
+ if (result.translations == undefined || result.translations == null) {
528
603
  return this.missingTranslation(scope, options);
529
604
  }
530
605
 
531
- pluralizer = this.pluralization.get(options.locale);
532
- keys = pluralizer(count);
533
-
534
- while (keys.length) {
535
- key = keys.shift();
606
+ options.count = String(count);
536
607
 
537
- if (this.isSet(translations[key])) {
538
- message = translations[key];
539
- break;
540
- }
608
+ if (result.message != undefined && result.message != null) {
609
+ return this.interpolate(result.message, options);
610
+ }
611
+ else {
612
+ pluralizer = this.pluralization.get(options.locale);
613
+ return this.missingTranslation(scope + '.' + pluralizer(count)[0], options);
541
614
  }
542
-
543
- options.count = String(count);
544
- return this.interpolate(message, options);
545
615
  };
546
616
 
547
617
  // Return a missing translation message for the given parameters.
data/i18n-js.gemspec CHANGED
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
20
20
 
21
21
  s.add_dependency "i18n", "~> 0.6", ">= 0.6.6"
22
22
  s.add_development_dependency "appraisal", "~> 2.0"
23
- s.add_development_dependency "activesupport", ">= 3.2.22"
24
23
  s.add_development_dependency "rspec", "~> 3.0"
25
24
  s.add_development_dependency "rake", "~> 10.0"
26
25
  s.add_development_dependency "gem-release", ">= 0.7"
data/lib/i18n/js.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  require "yaml"
2
- require "i18n"
3
2
  require "fileutils"
3
+ require "i18n"
4
+
4
5
  require "i18n/js/utils"
6
+ require "i18n/js/private/hash_with_symbol_keys"
5
7
 
6
8
  module I18n
7
9
  module JS
@@ -43,16 +45,23 @@ module I18n
43
45
  end
44
46
 
45
47
  def self.configured_segments
46
- config[:translations].inject([]) do |segments, options|
47
- file = options[:file]
48
- only = options[:only] || '*'
49
- exceptions = [options[:except] || []].flatten
48
+ config[:translations].inject([]) do |segments, options_hash|
49
+ options_hash_with_symbol_keys = Private::HashWithSymbolKeys.new(options_hash)
50
+ file = options_hash_with_symbol_keys[:file]
51
+ only = options_hash_with_symbol_keys[:only] || '*'
52
+ exceptions = [options_hash_with_symbol_keys[:except] || []].flatten
50
53
 
51
54
  result = segment_for_scope(only, exceptions)
52
55
 
53
56
  merge_with_fallbacks!(result) if fallbacks
54
57
 
55
- segments << Segment.new(file, result, extract_segment_options(options)) unless result.empty?
58
+ unless result.empty?
59
+ segments << Segment.new(
60
+ file,
61
+ result,
62
+ extract_segment_options(options_hash_with_symbol_keys),
63
+ )
64
+ end
56
65
 
57
66
  segments
58
67
  end
@@ -91,11 +100,13 @@ module I18n
91
100
  # custom output directory
92
101
  def self.config
93
102
  if config?
94
- erb = ERB.new(File.read(config_file_path)).result
95
- (YAML.load(erb) || {}).with_indifferent_access
103
+ erb_result_from_yaml_file = ERB.new(File.read(config_file_path)).result
104
+ Private::HashWithSymbolKeys.new(
105
+ (::YAML.load(erb_result_from_yaml_file) || {})
106
+ )
96
107
  else
97
- {}
98
- end
108
+ Private::HashWithSymbolKeys.new({})
109
+ end.freeze
99
110
  end
100
111
 
101
112
  # Check if configuration file exist
@@ -151,7 +162,14 @@ module I18n
151
162
  def self.translations
152
163
  ::I18n.backend.instance_eval do
153
164
  init_translations unless initialized?
154
- translations.slice(*::I18n.available_locales)
165
+ # When activesupport is absent,
166
+ # the core extension (`#slice`) from `i18n` gem will be used instead
167
+ # And it's causing errors (at least in test)
168
+ #
169
+ # So the input is wrapped by our class for better `#slice`
170
+ Private::HashWithSymbolKeys.new(translations).
171
+ slice(*::I18n.available_locales).
172
+ to_h
155
173
  end
156
174
  end
157
175
 
@@ -184,7 +202,10 @@ module I18n
184
202
  end
185
203
 
186
204
  def self.extract_segment_options(options)
187
- segment_options = {js_extend: js_extend, sort_translation_keys: sort_translation_keys?}.with_indifferent_access
205
+ segment_options = Private::HashWithSymbolKeys.new({
206
+ js_extend: js_extend,
207
+ sort_translation_keys: sort_translation_keys?,
208
+ }).freeze
188
209
  segment_options.merge(options.slice(*Segment::OPTIONS))
189
210
  end
190
211
 
@@ -32,8 +32,11 @@ module I18n
32
32
  #
33
33
  # For detail see Pull Request:
34
34
  # https://github.com/fnando/i18n-js/pull/371
35
+ #
36
+ # Not using -> for JRuby compatibility
37
+ # See https://github.com/fnando/i18n-js/issues/419
35
38
  initializer_args = case sprockets_version
36
- when -> (v) { v2_only.match?("", v) || v3_plus.match?("", v) }
39
+ when lambda {|v| v2_only.match?("", v) || v3_plus.match?("", v) }
37
40
  { after: :engines_blank_point, before: :finisher_hook }
38
41
  else
39
42
  raise StandardError, "Sprockets version #{sprockets_version} is not supported"
@@ -32,7 +32,6 @@ module I18n
32
32
  end
33
33
 
34
34
  locales.map! { |locale| locale.to_sym }
35
- ensure_valid_locales!(locales)
36
35
  locales
37
36
  end
38
37
 
@@ -66,16 +65,6 @@ module I18n
66
65
 
67
66
  fail ArgumentError, "If fallbacks is passed as Array, it must ony include Strings or Symbols. Given: #{fallbacks}"
68
67
  end
69
-
70
- # Ensures that only valid locales are returned.
71
- #
72
- # @note
73
- # This ignores option `I18n.enforce_available_locales`
74
- def ensure_valid_locales!(locales)
75
- if locales.any? { |locale| !::I18n.available_locales.include?(locale) }
76
- fail ArgumentError, "Valid locales: #{::I18n.available_locales.join(", ")} - Given Locales: #{locales.join(", ")}"
77
- end
78
- end
79
68
  end
80
69
  end
81
70
  end
@@ -1,3 +1,5 @@
1
+ require "fileutils"
2
+
1
3
  module I18n
2
4
  module JS
3
5
  class Middleware
@@ -32,7 +34,13 @@ module I18n
32
34
  end
33
35
 
34
36
  def clear_cache
35
- File.delete(cache_path) if File.exist?(cache_path)
37
+ # `File.delete` will raise error when "multiple worker"
38
+ # Are running at the same time, like in a parallel test
39
+ #
40
+ # `FileUtils.rm_f` is tested manually
41
+ #
42
+ # See https://github.com/fnando/i18n-js/issues/436
43
+ FileUtils.rm_f(cache_path) if File.exist?(cache_path)
36
44
  end
37
45
 
38
46
  def save_cache(new_cache)
@@ -0,0 +1,36 @@
1
+ module I18n
2
+ module JS
3
+ # @api private
4
+ module Private
5
+ # Hash with string keys converted to symbol keys
6
+ # Used for handling values read on YAML
7
+ #
8
+ # @api private
9
+ class HashWithSymbolKeys < ::Hash
10
+ # An instance can only be created by passing in another hash
11
+ def initialize(hash)
12
+ raise TypeError unless hash.is_a?(::Hash)
13
+
14
+ hash.each_key do |key|
15
+ # Objects like `Integer` does not have `to_sym`
16
+ new_key = key.respond_to?(:to_sym) ? key.to_sym : key
17
+ self[new_key] = hash[key]
18
+ end
19
+
20
+ self.default = hash.default if hash.default
21
+ self.default_proc = hash.default_proc if hash.default_proc
22
+
23
+ freeze
24
+ end
25
+
26
+ # From AS Core extension
27
+ def slice(*keys)
28
+ hash = keys.each_with_object(Hash.new) do |k, hash|
29
+ hash[k] = self[k] if has_key?(k)
30
+ end
31
+ self.class.new(hash)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,5 @@
1
+ require "i18n/js/private/hash_with_symbol_keys"
2
+
1
3
  module I18n
2
4
  module JS
3
5
 
@@ -10,7 +12,13 @@ module I18n
10
12
 
11
13
  def initialize(file, translations, options = {})
12
14
  @file = file
13
- @translations = translations
15
+ # `#slice` will be used
16
+ # But when activesupport is absent,
17
+ # the core extension from `i18n` gem will be used instead
18
+ # And it's causing errors (at least in test)
19
+ #
20
+ # So the input is wrapped by our class for better `#slice`
21
+ @translations = Private::HashWithSymbolKeys.new(translations)
14
22
  @namespace = options[:namespace] || 'I18n'
15
23
  @pretty_print = !!options[:pretty_print]
16
24
  @js_extend = options.key?(:js_extend) ? !!options[:js_extend] : true
@@ -4,7 +4,7 @@ module I18n
4
4
  MAJOR = 3
5
5
  MINOR = 0
6
6
  PATCH = 0
7
- STRING = "#{MAJOR}.#{MINOR}.#{PATCH}.rc14"
7
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}.rc15"
8
8
  end
9
9
  end
10
10
  end
@@ -58,5 +58,28 @@ describe("Extend", function () {
58
58
  }
59
59
 
60
60
  expect(I18n.extend(obj1, obj2)).toEqual(expected);
61
- })
61
+ });
62
+
63
+ it("should correctly merge string, numberic and boolean values", function() {
64
+ var obj1 = {
65
+ test1: {
66
+ test2: false
67
+ }
68
+ }
69
+ , obj2 = {
70
+ test1: {
71
+ test3: 23,
72
+ test4: 'abc'
73
+ }
74
+ }
75
+ , expected = {
76
+ test1: {
77
+ test2: false
78
+ , test3: 23
79
+ , test4: 'abc'
80
+ }
81
+ }
82
+
83
+ expect(I18n.extend(obj1, obj2)).toEqual(expected);
84
+ });
62
85
  });
@@ -46,6 +46,17 @@ describe("Interpolation", function(){
46
46
  expect(I18n.t(translation_key, {count: 5})).toEqual("Hello World!");
47
47
  });
48
48
  });
49
+ describe("and translation key does contain pluralization with null content", function() {
50
+ beforeEach(function() {
51
+ translation_key = "sent";
52
+ });
53
+
54
+ it("return empty string", function() {
55
+ expect(I18n.t(translation_key, {count: 0})).toEqual('[missing "en.sent.zero" translation]');
56
+ expect(I18n.t(translation_key, {count: 1})).toEqual('[missing "en.sent.one" translation]');
57
+ expect(I18n.t(translation_key, {count: 5})).toEqual('[missing "en.sent.other" translation]');
58
+ });
59
+ });
49
60
  });
50
61
 
51
62
  describe("when count is NOT passed in", function() {
@@ -57,6 +57,16 @@ describe("Pluralization", function(){
57
57
  expect(I18n.p(0, "inbox")).toEqual("");
58
58
  });
59
59
 
60
+ it("returns missing message on null values", function(){
61
+ I18n.translations["en"]["sent"]["zero"] = null;
62
+ I18n.translations["en"]["sent"]["one"] = null;
63
+ I18n.translations["en"]["sent"]["other"] = null;
64
+
65
+ expect(I18n.p(0, "sent")).toEqual('[missing "en.sent.zero" translation]');
66
+ expect(I18n.p(1, "sent")).toEqual('[missing "en.sent.one" translation]');
67
+ expect(I18n.p(5, "sent")).toEqual('[missing "en.sent.other" translation]');
68
+ });
69
+
60
70
  it("pluralizes using custom rules", function() {
61
71
  I18n.locale = "custom";
62
72
 
@@ -103,4 +113,99 @@ describe("Pluralization", function(){
103
113
  expect(I18n.p(1, "inbox", options)).toEqual("You have 1 message");
104
114
  expect(I18n.p(5, "inbox", options)).toEqual("You have 5 messages");
105
115
  });
116
+
117
+ it("fallback to default locale when I18n.fallbacks is enabled", function() {
118
+ I18n.locale = "pt-BR";
119
+ I18n.fallbacks = true;
120
+ I18n.translations["pt-BR"].inbox= {
121
+ one: null
122
+ , other: null
123
+ , zero: null
124
+ };
125
+ expect(I18n.p(0, "inbox", { count: 0 })).toEqual("You have no messages");
126
+ expect(I18n.p(1, "inbox", { count: 1 })).toEqual("You have 1 message");
127
+ expect(I18n.p(5, "inbox", { count: 5 })).toEqual("You have 5 messages");
128
+ });
129
+
130
+ it("fallback to default locale when I18n.fallbacks is enabled", function() {
131
+ I18n.locale = "pt-BR";
132
+ I18n.fallbacks = true;
133
+ I18n.translations["pt-BR"].inbox= {
134
+ one: "Você tem uma mensagem"
135
+ , other: null
136
+ , zero: "Você não tem nenhuma mensagem"
137
+ };
138
+ expect(I18n.p(0, "inbox", { count: 0 })).toEqual("Você não tem nenhuma mensagem");
139
+ expect(I18n.p(1, "inbox", { count: 1 })).toEqual("Você tem uma mensagem");
140
+ expect(I18n.p(5, "inbox", { count: 5 })).toEqual('You have 5 messages');
141
+ });
142
+
143
+ it("fallback to 'other' scope", function() {
144
+ I18n.locale = "pt-BR";
145
+ I18n.fallbacks = true;
146
+ I18n.translations["pt-BR"].inbox= {
147
+ one: "Você tem uma mensagem"
148
+ , other: "Você tem {{count}} mensagens"
149
+ , zero: null
150
+ }
151
+ expect(I18n.p(0, "inbox", { count: 0 })).toEqual("Você tem 0 mensagens");
152
+ expect(I18n.p(1, "inbox", { count: 1 })).toEqual("Você tem uma mensagem");
153
+ expect(I18n.p(5, "inbox", { count: 5 })).toEqual("Você tem 5 mensagens");
154
+ });
155
+
156
+ it("fallback to defaulValue when defaultValue is string", function() {
157
+ I18n.locale = "pt-BR";
158
+ I18n.fallbacks = true;
159
+ I18n.translations["en"]["inbox"]["zero"] = null;
160
+ I18n.translations["en"]["inbox"]["one"] = null;
161
+ I18n.translations["en"]["inbox"]["other"] = null;
162
+ I18n.translations["pt-BR"].inbox= {
163
+ one: "Você tem uma mensagem"
164
+ , other: null
165
+ , zero: null
166
+ }
167
+ options = {
168
+ defaultValue: "default message"
169
+ };
170
+ expect(I18n.p(0, "inbox", options)).toEqual("default message");
171
+ expect(I18n.p(1, "inbox", options)).toEqual("Você tem uma mensagem");
172
+ expect(I18n.p(5, "inbox", options)).toEqual("default message");
173
+ });
174
+
175
+ it("fallback to defaulValue when defaultValue is an object", function() {
176
+ I18n.locale = "pt-BR";
177
+ I18n.fallbacks = true;
178
+ I18n.translations["en"]["inbox"]["zero"] = null;
179
+ I18n.translations["en"]["inbox"]["one"] = null;
180
+ I18n.translations["en"]["inbox"]["other"] = null;
181
+ I18n.translations["pt-BR"].inbox= {
182
+ one: "Você tem uma mensagem"
183
+ , other: null
184
+ , zero: null
185
+ }
186
+ options = {
187
+ defaultValue: {
188
+ zero: "default message for no message"
189
+ , one: "default message for 1 message"
190
+ , other: "default message for {{count}} messages"
191
+ }
192
+ };
193
+ expect(I18n.p(0, "inbox", options)).toEqual("default message for no message");
194
+ expect(I18n.p(1, "inbox", options)).toEqual("Você tem uma mensagem");
195
+ expect(I18n.p(5, "inbox", options)).toEqual("default message for 5 messages");
196
+ });
197
+
198
+ it("fallback to default locale when I18n.fallbacks is enabled and no translations in sub scope", function() {
199
+ I18n.locale = "pt-BR";
200
+ I18n.fallbacks = true;
201
+ I18n.translations["en"]["mailbox"] = {
202
+ inbox: I18n.translations["en"].inbox
203
+ }
204
+
205
+ expect(I18n.translations["pt-BR"]["mailbox"]).toEqual(undefined);
206
+ expect(I18n.p(0, "mailbox.inbox", { count: 0 })).toEqual("You have no messages");
207
+ expect(I18n.p(1, "mailbox.inbox", { count: 1 })).toEqual("You have 1 message");
208
+ expect(I18n.p(5, "mailbox.inbox", { count: 5 })).toEqual("You have 5 messages");
209
+ });
210
+
106
211
  });
@@ -30,6 +30,12 @@ var DEBUG = false;
30
30
  , zero: "You have no messages"
31
31
  }
32
32
 
33
+ , sent: {
34
+ one: null
35
+ , other: null
36
+ , zero: null
37
+ }
38
+
33
39
  , unread: {
34
40
  one: "You have 1 new message ({{unread}} unread)"
35
41
  , other: "You have {{count}} new messages ({{unread}} unread)"
@@ -42,7 +42,7 @@ describe I18n::JS::FallbackLocales do
42
42
 
43
43
  context "when given a invalid locale as fallbacks" do
44
44
  let(:fallbacks) { :invalid_locale }
45
- it { expect(fetching_locales).to raise_error(ArgumentError) }
45
+ it { should eq([:invalid_locale]) }
46
46
  end
47
47
 
48
48
  context "when given a invalid type as fallbacks" do
@@ -50,16 +50,6 @@ describe I18n::JS::FallbackLocales do
50
50
  it { expect(fetching_locales).to raise_error(ArgumentError) }
51
51
  end
52
52
 
53
- context "when given an invalid Array as fallbacks" do
54
- let(:fallbacks) { [:de, :en, :invalid_locale] }
55
- it { expect(fetching_locales).to raise_error(ArgumentError) }
56
- end
57
-
58
- context "when given a invalid Hash as fallbacks" do
59
- let(:fallbacks) do { :fr => [:de, :en, :invalid_locale] } end
60
- it { expect(fetching_locales).to raise_error(ArgumentError) }
61
- end
62
-
63
53
  # I18n::Backend::Fallbacks
64
54
  context "when I18n::Backend::Fallbacks is used" do
65
55
  let(:backend_with_fallbacks) { backend_class_with_fallbacks.new }
@@ -405,7 +405,7 @@ EOS
405
405
  it "executes erb in config file" do
406
406
  set_config "erb.yml"
407
407
 
408
- config_entry = I18n::JS.config["translations"].first
408
+ config_entry = I18n::JS.config[:translations].first
409
409
  config_entry["only"].should eq("*.date.formats")
410
410
  end
411
411
  end
data/spec/spec_helper.rb CHANGED
@@ -1,14 +1,16 @@
1
1
  require "i18n"
2
2
  require "json"
3
3
 
4
- require "active_support/all"
5
4
  require "i18n/js"
6
5
 
7
6
  module Helpers
8
7
  # Set the configuration as the current one
9
8
  def set_config(path)
10
9
  config_file_path = File.dirname(__FILE__) + "/fixtures/#{path}"
11
- I18n::JS.stub(:config? => true, :config_file_path => config_file_path)
10
+ allow(I18n::JS).to receive_messages(
11
+ :config? => true,
12
+ :config_file_path => config_file_path,
13
+ )
12
14
  end
13
15
 
14
16
  # Shortcut to I18n::JS.translations
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-js
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.rc14
4
+ version: 3.0.0.rc15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-29 00:00:00.000000000 Z
11
+ date: 2016-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -44,20 +44,6 @@ dependencies:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '2.0'
47
- - !ruby/object:Gem::Dependency
48
- name: activesupport
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: 3.2.22
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 3.2.22
61
47
  - !ruby/object:Gem::Dependency
62
48
  name: rspec
63
49
  requirement: !ruby/object:Gem::Requirement
@@ -127,6 +113,7 @@ files:
127
113
  - lib/i18n/js/engine.rb
128
114
  - lib/i18n/js/fallback_locales.rb
129
115
  - lib/i18n/js/middleware.rb
116
+ - lib/i18n/js/private/hash_with_symbol_keys.rb
130
117
  - lib/i18n/js/segment.rb
131
118
  - lib/i18n/js/utils.rb
132
119
  - lib/i18n/js/version.rb
@@ -208,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
208
195
  version: 1.3.1
209
196
  requirements: []
210
197
  rubyforge_project:
211
- rubygems_version: 2.6.6
198
+ rubygems_version: 2.6.7
212
199
  signing_key:
213
200
  specification_version: 4
214
201
  summary: It's a small library to provide the Rails I18n translations on the Javascript.