i18n-js 3.2.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|