i18n-js-pika 3.0.0.rc6
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 +7 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +52 -0
- data/README.md +326 -0
- data/Rakefile +13 -0
- data/app/assets/javascripts/i18n/filtered.js.erb +2 -0
- data/app/assets/javascripts/i18n/shims.js +93 -0
- data/app/assets/javascripts/i18n/translations.js +3 -0
- data/app/assets/javascripts/i18n.js +690 -0
- data/i18n-js.gemspec +27 -0
- data/lib/i18n/js/engine.rb +22 -0
- data/lib/i18n/js/middleware.rb +59 -0
- data/lib/i18n/js/version.rb +12 -0
- data/lib/i18n/js.rb +162 -0
- data/lib/i18n-js.rb +1 -0
- data/lib/tasks/export.rake +8 -0
- data/package.json +11 -0
- data/spec/fixtures/custom_path.yml +4 -0
- data/spec/fixtures/default.yml +4 -0
- data/spec/fixtures/js_file_per_locale.yml +3 -0
- data/spec/fixtures/locales.yml +76 -0
- data/spec/fixtures/multiple_conditions.yml +5 -0
- data/spec/fixtures/multiple_files.yml +6 -0
- data/spec/fixtures/no_config.yml +2 -0
- data/spec/fixtures/no_scope.yml +3 -0
- data/spec/fixtures/simple_scope.yml +4 -0
- data/spec/i18n_js_spec.rb +139 -0
- data/spec/js/currency.spec.js +60 -0
- data/spec/js/current_locale.spec.js +19 -0
- data/spec/js/dates.spec.js +222 -0
- data/spec/js/defaults.spec.js +23 -0
- data/spec/js/interpolation.spec.js +28 -0
- data/spec/js/jasmine/MIT.LICENSE +20 -0
- data/spec/js/jasmine/jasmine-html.js +190 -0
- data/spec/js/jasmine/jasmine.css +166 -0
- data/spec/js/jasmine/jasmine.js +2476 -0
- data/spec/js/jasmine/jasmine_favicon.png +0 -0
- data/spec/js/localization.spec.js +41 -0
- data/spec/js/numbers.spec.js +142 -0
- data/spec/js/placeholder.spec.js +24 -0
- data/spec/js/pluralization.spec.js +105 -0
- data/spec/js/prepare_options.spec.js +41 -0
- data/spec/js/specs.html +46 -0
- data/spec/js/translate.spec.js +120 -0
- data/spec/js/translations.js +120 -0
- data/spec/spec_helper.rb +41 -0
- metadata +196 -0
Binary file
|
@@ -0,0 +1,41 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n")
|
2
|
+
, Translations = require("./translations")
|
3
|
+
;
|
4
|
+
|
5
|
+
describe("Localization", function(){
|
6
|
+
var actual, expected;
|
7
|
+
|
8
|
+
beforeEach(function() {
|
9
|
+
I18n.reset();
|
10
|
+
I18n.translations = Translations();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("localizes number", function(){
|
14
|
+
expect(I18n.l("number", 1234567)).toEqual("1,234,567.000");
|
15
|
+
});
|
16
|
+
|
17
|
+
it("localizes currency", function(){
|
18
|
+
expect(I18n.l("currency", 1234567)).toEqual("$1,234,567.00");
|
19
|
+
});
|
20
|
+
|
21
|
+
it("localizes date strings", function(){
|
22
|
+
I18n.locale = "pt-BR";
|
23
|
+
|
24
|
+
expect(I18n.l("date.formats.default", "2009-11-29")).toEqual("29/11/2009");
|
25
|
+
expect(I18n.l("date.formats.short", "2009-01-07")).toEqual("07 de Janeiro");
|
26
|
+
expect(I18n.l("date.formats.long", "2009-01-07")).toEqual("07 de Janeiro de 2009");
|
27
|
+
});
|
28
|
+
|
29
|
+
it("localizes time strings", function(){
|
30
|
+
I18n.locale = "pt-BR";
|
31
|
+
|
32
|
+
expect(I18n.l("time.formats.default", "2009-11-29 15:07:59")).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
33
|
+
expect(I18n.l("time.formats.short", "2009-01-07 09:12:35")).toEqual("07/01, 09:12 h");
|
34
|
+
expect(I18n.l("time.formats.long", "2009-11-29 15:07:59")).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
35
|
+
});
|
36
|
+
|
37
|
+
it("localizes percentage", function(){
|
38
|
+
I18n.locale = "pt-BR";
|
39
|
+
expect(I18n.l("percentage", 123.45)).toEqual("123,45%");
|
40
|
+
});
|
41
|
+
});
|
@@ -0,0 +1,142 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n")
|
2
|
+
, Translations = require("./translations")
|
3
|
+
;
|
4
|
+
|
5
|
+
describe("Numbers", function(){
|
6
|
+
var actual, expected;
|
7
|
+
|
8
|
+
beforeEach(function() {
|
9
|
+
I18n.reset();
|
10
|
+
I18n.translations = Translations();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("formats number with default settings", function(){
|
14
|
+
expect(I18n.toNumber(1)).toEqual("1.000");
|
15
|
+
expect(I18n.toNumber(12)).toEqual("12.000");
|
16
|
+
expect(I18n.toNumber(123)).toEqual("123.000");
|
17
|
+
expect(I18n.toNumber(1234)).toEqual("1,234.000");
|
18
|
+
expect(I18n.toNumber(12345)).toEqual("12,345.000");
|
19
|
+
expect(I18n.toNumber(123456)).toEqual("123,456.000");
|
20
|
+
expect(I18n.toNumber(1234567)).toEqual("1,234,567.000");
|
21
|
+
expect(I18n.toNumber(12345678)).toEqual("12,345,678.000");
|
22
|
+
expect(I18n.toNumber(123456789)).toEqual("123,456,789.000");
|
23
|
+
});
|
24
|
+
|
25
|
+
it("formats negative numbers with default settings", function(){
|
26
|
+
expect(I18n.toNumber(-1)).toEqual("-1.000");
|
27
|
+
expect(I18n.toNumber(-12)).toEqual("-12.000");
|
28
|
+
expect(I18n.toNumber(-123)).toEqual("-123.000");
|
29
|
+
expect(I18n.toNumber(-1234)).toEqual("-1,234.000");
|
30
|
+
expect(I18n.toNumber(-12345)).toEqual("-12,345.000");
|
31
|
+
expect(I18n.toNumber(-123456)).toEqual("-123,456.000");
|
32
|
+
expect(I18n.toNumber(-1234567)).toEqual("-1,234,567.000");
|
33
|
+
expect(I18n.toNumber(-12345678)).toEqual("-12,345,678.000");
|
34
|
+
expect(I18n.toNumber(-123456789)).toEqual("-123,456,789.000");
|
35
|
+
});
|
36
|
+
|
37
|
+
it("formats number with partial translation and default options", function(){
|
38
|
+
I18n.translations.en.number = {
|
39
|
+
format: {
|
40
|
+
precision: 2
|
41
|
+
}
|
42
|
+
};
|
43
|
+
|
44
|
+
expect(I18n.toNumber(1234)).toEqual("1,234.00");
|
45
|
+
});
|
46
|
+
|
47
|
+
it("formats number with full translation and default options", function(){
|
48
|
+
I18n.translations.en.number = {
|
49
|
+
format: {
|
50
|
+
delimiter: ".",
|
51
|
+
separator: ",",
|
52
|
+
precision: 2
|
53
|
+
}
|
54
|
+
};
|
55
|
+
|
56
|
+
expect(I18n.toNumber(1234)).toEqual("1.234,00");
|
57
|
+
});
|
58
|
+
|
59
|
+
it("formats numbers with some custom options that should be merged with default options", function(){
|
60
|
+
expect(I18n.toNumber(1234.56, {precision: 0})).toEqual("1,235");
|
61
|
+
expect(I18n.toNumber(1234, {separator: '-'})).toEqual("1,234-000");
|
62
|
+
expect(I18n.toNumber(1234, {delimiter: '_'})).toEqual("1_234.000");
|
63
|
+
});
|
64
|
+
|
65
|
+
it("formats number considering options", function(){
|
66
|
+
options = {
|
67
|
+
precision: 2,
|
68
|
+
separator: ",",
|
69
|
+
delimiter: "."
|
70
|
+
};
|
71
|
+
|
72
|
+
expect(I18n.toNumber(1, options)).toEqual("1,00");
|
73
|
+
expect(I18n.toNumber(12, options)).toEqual("12,00");
|
74
|
+
expect(I18n.toNumber(123, options)).toEqual("123,00");
|
75
|
+
expect(I18n.toNumber(1234, options)).toEqual("1.234,00");
|
76
|
+
expect(I18n.toNumber(123456, options)).toEqual("123.456,00");
|
77
|
+
expect(I18n.toNumber(1234567, options)).toEqual("1.234.567,00");
|
78
|
+
expect(I18n.toNumber(12345678, options)).toEqual("12.345.678,00");
|
79
|
+
});
|
80
|
+
|
81
|
+
it("formats numbers with different precisions", function(){
|
82
|
+
options = {separator: ".", delimiter: ","};
|
83
|
+
|
84
|
+
options["precision"] = 2;
|
85
|
+
expect(I18n.toNumber(1.98, options)).toEqual("1.98");
|
86
|
+
|
87
|
+
options["precision"] = 3;
|
88
|
+
expect(I18n.toNumber(1.98, options)).toEqual("1.980");
|
89
|
+
|
90
|
+
options["precision"] = 2;
|
91
|
+
expect(I18n.toNumber(1.987, options)).toEqual("1.99");
|
92
|
+
|
93
|
+
options["precision"] = 1;
|
94
|
+
expect(I18n.toNumber(1.98, options)).toEqual("2.0");
|
95
|
+
|
96
|
+
options["precision"] = 0;
|
97
|
+
expect(I18n.toNumber(1.98, options)).toEqual("2");
|
98
|
+
});
|
99
|
+
|
100
|
+
it("returns number as human size", function(){
|
101
|
+
var kb = 1024;
|
102
|
+
|
103
|
+
expect(I18n.toHumanSize(1)).toEqual("1Byte");
|
104
|
+
expect(I18n.toHumanSize(100)).toEqual("100Bytes");
|
105
|
+
|
106
|
+
expect(I18n.toHumanSize(kb)).toEqual("1KB");
|
107
|
+
expect(I18n.toHumanSize(kb * 1.5)).toEqual("1.5KB");
|
108
|
+
|
109
|
+
expect(I18n.toHumanSize(kb * kb)).toEqual("1MB");
|
110
|
+
expect(I18n.toHumanSize(kb * kb * 1.5)).toEqual("1.5MB");
|
111
|
+
|
112
|
+
expect(I18n.toHumanSize(kb * kb * kb)).toEqual("1GB");
|
113
|
+
expect(I18n.toHumanSize(kb * kb * kb * 1.5)).toEqual("1.5GB");
|
114
|
+
|
115
|
+
expect(I18n.toHumanSize(kb * kb * kb * kb)).toEqual("1TB");
|
116
|
+
expect(I18n.toHumanSize(kb * kb * kb * kb * 1.5)).toEqual("1.5TB");
|
117
|
+
|
118
|
+
expect(I18n.toHumanSize(kb * kb * kb * kb * kb)).toEqual("1024TB");
|
119
|
+
});
|
120
|
+
|
121
|
+
it("returns number as human size using custom options", function(){
|
122
|
+
expect(I18n.toHumanSize(1024 * 1.6, {precision: 0})).toEqual("2KB");
|
123
|
+
});
|
124
|
+
|
125
|
+
it("formats numbers with strip insignificant zero", function() {
|
126
|
+
options = {separator: ".", delimiter: ",", strip_insignificant_zeros: true};
|
127
|
+
|
128
|
+
options["precision"] = 2;
|
129
|
+
expect(I18n.toNumber(1.0, options)).toEqual("1");
|
130
|
+
|
131
|
+
options["precision"] = 3;
|
132
|
+
expect(I18n.toNumber(1.98, options)).toEqual("1.98");
|
133
|
+
|
134
|
+
options["precision"] = 4;
|
135
|
+
expect(I18n.toNumber(1.987, options)).toEqual("1.987");
|
136
|
+
});
|
137
|
+
|
138
|
+
it("keeps significant zeros [issue#103]", function() {
|
139
|
+
actual = I18n.toNumber(30, {strip_insignificant_zeros: true, precision: 0});
|
140
|
+
expect(actual).toEqual("30");
|
141
|
+
});
|
142
|
+
});
|
@@ -0,0 +1,24 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n");
|
2
|
+
|
3
|
+
describe("Placeholder", function(){
|
4
|
+
beforeEach(function(){
|
5
|
+
I18n.reset();
|
6
|
+
});
|
7
|
+
|
8
|
+
it("matches {{name}}", function(){
|
9
|
+
expect("{{name}}").toMatch(I18n.placeholder);
|
10
|
+
});
|
11
|
+
|
12
|
+
it("matches %{name}", function(){
|
13
|
+
expect("%{name}").toMatch(I18n.placeholder);
|
14
|
+
});
|
15
|
+
|
16
|
+
it("returns placeholders", function(){
|
17
|
+
var translation = "I like %{javascript}. I also like %{ruby}"
|
18
|
+
, matches = translation.match(I18n.placeholder);
|
19
|
+
;
|
20
|
+
|
21
|
+
expect(matches[0]).toEqual("%{javascript}");
|
22
|
+
expect(matches[1]).toEqual("%{ruby}");
|
23
|
+
});
|
24
|
+
});
|
@@ -0,0 +1,105 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n")
|
2
|
+
, Translations = require("./translations")
|
3
|
+
;
|
4
|
+
|
5
|
+
describe("Pluralization", function(){
|
6
|
+
var actual, expected;
|
7
|
+
|
8
|
+
beforeEach(function(){
|
9
|
+
I18n.reset();
|
10
|
+
I18n.translations = Translations();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("sets alias", function() {
|
14
|
+
expect(I18n.p).toEqual(I18n.pluralize);
|
15
|
+
});
|
16
|
+
|
17
|
+
it("pluralizes scope", function(){
|
18
|
+
expect(I18n.p(0, "inbox")).toEqual("You have no messages");
|
19
|
+
expect(I18n.p(1, "inbox")).toEqual("You have 1 message");
|
20
|
+
expect(I18n.p(5, "inbox")).toEqual("You have 5 messages");
|
21
|
+
});
|
22
|
+
|
23
|
+
it("pluralizes using the 'other' scope", function(){
|
24
|
+
I18n.translations["en"]["inbox"]["zero"] = null;
|
25
|
+
expect(I18n.p(0, "inbox")).toEqual("You have 0 messages");
|
26
|
+
});
|
27
|
+
|
28
|
+
it("pluralizes using the 'zero' scope", function(){
|
29
|
+
I18n.translations["en"]["inbox"]["zero"] = "No messages (zero)";
|
30
|
+
|
31
|
+
expect(I18n.p(0, "inbox")).toEqual("No messages (zero)");
|
32
|
+
});
|
33
|
+
|
34
|
+
it("pluralizes using negative values", function(){
|
35
|
+
expect(I18n.p(-1, "inbox")).toEqual("You have -1 message");
|
36
|
+
expect(I18n.p(-5, "inbox")).toEqual("You have -5 messages");
|
37
|
+
});
|
38
|
+
|
39
|
+
it("returns missing translation", function(){
|
40
|
+
expect(I18n.p(-1, "missing")).toEqual('[missing "en.missing" translation]');
|
41
|
+
});
|
42
|
+
|
43
|
+
it("pluralizes using multiple placeholders", function(){
|
44
|
+
actual = I18n.p(1, "unread", {unread: 5});
|
45
|
+
expect(actual).toEqual("You have 1 new message (5 unread)");
|
46
|
+
|
47
|
+
actual = I18n.p(10, "unread", {unread: 2});
|
48
|
+
expect(actual).toEqual("You have 10 new messages (2 unread)");
|
49
|
+
|
50
|
+
actual = I18n.p(0, "unread", {unread: 5});
|
51
|
+
expect(actual).toEqual("You have no new messages (5 unread)");
|
52
|
+
});
|
53
|
+
|
54
|
+
it("allows empty strings", function(){
|
55
|
+
I18n.translations["en"]["inbox"]["zero"] = "";
|
56
|
+
|
57
|
+
expect(I18n.p(0, "inbox")).toEqual("");
|
58
|
+
});
|
59
|
+
|
60
|
+
it("pluralizes using custom rules", function() {
|
61
|
+
I18n.locale = "custom";
|
62
|
+
|
63
|
+
I18n.pluralization["custom"] = function(count) {
|
64
|
+
if (count === 0) { return ["zero"]; }
|
65
|
+
if (count >= 1 && count <= 5) { return ["few", "other"]; }
|
66
|
+
return ["other"];
|
67
|
+
};
|
68
|
+
|
69
|
+
I18n.translations["custom"] = {
|
70
|
+
"things": {
|
71
|
+
"zero": "No things"
|
72
|
+
, "few": "A few things"
|
73
|
+
, "other": "%{count} things"
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
expect(I18n.p(0, "things")).toEqual("No things");
|
78
|
+
expect(I18n.p(4, "things")).toEqual("A few things");
|
79
|
+
expect(I18n.p(10, "things")).toEqual("10 things");
|
80
|
+
});
|
81
|
+
|
82
|
+
it("pluralizes default value", function(){
|
83
|
+
options = {defaultValue: {
|
84
|
+
zero: "No things here!"
|
85
|
+
, one: "There is {{count}} thing here!"
|
86
|
+
, other: "There are {{count}} things here!"
|
87
|
+
}};
|
88
|
+
|
89
|
+
expect(I18n.p(0, "things", options)).toEqual("No things here!");
|
90
|
+
expect(I18n.p(1, "things", options)).toEqual("There is 1 thing here!");
|
91
|
+
expect(I18n.p(5, "things", options)).toEqual("There are 5 things here!");
|
92
|
+
});
|
93
|
+
|
94
|
+
it("ignores pluralization when scope exists", function(){
|
95
|
+
options = {defaultValue: {
|
96
|
+
zero: "No things here!"
|
97
|
+
, one: "There is {{count}} thing here!"
|
98
|
+
, other: "There are {{count}} things here!"
|
99
|
+
}};
|
100
|
+
|
101
|
+
expect(I18n.p(0, "inbox", options)).toEqual("You have no messages");
|
102
|
+
expect(I18n.p(1, "inbox", options)).toEqual("You have 1 message");
|
103
|
+
expect(I18n.p(5, "inbox", options)).toEqual("You have 5 messages");
|
104
|
+
});
|
105
|
+
});
|
@@ -0,0 +1,41 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n");
|
2
|
+
|
3
|
+
describe("Prepare options", function(){
|
4
|
+
beforeEach(function(){
|
5
|
+
I18n.reset();
|
6
|
+
});
|
7
|
+
|
8
|
+
it("merges two objects", function(){
|
9
|
+
var options = I18n.prepareOptions(
|
10
|
+
{name: "Mary Doe"},
|
11
|
+
{name: "John Doe", role: "user"}
|
12
|
+
);
|
13
|
+
|
14
|
+
expect(options.name).toEqual("Mary Doe");
|
15
|
+
expect(options.role).toEqual("user");
|
16
|
+
});
|
17
|
+
|
18
|
+
it("merges multiple objects", function(){
|
19
|
+
var options = I18n.prepareOptions(
|
20
|
+
{name: "Mary Doe"},
|
21
|
+
{name: "John Doe", role: "user"},
|
22
|
+
{age: 33},
|
23
|
+
{email: "mary@doe.com", url: "http://marydoe.com"},
|
24
|
+
{role: "admin", email: "john@doe.com"}
|
25
|
+
);
|
26
|
+
|
27
|
+
expect(options.name).toEqual("Mary Doe");
|
28
|
+
expect(options.role).toEqual("user");
|
29
|
+
expect(options.age).toEqual(33);
|
30
|
+
expect(options.email).toEqual("mary@doe.com");
|
31
|
+
expect(options.url).toEqual("http://marydoe.com");
|
32
|
+
});
|
33
|
+
|
34
|
+
it("returns an empty object when values are null", function(){
|
35
|
+
expect(I18n.prepareOptions(null, null)).toEqual({});
|
36
|
+
});
|
37
|
+
|
38
|
+
it("returns an empty object when values are undefined", function(){
|
39
|
+
expect(I18n.prepareOptions(undefined, undefined)).toEqual({});
|
40
|
+
});
|
41
|
+
});
|
data/spec/js/specs.html
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<title>Jasmine Spec Runner</title>
|
6
|
+
<link rel="stylesheet" href="jasmine/jasmine.css" type="text/css">
|
7
|
+
</head>
|
8
|
+
|
9
|
+
<body>
|
10
|
+
<!-- load jasmine -->
|
11
|
+
<script type="text/javascript" src="jasmine/jasmine.js"></script>
|
12
|
+
<script type="text/javascript" src="jasmine/jasmine-html.js"></script>
|
13
|
+
|
14
|
+
<!-- load your javascript files -->
|
15
|
+
<script type="text/javascript" src="../../app/assets/javascripts/i18n.js"></script>
|
16
|
+
<script type="text/javascript">
|
17
|
+
function require(path) {
|
18
|
+
if (path.match(/i18n/)) {
|
19
|
+
return I18n;
|
20
|
+
} else {
|
21
|
+
return Translations;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
</script>
|
25
|
+
|
26
|
+
<!-- load your spec files -->
|
27
|
+
<script type="text/javascript" src="translations.js"></script>
|
28
|
+
<script type="text/javascript" src="currency.spec.js"></script>
|
29
|
+
<script type="text/javascript" src="current_locale.spec.js"></script>
|
30
|
+
<script type="text/javascript" src="dates.spec.js"></script>
|
31
|
+
<script type="text/javascript" src="defaults.spec.js"></script>
|
32
|
+
<script type="text/javascript" src="interpolation.spec.js"></script>
|
33
|
+
<script type="text/javascript" src="localization.spec.js"></script>
|
34
|
+
<script type="text/javascript" src="numbers.spec.js"></script>
|
35
|
+
<script type="text/javascript" src="placeholder.spec.js"></script>
|
36
|
+
<script type="text/javascript" src="pluralization.spec.js"></script>
|
37
|
+
<script type="text/javascript" src="prepare_options.spec.js"></script>
|
38
|
+
<script type="text/javascript" src="translate.spec.js"></script>
|
39
|
+
|
40
|
+
<!-- run specs -->
|
41
|
+
<script type="text/javascript">
|
42
|
+
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
43
|
+
jasmine.getEnv().execute();
|
44
|
+
</script>
|
45
|
+
</body>
|
46
|
+
</html>
|
@@ -0,0 +1,120 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n")
|
2
|
+
, Translations = require("./translations")
|
3
|
+
;
|
4
|
+
|
5
|
+
describe("Translate", function(){
|
6
|
+
var actual, expected;
|
7
|
+
|
8
|
+
beforeEach(function(){
|
9
|
+
I18n.reset();
|
10
|
+
I18n.translations = Translations();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("returns translation for single scope", function(){
|
14
|
+
expect(I18n.t("hello")).toEqual("Hello World!");
|
15
|
+
});
|
16
|
+
|
17
|
+
it("returns translation as object", function(){
|
18
|
+
expect(I18n.t("greetings")).toEqual(I18n.translations.en.greetings);
|
19
|
+
});
|
20
|
+
|
21
|
+
it("returns missing message translation for invalid scope", function(){
|
22
|
+
actual = I18n.t("invalid.scope");
|
23
|
+
expected = '[missing "en.invalid.scope" translation]';
|
24
|
+
expect(actual).toEqual(expected);
|
25
|
+
});
|
26
|
+
|
27
|
+
it("returns translation for single scope on a custom locale", function(){
|
28
|
+
I18n.locale = "pt-BR";
|
29
|
+
expect(I18n.t("hello")).toEqual("Olá Mundo!");
|
30
|
+
});
|
31
|
+
|
32
|
+
it("returns translation for multiple scopes", function(){
|
33
|
+
expect(I18n.t("greetings.stranger")).toEqual("Hello stranger!");
|
34
|
+
});
|
35
|
+
|
36
|
+
it("returns translation with default locale option", function(){
|
37
|
+
expect(I18n.t("hello", {locale: "en"})).toEqual("Hello World!");
|
38
|
+
expect(I18n.t("hello", {locale: "pt-BR"})).toEqual("Olá Mundo!");
|
39
|
+
});
|
40
|
+
|
41
|
+
it("fallbacks to the default locale when I18n.fallbackss is enabled", function(){
|
42
|
+
I18n.locale = "pt-BR";
|
43
|
+
I18n.fallbacks = true;
|
44
|
+
expect(I18n.t("greetings.stranger")).toEqual("Hello stranger!");
|
45
|
+
});
|
46
|
+
|
47
|
+
it("fallbacks to default locale when providing an unknown locale", function(){
|
48
|
+
I18n.locale = "fr";
|
49
|
+
I18n.fallbacks = true;
|
50
|
+
expect(I18n.t("greetings.stranger")).toEqual("Hello stranger!");
|
51
|
+
});
|
52
|
+
|
53
|
+
it("fallbacks to less specific locale", function(){
|
54
|
+
I18n.locale = "de-DE";
|
55
|
+
I18n.fallbacks = true;
|
56
|
+
expect(I18n.t("hello")).toEqual("Hallo Welt!");
|
57
|
+
});
|
58
|
+
|
59
|
+
it("fallbacks using custom rules (function)", function(){
|
60
|
+
I18n.locale = "no";
|
61
|
+
I18n.fallbacks = true;
|
62
|
+
I18n.locales["no"] = function() {
|
63
|
+
return ["nb"];
|
64
|
+
};
|
65
|
+
|
66
|
+
expect(I18n.t("hello")).toEqual("Hei Verden!");
|
67
|
+
});
|
68
|
+
|
69
|
+
it("fallbacks using custom rules (array)", function() {
|
70
|
+
I18n.locale = "no";
|
71
|
+
I18n.fallbacks = true;
|
72
|
+
I18n.locales["no"] = ["no", "nb"];
|
73
|
+
|
74
|
+
expect(I18n.t("hello")).toEqual("Hei Verden!");
|
75
|
+
});
|
76
|
+
|
77
|
+
it("fallbacks using custom rules (string)", function() {
|
78
|
+
I18n.locale = "no";
|
79
|
+
I18n.fallbacks = true;
|
80
|
+
I18n.locales["no"] = "nb";
|
81
|
+
|
82
|
+
expect(I18n.t("hello")).toEqual("Hei Verden!");
|
83
|
+
});
|
84
|
+
|
85
|
+
it("uses default value for simple translation", function(){
|
86
|
+
actual = I18n.t("warning", {defaultValue: "Warning!"});
|
87
|
+
expect(actual).toEqual("Warning!");
|
88
|
+
});
|
89
|
+
|
90
|
+
it("uses default value for unknown locale", function(){
|
91
|
+
I18n.locale = "fr";
|
92
|
+
actual = I18n.t("warning", {defaultValue: "Warning!"});
|
93
|
+
expect(actual).toEqual("Warning!");
|
94
|
+
});
|
95
|
+
|
96
|
+
it("uses default value with interpolation", function(){
|
97
|
+
actual = I18n.t(
|
98
|
+
"alert",
|
99
|
+
{defaultValue: "Attention! {{message}}", message: "You're out of quota!"}
|
100
|
+
);
|
101
|
+
|
102
|
+
expect(actual).toEqual("Attention! You're out of quota!");
|
103
|
+
});
|
104
|
+
|
105
|
+
it("ignores default value when scope exists", function(){
|
106
|
+
actual = I18n.t("hello", {defaultValue: "What's up?"});
|
107
|
+
expect(actual).toEqual("Hello World!");
|
108
|
+
});
|
109
|
+
|
110
|
+
it("returns translation for custom scope separator", function(){
|
111
|
+
I18n.defaultSeparator = "•";
|
112
|
+
actual = I18n.t("greetings•stranger");
|
113
|
+
expect(actual).toEqual("Hello stranger!");
|
114
|
+
});
|
115
|
+
|
116
|
+
it("returns boolean values", function() {
|
117
|
+
expect(I18n.t("booleans.yes")).toEqual(true);
|
118
|
+
expect(I18n.t("booleans.no")).toEqual(false);
|
119
|
+
});
|
120
|
+
});
|
@@ -0,0 +1,120 @@
|
|
1
|
+
;(function(){
|
2
|
+
var generator = function() {
|
3
|
+
var Translations = {};
|
4
|
+
|
5
|
+
Translations.en = {
|
6
|
+
hello: "Hello World!"
|
7
|
+
|
8
|
+
, booleans: {
|
9
|
+
yes: true,
|
10
|
+
no: false
|
11
|
+
}
|
12
|
+
|
13
|
+
, greetings: {
|
14
|
+
stranger: "Hello stranger!"
|
15
|
+
, name: "Hello {{name}}!"
|
16
|
+
}
|
17
|
+
|
18
|
+
, profile: {
|
19
|
+
details: "{{name}} is {{age}}-years old"
|
20
|
+
}
|
21
|
+
|
22
|
+
, inbox: {
|
23
|
+
one: "You have {{count}} message"
|
24
|
+
, other: "You have {{count}} messages"
|
25
|
+
, zero: "You have no messages"
|
26
|
+
}
|
27
|
+
|
28
|
+
, unread: {
|
29
|
+
one: "You have 1 new message ({{unread}} unread)"
|
30
|
+
, other: "You have {{count}} new messages ({{unread}} unread)"
|
31
|
+
, zero: "You have no new messages ({{unread}} unread)"
|
32
|
+
}
|
33
|
+
|
34
|
+
, number: {
|
35
|
+
human: {
|
36
|
+
storage_units: {
|
37
|
+
units: {
|
38
|
+
"byte": {
|
39
|
+
one: "Byte"
|
40
|
+
, other: "Bytes"
|
41
|
+
}
|
42
|
+
, "kb": "KB"
|
43
|
+
, "mb": "MB"
|
44
|
+
, "gb": "GB"
|
45
|
+
, "tb": "TB"
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
};
|
51
|
+
|
52
|
+
Translations["en-US"] = {
|
53
|
+
date: {
|
54
|
+
formats: {
|
55
|
+
"default": "%d/%m/%Y"
|
56
|
+
, "short": "%d de %B"
|
57
|
+
, "long": "%d de %B de %Y"
|
58
|
+
}
|
59
|
+
|
60
|
+
, day_names: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
61
|
+
, abbr_day_names: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
|
62
|
+
, month_names: [null, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
|
63
|
+
, abbr_month_names: [null, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]
|
64
|
+
, meridian: ["am", "pm"]
|
65
|
+
}
|
66
|
+
};
|
67
|
+
|
68
|
+
Translations["pt-BR"] = {
|
69
|
+
hello: "Olá Mundo!"
|
70
|
+
|
71
|
+
, number: {
|
72
|
+
percentage: {
|
73
|
+
format: {
|
74
|
+
delimiter: ""
|
75
|
+
, separator: ","
|
76
|
+
, precision: 2
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
, date: {
|
82
|
+
formats: {
|
83
|
+
"default": "%d/%m/%Y"
|
84
|
+
, "short": "%d de %B"
|
85
|
+
, "long": "%d de %B de %Y"
|
86
|
+
}
|
87
|
+
, day_names: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"]
|
88
|
+
, abbr_day_names: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"]
|
89
|
+
, month_names: [null, "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"]
|
90
|
+
, abbr_month_names: [null, "Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
|
91
|
+
}
|
92
|
+
|
93
|
+
, time: {
|
94
|
+
formats: {
|
95
|
+
"default": "%A, %d de %B de %Y, %H:%M h"
|
96
|
+
, "short": "%d/%m, %H:%M h"
|
97
|
+
, "long": "%A, %d de %B de %Y, %H:%M h"
|
98
|
+
}
|
99
|
+
, am: "AM"
|
100
|
+
, pm: "PM"
|
101
|
+
}
|
102
|
+
};
|
103
|
+
|
104
|
+
Translations["de"] = {
|
105
|
+
hello: "Hallo Welt!"
|
106
|
+
};
|
107
|
+
|
108
|
+
Translations["nb"] = {
|
109
|
+
hello: "Hei Verden!"
|
110
|
+
};
|
111
|
+
|
112
|
+
return Translations;
|
113
|
+
};
|
114
|
+
|
115
|
+
if (typeof(exports) === "undefined") {
|
116
|
+
window.Translations = generator;
|
117
|
+
} else {
|
118
|
+
module.exports = generator;
|
119
|
+
}
|
120
|
+
})();
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "i18n"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
require "active_support/all"
|
5
|
+
require "i18n/js"
|
6
|
+
|
7
|
+
module Helpers
|
8
|
+
# Set the configuration as the current one
|
9
|
+
def set_config(path)
|
10
|
+
config = HashWithIndifferentAccess.new(YAML.load_file(File.dirname(__FILE__) + "/fixtures/#{path}"))
|
11
|
+
I18n::JS.stub(:config? => true, :config => config)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Shortcut to I18n::JS.translations
|
15
|
+
def translations
|
16
|
+
I18n::JS.translations
|
17
|
+
end
|
18
|
+
|
19
|
+
def file_should_exist(name)
|
20
|
+
file_path = File.join(I18n::JS.export_dir, name)
|
21
|
+
File.should be_file(file_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def temp_path(file_name = "")
|
25
|
+
File.expand_path("../../tmp/i18n-js/#{file_name}", __FILE__)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
RSpec.configure do |config|
|
30
|
+
config.before do
|
31
|
+
I18n.load_path = [File.dirname(__FILE__) + "/fixtures/locales.yml"]
|
32
|
+
FileUtils.rm_rf(temp_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
config.after do
|
36
|
+
FileUtils.rm_rf(temp_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
config.include Helpers
|
40
|
+
end
|
41
|
+
|