socialcast-i18n-js 4.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/Gemfile +2 -0
- data/README.md +324 -0
- data/README.rdoc +320 -0
- data/Rakefile +13 -0
- data/app/assets/javascripts/i18n/translations.js.erb +6 -0
- data/app/assets/javascripts/i18n.js +661 -0
- data/config/i18n-js.yml +22 -0
- data/i18n-js.gemspec +28 -0
- data/lib/i18n/js/engine.rb +6 -0
- data/lib/i18n/js/file_dependency_processor.rb +17 -0
- data/lib/i18n/js/railtie.rb +17 -0
- data/lib/i18n/js/translator.rb +56 -0
- data/lib/i18n/js/version.rb +10 -0
- data/lib/i18n-js/engine.rb +63 -0
- data/lib/i18n-js/middleware.rb +59 -0
- data/lib/i18n-js/railtie.rb +13 -0
- data/lib/i18n-js/rake.rb +16 -0
- data/lib/i18n-js/version.rb +10 -0
- data/lib/i18n-js.rb +22 -0
- data/lib/tasks/i18n-js.rake +17 -0
- data/spec/file_dependency_processor_spec.rb +32 -0
- data/spec/fixtures/custom_path.yml +2 -0
- data/spec/fixtures/default.yml +2 -0
- data/spec/fixtures/js_file_per_locale.yml +1 -0
- data/spec/fixtures/locales.yml +76 -0
- data/spec/fixtures/multiple_conditions.yml +3 -0
- data/spec/fixtures/no_config.yml +2 -0
- data/spec/fixtures/simple_scope.yml +2 -0
- data/spec/i18n_js_spec.rb +11 -0
- data/spec/i18n_spec.js +820 -0
- data/spec/i18n_spec.rb +205 -0
- data/spec/js/currency.spec.js +60 -0
- data/spec/js/current_locale.spec.js +19 -0
- data/spec/js/dates.spec.js +218 -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 +124 -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 +119 -0
- data/spec/js/translations.js +115 -0
- data/spec/resources/custom_path.yml +4 -0
- data/spec/resources/default.yml +4 -0
- data/spec/resources/js_file_per_locale.yml +3 -0
- data/spec/resources/locales.yml +76 -0
- data/spec/resources/multiple_conditions.yml +6 -0
- data/spec/resources/multiple_files.yml +6 -0
- data/spec/resources/no_config.yml +2 -0
- data/spec/resources/no_scope.yml +3 -0
- data/spec/resources/simple_scope.yml +4 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/translator_spec.rb +45 -0
- data/vendor/assets/javascripts/i18n/translations.js.erb +9 -0
- data/vendor/assets/javascripts/i18n.js +531 -0
- data/vendor/assets/javascripts/underscore.js +1059 -0
- metadata +240 -0
data/spec/i18n_spec.rb
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
if File.basename(Rails.root) != "tmp"
|
4
|
+
abort <<-TXT
|
5
|
+
\e[31;5m
|
6
|
+
WARNING: That will remove your project!
|
7
|
+
Please go to #{File.expand_path(File.dirname(__FILE__) + "/..")} and run `rake spec`\e[0m
|
8
|
+
TXT
|
9
|
+
end
|
10
|
+
|
11
|
+
describe SimplesIdeias::I18n do
|
12
|
+
before do
|
13
|
+
# Remove temporary directory if already present
|
14
|
+
FileUtils.rm_r(Rails.root) if File.exist?(Rails.root)
|
15
|
+
|
16
|
+
# Create temporary directory to test the files generation
|
17
|
+
%w( config public/javascripts ).each do |path|
|
18
|
+
FileUtils.mkdir_p Rails.root.join(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Overwrite defaut locales path to use fixtures
|
22
|
+
I18n.load_path = [File.dirname(__FILE__) + "/resources/locales.yml"]
|
23
|
+
end
|
24
|
+
|
25
|
+
after do
|
26
|
+
# Remove temporary directory
|
27
|
+
FileUtils.rm_r(Rails.root)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "copies the configuration file" do
|
31
|
+
File.should_not be_file(SimplesIdeias::I18n.config_file)
|
32
|
+
SimplesIdeias::I18n.setup!
|
33
|
+
File.should be_file(SimplesIdeias::I18n.config_file)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "keeps existing configuration file" do
|
37
|
+
File.open(SimplesIdeias::I18n.config_file, "w+") {|f| f << "ORIGINAL"}
|
38
|
+
SimplesIdeias::I18n.setup!
|
39
|
+
|
40
|
+
File.read(SimplesIdeias::I18n.config_file).should == "ORIGINAL"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "copies JavaScript library" do
|
44
|
+
path = Rails.root.join("public/javascripts/i18n.js")
|
45
|
+
|
46
|
+
File.should_not be_file(path)
|
47
|
+
SimplesIdeias::I18n.setup!
|
48
|
+
File.should be_file(path)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "loads configuration file" do
|
52
|
+
set_config "default.yml"
|
53
|
+
SimplesIdeias::I18n.setup!
|
54
|
+
|
55
|
+
SimplesIdeias::I18n.config?.should be_true
|
56
|
+
SimplesIdeias::I18n.config.should be_kind_of(HashWithIndifferentAccess)
|
57
|
+
SimplesIdeias::I18n.config.should_not be_empty
|
58
|
+
end
|
59
|
+
|
60
|
+
it "sets empty hash as configuration when no file is found" do
|
61
|
+
SimplesIdeias::I18n.config?.should be_false
|
62
|
+
SimplesIdeias::I18n.config.should == {}
|
63
|
+
end
|
64
|
+
|
65
|
+
it "exports messages to default path when configuration file doesn't exist" do
|
66
|
+
SimplesIdeias::I18n.export!
|
67
|
+
Rails.root.join(SimplesIdeias::I18n.export_dir, "translations.js").should be_file
|
68
|
+
end
|
69
|
+
|
70
|
+
it "exports messages using custom output path" do
|
71
|
+
set_config "custom_path.yml"
|
72
|
+
SimplesIdeias::I18n.should_receive(:save).with(translations, "public/javascripts/translations/all.js")
|
73
|
+
SimplesIdeias::I18n.export!
|
74
|
+
end
|
75
|
+
|
76
|
+
it "sets default scope to * when not specified" do
|
77
|
+
set_config "no_scope.yml"
|
78
|
+
SimplesIdeias::I18n.should_receive(:save).with(translations, "public/javascripts/no_scope.js")
|
79
|
+
SimplesIdeias::I18n.export!
|
80
|
+
end
|
81
|
+
|
82
|
+
it "exports to multiple files" do
|
83
|
+
set_config "multiple_files.yml"
|
84
|
+
SimplesIdeias::I18n.export!
|
85
|
+
|
86
|
+
File.should be_file(Rails.root.join("public/javascripts/all.js"))
|
87
|
+
File.should be_file(Rails.root.join("public/javascripts/tudo.js"))
|
88
|
+
end
|
89
|
+
|
90
|
+
it "ignores an empty config file" do
|
91
|
+
set_config "no_config.yml"
|
92
|
+
SimplesIdeias::I18n.export!
|
93
|
+
Rails.root.join(SimplesIdeias::I18n.export_dir, "translations.js").should be_file
|
94
|
+
end
|
95
|
+
|
96
|
+
it "exports to a JS file per available locale" do
|
97
|
+
set_config "js_file_per_locale.yml"
|
98
|
+
SimplesIdeias::I18n.export!
|
99
|
+
|
100
|
+
File.should be_file(Rails.root.join("public/javascripts/i18n/en.js"))
|
101
|
+
end
|
102
|
+
|
103
|
+
it "exports with multiple conditions" do
|
104
|
+
set_config "multiple_conditions.yml"
|
105
|
+
SimplesIdeias::I18n.export!
|
106
|
+
File.should be_file(Rails.root.join("public/javascripts/bitsnpieces.js"))
|
107
|
+
end
|
108
|
+
|
109
|
+
it "filters translations using scope *.date.formats" do
|
110
|
+
result = SimplesIdeias::I18n.filter(translations, "*.date.formats")
|
111
|
+
result[:en][:date].keys.should == [:formats]
|
112
|
+
result[:fr][:date].keys.should == [:formats]
|
113
|
+
end
|
114
|
+
|
115
|
+
it "filters translations using scope [*.date.formats, *.number.currency.format]" do
|
116
|
+
result = SimplesIdeias::I18n.scoped_translations(["*.date.formats", "*.number.currency.format"])
|
117
|
+
result[:en].keys.collect(&:to_s).sort.should == %w[ date number ]
|
118
|
+
result[:fr].keys.collect(&:to_s).sort.should == %w[ date number ]
|
119
|
+
end
|
120
|
+
|
121
|
+
it "filters translations using multi-star scope" do
|
122
|
+
result = SimplesIdeias::I18n.scoped_translations("*.*.formats")
|
123
|
+
|
124
|
+
result[:en].keys.collect(&:to_s).sort.should == %w[ date time ]
|
125
|
+
result[:fr].keys.collect(&:to_s).sort.should == %w[ date time ]
|
126
|
+
|
127
|
+
result[:en][:date].keys.should == [:formats]
|
128
|
+
result[:en][:time].keys.should == [:formats]
|
129
|
+
|
130
|
+
result[:fr][:date].keys.should == [:formats]
|
131
|
+
result[:fr][:time].keys.should == [:formats]
|
132
|
+
end
|
133
|
+
|
134
|
+
it "filters translations using alternated stars" do
|
135
|
+
result = SimplesIdeias::I18n.scoped_translations("*.admin.*.title")
|
136
|
+
|
137
|
+
result[:en][:admin].keys.collect(&:to_s).sort.should == %w[ edit show ]
|
138
|
+
result[:fr][:admin].keys.collect(&:to_s).sort.should == %w[ edit show ]
|
139
|
+
|
140
|
+
result[:en][:admin][:show][:title].should == "Show"
|
141
|
+
result[:fr][:admin][:show][:title].should == "Visualiser"
|
142
|
+
|
143
|
+
result[:en][:admin][:edit][:title].should == "Edit"
|
144
|
+
result[:fr][:admin][:edit][:title].should == "Editer"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "performs a deep merge" do
|
148
|
+
target = {:a => {:b => 1}}
|
149
|
+
result = SimplesIdeias::I18n.deep_merge(target, {:a => {:c => 2}})
|
150
|
+
|
151
|
+
result[:a].should == {:b => 1, :c => 2}
|
152
|
+
end
|
153
|
+
|
154
|
+
it "performs a banged deep merge" do
|
155
|
+
target = {:a => {:b => 1}}
|
156
|
+
SimplesIdeias::I18n.deep_merge!(target, {:a => {:c => 2}})
|
157
|
+
|
158
|
+
target[:a].should == {:b => 1, :c => 2}
|
159
|
+
end
|
160
|
+
|
161
|
+
it "updates the javascript library" do
|
162
|
+
FakeWeb.register_uri(:get, "https://raw.github.com/fnando/i18n-js/master/vendor/assets/javascripts/i18n.js", :body => "UPDATED")
|
163
|
+
|
164
|
+
SimplesIdeias::I18n.setup!
|
165
|
+
SimplesIdeias::I18n.update!
|
166
|
+
File.read(SimplesIdeias::I18n.javascript_file).should == "UPDATED"
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#export_dir" do
|
170
|
+
it "detects asset pipeline support" do
|
171
|
+
SimplesIdeias::I18n.stub :has_asset_pipeline? => true
|
172
|
+
SimplesIdeias::I18n.export_dir == "vendor/assets/javascripts"
|
173
|
+
end
|
174
|
+
|
175
|
+
it "detects older Rails" do
|
176
|
+
SimplesIdeias::I18n.stub :has_asset_pipeline? => false
|
177
|
+
SimplesIdeias::I18n.export_dir.to_s.should == "public/javascripts"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#has_asset_pipeline?" do
|
182
|
+
it "detects support" do
|
183
|
+
Rails.stub_chain(:configuration, :assets, :enabled => true)
|
184
|
+
SimplesIdeias::I18n.should have_asset_pipeline
|
185
|
+
end
|
186
|
+
|
187
|
+
it "skips support" do
|
188
|
+
SimplesIdeias::I18n.should_not have_asset_pipeline
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
# Set the configuration as the current one
|
194
|
+
def set_config(path)
|
195
|
+
config = HashWithIndifferentAccess.new(YAML.load_file(File.dirname(__FILE__) + "/resources/#{path}"))
|
196
|
+
SimplesIdeias::I18n.stub(:config? => true)
|
197
|
+
SimplesIdeias::I18n.stub(:config => config)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Shortcut to SimplesIdeias::I18n.translations
|
201
|
+
def translations
|
202
|
+
SimplesIdeias::I18n.translations
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n")
|
2
|
+
, Translations = require("./translations")
|
3
|
+
;
|
4
|
+
|
5
|
+
describe("Currency", function(){
|
6
|
+
var actual, expected;
|
7
|
+
|
8
|
+
beforeEach(function() {
|
9
|
+
I18n.reset();
|
10
|
+
I18n.translations = Translations();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("formats currency with default settings", function(){
|
14
|
+
expect(I18n.toCurrency(100.99)).toEqual("$100.99");
|
15
|
+
expect(I18n.toCurrency(1000.99)).toEqual("$1,000.99");
|
16
|
+
});
|
17
|
+
|
18
|
+
it("formats currency with custom settings", function(){
|
19
|
+
I18n.translations.en.number = {
|
20
|
+
currency: {
|
21
|
+
format: {
|
22
|
+
format: "%n %u",
|
23
|
+
unit: "USD",
|
24
|
+
delimiter: ".",
|
25
|
+
separator: ",",
|
26
|
+
precision: 2
|
27
|
+
}
|
28
|
+
}
|
29
|
+
};
|
30
|
+
|
31
|
+
expect(I18n.toCurrency(12)).toEqual("12,00 USD");
|
32
|
+
expect(I18n.toCurrency(123)).toEqual("123,00 USD");
|
33
|
+
expect(I18n.toCurrency(1234.56)).toEqual("1.234,56 USD");
|
34
|
+
});
|
35
|
+
|
36
|
+
it("formats currency with custom settings and partial overriding", function(){
|
37
|
+
I18n.translations.en.number = {
|
38
|
+
currency: {
|
39
|
+
format: {
|
40
|
+
format: "%n %u",
|
41
|
+
unit: "USD",
|
42
|
+
delimiter: ".",
|
43
|
+
separator: ",",
|
44
|
+
precision: 2
|
45
|
+
}
|
46
|
+
}
|
47
|
+
};
|
48
|
+
|
49
|
+
expect(I18n.toCurrency(12, {precision: 0})).toEqual("12 USD");
|
50
|
+
expect(I18n.toCurrency(123, {unit: "bucks"})).toEqual("123,00 bucks");
|
51
|
+
});
|
52
|
+
|
53
|
+
it("formats currency with some custom options that should be merged with default options", function(){
|
54
|
+
expect(I18n.toCurrency(1234, {precision: 0})).toEqual("$1,234");
|
55
|
+
expect(I18n.toCurrency(1234, {unit: "º"})).toEqual("º1,234.00");
|
56
|
+
expect(I18n.toCurrency(1234, {separator: "-"})).toEqual("$1,234-00");
|
57
|
+
expect(I18n.toCurrency(1234, {delimiter: "-"})).toEqual("$1-234.00");
|
58
|
+
expect(I18n.toCurrency(1234, {format: "%u %n"})).toEqual("$ 1,234.00");
|
59
|
+
});
|
60
|
+
});
|
@@ -0,0 +1,19 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n");
|
2
|
+
|
3
|
+
describe("Current locale", function(){
|
4
|
+
beforeEach(function(){
|
5
|
+
I18n.reset();
|
6
|
+
});
|
7
|
+
|
8
|
+
it("returns I18n.locale", function(){
|
9
|
+
I18n.locale = "pt-BR";
|
10
|
+
expect(I18n.currentLocale()).toEqual("pt-BR");
|
11
|
+
});
|
12
|
+
|
13
|
+
it("returns I18n.defaultLocale", function(){
|
14
|
+
I18n.locale = null;
|
15
|
+
I18n.defaultLocale = "pt-BR";
|
16
|
+
|
17
|
+
expect(I18n.currentLocale()).toEqual("pt-BR");
|
18
|
+
});
|
19
|
+
});
|
@@ -0,0 +1,218 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n")
|
2
|
+
, Translations = require("./translations")
|
3
|
+
;
|
4
|
+
|
5
|
+
describe("Dates", function(){
|
6
|
+
var actual, expected;
|
7
|
+
|
8
|
+
beforeEach(function() {
|
9
|
+
I18n.reset();
|
10
|
+
I18n.translations = Translations();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("parses date", function(){
|
14
|
+
expected = new Date(2009, 0, 24, 0, 0, 0);
|
15
|
+
actual = I18n.parseDate("2009-01-24");
|
16
|
+
expect(actual.toString()).toEqual(expected.toString());
|
17
|
+
|
18
|
+
expected = new Date(2009, 0, 24, 0, 15, 0);
|
19
|
+
actual = I18n.parseDate("2009-01-24 00:15:00");
|
20
|
+
expect(actual.toString()).toEqual(expected.toString());
|
21
|
+
|
22
|
+
expected = new Date(2009, 0, 24, 0, 0, 15);
|
23
|
+
actual = I18n.parseDate("2009-01-24 00:00:15");
|
24
|
+
expect(actual.toString()).toEqual(expected.toString());
|
25
|
+
|
26
|
+
expected = new Date(2009, 0, 24, 15, 33, 44);
|
27
|
+
actual = I18n.parseDate("2009-01-24 15:33:44");
|
28
|
+
expect(actual.toString()).toEqual(expected.toString());
|
29
|
+
|
30
|
+
expected = new Date(2009, 0, 24, 0, 0, 0);
|
31
|
+
actual = I18n.parseDate(expected.getTime());
|
32
|
+
expect(actual.toString()).toEqual(expected.toString());
|
33
|
+
|
34
|
+
expected = new Date(2009, 0, 24, 0, 0, 0);
|
35
|
+
actual = I18n.parseDate("01/24/2009");
|
36
|
+
expect(actual.toString()).toEqual(expected.toString());
|
37
|
+
|
38
|
+
expected = new Date(2009, 0, 24, 14, 33, 55);
|
39
|
+
actual = I18n.parseDate(expected).toString();
|
40
|
+
expect(actual).toEqual(expected.toString());
|
41
|
+
|
42
|
+
expected = new Date(2009, 0, 24, 15, 33, 44);
|
43
|
+
actual = I18n.parseDate("2009-01-24T15:33:44");
|
44
|
+
expect(actual.toString()).toEqual(expected.toString());
|
45
|
+
|
46
|
+
expected = new Date(Date.UTC(2011, 6, 20, 12, 51, 55));
|
47
|
+
actual = I18n.parseDate("2011-07-20T12:51:55+0000");
|
48
|
+
expect(actual.toString()).toEqual(expected.toString());
|
49
|
+
|
50
|
+
expected = new Date(Date.UTC(2011, 6, 20, 13, 03, 39));
|
51
|
+
actual = I18n.parseDate("Wed Jul 20 13:03:39 +0000 2011");
|
52
|
+
expect(actual.toString()).toEqual(expected.toString());
|
53
|
+
|
54
|
+
expected = new Date(Date.UTC(2009, 0, 24, 15, 33, 44));
|
55
|
+
actual = I18n.parseDate("2009-01-24T15:33:44Z");
|
56
|
+
expect(actual.toString()).toEqual(expected.toString());
|
57
|
+
});
|
58
|
+
|
59
|
+
it("formats date", function(){
|
60
|
+
I18n.locale = "pt-BR";
|
61
|
+
|
62
|
+
// 2009-04-26 19:35:44 (Sunday)
|
63
|
+
var date = new Date(2009, 3, 26, 19, 35, 44);
|
64
|
+
|
65
|
+
// short week day
|
66
|
+
expect(I18n.strftime(date, "%a")).toEqual("Dom");
|
67
|
+
|
68
|
+
// full week day
|
69
|
+
expect(I18n.strftime(date, "%A")).toEqual("Domingo");
|
70
|
+
|
71
|
+
// short month
|
72
|
+
expect(I18n.strftime(date, "%b")).toEqual("Abr");
|
73
|
+
|
74
|
+
// full month
|
75
|
+
expect(I18n.strftime(date, "%B")).toEqual("Abril");
|
76
|
+
|
77
|
+
// day
|
78
|
+
expect(I18n.strftime(date, "%d")).toEqual("26");
|
79
|
+
|
80
|
+
// 24-hour
|
81
|
+
expect(I18n.strftime(date, "%H")).toEqual("19");
|
82
|
+
|
83
|
+
// 12-hour
|
84
|
+
expect(I18n.strftime(date, "%I")).toEqual("07");
|
85
|
+
|
86
|
+
// month
|
87
|
+
expect(I18n.strftime(date, "%m")).toEqual("04");
|
88
|
+
|
89
|
+
// minutes
|
90
|
+
expect(I18n.strftime(date, "%M")).toEqual("35");
|
91
|
+
|
92
|
+
// meridian
|
93
|
+
expect(I18n.strftime(date, "%p")).toEqual("PM");
|
94
|
+
|
95
|
+
// seconds
|
96
|
+
expect(I18n.strftime(date, "%S")).toEqual("44");
|
97
|
+
|
98
|
+
// week day
|
99
|
+
expect(I18n.strftime(date, "%w")).toEqual("0");
|
100
|
+
|
101
|
+
// short year
|
102
|
+
expect(I18n.strftime(date, "%y")).toEqual("09");
|
103
|
+
|
104
|
+
// full year
|
105
|
+
expect(I18n.strftime(date, "%Y")).toEqual("2009");
|
106
|
+
});
|
107
|
+
|
108
|
+
it("formats date without padding", function(){
|
109
|
+
I18n.locale = "pt-BR";
|
110
|
+
|
111
|
+
// 2009-04-26 19:35:44 (Sunday)
|
112
|
+
var date = new Date(2009, 3, 9, 7, 8, 9);
|
113
|
+
|
114
|
+
// 24-hour without padding
|
115
|
+
expect(I18n.strftime(date, "%-H")).toEqual("7");
|
116
|
+
|
117
|
+
// 12-hour without padding
|
118
|
+
expect(I18n.strftime(date, "%-I")).toEqual("7");
|
119
|
+
|
120
|
+
// minutes without padding
|
121
|
+
expect(I18n.strftime(date, "%-M")).toEqual("8");
|
122
|
+
|
123
|
+
// seconds without padding
|
124
|
+
expect(I18n.strftime(date, "%-S")).toEqual("9");
|
125
|
+
|
126
|
+
// short year without padding
|
127
|
+
expect(I18n.strftime(date, "%-y")).toEqual("9");
|
128
|
+
|
129
|
+
// month without padding
|
130
|
+
expect(I18n.strftime(date, "%-m")).toEqual("4");
|
131
|
+
|
132
|
+
// day without padding
|
133
|
+
expect(I18n.strftime(date, "%-d")).toEqual("9");
|
134
|
+
expect(I18n.strftime(date, "%e")).toEqual("9");
|
135
|
+
});
|
136
|
+
|
137
|
+
it("formats date with padding", function(){
|
138
|
+
I18n.locale = "pt-BR";
|
139
|
+
|
140
|
+
// 2009-04-26 19:35:44 (Sunday)
|
141
|
+
var date = new Date(2009, 3, 9, 7, 8, 9);
|
142
|
+
|
143
|
+
// 24-hour
|
144
|
+
expect(I18n.strftime(date, "%H")).toEqual("07");
|
145
|
+
|
146
|
+
// 12-hour
|
147
|
+
expect(I18n.strftime(date, "%I")).toEqual("07");
|
148
|
+
|
149
|
+
// minutes
|
150
|
+
expect(I18n.strftime(date, "%M")).toEqual("08");
|
151
|
+
|
152
|
+
// seconds
|
153
|
+
expect(I18n.strftime(date, "%S")).toEqual("09");
|
154
|
+
|
155
|
+
// short year
|
156
|
+
expect(I18n.strftime(date, "%y")).toEqual("09");
|
157
|
+
|
158
|
+
// month
|
159
|
+
expect(I18n.strftime(date, "%m")).toEqual("04");
|
160
|
+
|
161
|
+
// day
|
162
|
+
expect(I18n.strftime(date, "%d")).toEqual("09");
|
163
|
+
});
|
164
|
+
|
165
|
+
it("formats date with negative time zone", function(){
|
166
|
+
I18n.locale = "pt-BR";
|
167
|
+
var date = new Date(2009, 3, 26, 19, 35, 44);
|
168
|
+
|
169
|
+
spyOn(date, "getTimezoneOffset").andReturn(345);
|
170
|
+
|
171
|
+
expect(I18n.strftime(date, "%z")).toMatch(/^(\+|-)[\d]{4}$/);
|
172
|
+
expect(I18n.strftime(date, "%z")).toEqual("-0545");
|
173
|
+
});
|
174
|
+
|
175
|
+
it("formats date with positive time zone", function(){
|
176
|
+
I18n.locale = "pt-BR";
|
177
|
+
var date = new Date(2009, 3, 26, 19, 35, 44);
|
178
|
+
|
179
|
+
spyOn(date, "getTimezoneOffset").andReturn(-345);
|
180
|
+
|
181
|
+
expect(I18n.strftime(date, "%z")).toMatch(/^(\+|-)[\d]{4}$/);
|
182
|
+
expect(I18n.strftime(date, "%z")).toEqual("+0545");
|
183
|
+
});
|
184
|
+
|
185
|
+
it("formats date with custom meridian", function(){
|
186
|
+
I18n.locale = "en-US";
|
187
|
+
var date = new Date(2009, 3, 26, 19, 35, 44);
|
188
|
+
expect(I18n.strftime(date, "%p")).toEqual("pm");
|
189
|
+
});
|
190
|
+
|
191
|
+
it("formats date with meridian boundaries", function(){
|
192
|
+
I18n.locale = "en-US";
|
193
|
+
var date = new Date(2009, 3, 26, 0, 35, 44);
|
194
|
+
expect(I18n.strftime(date, "%p")).toEqual("am");
|
195
|
+
|
196
|
+
date = new Date(2009, 3, 26, 12, 35, 44);
|
197
|
+
expect(I18n.strftime(date, "%p")).toEqual("pm");
|
198
|
+
});
|
199
|
+
|
200
|
+
it("formats date using 12-hours format", function(){
|
201
|
+
I18n.locale = "pt-BR";
|
202
|
+
var date = new Date(2009, 3, 26, 19, 35, 44);
|
203
|
+
expect(I18n.strftime(date, "%I")).toEqual("07");
|
204
|
+
|
205
|
+
date = new Date(2009, 3, 26, 12, 35, 44);
|
206
|
+
expect(I18n.strftime(date, "%I")).toEqual("12");
|
207
|
+
|
208
|
+
date = new Date(2009, 3, 26, 0, 35, 44);
|
209
|
+
expect(I18n.strftime(date, "%I")).toEqual("12");
|
210
|
+
});
|
211
|
+
|
212
|
+
it("defaults to English", function() {
|
213
|
+
I18n.locale = "wk";
|
214
|
+
|
215
|
+
var date = new Date(2009, 3, 26, 19, 35, 44);
|
216
|
+
expect(I18n.strftime(date, "%a")).toEqual("Sun");
|
217
|
+
});
|
218
|
+
});
|
@@ -0,0 +1,23 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n");
|
2
|
+
|
3
|
+
describe("Defaults", function(){
|
4
|
+
beforeEach(function(){
|
5
|
+
I18n.reset();
|
6
|
+
});
|
7
|
+
|
8
|
+
it("sets the default locale", function(){
|
9
|
+
expect(I18n.defaultLocale).toEqual("en");
|
10
|
+
});
|
11
|
+
|
12
|
+
it("sets current locale", function(){
|
13
|
+
expect(I18n.locale).toEqual("en");
|
14
|
+
});
|
15
|
+
|
16
|
+
it("sets default separator", function(){
|
17
|
+
expect(I18n.defaultSeparator).toEqual(".");
|
18
|
+
});
|
19
|
+
|
20
|
+
it("sets fallback", function(){
|
21
|
+
expect(I18n.fallbacks).toEqual(false);
|
22
|
+
});
|
23
|
+
});
|
@@ -0,0 +1,28 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n")
|
2
|
+
, Translations = require("./translations")
|
3
|
+
;
|
4
|
+
|
5
|
+
describe("Interpolation", function(){
|
6
|
+
var actual, expected;
|
7
|
+
|
8
|
+
beforeEach(function(){
|
9
|
+
I18n.reset();
|
10
|
+
I18n.translations = Translations();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("performs single interpolation", function(){
|
14
|
+
actual = I18n.t("greetings.name", {name: "John Doe"});
|
15
|
+
expect(actual).toEqual("Hello John Doe!");
|
16
|
+
});
|
17
|
+
|
18
|
+
it("performs multiple interpolations", function(){
|
19
|
+
actual = I18n.t("profile.details", {name: "John Doe", age: 27});
|
20
|
+
expect(actual).toEqual("John Doe is 27-years old");
|
21
|
+
});
|
22
|
+
|
23
|
+
it("performs interpolation with the count option", function(){
|
24
|
+
expect(I18n.t("inbox", {count: 0})).toEqual("You have no messages");
|
25
|
+
expect(I18n.t("inbox", {count: 1})).toEqual("You have 1 message");
|
26
|
+
expect(I18n.t("inbox", {count: 5})).toEqual("You have 5 messages");
|
27
|
+
});
|
28
|
+
});
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008-2011 Pivotal Labs
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|