i18n-js 3.2.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -6
- data/Appraisals +16 -0
- data/CHANGELOG.md +20 -1
- data/app/assets/javascripts/i18n.js +16 -18
- data/gemfiles/i18n_0_6.gemfile +7 -0
- data/gemfiles/i18n_0_7.gemfile +7 -0
- data/gemfiles/i18n_1_2.gemfile +7 -0
- data/gemfiles/i18n_1_3.gemfile +7 -0
- data/gemfiles/i18n_1_4.gemfile +7 -0
- data/gemfiles/i18n_1_5.gemfile +7 -0
- data/i18n-js.gemspec +1 -3
- data/lib/i18n/js/formatters/base.rb +23 -0
- data/lib/i18n/js/formatters/js.rb +31 -0
- data/lib/i18n/js/formatters/json.rb +13 -0
- data/lib/i18n/js/segment.rb +15 -39
- data/lib/i18n/js/utils.rb +16 -3
- data/lib/i18n/js/version.rb +1 -1
- data/package.json +1 -1
- data/spec/fixtures/json_only.yml +10 -0
- data/spec/fixtures/locales.yml +7 -0
- data/spec/fixtures/merge_plurals.yml +6 -0
- data/spec/js/translations.js +0 -1
- data/spec/ruby/i18n/js/segment_spec.rb +50 -20
- data/spec/ruby/i18n/js/utils_spec.rb +14 -14
- data/spec/ruby/i18n/js_spec.rb +94 -74
- data/spec/spec_helper.rb +2 -2
- metadata +16 -13
- data/lib/i18n/js/errors.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ceb49e2e527b6abd26c72eb57d2489197ed2d3991b24bc79acef35869a171232
|
4
|
+
data.tar.gz: 40f6a0b8c6c9d312db6a859123f22f7a8a46e7ef92f495b7ea024d6885e88b85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 030147ab7bb566fcadadb31090480fbcf233850ec9ea0468e8b4d7d984d8a5a77c7e9a7366e8babb40139313c2306774d10e8812869c0a6c083d66b9a4312224
|
7
|
+
data.tar.gz: 388552233bb2a66c6c899d28daca4a9ca49aa115b19cc765ba2cbe00308f9c4b3840fb92c0ca4fc71a78e5a2bed5a780e8cc7431348a7d53f5b11dc806d741ed
|
data/.travis.yml
CHANGED
@@ -8,23 +8,25 @@ cache:
|
|
8
8
|
directories:
|
9
9
|
- node_modules
|
10
10
|
rvm:
|
11
|
-
- 2.1
|
12
|
-
- 2.2
|
13
11
|
- 2.3
|
14
12
|
- 2.4
|
15
13
|
- 2.5
|
14
|
+
- 2.6
|
16
15
|
- ruby-head
|
17
16
|
before_install:
|
18
|
-
#
|
17
|
+
# Needed to test JS
|
19
18
|
- yarn install
|
20
|
-
# Bundler 1.16.1 and rubygems 2.7.3 got issue
|
21
|
-
# https://github.com/travis-ci/travis-ci/issues/8978#issuecomment-354036443
|
22
|
-
- gem update --system
|
23
19
|
gemfile:
|
20
|
+
- gemfiles/i18n_0_6.gemfile
|
21
|
+
- gemfiles/i18n_0_7.gemfile
|
24
22
|
- gemfiles/i18n_0_8.gemfile
|
25
23
|
- gemfiles/i18n_0_9.gemfile
|
26
24
|
- gemfiles/i18n_1_0.gemfile
|
27
25
|
- gemfiles/i18n_1_1.gemfile
|
26
|
+
- gemfiles/i18n_1_2.gemfile
|
27
|
+
- gemfiles/i18n_1_3.gemfile
|
28
|
+
- gemfiles/i18n_1_4.gemfile
|
29
|
+
- gemfiles/i18n_1_5.gemfile
|
28
30
|
matrix:
|
29
31
|
fast_finish: true
|
30
32
|
allow_failures:
|
data/Appraisals
CHANGED
@@ -14,3 +14,19 @@ end
|
|
14
14
|
appraise "i18n_1_1" do
|
15
15
|
gem "i18n", "~> 1.1.0"
|
16
16
|
end
|
17
|
+
|
18
|
+
appraise "i18n_1_2" do
|
19
|
+
gem "i18n", "~> 1.2.0"
|
20
|
+
end
|
21
|
+
|
22
|
+
appraise "i18n_1_3" do
|
23
|
+
gem "i18n", "~> 1.3.0"
|
24
|
+
end
|
25
|
+
|
26
|
+
appraise "i18n_1_4" do
|
27
|
+
gem "i18n", "~> 1.4.0"
|
28
|
+
end
|
29
|
+
|
30
|
+
appraise "i18n_1_5" do
|
31
|
+
gem "i18n", "~> 1.5.1"
|
32
|
+
end
|
data/CHANGELOG.md
CHANGED
@@ -18,6 +18,24 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
18
18
|
- Nothing
|
19
19
|
|
20
20
|
|
21
|
+
## [3.2.1] - 2019-01-22
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
|
25
|
+
- [Ruby] `json_only` option should allow multiple locales.
|
26
|
+
(PR: https://github.com/fnando/i18n-js/pull/531)
|
27
|
+
- [Ruby] Simplified and cleaned code related to JS/JSON formatting.
|
28
|
+
(PR: https://github.com/fnando/i18n-js/pull/531)
|
29
|
+
- [JS] Use strict value comparison
|
30
|
+
|
31
|
+
### Fixed
|
32
|
+
|
33
|
+
- [Ruby] Relax `i18n` version requirement back to `>= 0.6.6`
|
34
|
+
(PR: https://github.com/fnando/i18n-js/pull/530)
|
35
|
+
- [Ruby] Fix merging of plural keys across locales.
|
36
|
+
(PR: https://github.com/fnando/i18n-js/pull/472)
|
37
|
+
|
38
|
+
|
21
39
|
## [3.2.0] - 2018-11-16
|
22
40
|
|
23
41
|
### Added
|
@@ -359,7 +377,8 @@ And today is not April Fools' Day
|
|
359
377
|
|
360
378
|
|
361
379
|
|
362
|
-
[Unreleased]: https://github.com/fnando/i18n-js/compare/v3.2.
|
380
|
+
[Unreleased]: https://github.com/fnando/i18n-js/compare/v3.2.1...HEAD
|
381
|
+
[3.2.1]: https://github.com/fnando/i18n-js/compare/v3.2.0...v3.2.1
|
363
382
|
[3.2.0]: https://github.com/fnando/i18n-js/compare/v3.1.0...v3.2.0
|
364
383
|
[3.1.0]: https://github.com/fnando/i18n-js/compare/v3.0.11...v3.1.0
|
365
384
|
[3.0.11]: https://github.com/fnando/i18n-js/compare/v3.0.10...v3.0.11
|
@@ -107,7 +107,7 @@
|
|
107
107
|
// Shift back
|
108
108
|
value = value.toString().split('e');
|
109
109
|
return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
|
110
|
-
}
|
110
|
+
};
|
111
111
|
|
112
112
|
var lazyEvaluate = function(message, scope) {
|
113
113
|
if (isFunction(message)) {
|
@@ -115,7 +115,7 @@
|
|
115
115
|
} else {
|
116
116
|
return message;
|
117
117
|
}
|
118
|
-
}
|
118
|
+
};
|
119
119
|
|
120
120
|
var merge = function (dest, obj) {
|
121
121
|
var key, value;
|
@@ -389,7 +389,7 @@
|
|
389
389
|
// This is used internally by some functions and should not be used as an
|
390
390
|
// public API.
|
391
391
|
I18n.lookup = function(scope, options) {
|
392
|
-
options = options || {}
|
392
|
+
options = options || {};
|
393
393
|
|
394
394
|
var locales = this.locales.get(options.locale).slice()
|
395
395
|
, locale
|
@@ -448,7 +448,7 @@
|
|
448
448
|
|
449
449
|
// Lookup dedicated to pluralization
|
450
450
|
I18n.pluralizationLookup = function(count, scope, options) {
|
451
|
-
options = options || {}
|
451
|
+
options = options || {};
|
452
452
|
var locales = this.locales.get(options.locale).slice()
|
453
453
|
, locale
|
454
454
|
, scopes
|
@@ -471,16 +471,16 @@
|
|
471
471
|
if (!isObject(translations)) {
|
472
472
|
break;
|
473
473
|
}
|
474
|
-
if (scopes.length
|
474
|
+
if (scopes.length === 0) {
|
475
475
|
message = this.pluralizationLookupWithoutFallback(count, locale, translations);
|
476
476
|
}
|
477
477
|
}
|
478
|
-
if (message
|
478
|
+
if (typeof message !== "undefined" && message !== null) {
|
479
479
|
break;
|
480
480
|
}
|
481
481
|
}
|
482
482
|
|
483
|
-
if (message
|
483
|
+
if (typeof message === "undefined" || message === null) {
|
484
484
|
if (isSet(options.defaultValue)) {
|
485
485
|
if (isObject(options.defaultValue)) {
|
486
486
|
message = this.pluralizationLookupWithoutFallback(count, options.locale, options.defaultValue);
|
@@ -570,7 +570,7 @@
|
|
570
570
|
|
571
571
|
// Translate the given scope with the provided options.
|
572
572
|
I18n.translate = function(scope, options) {
|
573
|
-
options = options || {}
|
573
|
+
options = options || {};
|
574
574
|
|
575
575
|
var translationOptions = this.createTranslationOptions(scope, options);
|
576
576
|
|
@@ -619,7 +619,7 @@
|
|
619
619
|
return message;
|
620
620
|
}
|
621
621
|
|
622
|
-
options = options || {}
|
622
|
+
options = options || {};
|
623
623
|
var matches = message.match(this.placeholder)
|
624
624
|
, placeholder
|
625
625
|
, value
|
@@ -631,8 +631,6 @@
|
|
631
631
|
return message;
|
632
632
|
}
|
633
633
|
|
634
|
-
var value;
|
635
|
-
|
636
634
|
while (matches.length) {
|
637
635
|
placeholder = matches.shift();
|
638
636
|
name = placeholder.replace(this.placeholder, "$1");
|
@@ -645,7 +643,7 @@
|
|
645
643
|
value = this.missingPlaceholder(placeholder, message, options);
|
646
644
|
}
|
647
645
|
|
648
|
-
regex = new RegExp(placeholder.replace(
|
646
|
+
regex = new RegExp(placeholder.replace(/{/gm, "\\{").replace(/}/gm, "\\}"));
|
649
647
|
message = message.replace(regex, value);
|
650
648
|
}
|
651
649
|
|
@@ -657,14 +655,14 @@
|
|
657
655
|
// which will be retrieved from `options`.
|
658
656
|
I18n.pluralize = function(count, scope, options) {
|
659
657
|
options = this.prepareOptions({count: String(count)}, options)
|
660
|
-
var pluralizer,
|
658
|
+
var pluralizer, result;
|
661
659
|
|
662
660
|
result = this.pluralizationLookup(count, scope, options);
|
663
|
-
if (result.translations
|
661
|
+
if (typeof result.translations === "undefined" || result.translations == null) {
|
664
662
|
return this.missingTranslation(scope, options);
|
665
663
|
}
|
666
664
|
|
667
|
-
if (result.message
|
665
|
+
if (typeof result.message !== "undefined" && result.message != null) {
|
668
666
|
return this.interpolate(result.message, options);
|
669
667
|
}
|
670
668
|
else {
|
@@ -676,7 +674,7 @@
|
|
676
674
|
// Return a missing translation message for the given parameters.
|
677
675
|
I18n.missingTranslation = function(scope, options) {
|
678
676
|
//guess intended string
|
679
|
-
if(this.missingBehaviour
|
677
|
+
if(this.missingBehaviour === 'guess'){
|
680
678
|
//get only the last portion of the scope
|
681
679
|
var s = scope.split('.').slice(-1)[0];
|
682
680
|
//replace underscore with space && camelcase with space and lowercase letter
|
@@ -838,7 +836,7 @@
|
|
838
836
|
// we have a date, so just return it.
|
839
837
|
if (typeof(date) == "object") {
|
840
838
|
return date;
|
841
|
-
}
|
839
|
+
}
|
842
840
|
|
843
841
|
matches = date.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2})([\.,]\d{1,3})?)?(Z|\+00:?00)?/);
|
844
842
|
|
@@ -1036,7 +1034,7 @@
|
|
1036
1034
|
};
|
1037
1035
|
|
1038
1036
|
I18n.getFullScope = function(scope, options) {
|
1039
|
-
options = options || {}
|
1037
|
+
options = options || {};
|
1040
1038
|
|
1041
1039
|
// Deal with the scope as an array.
|
1042
1040
|
if (isArray(scope)) {
|
data/i18n-js.gemspec
CHANGED
@@ -18,9 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
|
22
|
-
# https://nvd.nist.gov/vuln/detail/CVE-2014-10077
|
23
|
-
s.add_dependency "i18n", ">= 0.8.0", "< 2"
|
21
|
+
s.add_dependency "i18n", ">= 0.6.6"
|
24
22
|
|
25
23
|
s.add_development_dependency "appraisal", "~> 2.0"
|
26
24
|
s.add_development_dependency "rspec", "~> 3.0"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module I18n
|
2
|
+
module JS
|
3
|
+
module Formatters
|
4
|
+
class Base
|
5
|
+
def initialize(js_extend: false, namespace: nil, pretty_print: false)
|
6
|
+
@js_extend = js_extend
|
7
|
+
@namespace = namespace
|
8
|
+
@pretty_print = pretty_print
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def format_json(translations)
|
14
|
+
if @pretty_print
|
15
|
+
::JSON.pretty_generate(translations)
|
16
|
+
else
|
17
|
+
translations.to_json
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "i18n/js/formatters/base"
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module JS
|
5
|
+
module Formatters
|
6
|
+
class JS < Base
|
7
|
+
def format(translations)
|
8
|
+
contents = header
|
9
|
+
translations.each do |locale, translations_for_locale|
|
10
|
+
contents << line(locale, format_json(translations_for_locale))
|
11
|
+
end
|
12
|
+
contents
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def header
|
18
|
+
%(#{@namespace}.translations || (#{@namespace}.translations = {});\n)
|
19
|
+
end
|
20
|
+
|
21
|
+
def line(locale, translations)
|
22
|
+
if @js_extend
|
23
|
+
%(#{@namespace}.translations["#{locale}"] = I18n.extend((#{@namespace}.translations["#{locale}"] || {}), #{translations});\n)
|
24
|
+
else
|
25
|
+
%(#{@namespace}.translations["#{locale}"] = #{translations};\n)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/i18n/js/segment.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "i18n/js/private/hash_with_symbol_keys"
|
2
|
-
require "i18n/js/
|
2
|
+
require "i18n/js/formatters/js"
|
3
|
+
require "i18n/js/formatters/json"
|
3
4
|
|
4
5
|
module I18n
|
5
6
|
module JS
|
@@ -34,21 +35,20 @@ module I18n
|
|
34
35
|
write_file(file_for_locale(locale), @translations.slice(locale))
|
35
36
|
end
|
36
37
|
else
|
37
|
-
if @json_only
|
38
|
-
raise I18n::JS::JsonOnlyLocaleRequiredError
|
39
|
-
end
|
40
38
|
write_file
|
41
39
|
end
|
42
40
|
end
|
43
41
|
|
44
42
|
protected
|
45
43
|
|
44
|
+
def file_for_locale(locale)
|
45
|
+
@file.gsub(LOCALE_INTERPOLATOR, locale.to_s)
|
46
|
+
end
|
47
|
+
|
46
48
|
def write_file(_file = @file, _translations = @translations)
|
47
49
|
FileUtils.mkdir_p File.dirname(_file)
|
48
|
-
|
49
|
-
|
50
|
-
contents << js_translations(locale, translations_for_locale)
|
51
|
-
end
|
50
|
+
_translations = Utils.deep_key_sort(_translations) if @sort_translation_keys
|
51
|
+
contents = formatter.format(_translations)
|
52
52
|
|
53
53
|
return if File.exist?(_file) && File.read(_file) == contents
|
54
54
|
|
@@ -57,42 +57,18 @@ module I18n
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
60
|
+
def formatter
|
61
61
|
if @json_only
|
62
|
-
|
62
|
+
Formatters::JSON.new(**formatter_options)
|
63
63
|
else
|
64
|
-
|
64
|
+
Formatters::JS.new(**formatter_options)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
def js_translations_line(locale, translations)
|
75
|
-
if @json_only
|
76
|
-
%({"#{locale}":#{translations}})
|
77
|
-
elsif @js_extend
|
78
|
-
%(#{@namespace}.translations["#{locale}"] = I18n.extend((#{@namespace}.translations["#{locale}"] || {}), #{translations});\n)
|
79
|
-
else
|
80
|
-
%(#{@namespace}.translations["#{locale}"] = #{translations};\n)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# Outputs pretty or ugly JSON depending on :pretty_print option
|
85
|
-
def print_json(translations)
|
86
|
-
if @pretty_print
|
87
|
-
JSON.pretty_generate(translations)
|
88
|
-
else
|
89
|
-
translations.to_json
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# interpolates filename
|
94
|
-
def file_for_locale(locale)
|
95
|
-
@file.gsub(LOCALE_INTERPOLATOR, locale.to_s)
|
68
|
+
def formatter_options
|
69
|
+
{ js_extend: @js_extend,
|
70
|
+
namespace: @namespace,
|
71
|
+
pretty_print: @pretty_print }
|
96
72
|
end
|
97
73
|
end
|
98
74
|
end
|
data/lib/i18n/js/utils.rb
CHANGED
@@ -1,10 +1,23 @@
|
|
1
1
|
module I18n
|
2
2
|
module JS
|
3
3
|
module Utils
|
4
|
-
|
5
|
-
|
4
|
+
PLURAL_KEYS = %i[zero one two few many other].freeze
|
5
|
+
|
6
|
+
# Based on deep_merge by Stefan Rusterholz, see <http://www.ruby-forum.com/topic/142809>.
|
7
|
+
# This method is used to handle I18n fallbacks. Given two equivalent path nodes in two locale trees:
|
8
|
+
# 1. If the node in the current locale appears to be an I18n pluralization (:one, :other, etc.),
|
9
|
+
# use the node as-is without merging. This prevents mixing locales with different pluralization schemes.
|
10
|
+
# 2. Else if both nodes are Hashes, combine (merge) the key-value pairs of the two nodes into one,
|
11
|
+
# prioritizing the current locale.
|
12
|
+
# 3. Else if either node is nil, use the other node.
|
6
13
|
MERGER = proc do |_key, v1, v2|
|
7
|
-
|
14
|
+
if Hash === v2 && (v2.keys - PLURAL_KEYS).empty?
|
15
|
+
v2
|
16
|
+
elsif Hash === v1 && Hash === v2
|
17
|
+
v1.merge(v2, &MERGER)
|
18
|
+
else
|
19
|
+
v2.nil? ? v1 : v2
|
20
|
+
end
|
8
21
|
end
|
9
22
|
|
10
23
|
HASH_NIL_VALUE_CLEANER_PROC = proc do |k, v|
|
data/lib/i18n/js/version.rb
CHANGED
data/package.json
CHANGED
data/spec/fixtures/json_only.yml
CHANGED
@@ -6,3 +6,13 @@ translations:
|
|
6
6
|
only:
|
7
7
|
- "*.date.formats.*"
|
8
8
|
- "*.number.currency.*"
|
9
|
+
|
10
|
+
- file: "tmp/i18n-js/json_only_multi.js"
|
11
|
+
only:
|
12
|
+
- "*.date.formats.*"
|
13
|
+
- "*.number.currency.*"
|
14
|
+
|
15
|
+
- file: "tmp/i18n-js/json_only_multi_pretty.js"
|
16
|
+
only:
|
17
|
+
- "*.date.formats.*"
|
18
|
+
- "*.number.currency.*"
|
data/spec/fixtures/locales.yml
CHANGED
@@ -37,6 +37,9 @@ en:
|
|
37
37
|
foo: "Foo"
|
38
38
|
fallback_test: "Success"
|
39
39
|
null_test: "fallback for null"
|
40
|
+
merge_plurals:
|
41
|
+
one: Apple
|
42
|
+
other: Apples
|
40
43
|
|
41
44
|
de:
|
42
45
|
fallback_test: "Erfolg"
|
@@ -81,6 +84,10 @@ fr:
|
|
81
84
|
note: "plus de détails"
|
82
85
|
edit:
|
83
86
|
title: "Editer"
|
87
|
+
merge_plurals:
|
88
|
+
zero: Pomme
|
89
|
+
one: Pomme
|
90
|
+
other: Pommes
|
84
91
|
|
85
92
|
ja:
|
86
93
|
admin:
|
data/spec/js/translations.js
CHANGED
@@ -19,22 +19,22 @@ describe I18n::JS::Segment do
|
|
19
19
|
describe ".new" do
|
20
20
|
|
21
21
|
it "should persist the file path variable" do
|
22
|
-
subject.file.
|
22
|
+
expect(subject.file).to eql("tmp/i18n-js/segment.js")
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should persist the translations variable" do
|
26
|
-
subject.translations.
|
26
|
+
expect(subject.translations).to eql(translations)
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should persist the namespace variable" do
|
30
|
-
subject.namespace.
|
30
|
+
expect(subject.namespace).to eql("MyNamespace")
|
31
31
|
end
|
32
32
|
|
33
33
|
context "when namespace is nil" do
|
34
34
|
let(:namespace){ nil }
|
35
35
|
|
36
36
|
it "should default namespace to `I18n`" do
|
37
|
-
subject.namespace.
|
37
|
+
expect(subject.namespace).to eql("I18n")
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -42,13 +42,13 @@ describe I18n::JS::Segment do
|
|
42
42
|
subject { I18n::JS::Segment.new(file, translations) }
|
43
43
|
|
44
44
|
it "should default namespace to `I18n`" do
|
45
|
-
subject.namespace.
|
45
|
+
expect(subject.namespace).to eql("I18n")
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
context "when pretty_print is nil" do
|
50
50
|
it "should set pretty_print to false" do
|
51
|
-
subject.pretty_print.
|
51
|
+
expect(subject.pretty_print).to be false
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -56,7 +56,7 @@ describe I18n::JS::Segment do
|
|
56
56
|
let(:pretty_print){ 1 }
|
57
57
|
|
58
58
|
it "should set pretty_print to true" do
|
59
|
-
subject.pretty_print.
|
59
|
+
expect(subject.pretty_print).to be true
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -64,19 +64,20 @@ describe I18n::JS::Segment do
|
|
64
64
|
describe "#saving!" do
|
65
65
|
before { allow(I18n::JS).to receive(:export_i18n_js_dir_path).and_return(temp_path) }
|
66
66
|
|
67
|
-
context "when json_only is true" do
|
67
|
+
context "when json_only is true with locale" do
|
68
68
|
let(:file){ "tmp/i18n-js/%{locale}.js" }
|
69
69
|
let(:json_only){ true }
|
70
|
-
|
70
|
+
|
71
|
+
it 'should output JSON files per locale' do
|
71
72
|
subject.save!
|
72
73
|
file_should_exist "en.js"
|
73
74
|
file_should_exist "fr.js"
|
74
75
|
|
75
|
-
File.
|
76
|
+
expect(File.read(File.join(temp_path, "en.js"))).to eql(
|
76
77
|
%Q({"en":{"test":"Test"}})
|
77
78
|
)
|
78
79
|
|
79
|
-
File.
|
80
|
+
expect(File.read(File.join(temp_path, "fr.js"))).to eql(
|
80
81
|
%Q({"fr":{"test":"Test2"}})
|
81
82
|
)
|
82
83
|
end
|
@@ -85,8 +86,37 @@ describe I18n::JS::Segment do
|
|
85
86
|
context "when json_only is true without locale" do
|
86
87
|
let(:file){ "tmp/i18n-js/segment.js" }
|
87
88
|
let(:json_only){ true }
|
88
|
-
|
89
|
-
|
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
|
90
120
|
end
|
91
121
|
end
|
92
122
|
end
|
@@ -99,7 +129,7 @@ describe I18n::JS::Segment do
|
|
99
129
|
it "should write the file" do
|
100
130
|
file_should_exist "segment.js"
|
101
131
|
|
102
|
-
File.open(File.join(temp_path, "segment.js")){|f| f.read}.
|
132
|
+
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
103
133
|
MyNamespace.translations || (MyNamespace.translations = {});
|
104
134
|
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"test":"Test"});
|
105
135
|
MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), {"test":"Test2"});
|
@@ -114,12 +144,12 @@ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] ||
|
|
114
144
|
file_should_exist "en.js"
|
115
145
|
file_should_exist "fr.js"
|
116
146
|
|
117
|
-
File.open(File.join(temp_path, "en.js")){|f| f.read}.
|
147
|
+
expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
|
118
148
|
MyNamespace.translations || (MyNamespace.translations = {});
|
119
149
|
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"test":"Test"});
|
120
150
|
EOF
|
121
151
|
|
122
|
-
File.open(File.join(temp_path, "fr.js")){|f| f.read}.
|
152
|
+
expect(File.open(File.join(temp_path, "fr.js")){|f| f.read}).to eql <<-EOF
|
123
153
|
MyNamespace.translations || (MyNamespace.translations = {});
|
124
154
|
MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), {"test":"Test2"});
|
125
155
|
EOF
|
@@ -134,7 +164,7 @@ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] ||
|
|
134
164
|
it 'should output the keys as sorted' do
|
135
165
|
file_should_exist "segment.js"
|
136
166
|
|
137
|
-
File.open(File.join(temp_path, "segment.js")){|f| f.read}.
|
167
|
+
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
138
168
|
MyNamespace.translations || (MyNamespace.translations = {});
|
139
169
|
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"a":"Test","b":"Test"});
|
140
170
|
EOF
|
@@ -149,7 +179,7 @@ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] ||
|
|
149
179
|
it 'should output the keys as sorted' do
|
150
180
|
file_should_exist "segment.js"
|
151
181
|
|
152
|
-
File.open(File.join(temp_path, "segment.js")){|f| f.read}.
|
182
|
+
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
153
183
|
MyNamespace.translations || (MyNamespace.translations = {});
|
154
184
|
MyNamespace.translations["en"] = {"a":"Test","b":"Test"};
|
155
185
|
EOF
|
@@ -164,7 +194,7 @@ MyNamespace.translations["en"] = {"a":"Test","b":"Test"};
|
|
164
194
|
it 'should output the keys as sorted' do
|
165
195
|
file_should_exist "segment.js"
|
166
196
|
|
167
|
-
File.open(File.join(temp_path, "segment.js")){|f| f.read}.
|
197
|
+
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
168
198
|
MyNamespace.translations || (MyNamespace.translations = {});
|
169
199
|
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"a":"Test","b":"Test"});
|
170
200
|
EOF
|
@@ -179,7 +209,7 @@ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] ||
|
|
179
209
|
it 'should output the keys as sorted' do
|
180
210
|
file_should_exist "segment.js"
|
181
211
|
|
182
|
-
File.open(File.join(temp_path, "segment.js")){|f| f.read}.
|
212
|
+
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
183
213
|
MyNamespace.translations || (MyNamespace.translations = {});
|
184
214
|
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"b":"Test","a":"Test"});
|
185
215
|
EOF
|
@@ -28,14 +28,14 @@ describe I18n::JS::Utils do
|
|
28
28
|
target = {:a => {:b => 1}}
|
29
29
|
result = described_class.deep_merge(target, {:a => {:c => 2}})
|
30
30
|
|
31
|
-
result[:a].
|
31
|
+
expect(result[:a]).to eql({:b => 1, :c => 2})
|
32
32
|
end
|
33
33
|
|
34
34
|
it "performs a banged deep merge" do
|
35
35
|
target = {:a => {:b => 1}}
|
36
36
|
described_class.deep_merge!(target, {:a => {:c => 2}})
|
37
37
|
|
38
|
-
target[:a].
|
38
|
+
expect(target[:a]).to eql({:b => 1, :c => 2})
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -45,7 +45,7 @@ describe I18n::JS::Utils do
|
|
45
45
|
|
46
46
|
result = described_class.deep_reject(hash) { |k, v| k == :b }
|
47
47
|
|
48
|
-
result.
|
48
|
+
expect(result).to eql({:a => {}})
|
49
49
|
end
|
50
50
|
|
51
51
|
it "performs a deep keys rejection prunning the whole tree if necessary" do
|
@@ -53,7 +53,7 @@ describe I18n::JS::Utils do
|
|
53
53
|
|
54
54
|
result = described_class.deep_reject(hash) { |k, v| k == :b }
|
55
55
|
|
56
|
-
result.
|
56
|
+
expect(result).to eql({:a => {}})
|
57
57
|
end
|
58
58
|
|
59
59
|
|
@@ -62,8 +62,8 @@ describe I18n::JS::Utils do
|
|
62
62
|
|
63
63
|
result = described_class.deep_reject(hash) { |k, v| k == :b }
|
64
64
|
|
65
|
-
result.
|
66
|
-
hash.
|
65
|
+
expect(result).to eql({:a => {:c => 2}})
|
66
|
+
expect(hash).to eql({:a => {:b => 1, :c => 2}})
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -73,7 +73,7 @@ describe I18n::JS::Utils do
|
|
73
73
|
|
74
74
|
it "performs a deep keys sort without changing the original hash" do
|
75
75
|
should eql({:y => 3, :z => {:a => 2, :b => 1}})
|
76
|
-
unsorted_hash.
|
76
|
+
expect(unsorted_hash).to eql({:z => {:b => 1, :a => 2}, :y => 3})
|
77
77
|
end
|
78
78
|
|
79
79
|
# Idea from gem `rails_admin`
|
@@ -91,16 +91,16 @@ describe I18n::JS::Utils do
|
|
91
91
|
|
92
92
|
describe ".scopes_match?" do
|
93
93
|
it "performs a comparison of literal scopes" do
|
94
|
-
described_class.scopes_match?([:a, :b], [:a, :b, :c]).
|
95
|
-
described_class.scopes_match?([:a, :b, :c], [:a, :b, :c]).
|
96
|
-
described_class.scopes_match?([:a, :b, :c], [:a, :b, :d]).
|
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
97
|
end
|
98
98
|
|
99
99
|
it "performs a comparison of wildcard scopes" do
|
100
|
-
described_class.scopes_match?([:a, '*'], [:a, :b, :c]).
|
101
|
-
described_class.scopes_match?([:a, '*', :c], [:a, :b, :c]).
|
102
|
-
described_class.scopes_match?([:a, :b, :c], [:a, '*', :c]).
|
103
|
-
described_class.scopes_match?([:a, :b, :c], [:a, '*', '*']).
|
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
104
|
end
|
105
105
|
end
|
106
106
|
end
|
data/spec/ruby/i18n/js_spec.rb
CHANGED
@@ -30,15 +30,15 @@ describe I18n::JS do
|
|
30
30
|
|
31
31
|
it "exports messages using custom output path" do
|
32
32
|
set_config "custom_path.yml"
|
33
|
-
I18n::JS::Segment.
|
34
|
-
I18n::JS::Segment.
|
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
35
|
I18n::JS.export
|
36
36
|
end
|
37
37
|
|
38
38
|
it "sets default scope to * when not specified" do
|
39
39
|
set_config "no_scope.yml"
|
40
|
-
I18n::JS::Segment.
|
41
|
-
I18n::JS::Segment.
|
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
42
|
I18n::JS.export
|
43
43
|
end
|
44
44
|
|
@@ -91,7 +91,7 @@ EOS
|
|
91
91
|
set_config "multiple_conditions_per_locale.yml"
|
92
92
|
|
93
93
|
result = I18n::JS.translation_segments
|
94
|
-
result.map(&:file).
|
94
|
+
expect(result.map(&:file)).to eql(["tmp/i18n-js/bits.%{locale}.js"])
|
95
95
|
|
96
96
|
result.map(&:save!)
|
97
97
|
|
@@ -142,40 +142,40 @@ EOS
|
|
142
142
|
context "filters" do
|
143
143
|
it "filters translations using scope *.date.formats" do
|
144
144
|
result = I18n::JS.filter(translations, "*.date.formats")
|
145
|
-
result[:en][:date].keys.
|
146
|
-
result[:fr][:date].keys.
|
145
|
+
expect(result[:en][:date].keys).to eql([:formats])
|
146
|
+
expect(result[:fr][:date].keys).to eql([:formats])
|
147
147
|
end
|
148
148
|
|
149
149
|
it "filters translations using scope [*.date.formats, *.number.currency.format]" do
|
150
150
|
result = I18n::JS.scoped_translations(["*.date.formats", "*.number.currency.format"])
|
151
|
-
result[:en].keys.collect(&:to_s).sort.
|
152
|
-
result[:fr].keys.collect(&:to_s).sort.
|
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
153
|
end
|
154
154
|
|
155
155
|
it "filters translations using multi-star scope" do
|
156
156
|
result = I18n::JS.scoped_translations("*.*.formats")
|
157
157
|
|
158
|
-
result[:en].keys.collect(&:to_s).sort.
|
159
|
-
result[:fr].keys.collect(&:to_s).sort.
|
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
160
|
|
161
|
-
result[:en][:date].keys.
|
162
|
-
result[:en][:time].keys.
|
161
|
+
expect(result[:en][:date].keys).to eql([:formats])
|
162
|
+
expect(result[:en][:time].keys).to eql([:formats])
|
163
163
|
|
164
|
-
result[:fr][:date].keys.
|
165
|
-
result[:fr][:time].keys.
|
164
|
+
expect(result[:fr][:date].keys).to eql([:formats])
|
165
|
+
expect(result[:fr][:time].keys).to eql([:formats])
|
166
166
|
end
|
167
167
|
|
168
168
|
it "filters translations using alternated stars" do
|
169
169
|
result = I18n::JS.scoped_translations("*.admin.*.title")
|
170
170
|
|
171
|
-
result[:en][:admin].keys.collect(&:to_s).sort.
|
172
|
-
result[:fr][:admin].keys.collect(&:to_s).sort.
|
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
173
|
|
174
|
-
result[:en][:admin][:show][:title].
|
175
|
-
result[:fr][:admin][:show][:title].
|
174
|
+
expect(result[:en][:admin][:show][:title]).to eql("Show")
|
175
|
+
expect(result[:fr][:admin][:show][:title]).to eql("Visualiser")
|
176
176
|
|
177
|
-
result[:en][:admin][:edit][:title].
|
178
|
-
result[:fr][:admin][:edit][:title].
|
177
|
+
expect(result[:en][:admin][:edit][:title]).to eql("Edit")
|
178
|
+
expect(result[:fr][:admin][:edit][:title]).to eql("Editer")
|
179
179
|
end
|
180
180
|
|
181
181
|
describe ".filtered_translations" do
|
@@ -227,50 +227,50 @@ EOS
|
|
227
227
|
it "does not include scopes listed in the exceptions list" do
|
228
228
|
result = I18n::JS.scoped_translations("*", ['de.*', '*.admin', '*.*.currency'])
|
229
229
|
|
230
|
-
result[:de].
|
230
|
+
expect(result[:de]).to be_empty
|
231
231
|
|
232
|
-
result[:en][:admin].
|
233
|
-
result[:fr][:admin].
|
234
|
-
result[:ja][:admin].
|
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
235
|
|
236
|
-
result[:en][:number][:currency].
|
237
|
-
result[:fr][:number][:currency].
|
236
|
+
expect(result[:en][:number][:currency]).to be_nil
|
237
|
+
expect(result[:fr][:number][:currency]).to be_nil
|
238
238
|
end
|
239
239
|
|
240
240
|
it "does not include scopes listed in the exceptions list and respects the 'only' option" do
|
241
241
|
result = I18n::JS.scoped_translations("fr.*", ['*.admin', '*.*.currency'])
|
242
242
|
|
243
|
-
result[:en].
|
244
|
-
result[:de].
|
245
|
-
result[:ja].
|
243
|
+
expect(result[:en]).to be_nil
|
244
|
+
expect(result[:de]).to be_nil
|
245
|
+
expect(result[:ja]).to be_nil
|
246
246
|
|
247
|
-
result[:fr][:admin].
|
248
|
-
result[:fr][:number][:currency].
|
247
|
+
expect(result[:fr][:admin]).to be_nil
|
248
|
+
expect(result[:fr][:number][:currency]).to be_nil
|
249
249
|
|
250
|
-
result[:fr][:time][:am].
|
250
|
+
expect(result[:fr][:time][:am]).to be_a(String)
|
251
251
|
end
|
252
252
|
|
253
253
|
it "does exclude absolute scopes listed in the exceptions list" do
|
254
254
|
result = I18n::JS.scoped_translations("*", ['de', 'en.admin', 'fr.number.currency'])
|
255
255
|
|
256
|
-
result[:de].
|
256
|
+
expect(result[:de]).to be_nil
|
257
257
|
|
258
|
-
result[:en].
|
259
|
-
result[:en][:admin].
|
258
|
+
expect(result[:en]).to be_a(Hash)
|
259
|
+
expect(result[:en][:admin]).to be_nil
|
260
260
|
|
261
|
-
result[:fr][:number].
|
262
|
-
result[:fr][:number][:currency].
|
261
|
+
expect(result[:fr][:number]).to be_a(Hash)
|
262
|
+
expect(result[:fr][:number][:currency]).to be_nil
|
263
263
|
end
|
264
264
|
|
265
265
|
it "does not exclude non-absolute scopes listed in the exceptions list" do
|
266
266
|
result = I18n::JS.scoped_translations("*", ['admin', 'currency'])
|
267
267
|
|
268
|
-
result[:en][:admin].
|
269
|
-
result[:fr][:admin].
|
270
|
-
result[:ja][:admin].
|
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
271
|
|
272
|
-
result[:en][:number][:currency].
|
273
|
-
result[:fr][:number][:currency].
|
272
|
+
expect(result[:en][:number][:currency]).to be_a(Hash)
|
273
|
+
expect(result[:fr][:number][:currency]).to be_a(Hash)
|
274
274
|
end
|
275
275
|
end
|
276
276
|
|
@@ -281,30 +281,30 @@ EOS
|
|
281
281
|
|
282
282
|
it "exports without fallback when disabled" do
|
283
283
|
set_config "js_file_per_locale_without_fallbacks.yml"
|
284
|
-
subject[:fr][:fallback_test].
|
285
|
-
subject[:fr][:null_test].
|
286
|
-
subject[:de][:null_test].
|
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
287
|
end
|
288
288
|
|
289
289
|
it "exports with default_locale as fallback when enabled" do
|
290
290
|
set_config "js_file_per_locale_with_fallbacks_enabled.yml"
|
291
|
-
subject[:fr][:fallback_test].
|
292
|
-
subject[:fr][:null_test].
|
293
|
-
subject[:de][:null_test].
|
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
294
|
end
|
295
295
|
|
296
296
|
it "exports with default_locale as fallback when enabled with :default_locale" do
|
297
297
|
set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml"
|
298
|
-
subject[:fr][:fallback_test].
|
299
|
-
subject[:fr][:null_test].
|
300
|
-
subject[:de][:null_test].
|
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
301
|
end
|
302
302
|
|
303
303
|
it "exports with given locale as fallback" do
|
304
304
|
set_config "js_file_per_locale_with_fallbacks_as_locale.yml"
|
305
|
-
subject[:fr][:fallback_test].
|
306
|
-
subject[:fr][:null_test].
|
307
|
-
subject[:de][:null_test].
|
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
308
|
end
|
309
309
|
|
310
310
|
context "when given locale is in `I18n.available_locales` but its translation is missing" do
|
@@ -336,17 +336,17 @@ EOS
|
|
336
336
|
|
337
337
|
it "exports with defined locale as fallback when enabled" do
|
338
338
|
set_config "js_file_per_locale_with_fallbacks_enabled.yml"
|
339
|
-
subject[:fr][:fallback_test].
|
339
|
+
expect(subject[:fr][:fallback_test]).to eql("Erfolg")
|
340
340
|
end
|
341
341
|
|
342
342
|
it "exports with defined locale as fallback when enabled with :default_locale" do
|
343
343
|
set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml"
|
344
|
-
subject[:fr][:fallback_test].
|
344
|
+
expect(subject[:fr][:fallback_test]).to eql("Success")
|
345
345
|
end
|
346
346
|
|
347
347
|
it "exports with Fallbacks as Hash" do
|
348
348
|
set_config "js_file_per_locale_with_fallbacks_as_hash.yml"
|
349
|
-
subject[:fr][:fallback_test].
|
349
|
+
expect(subject[:fr][:fallback_test]).to eql("Erfolg")
|
350
350
|
end
|
351
351
|
end
|
352
352
|
end
|
@@ -389,9 +389,9 @@ EOS
|
|
389
389
|
it "should allow all locales" do
|
390
390
|
result = I18n::JS.scoped_translations("*.admin.*.title")
|
391
391
|
|
392
|
-
result[:en][:admin][:show][:title].
|
393
|
-
result[:fr][:admin][:show][:title].
|
394
|
-
result[:ja][:admin][:show][:title].
|
392
|
+
expect(result[:en][:admin][:show][:title]).to eql("Show")
|
393
|
+
expect(result[:fr][:admin][:show][:title]).to eql("Visualiser")
|
394
|
+
expect(result[:ja][:admin][:show][:title]).to eql("Ignore me")
|
395
395
|
end
|
396
396
|
end
|
397
397
|
|
@@ -401,28 +401,28 @@ EOS
|
|
401
401
|
it "should ignore non-valid locales" do
|
402
402
|
result = I18n::JS.scoped_translations("*.admin.*.title")
|
403
403
|
|
404
|
-
result[:en][:admin][:show][:title].
|
405
|
-
result[:fr][:admin][:show][:title].
|
406
|
-
result.keys.include?(:ja).
|
404
|
+
expect(result[:en][:admin][:show][:title]).to eql("Show")
|
405
|
+
expect(result[:fr][:admin][:show][:title]).to eql("Visualiser")
|
406
|
+
expect(result.keys.include?(:ja)).to eql(false)
|
407
407
|
end
|
408
408
|
end
|
409
409
|
end
|
410
410
|
|
411
411
|
context "general" do
|
412
412
|
it "sets export directory" do
|
413
|
-
I18n::JS::DEFAULT_EXPORT_DIR_PATH.
|
413
|
+
expect(I18n::JS::DEFAULT_EXPORT_DIR_PATH).to eql("public/javascripts")
|
414
414
|
end
|
415
415
|
|
416
416
|
it "sets empty hash as configuration when no file is found" do
|
417
|
-
I18n::JS.config_file_exists
|
418
|
-
I18n::JS.config.
|
417
|
+
expect(I18n::JS.config_file_exists?).to eql(false)
|
418
|
+
expect(I18n::JS.config).to eql({})
|
419
419
|
end
|
420
420
|
|
421
421
|
it "executes erb in config file" do
|
422
422
|
set_config "erb.yml"
|
423
423
|
|
424
424
|
config_entry = I18n::JS.config[:translations].first
|
425
|
-
config_entry["only"].
|
425
|
+
expect(config_entry["only"]).to eq("*.date.formats")
|
426
426
|
end
|
427
427
|
end
|
428
428
|
|
@@ -434,7 +434,7 @@ EOS
|
|
434
434
|
allow(FileUtils).to receive(:mkdir_p).and_call_original
|
435
435
|
allow(FileUtils).to receive(:cp).and_call_original
|
436
436
|
|
437
|
-
described_class.
|
437
|
+
allow(described_class).to receive(:export_i18n_js_dir_path).and_return(export_i18n_js_dir_path)
|
438
438
|
I18n::JS.export_i18n_js
|
439
439
|
end
|
440
440
|
|
@@ -448,7 +448,7 @@ EOS
|
|
448
448
|
expect(FileUtils).to have_received(:cp).once
|
449
449
|
end
|
450
450
|
it "exports the file" do
|
451
|
-
File.
|
451
|
+
expect(File).to be_file(File.join(I18n::JS.export_i18n_js_dir_path, "i18n.js"))
|
452
452
|
end
|
453
453
|
end
|
454
454
|
|
@@ -484,7 +484,7 @@ EOS
|
|
484
484
|
expect(FileUtils).to have_received(:cp).once
|
485
485
|
end
|
486
486
|
it "exports the file" do
|
487
|
-
File.
|
487
|
+
expect(File).to be_file(File.join(config_export_path, "i18n.js"))
|
488
488
|
end
|
489
489
|
end
|
490
490
|
|
@@ -595,11 +595,10 @@ EOS
|
|
595
595
|
end
|
596
596
|
|
597
597
|
it "exports with the keys sorted" do
|
598
|
-
expect(subject).to eq
|
598
|
+
expect(subject).to eq <<EOS
|
599
599
|
I18n.translations || (I18n.translations = {});
|
600
|
-
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), {"admin":{"edit":{"title":"Edit"},"show":{"note":"more details","title":"Show"}},"date":{"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"},"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"]},"fallback_test":"Success","foo":"Foo","null_test":"fallback for null","number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}},"format":{"delimiter":",","precision":3,"separator":"."}},"time":{"am":"am","formats":{"default":"%a, %d %b %Y %H:%M:%S %z","long":"%B %d, %Y %H:%M","short":"%d %b %H:%M"},"pm":"pm"}});
|
600
|
+
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"},"null_test":"fallback for null","number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}},"format":{"delimiter":",","precision":3,"separator":"."}},"time":{"am":"am","formats":{"default":"%a, %d %b %Y %H:%M:%S %z","long":"%B %d, %Y %H:%M","short":"%d %b %H:%M"},"pm":"pm"}});
|
601
601
|
EOS
|
602
|
-
)
|
603
602
|
end
|
604
603
|
end
|
605
604
|
end
|
@@ -640,4 +639,25 @@ EOS
|
|
640
639
|
)
|
641
640
|
end
|
642
641
|
end
|
642
|
+
|
643
|
+
describe "merging plural keys" do
|
644
|
+
before do
|
645
|
+
stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
|
646
|
+
end
|
647
|
+
|
648
|
+
subject do
|
649
|
+
File.read(File.join(I18n::JS.export_i18n_js_dir_path, "merge_plurals.js"))
|
650
|
+
end
|
651
|
+
|
652
|
+
it "should correctly merge the plural keys" do
|
653
|
+
set_config "merge_plurals.yml"
|
654
|
+
I18n::JS.export
|
655
|
+
file_should_exist "merge_plurals.js"
|
656
|
+
|
657
|
+
expect(subject).to eq <<EOS
|
658
|
+
I18n.translations || (I18n.translations = {});
|
659
|
+
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\"}});
|
660
|
+
EOS
|
661
|
+
end
|
662
|
+
end
|
643
663
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -70,10 +70,10 @@ RSpec.configure do |config|
|
|
70
70
|
|
71
71
|
# Remove deprecation warnings
|
72
72
|
config.expect_with :rspec do |c|
|
73
|
-
c.syntax = [:
|
73
|
+
c.syntax = [:expect]
|
74
74
|
end
|
75
75
|
config.mock_with :rspec do |c|
|
76
|
-
c.syntax = [:
|
76
|
+
c.syntax = [:expect]
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
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.2.
|
4
|
+
version: 3.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nando Vieira
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -16,20 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '2'
|
19
|
+
version: 0.6.6
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '2'
|
26
|
+
version: 0.6.6
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: appraisal
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,17 +114,25 @@ files:
|
|
120
114
|
- app/assets/javascripts/i18n/filtered.js.erb
|
121
115
|
- app/assets/javascripts/i18n/shims.js
|
122
116
|
- app/assets/javascripts/i18n/translations.js
|
117
|
+
- gemfiles/i18n_0_6.gemfile
|
118
|
+
- gemfiles/i18n_0_7.gemfile
|
123
119
|
- gemfiles/i18n_0_8.gemfile
|
124
120
|
- gemfiles/i18n_0_9.gemfile
|
125
121
|
- gemfiles/i18n_1_0.gemfile
|
126
122
|
- gemfiles/i18n_1_1.gemfile
|
123
|
+
- gemfiles/i18n_1_2.gemfile
|
124
|
+
- gemfiles/i18n_1_3.gemfile
|
125
|
+
- gemfiles/i18n_1_4.gemfile
|
126
|
+
- gemfiles/i18n_1_5.gemfile
|
127
127
|
- i18n-js.gemspec
|
128
128
|
- lib/i18n-js.rb
|
129
129
|
- lib/i18n/js.rb
|
130
130
|
- lib/i18n/js/dependencies.rb
|
131
131
|
- lib/i18n/js/engine.rb
|
132
|
-
- lib/i18n/js/errors.rb
|
133
132
|
- lib/i18n/js/fallback_locales.rb
|
133
|
+
- lib/i18n/js/formatters/base.rb
|
134
|
+
- lib/i18n/js/formatters/js.rb
|
135
|
+
- lib/i18n/js/formatters/json.rb
|
134
136
|
- lib/i18n/js/middleware.rb
|
135
137
|
- lib/i18n/js/private/hash_with_symbol_keys.rb
|
136
138
|
- lib/i18n/js/segment.rb
|
@@ -160,6 +162,7 @@ files:
|
|
160
162
|
- spec/fixtures/js_sort_translation_keys_true.yml
|
161
163
|
- spec/fixtures/json_only.yml
|
162
164
|
- spec/fixtures/locales.yml
|
165
|
+
- spec/fixtures/merge_plurals.yml
|
163
166
|
- spec/fixtures/multiple_conditions.yml
|
164
167
|
- spec/fixtures/multiple_conditions_per_locale.yml
|
165
168
|
- spec/fixtures/multiple_files.yml
|
@@ -214,8 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
217
|
- !ruby/object:Gem::Version
|
215
218
|
version: '0'
|
216
219
|
requirements: []
|
217
|
-
|
218
|
-
rubygems_version: 2.7.8
|
220
|
+
rubygems_version: 3.0.2
|
219
221
|
signing_key:
|
220
222
|
specification_version: 4
|
221
223
|
summary: It's a small library to provide the Rails I18n translations on the Javascript.
|
@@ -240,6 +242,7 @@ test_files:
|
|
240
242
|
- spec/fixtures/js_sort_translation_keys_true.yml
|
241
243
|
- spec/fixtures/json_only.yml
|
242
244
|
- spec/fixtures/locales.yml
|
245
|
+
- spec/fixtures/merge_plurals.yml
|
243
246
|
- spec/fixtures/multiple_conditions.yml
|
244
247
|
- spec/fixtures/multiple_conditions_per_locale.yml
|
245
248
|
- spec/fixtures/multiple_files.yml
|