twitter_cldr 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +32 -0
- data/History.txt +78 -0
- data/README.md +72 -62
- data/Rakefile +22 -0
- data/js/lib/compiler.rb +40 -0
- data/js/lib/mustache/bundle.coffee +14 -0
- data/js/lib/mustache/calendars/datetime.coffee +240 -0
- data/js/lib/mustache/calendars/timespan.coffee +52 -0
- data/js/lib/mustache/plurals/rules.coffee +14 -0
- data/js/lib/renderers/base.rb +18 -0
- data/js/lib/renderers/bundle.rb +18 -0
- data/js/lib/renderers/calendars/datetime_renderer.rb +34 -0
- data/js/lib/renderers/calendars/timespan_renderer.rb +39 -0
- data/js/lib/renderers/plurals/rules/plural_rules_compiler.rb +89 -0
- data/js/lib/renderers/plurals/rules/plural_rules_renderer.rb +26 -0
- data/js/lib/twitter_cldr_js.rb +85 -0
- data/js/spec/js/calendars/datetime_spec.js +418 -0
- data/js/spec/js/calendars/timespan_spec.js +91 -0
- data/js/spec/js/plurals/plural_rules_spec.js +28 -0
- data/js/spec/js/support/jasmine.yml +8 -0
- data/js/spec/rb/renderers/plurals/plural_rules_compiler_spec.rb +52 -0
- data/js/spec/rb/spec_helper.rb +13 -0
- data/lib/twitter_cldr.rb +2 -1
- data/lib/twitter_cldr/collation.rb +2 -1
- data/lib/twitter_cldr/collation/collator.rb +49 -31
- data/lib/twitter_cldr/collation/{sort_key.rb → sort_key_builder.rb} +31 -8
- data/lib/twitter_cldr/collation/trie.rb +116 -24
- data/lib/twitter_cldr/collation/trie_builder.rb +54 -28
- data/lib/twitter_cldr/collation/trie_with_fallback.rb +55 -0
- data/lib/twitter_cldr/core_ext/array.rb +14 -1
- data/lib/twitter_cldr/core_ext/calendars/datetime.rb +8 -2
- data/lib/twitter_cldr/core_ext/calendars/timespan.rb +5 -5
- data/lib/twitter_cldr/formatters/calendars/timespan_formatter.rb +10 -10
- data/lib/twitter_cldr/formatters/plurals/rules.rb +3 -5
- data/lib/twitter_cldr/resources.rb +11 -0
- data/lib/twitter_cldr/resources/import.rb +12 -0
- data/lib/twitter_cldr/resources/import/tailoring.rb +193 -0
- data/lib/twitter_cldr/{shared/resources.rb → resources/loader.rb} +17 -4
- data/lib/twitter_cldr/shared.rb +0 -1
- data/lib/twitter_cldr/tokenizers/base.rb +9 -9
- data/lib/twitter_cldr/tokenizers/calendars/datetime_tokenizer.rb +0 -4
- data/lib/twitter_cldr/tokenizers/calendars/timespan_tokenizer.rb +21 -7
- data/lib/twitter_cldr/utils.rb +11 -0
- data/lib/twitter_cldr/version.rb +1 -1
- data/resources/collation/tailoring/af.yml +3 -0
- data/resources/collation/tailoring/ar.yml +21 -0
- data/resources/collation/tailoring/ca.yml +9 -0
- data/resources/collation/tailoring/cs.yml +25 -0
- data/resources/collation/tailoring/da.yml +59 -0
- data/resources/collation/tailoring/de.yml +3 -0
- data/resources/collation/tailoring/el.yml +3 -0
- data/resources/collation/tailoring/en.yml +3 -0
- data/resources/collation/tailoring/es.yml +5 -0
- data/resources/collation/tailoring/eu.yml +3 -0
- data/resources/collation/tailoring/fa.yml +73 -0
- data/resources/collation/tailoring/fi.yml +61 -0
- data/resources/collation/tailoring/fil.yml +11 -0
- data/resources/collation/tailoring/fr.yml +3 -0
- data/resources/collation/tailoring/he.yml +3 -0
- data/resources/collation/tailoring/hi.yml +7 -0
- data/resources/collation/tailoring/hu.yml +125 -0
- data/resources/collation/tailoring/id.yml +3 -0
- data/resources/collation/tailoring/it.yml +3 -0
- data/resources/collation/tailoring/ja.yml +14647 -0
- data/resources/collation/tailoring/ko.yml +14953 -0
- data/resources/collation/tailoring/ms.yml +3 -0
- data/resources/collation/tailoring/nb.yml +59 -0
- data/resources/collation/tailoring/nl.yml +3 -0
- data/resources/collation/tailoring/pl.yml +37 -0
- data/resources/collation/tailoring/pt.yml +3 -0
- data/resources/collation/tailoring/ru.yml +3 -0
- data/resources/collation/tailoring/sv.yml +63 -0
- data/resources/collation/tailoring/th.yml +19 -0
- data/resources/collation/tailoring/tr.yml +27 -0
- data/resources/collation/tailoring/uk.yml +5 -0
- data/resources/collation/tailoring/ur.yml +163 -0
- data/resources/collation/tailoring/zh-Hant.yml +3 -0
- data/resources/collation/tailoring/zh.yml +149 -0
- data/resources/custom/locales/af/units.yml +19 -0
- data/resources/custom/locales/ar/units.yml +35 -0
- data/resources/custom/locales/ca/units.yml +19 -0
- data/resources/custom/locales/cs/units.yml +23 -0
- data/resources/custom/locales/da/units.yml +19 -0
- data/resources/custom/locales/de/units.yml +19 -0
- data/resources/custom/locales/el/units.yml +19 -0
- data/resources/custom/locales/en/units.yml +18 -0
- data/resources/custom/locales/es/units.yml +19 -0
- data/resources/custom/locales/eu/units.yml +19 -0
- data/resources/custom/locales/fa/units.yml +15 -0
- data/resources/custom/locales/fi/units.yml +19 -0
- data/resources/custom/locales/fil/units.yml +19 -0
- data/resources/custom/locales/fr/units.yml +19 -0
- data/resources/custom/locales/he/units.yml +19 -0
- data/resources/custom/locales/hi/units.yml +19 -0
- data/resources/custom/locales/hu/units.yml +15 -0
- data/resources/custom/locales/id/units.yml +15 -0
- data/resources/custom/locales/it/units.yml +19 -0
- data/resources/custom/locales/ja/units.yml +15 -0
- data/resources/custom/locales/ko/units.yml +15 -0
- data/resources/custom/locales/ms/units.yml +15 -0
- data/resources/custom/locales/nb/units.yml +19 -0
- data/resources/custom/locales/nl/units.yml +19 -0
- data/resources/custom/locales/pl/units.yml +23 -0
- data/resources/custom/locales/pt/units.yml +19 -0
- data/resources/custom/locales/ru/units.yml +27 -0
- data/resources/custom/locales/sv/units.yml +19 -0
- data/resources/custom/locales/th/units.yml +15 -0
- data/resources/custom/locales/tr/units.yml +15 -0
- data/resources/custom/locales/uk/units.yml +27 -0
- data/resources/custom/locales/ur/units.yml +19 -0
- data/resources/custom/locales/zh-Hant/units.yml +15 -0
- data/resources/custom/locales/zh/units.yml +15 -0
- data/resources/locales/af/units.yml +112 -65
- data/resources/locales/ar/units.yml +196 -126
- data/resources/locales/ca/units.yml +112 -70
- data/resources/locales/cs/units.yml +140 -91
- data/resources/locales/da/units.yml +98 -56
- data/resources/locales/de/units.yml +112 -70
- data/resources/locales/el/units.yml +119 -84
- data/resources/locales/en/units.yml +84 -42
- data/resources/locales/es/units.yml +112 -70
- data/resources/locales/eu/units.yml +105 -68
- data/resources/locales/fa/units.yml +98 -63
- data/resources/locales/fi/units.yml +112 -70
- data/resources/locales/fil/units.yml +98 -56
- data/resources/locales/fr/units.yml +112 -70
- data/resources/locales/he/units.yml +98 -56
- data/resources/locales/hi/units.yml +98 -56
- data/resources/locales/hu/units.yml +84 -49
- data/resources/locales/id/units.yml +84 -49
- data/resources/locales/it/units.yml +98 -56
- data/resources/locales/ja/units.yml +84 -49
- data/resources/locales/ko/units.yml +84 -49
- data/resources/locales/ms/units.yml +112 -63
- data/resources/locales/nb/units.yml +106 -64
- data/resources/locales/nl/units.yml +98 -56
- data/resources/locales/pl/units.yml +181 -112
- data/resources/locales/pt/units.yml +112 -70
- data/resources/locales/ru/units.yml +168 -112
- data/resources/locales/sv/units.yml +112 -70
- data/resources/locales/th/units.yml +84 -49
- data/resources/locales/tr/units.yml +84 -49
- data/resources/locales/uk/units.yml +168 -112
- data/resources/locales/ur/units.yml +112 -63
- data/resources/locales/zh-Hant/units.yml +84 -49
- data/resources/locales/zh/units.yml +84 -49
- data/spec/collation/collation_spec.rb +1 -1
- data/spec/collation/collator_spec.rb +120 -48
- data/spec/collation/sort_key_builder_spec.rb +80 -0
- data/spec/collation/tailoring_spec.rb +137 -0
- data/spec/collation/tailoring_tests/af.txt +321 -0
- data/spec/collation/tailoring_tests/ar.txt +188 -0
- data/spec/collation/tailoring_tests/ca.txt +446 -0
- data/spec/collation/tailoring_tests/cs.txt +273 -0
- data/spec/collation/tailoring_tests/da.txt +293 -0
- data/spec/collation/tailoring_tests/de.txt +414 -0
- data/spec/collation/tailoring_tests/el.txt +228 -0
- data/spec/collation/tailoring_tests/en.txt +399 -0
- data/spec/collation/tailoring_tests/es.txt +402 -0
- data/spec/collation/tailoring_tests/eu.txt +183 -0
- data/spec/collation/tailoring_tests/fa.txt +263 -0
- data/spec/collation/tailoring_tests/fi.txt +389 -0
- data/spec/collation/tailoring_tests/fil.txt +279 -0
- data/spec/collation/tailoring_tests/fr.txt +363 -0
- data/spec/collation/tailoring_tests/he.txt +167 -0
- data/spec/collation/tailoring_tests/hi.txt +230 -0
- data/spec/collation/tailoring_tests/hu.txt +773 -0
- data/spec/collation/tailoring_tests/id.txt +171 -0
- data/spec/collation/tailoring_tests/it.txt +231 -0
- data/spec/collation/tailoring_tests/ja.txt +4287 -0
- data/spec/collation/tailoring_tests/ko.txt +1761 -0
- data/spec/collation/tailoring_tests/ms.txt +531 -0
- data/spec/collation/tailoring_tests/nb.txt +375 -0
- data/spec/collation/tailoring_tests/nl.txt +273 -0
- data/spec/collation/tailoring_tests/pl.txt +225 -0
- data/spec/collation/tailoring_tests/pt.txt +405 -0
- data/spec/collation/tailoring_tests/ru.txt +213 -0
- data/spec/collation/tailoring_tests/sv.txt +353 -0
- data/spec/collation/tailoring_tests/th.txt +239 -0
- data/spec/collation/tailoring_tests/tr.txt +414 -0
- data/spec/collation/tailoring_tests/uk.txt +218 -0
- data/spec/collation/tailoring_tests/ur.txt +284 -0
- data/spec/collation/tailoring_tests/zh-Hant.txt +626 -0
- data/spec/collation/tailoring_tests/zh.txt +717 -0
- data/spec/collation/trie_builder_spec.rb +131 -51
- data/spec/collation/trie_spec.rb +301 -26
- data/spec/collation/trie_with_fallback_spec.rb +41 -0
- data/spec/core_ext/array_spec.rb +46 -3
- data/spec/core_ext/calendars/date_spec.rb +24 -24
- data/spec/core_ext/calendars/datetime_spec.rb +7 -0
- data/spec/core_ext/calendars/time_spec.rb +2 -2
- data/spec/formatters/calendars/timespan_formatter_spec.rb +47 -18
- data/spec/formatters/plurals/rules_spec.rb +3 -11
- data/spec/readme_spec.rb +15 -15
- data/spec/resources/loader_spec.rb +94 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/tokenizers/calendars/timespan_tokenizer_spec.rb +1 -1
- data/spec/twitter_cldr_spec.rb +3 -3
- data/spec/utils_spec.rb +38 -0
- data/twitter_cldr.gemspec +25 -0
- metadata +156 -110
- data/spec/collation/sort_key_spec.rb +0 -56
- data/spec/shared/resources_spec.rb +0 -75
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2012 Twitter, Inc
|
4
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
5
|
+
|
6
|
+
require 'spec_helper'
|
7
|
+
|
8
|
+
include TwitterCldr::Collation
|
9
|
+
|
10
|
+
describe TrieWithFallback do
|
11
|
+
|
12
|
+
let(:fallback) { Trie.new }
|
13
|
+
let(:trie) { TrieWithFallback.new(fallback) }
|
14
|
+
|
15
|
+
before(:each) { trie.add([1, 2, 3], 'value') }
|
16
|
+
|
17
|
+
describe '#get' do
|
18
|
+
it 'returns result if the key is present' do
|
19
|
+
dont_allow(fallback).get
|
20
|
+
trie.get([1, 2, 3]).should == 'value'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'resorts to the fallback if the key is not present' do
|
24
|
+
mock(fallback).get([3, 2, 1]) { 'fallback-value' }
|
25
|
+
trie.get([3, 2, 1]).should == 'fallback-value'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#find_prefix' do
|
30
|
+
it 'returns result if the key is present' do
|
31
|
+
dont_allow(fallback).find_prefix
|
32
|
+
trie.find_prefix([1, 2, 3, 4]).first(2).should == ['value', 3]
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'resorts to the fallback if the key is not present' do
|
36
|
+
mock(fallback).find_prefix([3, 2, 1]) { 'fallback-result' }
|
37
|
+
trie.find_prefix([3, 2, 1]).should == 'fallback-result'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/core_ext/array_spec.rb
CHANGED
@@ -8,9 +8,52 @@ require 'spec_helper'
|
|
8
8
|
include TwitterCldr
|
9
9
|
|
10
10
|
describe LocalizedArray do
|
11
|
-
describe
|
12
|
-
it
|
13
|
-
[
|
11
|
+
describe '#code_points_to_string' do
|
12
|
+
it 'transforms an array of code points into a string' do
|
13
|
+
%w[0074 0077 0069 0074 0074 0065 0072].localize.code_points_to_string.should == 'twitter'
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
describe 'strings sorting' do
|
18
|
+
let(:locale) { :da }
|
19
|
+
let(:array) { %w[bca aaa abc] }
|
20
|
+
let(:sorted) { %w[aaa abc bca] }
|
21
|
+
let(:localized) { array.localize(locale) }
|
22
|
+
|
23
|
+
before(:each) { mock(TwitterCldr::Collation::Collator).new(locale) { FakeCollator.new } }
|
24
|
+
|
25
|
+
describe '#sort' do
|
26
|
+
it 'returns a new LocalizedArray' do
|
27
|
+
localized.sort.should be_instance_of(LocalizedArray)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'does not change the original array' do
|
31
|
+
lambda { localized.sort }.should_not change { localized.base_obj }
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'sorts strings in the array with corresponding collator' do
|
35
|
+
localized.sort.base_obj.should == sorted
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#sort!' do
|
40
|
+
it 'returns self' do
|
41
|
+
localized.sort!.object_id.should == localized.object_id
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'sorts the array in-place' do
|
45
|
+
localized.sort!.base_obj.should == sorted
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class FakeCollator
|
52
|
+
def sort(array)
|
53
|
+
array.sort
|
54
|
+
end
|
55
|
+
|
56
|
+
def sort!(array)
|
57
|
+
array.sort!
|
58
|
+
end
|
16
59
|
end
|
@@ -47,41 +47,41 @@ describe Date do
|
|
47
47
|
it "should ago-ify from now when no base_time given" do
|
48
48
|
stub(Time).now { Time.gm(2010,8,6,12,12,30) }
|
49
49
|
loc_date = date.localize(:ko)
|
50
|
-
loc_date.ago(:unit => :hour).should
|
50
|
+
loc_date.ago.to_s(:unit => :hour).should match_normalized("756시간 전")
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should ago-ify with appropriate unit when no unit given" do
|
54
54
|
loc_date = date.localize(:en)
|
55
|
-
loc_date.ago(:base_time => base_time).should
|
56
|
-
loc_date.ago(:base_time => Time.gm(2010,12,6,12,12,30)).should
|
57
|
-
loc_date.ago(:base_time => Time.gm(2010,7,7,12,12,30)).should
|
58
|
-
loc_date.ago(:base_time => Time.gm(2010,7,6,12,12,30)).should
|
59
|
-
loc_date.ago(:base_time => Time.gm(2010,7,6,0,39,0)).should
|
55
|
+
loc_date.ago(:base_time => base_time).to_s.should match_normalized("1 month ago")
|
56
|
+
loc_date.ago(:base_time => Time.gm(2010,12,6,12,12,30)).to_s.should match_normalized("5 months ago")
|
57
|
+
loc_date.ago(:base_time => Time.gm(2010,7,7,12,12,30)).to_s.should match_normalized("1 day ago")
|
58
|
+
loc_date.ago(:base_time => Time.gm(2010,7,6,12,12,30)).to_s.should match_normalized("12 hours ago")
|
59
|
+
loc_date.ago(:base_time => Time.gm(2010,7,6,0,39,0)).to_s.should match_normalized("39 minutes ago")
|
60
60
|
end
|
61
61
|
|
62
62
|
it "should ago-ify with strings regardless of variable's placement or existence" do
|
63
63
|
loc_date = date.localize(:ar)
|
64
|
-
loc_date.ago(:base_time => base_time
|
65
|
-
loc_date.ago(:base_time => base_time
|
66
|
-
loc_date.ago(:base_time => base_time
|
67
|
-
loc_date.ago(:base_time => base_time
|
64
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :hour).should match_normalized("قبل 756 ساعة")
|
65
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("قبل 31 يومًا")
|
66
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :month).should match_normalized("قبل شهر واحد")
|
67
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :year).should match_normalized("قبل 0 سنة")
|
68
68
|
|
69
69
|
loc_date = date.localize(:fa)
|
70
|
-
loc_date.ago(:base_time => base_time
|
70
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("31 روز پیش")
|
71
71
|
|
72
72
|
loc_date = date.localize(:en)
|
73
|
-
loc_date.ago(:base_time => base_time
|
73
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("31 days ago")
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should ago-ify a date with a number of different units" do
|
77
77
|
date = Date.new(2010,6,6)
|
78
78
|
loc_date = date.localize(:de)
|
79
|
-
loc_date.ago(:base_time => base_time
|
80
|
-
loc_date.ago(:base_time => base_time
|
81
|
-
loc_date.ago(:base_time => base_time
|
82
|
-
loc_date.ago(:base_time => base_time
|
83
|
-
loc_date.ago(:base_time => base_time
|
84
|
-
loc_date.ago(:base_time => base_time
|
79
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :second).should match_normalized("Vor 5314350 Sekunden")
|
80
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :minute).should match_normalized("Vor 88572 Minuten")
|
81
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :hour).should match_normalized("Vor 1476 Stunden")
|
82
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("Vor 61 Tagen")
|
83
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :month).should match_normalized("Vor 2 Monaten")
|
84
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :year).should match_normalized("Vor 0 Jahren")
|
85
85
|
end
|
86
86
|
|
87
87
|
it "should return an error if called on a date in the future" do
|
@@ -97,12 +97,12 @@ describe Date do
|
|
97
97
|
it "should until-ify with a number of different units" do
|
98
98
|
date = Date.new(2010,10,10)
|
99
99
|
loc_date = date.localize(:de)
|
100
|
-
loc_date.until(:base_time => base_time
|
101
|
-
loc_date.until(:base_time => base_time
|
102
|
-
loc_date.until(:base_time => base_time
|
103
|
-
loc_date.until(:base_time => base_time
|
104
|
-
loc_date.until(:base_time => base_time
|
105
|
-
loc_date.until(:base_time => base_time
|
100
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :second).should match_normalized("In 5572050 Sekunden")
|
101
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :minute).should match_normalized("In 92867 Minuten")
|
102
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :hour).should match_normalized("In 1547 Stunden")
|
103
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :day).should match_normalized("In 64 Tagen")
|
104
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :month).should match_normalized("In 2 Monaten")
|
105
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :year).should match_normalized("In 0 Jahren")
|
106
106
|
end
|
107
107
|
|
108
108
|
it "should return an error if called on a date in the past" do
|
@@ -80,4 +80,11 @@ describe LocalizedDateTime do
|
|
80
80
|
time.base_obj.getgm.strftime("%H:%M:%S").should == "22:05:00"
|
81
81
|
end
|
82
82
|
end
|
83
|
+
|
84
|
+
describe "#to_timespan" do
|
85
|
+
it "should return a localized timespan with a direction of :none" do
|
86
|
+
ts = DateTime.new(1987, 9, 20, 22, 5).localize.to_timespan
|
87
|
+
ts.formatter.instance_variable_get(:'@direction').should == :none
|
88
|
+
end
|
89
|
+
end
|
83
90
|
end
|
@@ -64,8 +64,8 @@ describe "#ago" do
|
|
64
64
|
time = Time.now
|
65
65
|
base_time = time + 172800
|
66
66
|
loc_time = time.localize(:de)
|
67
|
-
loc_time.ago(
|
68
|
-
loc_time.ago(
|
67
|
+
loc_time.ago(:base_time => base_time).to_s(:unit => :hour).should match_normalized("Vor 48 Stunden")
|
68
|
+
loc_time.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("Vor 2 Tagen")
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -12,27 +12,56 @@ describe TimespanFormatter do
|
|
12
12
|
describe "#format" do
|
13
13
|
let(:formatter) { TimespanFormatter.new(:locale => :de) }
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
context "default type" do
|
16
|
+
describe "non-directional" do
|
17
|
+
it "works for a variety of units" do
|
18
|
+
formatter.format(3273932, :unit => :year, :direction => :none).should match_normalized('0 Jahre')
|
19
|
+
formatter.format(3273932, :unit => :month, :direction => :none).should match_normalized('1 Monat')
|
20
|
+
formatter.format(3273932, :unit => :week, :direction => :none).should match_normalized('5 Wochen')
|
21
|
+
formatter.format(3273932, :unit => :day, :direction => :none).should match_normalized('37 Tage')
|
22
|
+
formatter.format(3273932, :unit => :hour, :direction => :none).should match_normalized('909 Stunden')
|
23
|
+
formatter.format(3273932, :unit => :minute, :direction => :none).should match_normalized('54565 Minuten')
|
24
|
+
formatter.format(3273932, :unit => :second, :direction => :none).should match_normalized('3273932 Sekunden')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#ago" do
|
29
|
+
it "works for a variety of units" do
|
30
|
+
formatter.format(-3273932, :unit => :year).should match_normalized('Vor 0 Jahren')
|
31
|
+
formatter.format(-3273932, :unit => :month).should match_normalized('Vor 1 Monat')
|
32
|
+
formatter.format(-3273932, :unit => :week).should match_normalized('Vor 5 Wochen')
|
33
|
+
formatter.format(-3273932, :unit => :day).should match_normalized('Vor 37 Tagen')
|
34
|
+
formatter.format(-3273932, :unit => :hour).should match_normalized('Vor 909 Stunden')
|
35
|
+
formatter.format(-3273932, :unit => :minute).should match_normalized('Vor 54565 Minuten')
|
36
|
+
formatter.format(-3273932, :unit => :second).should match_normalized('Vor 3273932 Sekunden')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#until" do
|
41
|
+
it "works for a variety of units" do
|
42
|
+
formatter.format(3273932, :unit => :year).should match_normalized('In 0 Jahren')
|
43
|
+
formatter.format(3273932, :unit => :month).should match_normalized('In 1 Monat')
|
44
|
+
formatter.format(3273932, :unit => :week).should match_normalized('In 5 Wochen')
|
45
|
+
formatter.format(3273932, :unit => :day).should match_normalized('In 37 Tagen')
|
46
|
+
formatter.format(3273932, :unit => :hour).should match_normalized('In 909 Stunden')
|
47
|
+
formatter.format(3273932, :unit => :minute).should match_normalized('In 54565 Minuten')
|
48
|
+
formatter.format(3273932, :unit => :second).should match_normalized('In 3273932 Sekunden')
|
49
|
+
end
|
24
50
|
end
|
25
51
|
end
|
26
52
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
53
|
+
context "abbreviated type" do
|
54
|
+
let(:options) { { :type => :abbreviated } }
|
55
|
+
|
56
|
+
# Note: non-directional timespans are the only ones that support the abbreviated type (i.e. ago and until cannot be abbreviated)
|
57
|
+
describe "non-directional" do
|
58
|
+
it "works for a variety of units" do
|
59
|
+
# year/month/week not supported
|
60
|
+
formatter.format(3273932, options.merge(:unit => :day, :direction => :none)).should match_normalized('37d')
|
61
|
+
formatter.format(3273932, options.merge(:unit => :hour, :direction => :none)).should match_normalized('909h')
|
62
|
+
formatter.format(3273932, options.merge(:unit => :minute, :direction => :none)).should match_normalized('54565m')
|
63
|
+
formatter.format(3273932, options.merge(:unit => :second, :direction => :none)).should match_normalized('3273932s')
|
64
|
+
end
|
36
65
|
end
|
37
66
|
end
|
38
67
|
end
|
@@ -12,17 +12,9 @@ describe Rules do
|
|
12
12
|
it "calls eval on the hash that gets returned, lambdas and all" do
|
13
13
|
result = Rules.send(:get_resource, :ru)
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
plural = result[:ru][:i18n][:plural]
|
21
|
-
|
22
|
-
plural.should include(:keys, :rule)
|
23
|
-
|
24
|
-
plural[:keys].size.should == 4
|
25
|
-
plural[:rule].should be_a(Proc)
|
15
|
+
result.should include(:keys, :rule)
|
16
|
+
result[:keys].size.should == 4
|
17
|
+
result[:rule].should be_a(Proc)
|
26
18
|
end
|
27
19
|
end
|
28
20
|
|
data/spec/readme_spec.rb
CHANGED
@@ -75,28 +75,28 @@ describe "README" do
|
|
75
75
|
end
|
76
76
|
|
77
77
|
it "verifies relative time spans" do
|
78
|
-
(DateTime.now - 1).localize.ago.should
|
79
|
-
(DateTime.now - 0.5).localize.ago.should
|
78
|
+
(DateTime.now - 1).localize.ago.to_s.should match_normalized("1 day ago")
|
79
|
+
(DateTime.now - 0.5).localize.ago.to_s.should match_normalized("12 hours ago") # (i.e. half a day)
|
80
80
|
|
81
|
-
(DateTime.now + 1).localize.until.should
|
82
|
-
(DateTime.now + 0.5).localize.until.should
|
81
|
+
(DateTime.now + 1).localize.until.to_s.should match_normalized("In 1 day")
|
82
|
+
(DateTime.now + 0.5).localize.until.to_s.should match_normalized("In 12 hours")
|
83
83
|
|
84
|
-
(DateTime.now - 1).localize(:de).ago.should
|
85
|
-
(DateTime.now + 1).localize(:de).until.should
|
84
|
+
(DateTime.now - 1).localize(:de).ago.to_s.should match_normalized("Vor 1 Tag")
|
85
|
+
(DateTime.now + 1).localize(:de).until.to_s.should match_normalized("In 1 Tag")
|
86
86
|
|
87
|
-
(DateTime.now - 1).localize(:de).ago(:unit => :hour).should
|
88
|
-
(DateTime.now + 1).localize(:de).until(:unit => :hour).should
|
87
|
+
(DateTime.now - 1).localize(:de).ago.to_s(:unit => :hour).should match_normalized("Vor 24 Stunden")
|
88
|
+
(DateTime.now + 1).localize(:de).until.to_s(:unit => :hour).should match_normalized("In 24 Stunden")
|
89
89
|
|
90
90
|
# 86400 = 1 day in seconds, 259200 = 3 days in seconds
|
91
|
-
(Time.now + 86400).localize(:de).ago(:
|
91
|
+
(Time.now + 86400).localize(:de).ago(:base_time => (Time.now + 259200)).to_s(:unit => :hour).should match_normalized("Vor 48 Stunden")
|
92
92
|
|
93
|
-
ts = TwitterCldr::LocalizedTimespan.new(86400, :de)
|
94
|
-
ts.to_s.should
|
95
|
-
ts.to_s(:hour).should
|
93
|
+
ts = TwitterCldr::LocalizedTimespan.new(86400, :locale => :de)
|
94
|
+
ts.to_s.should match_normalized("In 1 Tag")
|
95
|
+
ts.to_s(:unit => :hour).should match_normalized("In 24 Stunden")
|
96
96
|
|
97
|
-
ts = TwitterCldr::LocalizedTimespan.new(-86400, :de)
|
98
|
-
ts.to_s.should
|
99
|
-
ts.to_s(:hour).should
|
97
|
+
ts = TwitterCldr::LocalizedTimespan.new(-86400, :locale => :de)
|
98
|
+
ts.to_s.should match_normalized("Vor 1 Tag")
|
99
|
+
ts.to_s(:unit => :hour).should match_normalized("Vor 24 Stunden")
|
100
100
|
end
|
101
101
|
|
102
102
|
it "verifies plural rules" do
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2012 Twitter, Inc
|
4
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
5
|
+
|
6
|
+
require 'spec_helper'
|
7
|
+
|
8
|
+
include TwitterCldr::Resources
|
9
|
+
|
10
|
+
describe Loader do
|
11
|
+
let(:loader) { Loader.new }
|
12
|
+
|
13
|
+
describe '#get_resource' do
|
14
|
+
let(:resource_path) { 'random/resource.yml' }
|
15
|
+
let(:resource_content) { 'random YAML content' }
|
16
|
+
|
17
|
+
it 'loads the correct YAML file' do
|
18
|
+
stub_resource_file(resource_path, "---\n- 1\n- 2\n")
|
19
|
+
loader.get_resource(:random, :resource).should == [1, 2]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'symbolizes hash keys' do
|
23
|
+
stub_resource_file(resource_path, "---\na:\n b: 3\n")
|
24
|
+
loader.get_resource(:random, :resource).should == { :a => { :b => 3 } }
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'loads the resource only once' do
|
28
|
+
mock(loader).load_resource(resource_path).once { resource_content }
|
29
|
+
|
30
|
+
result = loader.get_resource(:random, :resource)
|
31
|
+
result.should == resource_content
|
32
|
+
# second time load_resource is not called but we get the same object as before
|
33
|
+
loader.get_resource(:random, :resource).object_id.should == result.object_id
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'accepts a variable length resource path both in symbols and strings' do
|
37
|
+
stub(loader).load_resource('foo/bar/baz.yml') { 'foo-bar-baz' }
|
38
|
+
loader.get_resource('foo', :bar, 'baz').should == 'foo-bar-baz'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'raises an exception if resource file is missing' do
|
42
|
+
mock(File).file?(File.join(TwitterCldr::RESOURCES_DIR, 'foo/bar.yml')) { false }
|
43
|
+
lambda { loader.get_resource(:foo, :bar) }.should raise_error(ArgumentError, "Resource 'foo/bar.yml' not found.")
|
44
|
+
end
|
45
|
+
|
46
|
+
context "custom resources" do
|
47
|
+
it "doesn't merge the custom resource if it doesn't exist" do
|
48
|
+
mock(loader).read_resource_file('foo/bar.yml') { "foo: bar" }
|
49
|
+
loader.get_resource(:foo, :bar).should == { :foo => "bar" }
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'merges the given file with its corresponding custom resource if it exists' do
|
53
|
+
mock(loader).read_resource_file('foo/bar.yml') { "foo: bar" }
|
54
|
+
mock(loader).resource_exists?('custom/foo/bar.yml') { true }
|
55
|
+
mock(loader).read_resource_file('custom/foo/bar.yml') { "bar: baz" }
|
56
|
+
|
57
|
+
# make sure load_resource is called with custom = false the second time
|
58
|
+
mock.proxy(loader).load_resource("foo/bar.yml")
|
59
|
+
mock.proxy(loader).load_resource("custom/foo/bar.yml", false)
|
60
|
+
|
61
|
+
loader.get_resource(:foo, :bar).should == { :foo => "bar", :bar => "baz" }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#get_locale_resource' do
|
67
|
+
it 'loads the correct locale resource file' do
|
68
|
+
stub(loader).get_resource(:locales, :de, :numbers) { 'foo' }
|
69
|
+
loader.get_locale_resource(:de, :numbers).should == 'foo'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'loads the resource only once' do
|
73
|
+
mock(loader).load_resource('locales/de/numbers.yml').once { 'foo' }
|
74
|
+
|
75
|
+
result = loader.get_locale_resource(:de, :numbers)
|
76
|
+
# second time get_resource is not called but we get the same object as before
|
77
|
+
loader.get_locale_resource(:de, :numbers).object_id.should == result.object_id
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'converts locales' do
|
81
|
+
mock(TwitterCldr).convert_locale('zh-tw') { :'zh-Hant' }
|
82
|
+
mock(loader).get_resource(:locales, :'zh-Hant', :numbers) { 'foo' }
|
83
|
+
|
84
|
+
loader.get_locale_resource('zh-tw', :numbers).should == 'foo'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def stub_resource_file(resource_path, content)
|
89
|
+
file_path = File.join(TwitterCldr::RESOURCES_DIR, resource_path)
|
90
|
+
stub(File).read(file_path) { content }
|
91
|
+
stub(File).file?(file_path) { true }
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -28,6 +28,12 @@ RSpec.configure do |config|
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
RSpec::Matchers.define :match_normalized do |expected|
|
32
|
+
match do |actual|
|
33
|
+
expected.localize.normalize(:using => :NFKC).to_s == actual.localize.normalize(:using => :NFKC).to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
31
37
|
def check_token_list(got, expected)
|
32
38
|
got.size.should == expected.size
|
33
39
|
expected.each_with_index do |exp_hash, index|
|