i18n-js 3.3.0 → 3.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +1 -1
- data/.github/FUNDING.yml +3 -0
- data/.github/workflows/tests.yaml +106 -0
- data/Appraisals +16 -0
- data/CHANGELOG.md +153 -4
- data/README.md +505 -333
- data/app/assets/javascripts/i18n/shims.js +35 -3
- data/app/assets/javascripts/i18n.js +37 -33
- data/gemfiles/i18n_1_10.gemfile +7 -0
- data/gemfiles/i18n_1_7.gemfile +7 -0
- data/gemfiles/i18n_1_8.gemfile +7 -0
- data/gemfiles/i18n_1_9.gemfile +7 -0
- data/i18n-js.gemspec +2 -2
- data/i18njs.png +0 -0
- data/lib/i18n/js/dependencies.rb +6 -2
- data/lib/i18n/js/engine.rb +1 -1
- data/lib/i18n/js/formatters/base.rb +3 -1
- data/lib/i18n/js/formatters/js.rb +12 -4
- data/lib/i18n/js/middleware.rb +1 -1
- data/lib/i18n/js/private/config_store.rb +31 -0
- data/lib/i18n/js/segment.rb +9 -3
- data/lib/i18n/js/utils.rb +34 -8
- data/lib/i18n/js/version.rb +1 -1
- data/lib/i18n/js.rb +25 -10
- data/package.json +2 -2
- data/spec/fixtures/js_available_locales_custom.yml +1 -0
- data/spec/fixtures/{js_file_with_namespace_and_pretty_print.yml → js_file_with_namespace_prefix_and_pretty_print.yml} +2 -0
- data/spec/fixtures/locales.yml +38 -0
- data/spec/fixtures/merge_plurals_with_no_overrides.yml +4 -0
- data/spec/fixtures/merge_plurals_with_partial_overrides.yml +4 -0
- data/spec/fixtures/millions.yml +4 -0
- data/spec/js/dates.spec.js +1 -0
- data/spec/js/json_parsable.spec.js +14 -0
- data/spec/js/localization.spec.js +38 -14
- data/spec/js/numbers.spec.js +4 -0
- data/spec/js/pluralization.spec.js +19 -2
- data/spec/js/require.js +4 -4
- data/spec/js/translate.spec.js +68 -48
- data/spec/js/translations.js +27 -2
- data/spec/ruby/i18n/js/segment_spec.rb +75 -8
- data/spec/ruby/i18n/js/utils_spec.rb +32 -0
- data/spec/ruby/i18n/js_spec.rb +169 -35
- data/spec/spec_helper.rb +1 -0
- data/yarn.lock +32 -25
- metadata +26 -9
- data/.travis.yml +0 -37
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "i18n-js",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.9.2",
|
4
4
|
"description": "A javascript library similar to Ruby on Rails i18n gem",
|
5
5
|
"author": "Nando Vieira",
|
6
6
|
"license": "MIT",
|
@@ -8,7 +8,7 @@
|
|
8
8
|
"i18n"
|
9
9
|
],
|
10
10
|
"devDependencies": {
|
11
|
-
"jasmine-node": "^
|
11
|
+
"jasmine-node": "^3.0.0"
|
12
12
|
},
|
13
13
|
"main": "app/assets/javascripts/i18n.js",
|
14
14
|
"scripts": {
|
@@ -0,0 +1 @@
|
|
1
|
+
js_available_locales: ["en", "foo"]
|
data/spec/fixtures/locales.yml
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
en:
|
2
2
|
number:
|
3
|
+
human:
|
4
|
+
decimal_units:
|
5
|
+
units:
|
6
|
+
million: Million
|
3
7
|
format:
|
4
8
|
separator: "."
|
5
9
|
delimiter: ","
|
@@ -40,6 +44,29 @@ en:
|
|
40
44
|
merge_plurals:
|
41
45
|
one: Apple
|
42
46
|
other: Apples
|
47
|
+
merge_plurals_with_no_overrides:
|
48
|
+
zero: "No Apple"
|
49
|
+
one: Apple
|
50
|
+
other: Apples
|
51
|
+
merge_plurals_with_partial_overrides:
|
52
|
+
one: Cat
|
53
|
+
other: Cats
|
54
|
+
|
55
|
+
es:
|
56
|
+
number:
|
57
|
+
human:
|
58
|
+
decimal_units:
|
59
|
+
units:
|
60
|
+
million:
|
61
|
+
one: millón
|
62
|
+
other: millones
|
63
|
+
|
64
|
+
ru:
|
65
|
+
merge_plurals_with_no_overrides:
|
66
|
+
one: кот
|
67
|
+
few: кошек
|
68
|
+
many: кошка
|
69
|
+
other: кошек
|
43
70
|
|
44
71
|
de:
|
45
72
|
fallback_test: "Erfolg"
|
@@ -89,6 +116,17 @@ fr:
|
|
89
116
|
one: Pomme
|
90
117
|
other: Pommes
|
91
118
|
|
119
|
+
en-US:
|
120
|
+
merge_plurals_with_no_overrides:
|
121
|
+
zero:
|
122
|
+
one:
|
123
|
+
other:
|
124
|
+
merge_plurals_with_partial_overrides:
|
125
|
+
one: Cat
|
126
|
+
few:
|
127
|
+
many:
|
128
|
+
other:
|
129
|
+
|
92
130
|
ja:
|
93
131
|
admin:
|
94
132
|
show:
|
data/spec/js/dates.spec.js
CHANGED
@@ -132,6 +132,7 @@ describe("Dates", function(){
|
|
132
132
|
|
133
133
|
// 24-hour without padding
|
134
134
|
expect(I18n.strftime(date, "%-H")).toEqual("7");
|
135
|
+
expect(I18n.strftime(date, "%k")).toEqual("7");
|
135
136
|
|
136
137
|
// 12-hour without padding
|
137
138
|
expect(I18n.strftime(date, "%-I")).toEqual("7");
|
@@ -0,0 +1,14 @@
|
|
1
|
+
describe("JSON.parse", function () {
|
2
|
+
it('should parse', function () {
|
3
|
+
expect(JSON.parse('{"a":"Test\'s"}')).toEqual({
|
4
|
+
a: "Test's"
|
5
|
+
})
|
6
|
+
|
7
|
+
expect(JSON.parse('{"a":"say \\"hello\\""}')).toEqual({
|
8
|
+
a: 'say "hello"'
|
9
|
+
});
|
10
|
+
expect(JSON.parse('{"double-backslash-in-double-quote":"\\"\\\\\\\\\\""}')).toEqual({
|
11
|
+
'double-backslash-in-double-quote': '"\\\\"'
|
12
|
+
});
|
13
|
+
})
|
14
|
+
})
|
@@ -10,45 +10,69 @@ describe("Localization", function(){
|
|
10
10
|
I18n.translations = Translations();
|
11
11
|
});
|
12
12
|
|
13
|
+
it("sets bound alias", function() {
|
14
|
+
expect(I18n.l).toEqual(jasmine.any(Function));
|
15
|
+
expect(I18n.l).not.toBe(I18n.localize);
|
16
|
+
});
|
17
|
+
|
13
18
|
it("localizes number", function(){
|
14
|
-
expect(I18n.
|
19
|
+
expect(I18n.localize("number", 1234567)).toEqual("1,234,567.000");
|
20
|
+
});
|
21
|
+
|
22
|
+
it("localizes number with 'l' shortcut", function(){
|
23
|
+
var l = I18n.l;
|
24
|
+
expect(l("number", 1234567)).toEqual("1,234,567.000");
|
15
25
|
});
|
16
26
|
|
17
27
|
it("localizes currency", function(){
|
18
|
-
expect(I18n.
|
28
|
+
expect(I18n.localize("currency", 1234567)).toEqual("$1,234,567.00");
|
19
29
|
});
|
20
30
|
|
21
31
|
it("localizes date strings", function(){
|
22
32
|
I18n.locale = "pt-BR";
|
23
33
|
|
24
|
-
expect(I18n.
|
25
|
-
expect(I18n.
|
26
|
-
expect(I18n.
|
34
|
+
expect(I18n.localize("date.formats.default", "2009-11-29")).toEqual("29/11/2009");
|
35
|
+
expect(I18n.localize("date.formats.short", "2009-01-07")).toEqual("07 de Janeiro");
|
36
|
+
expect(I18n.localize("date.formats.long", "2009-01-07")).toEqual("07 de Janeiro de 2009");
|
37
|
+
});
|
38
|
+
|
39
|
+
it("localizes strings with locale from options", function(){
|
40
|
+
I18n.locale = "en";
|
41
|
+
|
42
|
+
expect(I18n.localize("date.formats.default", "2009-11-29", { locale: "pt-BR" })).toEqual("29/11/2009");
|
43
|
+
expect(I18n.localize("date.formats.short", "2009-01-07", { locale: "pt-BR" })).toEqual("07 de Janeiro");
|
44
|
+
expect(I18n.localize("date.formats.long", "2009-01-07", { locale: "pt-BR" })).toEqual("07 de Janeiro de 2009");
|
45
|
+
expect(I18n.localize("time.formats.default", "2009-11-29 15:07:59", { locale: "pt-BR" })).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
46
|
+
expect(I18n.localize("time.formats.short", "2009-01-07 09:12:35", { locale: "pt-BR" })).toEqual("07/01, 09:12 h");
|
47
|
+
expect(I18n.localize("time.formats.long", "2009-11-29 15:07:59", { locale: "pt-BR" })).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
48
|
+
expect(I18n.localize("number", 1234567, { locale: "pt-BR" })).toEqual("1,234,567.000");
|
49
|
+
expect(I18n.localize("currency", 1234567, { locale: "pt-BR" })).toEqual("R$ 1.234.567,00");
|
50
|
+
expect(I18n.localize("percentage", 123.45, { locale: "pt-BR" })).toEqual("123,45%");
|
27
51
|
});
|
28
52
|
|
29
53
|
it("localizes time strings", function(){
|
30
54
|
I18n.locale = "pt-BR";
|
31
55
|
|
32
|
-
expect(I18n.
|
33
|
-
expect(I18n.
|
34
|
-
expect(I18n.
|
56
|
+
expect(I18n.localize("time.formats.default", "2009-11-29 15:07:59")).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
57
|
+
expect(I18n.localize("time.formats.short", "2009-01-07 09:12:35")).toEqual("07/01, 09:12 h");
|
58
|
+
expect(I18n.localize("time.formats.long", "2009-11-29 15:07:59")).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
35
59
|
});
|
36
60
|
|
37
61
|
it("return 'Invalid Date' or original value for invalid input", function(){
|
38
|
-
expect(I18n.
|
39
|
-
expect(I18n.
|
40
|
-
expect(I18n.
|
62
|
+
expect(I18n.localize("time.formats.default", "")).toEqual("Invalid Date");
|
63
|
+
expect(I18n.localize("time.formats.default", null)).toEqual(null);
|
64
|
+
expect(I18n.localize("time.formats.default", undefined)).toEqual(undefined);
|
41
65
|
});
|
42
66
|
|
43
67
|
it("localizes date/time strings with placeholders", function(){
|
44
68
|
I18n.locale = "pt-BR";
|
45
69
|
|
46
|
-
expect(I18n.
|
47
|
-
expect(I18n.
|
70
|
+
expect(I18n.localize("date.formats.short_with_placeholders", "2009-01-07", { p1: "!", p2: "?" })).toEqual("07 de Janeiro ! ?");
|
71
|
+
expect(I18n.localize("time.formats.short_with_placeholders", "2009-01-07 09:12:35", { p1: "!" })).toEqual("07/01, 09:12 h !");
|
48
72
|
});
|
49
73
|
|
50
74
|
it("localizes percentage", function(){
|
51
75
|
I18n.locale = "pt-BR";
|
52
|
-
expect(I18n.
|
76
|
+
expect(I18n.localize("percentage", 123.45)).toEqual("123,45%");
|
53
77
|
});
|
54
78
|
});
|
data/spec/js/numbers.spec.js
CHANGED
@@ -150,6 +150,10 @@ describe("Numbers", function(){
|
|
150
150
|
expect(I18n.toHumanSize(1024 * 1.6, {precision: 0})).toEqual("2KB");
|
151
151
|
});
|
152
152
|
|
153
|
+
it("returns number as human size using custom scope", function(){
|
154
|
+
expect(I18n.toHumanSize(1024 * 1024, {scope: "extended"})).toEqual("1Megabyte");
|
155
|
+
});
|
156
|
+
|
153
157
|
it("formats numbers with strip insignificant zero", function() {
|
154
158
|
options = {separator: ".", delimiter: ",", strip_insignificant_zeros: true};
|
155
159
|
|
@@ -10,8 +10,9 @@ describe("Pluralization", function(){
|
|
10
10
|
I18n.translations = Translations();
|
11
11
|
});
|
12
12
|
|
13
|
-
it("sets alias", function() {
|
14
|
-
expect(I18n.p).toEqual(
|
13
|
+
it("sets bound alias", function() {
|
14
|
+
expect(I18n.p).toEqual(jasmine.any(Function));
|
15
|
+
expect(I18n.p).not.toBe(I18n.pluralize);
|
15
16
|
});
|
16
17
|
|
17
18
|
it("pluralizes scope", function(){
|
@@ -20,6 +21,13 @@ describe("Pluralization", function(){
|
|
20
21
|
expect(I18n.p(5, "inbox")).toEqual("You have 5 messages");
|
21
22
|
});
|
22
23
|
|
24
|
+
it("pluralizes scope with 'p' shortcut", function(){
|
25
|
+
var p = I18n.p;
|
26
|
+
expect(p(0, "inbox")).toEqual("You have no messages");
|
27
|
+
expect(p(1, "inbox")).toEqual("You have 1 message");
|
28
|
+
expect(p(5, "inbox")).toEqual("You have 5 messages");
|
29
|
+
});
|
30
|
+
|
23
31
|
it("pluralizes using the 'other' scope", function(){
|
24
32
|
I18n.translations["en"]["inbox"]["zero"] = null;
|
25
33
|
expect(I18n.p(0, "inbox")).toEqual("You have 0 messages");
|
@@ -140,6 +148,15 @@ describe("Pluralization", function(){
|
|
140
148
|
expect(I18n.p(5, "inbox", { count: 5 })).toEqual('You have 5 messages');
|
141
149
|
});
|
142
150
|
|
151
|
+
it("fallback to default locale when I18n.fallbacks is enabled and value is null", function() {
|
152
|
+
I18n.locale = "pt-BR";
|
153
|
+
I18n.fallbacks = true;
|
154
|
+
I18n.translations["pt-BR"].inbox = null;
|
155
|
+
expect(I18n.p(0, "inbox", { count: 0 })).toEqual("You have no messages");
|
156
|
+
expect(I18n.p(1, "inbox", { count: 1 })).toEqual("You have 1 message");
|
157
|
+
expect(I18n.p(5, "inbox", { count: 5 })).toEqual("You have 5 messages");
|
158
|
+
});
|
159
|
+
|
143
160
|
it("fallback to 'other' scope", function() {
|
144
161
|
I18n.locale = "pt-BR";
|
145
162
|
I18n.fallbacks = true;
|
data/spec/js/require.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/** vim: et:ts=4:sw=4:sts=4
|
2
2
|
* @license RequireJS 2.1.16 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved.
|
3
3
|
* Available via the MIT or new BSD license.
|
4
|
-
* see:
|
4
|
+
* see: https://github.com/jrburke/requirejs for details
|
5
5
|
*/
|
6
6
|
//Not using strict: uneven strict support in browsers, #392, and causes
|
7
7
|
//problems with requirejs.exec()/transpiler plugins that may not be strict.
|
@@ -163,7 +163,7 @@ var requirejs, require, define;
|
|
163
163
|
* @returns {Error}
|
164
164
|
*/
|
165
165
|
function makeError(id, msg, err, requireModules) {
|
166
|
-
var e = new Error(msg + '\
|
166
|
+
var e = new Error(msg + '\nhttps://requirejs.org/docs/errors.html#' + id);
|
167
167
|
e.requireType = id;
|
168
168
|
e.requireModules = requireModules;
|
169
169
|
if (err) {
|
@@ -1810,7 +1810,7 @@ var requirejs, require, define;
|
|
1810
1810
|
head = s.head = document.getElementsByTagName('head')[0];
|
1811
1811
|
//If BASE tag is in play, using appendChild is a problem for IE6.
|
1812
1812
|
//When that browser dies, this can be removed. Details in this jQuery bug:
|
1813
|
-
//
|
1813
|
+
//https://dev.jquery.com/ticket/2709
|
1814
1814
|
baseElement = document.getElementsByTagName('base')[0];
|
1815
1815
|
if (baseElement) {
|
1816
1816
|
head = s.head = baseElement.parentNode;
|
@@ -1829,7 +1829,7 @@ var requirejs, require, define;
|
|
1829
1829
|
*/
|
1830
1830
|
req.createNode = function (config, moduleName, url) {
|
1831
1831
|
var node = config.xhtml ?
|
1832
|
-
document.createElementNS('
|
1832
|
+
document.createElementNS('https://www.w3.org/1999/xhtml', 'html:script') :
|
1833
1833
|
document.createElement('script');
|
1834
1834
|
node.type = config.scriptType || 'text/javascript';
|
1835
1835
|
node.charset = 'utf-8';
|
data/spec/js/translate.spec.js
CHANGED
@@ -10,83 +10,98 @@ describe("Translate", function(){
|
|
10
10
|
I18n.translations = Translations();
|
11
11
|
});
|
12
12
|
|
13
|
+
it("sets bound alias", function() {
|
14
|
+
expect(I18n.t).toEqual(jasmine.any(Function));
|
15
|
+
expect(I18n.t).not.toBe(I18n.translate);
|
16
|
+
});
|
17
|
+
|
13
18
|
it("returns translation for single scope", function(){
|
14
|
-
expect(I18n.
|
19
|
+
expect(I18n.translate("hello")).toEqual("Hello World!");
|
20
|
+
});
|
21
|
+
|
22
|
+
it("returns translation with 't' shortcut", function(){
|
23
|
+
var t = I18n.t;
|
24
|
+
expect(t("hello")).toEqual("Hello World!");
|
15
25
|
});
|
16
26
|
|
17
27
|
it("returns translation as object", function(){
|
18
|
-
expect(I18n.
|
28
|
+
expect(I18n.translate("greetings")).toEqual(I18n.translations.en.greetings);
|
19
29
|
});
|
20
30
|
|
21
31
|
it("returns missing message translation for valid scope with null", function(){
|
22
|
-
actual = I18n.
|
32
|
+
actual = I18n.translate("null_key");
|
23
33
|
expected = '[missing "en.null_key" translation]';
|
24
34
|
expect(actual).toEqual(expected);
|
25
35
|
});
|
26
36
|
|
27
37
|
it("returns missing message translation for invalid scope", function(){
|
28
|
-
actual = I18n.
|
38
|
+
actual = I18n.translate("invalid.scope");
|
29
39
|
expected = '[missing "en.invalid.scope" translation]';
|
30
40
|
expect(actual).toEqual(expected);
|
31
41
|
});
|
32
42
|
|
33
43
|
it("returns missing message translation with provided locale for invalid scope", function(){
|
34
|
-
actual = I18n.
|
44
|
+
actual = I18n.translate("invalid.scope", { locale: "ja" });
|
35
45
|
expected = '[missing "ja.invalid.scope" translation]';
|
36
46
|
expect(actual).toEqual(expected);
|
37
47
|
});
|
38
48
|
|
39
49
|
it("returns guessed translation if missingBehaviour is set to guess", function(){
|
40
50
|
I18n.missingBehaviour = 'guess'
|
41
|
-
|
42
|
-
|
43
|
-
|
51
|
+
|
52
|
+
var actual_1 = I18n.translate("invalid.thisIsAutomaticallyGeneratedTranslation");
|
53
|
+
var expected_1 = 'this is automatically generated translation';
|
54
|
+
expect(actual_1).toEqual(expected_1);
|
55
|
+
|
56
|
+
var actual_2 = I18n.translate("invalid.this_is_automatically_generated_translation");
|
57
|
+
var expected_2 = 'this is automatically generated translation';
|
58
|
+
expect(actual_2).toEqual(expected_2);
|
44
59
|
});
|
45
60
|
|
46
61
|
it("returns guessed translation with prefix if missingBehaviour is set to guess and prefix is also provided", function(){
|
47
62
|
I18n.missingBehaviour = 'guess'
|
48
63
|
I18n.missingTranslationPrefix = 'EE: '
|
49
|
-
actual = I18n.
|
64
|
+
actual = I18n.translate("invalid.thisIsAutomaticallyGeneratedTranslation");
|
50
65
|
expected = 'EE: this is automatically generated translation';
|
51
66
|
expect(actual).toEqual(expected);
|
52
67
|
});
|
53
68
|
|
54
69
|
it("returns missing message translation for valid scope with scope", function(){
|
55
|
-
actual = I18n.
|
70
|
+
actual = I18n.translate("monster", {scope: "greetings"});
|
56
71
|
expected = '[missing "en.greetings.monster" translation]';
|
57
72
|
expect(actual).toEqual(expected);
|
58
73
|
});
|
59
74
|
|
60
75
|
it("returns translation for single scope on a custom locale", function(){
|
61
76
|
I18n.locale = "pt-BR";
|
62
|
-
expect(I18n.
|
77
|
+
expect(I18n.translate("hello")).toEqual("Olá Mundo!");
|
63
78
|
});
|
64
79
|
|
65
80
|
it("returns translation for multiple scopes", function(){
|
66
|
-
expect(I18n.
|
81
|
+
expect(I18n.translate("greetings.stranger")).toEqual("Hello stranger!");
|
67
82
|
});
|
68
83
|
|
69
84
|
it("returns translation with default locale option", function(){
|
70
|
-
expect(I18n.
|
71
|
-
expect(I18n.
|
85
|
+
expect(I18n.translate("hello", {locale: "en"})).toEqual("Hello World!");
|
86
|
+
expect(I18n.translate("hello", {locale: "pt-BR"})).toEqual("Olá Mundo!");
|
72
87
|
});
|
73
88
|
|
74
89
|
it("fallbacks to the default locale when I18n.fallbacks is enabled", function(){
|
75
90
|
I18n.locale = "pt-BR";
|
76
91
|
I18n.fallbacks = true;
|
77
|
-
expect(I18n.
|
92
|
+
expect(I18n.translate("greetings.stranger")).toEqual("Hello stranger!");
|
78
93
|
});
|
79
94
|
|
80
95
|
it("fallbacks to default locale when providing an unknown locale", function(){
|
81
96
|
I18n.locale = "fr";
|
82
97
|
I18n.fallbacks = true;
|
83
|
-
expect(I18n.
|
98
|
+
expect(I18n.translate("greetings.stranger")).toEqual("Hello stranger!");
|
84
99
|
});
|
85
100
|
|
86
101
|
it("fallbacks to less specific locale", function(){
|
87
102
|
I18n.locale = "de-DE";
|
88
103
|
I18n.fallbacks = true;
|
89
|
-
expect(I18n.
|
104
|
+
expect(I18n.translate("hello")).toEqual("Hallo Welt!");
|
90
105
|
});
|
91
106
|
|
92
107
|
describe("when a 3-part locale is used", function(){
|
@@ -96,15 +111,15 @@ describe("Translate", function(){
|
|
96
111
|
});
|
97
112
|
|
98
113
|
it("fallbacks to 2-part locale when absent", function(){
|
99
|
-
expect(I18n.
|
114
|
+
expect(I18n.translate("cat")).toEqual("貓");
|
100
115
|
});
|
101
116
|
|
102
117
|
it("fallbacks to 1-part locale when 2-part missing requested translation", function(){
|
103
|
-
expect(I18n.
|
118
|
+
expect(I18n.translate("dog")).toEqual("狗");
|
104
119
|
});
|
105
120
|
|
106
121
|
it("fallbacks to 2-part for the first time", function(){
|
107
|
-
expect(I18n.
|
122
|
+
expect(I18n.translate("dragon")).toEqual("龍");
|
108
123
|
});
|
109
124
|
});
|
110
125
|
|
@@ -115,7 +130,7 @@ describe("Translate", function(){
|
|
115
130
|
return ["nb"];
|
116
131
|
};
|
117
132
|
|
118
|
-
expect(I18n.
|
133
|
+
expect(I18n.translate("hello")).toEqual("Hei Verden!");
|
119
134
|
});
|
120
135
|
|
121
136
|
it("fallbacks using custom rules (array)", function() {
|
@@ -123,7 +138,7 @@ describe("Translate", function(){
|
|
123
138
|
I18n.fallbacks = true;
|
124
139
|
I18n.locales["no"] = ["no", "nb"];
|
125
140
|
|
126
|
-
expect(I18n.
|
141
|
+
expect(I18n.translate("hello")).toEqual("Hei Verden!");
|
127
142
|
});
|
128
143
|
|
129
144
|
it("fallbacks using custom rules (string)", function() {
|
@@ -131,25 +146,25 @@ describe("Translate", function(){
|
|
131
146
|
I18n.fallbacks = true;
|
132
147
|
I18n.locales["no"] = "nb";
|
133
148
|
|
134
|
-
expect(I18n.
|
149
|
+
expect(I18n.translate("hello")).toEqual("Hei Verden!");
|
135
150
|
});
|
136
151
|
|
137
152
|
describe("when provided default values", function() {
|
138
153
|
it("uses scope provided in defaults if scope doesn't exist", function() {
|
139
|
-
actual = I18n.
|
154
|
+
actual = I18n.translate("Hello!", {defaults: [{scope: "greetings.stranger"}]});
|
140
155
|
expect(actual).toEqual("Hello stranger!");
|
141
156
|
});
|
142
157
|
|
143
158
|
it("continues to fallback until a scope is found", function() {
|
144
159
|
var defaults = [{scope: "foo"}, {scope: "hello"}];
|
145
160
|
|
146
|
-
actual = I18n.
|
161
|
+
actual = I18n.translate("foo", {defaults: defaults});
|
147
162
|
expect(actual).toEqual("Hello World!");
|
148
163
|
});
|
149
164
|
|
150
165
|
it("uses message if specified as a default", function() {
|
151
166
|
var defaults = [{message: "Hello all!"}];
|
152
|
-
actual = I18n.
|
167
|
+
actual = I18n.translate("foo", {defaults: defaults});
|
153
168
|
expect(actual).toEqual("Hello all!");
|
154
169
|
});
|
155
170
|
|
@@ -158,7 +173,7 @@ describe("Translate", function(){
|
|
158
173
|
{scope: "bar"}
|
159
174
|
, {message: "Hello all!"}
|
160
175
|
, {scope: "hello"}];
|
161
|
-
actual = I18n.
|
176
|
+
actual = I18n.translate("foo", {defaults: defaults});
|
162
177
|
expect(actual).toEqual("Hello all!");
|
163
178
|
});
|
164
179
|
|
@@ -167,7 +182,7 @@ describe("Translate", function(){
|
|
167
182
|
defaults: [{scope: "bar"}]
|
168
183
|
, defaultValue: "Hello all!"
|
169
184
|
};
|
170
|
-
actual = I18n.
|
185
|
+
actual = I18n.translate("foo", options);
|
171
186
|
expect(actual).toEqual("Hello all!");
|
172
187
|
});
|
173
188
|
|
@@ -176,7 +191,7 @@ describe("Translate", function(){
|
|
176
191
|
defaults: [{scope: "hello"}]
|
177
192
|
, defaultValue: "Hello all!"
|
178
193
|
};
|
179
|
-
actual = I18n.
|
194
|
+
actual = I18n.translate("foo", options);
|
180
195
|
expect(actual).toEqual("Hello World!");
|
181
196
|
})
|
182
197
|
|
@@ -187,36 +202,36 @@ describe("Translate", function(){
|
|
187
202
|
return scope.toUpperCase();
|
188
203
|
}
|
189
204
|
};
|
190
|
-
actual = I18n.
|
205
|
+
actual = I18n.translate("foo", options);
|
191
206
|
expect(actual).toEqual("FOO");
|
192
207
|
})
|
193
208
|
|
194
209
|
it("pluralizes using the correct scope if translation is found within default scope", function() {
|
195
210
|
expect(I18n.translations["en"]["mailbox"]).toEqual(undefined);
|
196
|
-
actual = I18n.
|
197
|
-
expected = I18n.
|
211
|
+
actual = I18n.translate("mailbox.inbox", {count: 1, defaults: [{scope: "inbox"}]});
|
212
|
+
expected = I18n.translate("inbox", {count: 1})
|
198
213
|
expect(actual).toEqual(expected)
|
199
214
|
})
|
200
215
|
});
|
201
216
|
|
202
217
|
it("uses default value for simple translation", function(){
|
203
|
-
actual = I18n.
|
218
|
+
actual = I18n.translate("warning", {defaultValue: "Warning!"});
|
204
219
|
expect(actual).toEqual("Warning!");
|
205
220
|
});
|
206
221
|
|
207
222
|
it("uses default value for plural translation", function(){
|
208
|
-
actual = I18n.
|
223
|
+
actual = I18n.translate("message", {defaultValue: { one: '%{count} message', other: '%{count} messages'}, count: 1});
|
209
224
|
expect(actual).toEqual("1 message");
|
210
225
|
});
|
211
226
|
|
212
227
|
it("uses default value for unknown locale", function(){
|
213
228
|
I18n.locale = "fr";
|
214
|
-
actual = I18n.
|
229
|
+
actual = I18n.translate("warning", {defaultValue: "Warning!"});
|
215
230
|
expect(actual).toEqual("Warning!");
|
216
231
|
});
|
217
232
|
|
218
233
|
it("uses default value with interpolation", function(){
|
219
|
-
actual = I18n.
|
234
|
+
actual = I18n.translate(
|
220
235
|
"alert",
|
221
236
|
{defaultValue: "Attention! {{message}}", message: "You're out of quota!"}
|
222
237
|
);
|
@@ -225,33 +240,33 @@ describe("Translate", function(){
|
|
225
240
|
});
|
226
241
|
|
227
242
|
it("ignores default value when scope exists", function(){
|
228
|
-
actual = I18n.
|
243
|
+
actual = I18n.translate("hello", {defaultValue: "What's up?"});
|
229
244
|
expect(actual).toEqual("Hello World!");
|
230
245
|
});
|
231
246
|
|
232
247
|
it("returns translation for custom scope separator", function(){
|
233
248
|
I18n.defaultSeparator = "•";
|
234
|
-
actual = I18n.
|
249
|
+
actual = I18n.translate("greetings•stranger");
|
235
250
|
expect(actual).toEqual("Hello stranger!");
|
236
251
|
});
|
237
252
|
|
238
253
|
it("returns boolean values", function() {
|
239
|
-
expect(I18n.
|
240
|
-
expect(I18n.
|
254
|
+
expect(I18n.translate("booleans.yes")).toEqual(true);
|
255
|
+
expect(I18n.translate("booleans.no")).toEqual(false);
|
241
256
|
});
|
242
257
|
|
243
258
|
it("escapes $ when doing substitution (IE)", function(){
|
244
259
|
I18n.locale = "en";
|
245
260
|
|
246
|
-
expect(I18n.
|
247
|
-
expect(I18n.
|
248
|
-
expect(I18n.
|
261
|
+
expect(I18n.translate("paid", {price: "$0"})).toEqual("You were paid $0");
|
262
|
+
expect(I18n.translate("paid", {price: "$0.12"})).toEqual("You were paid $0.12");
|
263
|
+
expect(I18n.translate("paid", {price: "$1.35"})).toEqual("You were paid $1.35");
|
249
264
|
});
|
250
265
|
|
251
266
|
it("replaces all occurrences of escaped $", function(){
|
252
267
|
I18n.locale = "en";
|
253
268
|
|
254
|
-
expect(I18n.
|
269
|
+
expect(I18n.translate("paid_with_vat", {
|
255
270
|
price: "$0.12",
|
256
271
|
vat: "$0.02"}
|
257
272
|
)).toEqual("You were paid $0.12 (incl. VAT $0.02)");
|
@@ -259,20 +274,20 @@ describe("Translate", function(){
|
|
259
274
|
|
260
275
|
it("sets default scope", function(){
|
261
276
|
var options = {scope: "greetings"};
|
262
|
-
expect(I18n.
|
277
|
+
expect(I18n.translate("stranger", options)).toEqual("Hello stranger!");
|
263
278
|
});
|
264
279
|
|
265
280
|
it("accepts the scope as an array", function(){
|
266
|
-
expect(I18n.
|
281
|
+
expect(I18n.translate(["greetings", "stranger"])).toEqual("Hello stranger!");
|
267
282
|
});
|
268
283
|
|
269
284
|
it("accepts the scope as an array using a base scope", function(){
|
270
|
-
expect(I18n.
|
285
|
+
expect(I18n.translate(["stranger"], {scope: "greetings"})).toEqual("Hello stranger!");
|
271
286
|
});
|
272
287
|
|
273
288
|
it("returns an array with values interpolated", function(){
|
274
289
|
var options = {value: 314};
|
275
|
-
expect(I18n.
|
290
|
+
expect(I18n.translate("arrayWithParams", options)).toEqual([
|
276
291
|
null,
|
277
292
|
"An item with a param of " + options.value,
|
278
293
|
"Another item with a param of " + options.value,
|
@@ -281,4 +296,9 @@ describe("Translate", function(){
|
|
281
296
|
{foo: "bar"}
|
282
297
|
]);
|
283
298
|
});
|
299
|
+
|
300
|
+
|
301
|
+
it("returns value with key containing dot but different separator specified", function() {
|
302
|
+
expect(I18n.t(["A implies B means something."], {scope: "sentences_with_dots", separator: "|"})).toEqual("A implies B means that when A is true, B must be true.");
|
303
|
+
});
|
284
304
|
});
|