twitter_cldr 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/NOTICE +29 -1
- data/README.md +4 -11
- data/lib/twitter_cldr/formatters/calendars/date_formatter.rb +6 -1
- data/lib/twitter_cldr/formatters/calendars/datetime_formatter.rb +10 -1
- data/lib/twitter_cldr/formatters/calendars/time_formatter.rb +6 -1
- data/lib/twitter_cldr/formatters/calendars/timespan_formatter.rb +12 -2
- data/lib/twitter_cldr/formatters/numbers/currency_formatter.rb +12 -3
- data/lib/twitter_cldr/formatters/numbers/number_formatter.rb +9 -1
- data/lib/twitter_cldr/formatters/plurals/rules.rb +8 -3
- data/lib/twitter_cldr/localized/localized_date.rb +13 -0
- data/lib/twitter_cldr/localized/localized_datetime.rb +20 -7
- data/lib/twitter_cldr/localized/localized_object.rb +1 -1
- data/lib/twitter_cldr/localized/localized_string.rb +14 -0
- data/lib/twitter_cldr/localized/localized_time.rb +12 -0
- data/lib/twitter_cldr/localized/localized_timespan.rb +1 -1
- data/lib/twitter_cldr/parsers/number_parser.rb +113 -0
- data/lib/twitter_cldr/parsers.rb +10 -0
- data/lib/twitter_cldr/resources/loader.rb +49 -2
- data/lib/twitter_cldr/resources/locales_resources_importer.rb +22 -2
- data/lib/twitter_cldr/shared/calendar.rb +95 -12
- data/lib/twitter_cldr/shared/currencies.rb +18 -15
- data/lib/twitter_cldr/shared/languages.rb +4 -4
- data/lib/twitter_cldr/shared/numbers.rb +1 -1
- data/lib/twitter_cldr/shared/territories.rb +63 -0
- data/lib/twitter_cldr/shared.rb +2 -1
- data/lib/twitter_cldr/tokenizers/base.rb +10 -15
- data/lib/twitter_cldr/tokenizers/calendars/additional_date_format_selector.rb +6 -1
- data/lib/twitter_cldr/tokenizers/calendars/datetime_tokenizer.rb +11 -2
- data/lib/twitter_cldr/tokenizers/calendars/timespan_tokenizer.rb +12 -9
- data/lib/twitter_cldr/tokenizers/numbers/number_tokenizer.rb +2 -2
- data/lib/twitter_cldr/utils/territories.rb +56 -0
- data/lib/twitter_cldr/utils.rb +4 -3
- data/lib/twitter_cldr/version.rb +1 -1
- data/lib/twitter_cldr.rb +60 -8
- data/resources/collation/tailoring/hr.yml +32 -0
- data/resources/collation/tailoring/is.yml +30 -0
- data/resources/collation/tries/hr.dump +0 -0
- data/resources/collation/tries/is.dump +0 -0
- data/resources/custom/locales/he/units.yml +150 -13
- data/resources/custom/locales/hr/units.yml +9 -0
- data/resources/locales/af/territories.yml +262 -0
- data/resources/locales/ar/territories.yml +262 -0
- data/resources/locales/be/territories.yml +239 -0
- data/resources/locales/bg/territories.yml +262 -0
- data/resources/locales/bn/territories.yml +262 -0
- data/resources/locales/ca/territories.yml +262 -0
- data/resources/locales/cs/territories.yml +262 -0
- data/resources/locales/cy/territories.yml +5 -0
- data/resources/locales/da/territories.yml +262 -0
- data/resources/locales/de/territories.yml +262 -0
- data/resources/locales/el/territories.yml +262 -0
- data/resources/locales/en/territories.yml +262 -0
- data/resources/locales/es/territories.yml +262 -0
- data/resources/locales/eu/territories.yml +262 -0
- data/resources/locales/fa/territories.yml +262 -0
- data/resources/locales/fi/territories.yml +262 -0
- data/resources/locales/fil/territories.yml +262 -0
- data/resources/locales/fr/territories.yml +262 -0
- data/resources/locales/ga/territories.yml +251 -0
- data/resources/locales/gl/territories.yml +262 -0
- data/resources/locales/he/territories.yml +262 -0
- data/resources/locales/hi/territories.yml +262 -0
- data/resources/locales/hr/calendars.yml +299 -0
- data/resources/locales/hr/currencies.yml +1490 -0
- data/resources/locales/hr/languages.yml +576 -0
- data/resources/locales/hr/layout.yml +4 -0
- data/resources/locales/hr/lists.yml +7 -0
- data/resources/locales/hr/numbers.yml +59 -0
- data/resources/locales/hr/plurals.yml +5 -0
- data/resources/locales/hr/territories.yml +262 -0
- data/resources/locales/hr/units.yml +164 -0
- data/resources/locales/hu/territories.yml +262 -0
- data/resources/locales/id/territories.yml +262 -0
- data/resources/locales/is/calendars.yml +243 -0
- data/resources/locales/is/currencies.yml +478 -0
- data/resources/locales/is/languages.yml +495 -0
- data/resources/locales/is/layout.yml +4 -0
- data/resources/locales/is/lists.yml +7 -0
- data/resources/locales/is/numbers.yml +57 -0
- data/resources/locales/is/plurals.yml +3 -0
- data/resources/locales/is/territories.yml +262 -0
- data/resources/locales/is/units.yml +108 -0
- data/resources/locales/it/territories.yml +262 -0
- data/resources/locales/ja/territories.yml +262 -0
- data/resources/locales/ko/territories.yml +262 -0
- data/resources/locales/lv/territories.yml +262 -0
- data/resources/locales/ms/territories.yml +262 -0
- data/resources/locales/nb/territories.yml +262 -0
- data/resources/locales/nl/territories.yml +262 -0
- data/resources/locales/pl/territories.yml +262 -0
- data/resources/locales/pt/territories.yml +262 -0
- data/resources/locales/ro/territories.yml +262 -0
- data/resources/locales/ru/territories.yml +262 -0
- data/resources/locales/sk/territories.yml +262 -0
- data/resources/locales/sq/territories.yml +159 -0
- data/resources/locales/sr/territories.yml +262 -0
- data/resources/locales/sv/territories.yml +262 -0
- data/resources/locales/ta/territories.yml +262 -0
- data/resources/locales/th/territories.yml +262 -0
- data/resources/locales/tr/territories.yml +262 -0
- data/resources/locales/uk/territories.yml +262 -0
- data/resources/locales/ur/territories.yml +262 -0
- data/resources/locales/vi/territories.yml +262 -0
- data/resources/locales/zh/territories.yml +262 -0
- data/resources/locales/zh-Hant/territories.yml +262 -0
- data/resources/shared/iso_currency_symbols.yml +475 -0
- data/spec/formatters/numbers/currency_formatter_spec.rb +11 -2
- data/spec/formatters/plurals/rules_spec.rb +1 -1
- data/spec/localized/localized_date_spec.rb +22 -24
- data/spec/localized/localized_object_spec.rb +1 -1
- data/spec/localized/localized_string_spec.rb +33 -0
- data/spec/localized/localized_symbol_spec.rb +1 -1
- data/spec/normalization/base_spec.rb +1 -0
- data/spec/parsers/number_parser_spec.rb +189 -0
- data/spec/readme_spec.rb +10 -11
- data/spec/resources/loader_spec.rb +75 -1
- data/spec/shared/calendar_spec.rb +123 -1
- data/spec/shared/currencies_spec.rb +20 -24
- data/spec/shared/languages_spec.rb +27 -27
- data/spec/shared/numbers_spec.rb +1 -1
- data/spec/shared/territories_spec.rb +120 -0
- data/spec/spec_helper.rb +19 -2
- data/spec/twitter_cldr_spec.rb +234 -9
- data/spec/utils/territories_spec.rb +16 -0
- data/spec/utils_spec.rb +1 -1
- metadata +131 -37
- data/resources/shared/currencies.yml +0 -448
@@ -24,7 +24,16 @@ describe CurrencyFormatter do
|
|
24
24
|
|
25
25
|
it "should use the specified currency symbol when specified" do
|
26
26
|
# S/. is the symbol for the Peruvian Nuevo Sol, just in case you were curious
|
27
|
-
@formatter.format(12, :
|
27
|
+
@formatter.format(12, :symbol => "S/.").should == "S/.12.00"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should use the currency code as the symbol if the currency code can't be identified" do
|
31
|
+
@formatter.format(12, :currency => "XYZ").should == "XYZ12.00"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should respect the :use_cldr_symbol option" do
|
35
|
+
@formatter.format(12, :currency => "CAD").should == "$12.00"
|
36
|
+
@formatter.format(12, :currency => "CAD", :use_cldr_symbol => true).should == "CA$12.00"
|
28
37
|
end
|
29
38
|
|
30
39
|
it "should use the currency symbol for the corresponding currency code" do
|
@@ -35,7 +44,7 @@ describe CurrencyFormatter do
|
|
35
44
|
@formatter.format(12, :precision => 3).should == "$12.000"
|
36
45
|
end
|
37
46
|
|
38
|
-
it "should use the currency precision" do
|
47
|
+
it "should use the currency-specific default precision" do
|
39
48
|
@formatter.format(12, :currency => "TND").should == "TND12.000"
|
40
49
|
end
|
41
50
|
|
@@ -60,7 +60,7 @@ describe Rules do
|
|
60
60
|
|
61
61
|
describe "#all" do
|
62
62
|
it "gets rules for the default locale (usually supplied by FastGettext)" do
|
63
|
-
mock(TwitterCldr).
|
63
|
+
mock(TwitterCldr).locale { :ru }
|
64
64
|
Rules.all.should =~ [:one, :few, :many, :other]
|
65
65
|
end
|
66
66
|
end
|
@@ -12,66 +12,64 @@ describe LocalizedDate do
|
|
12
12
|
let(:date) { Date.today }
|
13
13
|
|
14
14
|
describe "#ago" do
|
15
|
-
let(:date) { Date.new(2010,7,6) }
|
16
|
-
let(:base_time) { Time.gm(2010,8,6,12,12,30) }
|
15
|
+
let(:date) { Date.new(2010, 7, 6) }
|
16
|
+
let(:base_time) { Time.gm(2010, 8, 6, 12, 12, 30) }
|
17
17
|
|
18
18
|
it "should ago-ify from now when no base_time given" do
|
19
|
-
stub(Time).now { Time.gm(2010,8,6,12,12,30) }
|
19
|
+
stub(Time).now { Time.gm(2010, 8, 6, 12, 12, 30) }
|
20
20
|
loc_date = date.localize(:ko)
|
21
|
-
loc_date.ago.to_s(:unit => :hour).should match_normalized("
|
21
|
+
loc_date.ago.to_s(:unit => :hour).should match_normalized("744시간 전")
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should ago-ify with appropriate unit when no unit given" do
|
25
25
|
loc_date = date.localize(:en)
|
26
26
|
loc_date.ago(:base_time => base_time).to_s.should match_normalized("1 month ago")
|
27
|
-
loc_date.ago(:base_time => Time.gm(2010,12,6,12,12,30)).to_s.should match_normalized("5 months ago")
|
28
|
-
loc_date.ago(:base_time => Time.gm(2010,7,7,12,12,30)).to_s.should match_normalized("
|
29
|
-
loc_date.ago(:base_time => Time.gm(2010,7,6,12,12,30)).to_s.should match_normalized("12 hours ago")
|
30
|
-
loc_date.ago(:base_time => Time.gm(2010,7,6,0,39,0)).to_s.should match_normalized("39 minutes ago")
|
27
|
+
loc_date.ago(:base_time => Time.gm(2010, 12, 6, 12, 12, 30)).to_s.should match_normalized("5 months ago")
|
28
|
+
loc_date.ago(:base_time => Time.gm(2010, 7, 7, 12, 12, 30)).to_s.should match_normalized("1 day ago")
|
31
29
|
end
|
32
30
|
|
33
31
|
it "should ago-ify with strings regardless of variable's placement or existence" do
|
34
32
|
loc_date = date.localize(:ar)
|
35
|
-
loc_date.ago(:base_time => base_time).to_s(:unit => :hour).should match_normalized("قبل
|
36
|
-
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("قبل
|
33
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :hour).should match_normalized("قبل 744 ساعة")
|
34
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("قبل 31 يومًا")
|
37
35
|
loc_date.ago(:base_time => base_time).to_s(:unit => :month).should match_normalized("قبل 1 من الشهور")
|
38
36
|
loc_date.ago(:base_time => base_time).to_s(:unit => :year).should match_normalized("قبل 0 من السنوات")
|
39
37
|
|
40
38
|
loc_date = date.localize(:fa)
|
41
|
-
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("
|
39
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("31 روز پیش")
|
42
40
|
|
43
41
|
loc_date = date.localize(:en)
|
44
|
-
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("
|
42
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("31 days ago")
|
45
43
|
end
|
46
44
|
|
47
45
|
it "should ago-ify a date with a number of different units" do
|
48
|
-
date = Date.new(2010,6,6)
|
46
|
+
date = Date.new(2010, 6, 6)
|
49
47
|
loc_date = date.localize(:de)
|
50
|
-
loc_date.ago(:base_time => base_time).to_s(:unit => :second).should match_normalized("Vor
|
51
|
-
loc_date.ago(:base_time => base_time).to_s(:unit => :minute).should match_normalized("Vor
|
52
|
-
loc_date.ago(:base_time => base_time).to_s(:unit => :hour).should match_normalized("Vor
|
53
|
-
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("Vor
|
48
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :second).should match_normalized("Vor 5270400 Sekunden")
|
49
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :minute).should match_normalized("Vor 87840 Minuten")
|
50
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :hour).should match_normalized("Vor 1464 Stunden")
|
51
|
+
loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("Vor 61 Tagen")
|
54
52
|
loc_date.ago(:base_time => base_time).to_s(:unit => :month).should match_normalized("Vor 2 Monaten")
|
55
53
|
loc_date.ago(:base_time => base_time).to_s(:unit => :year).should match_normalized("Vor 0 Jahren")
|
56
54
|
end
|
57
55
|
|
58
56
|
it "should return an error if called on a date in the future" do
|
59
|
-
date = Date.new(2010,10,10)
|
57
|
+
date = Date.new(2010, 10, 10)
|
60
58
|
loc_date = date.localize(:de)
|
61
59
|
lambda { loc_date.ago(base_time, :second)}.should raise_error(ArgumentError)
|
62
60
|
end
|
63
61
|
end
|
64
62
|
|
65
63
|
describe "#until" do
|
66
|
-
let(:base_time) { Time.gm(2010,8,6,12,12,30) }
|
64
|
+
let(:base_time) { Time.gm(2010, 8, 6, 12, 12, 30) }
|
67
65
|
|
68
66
|
it "should until-ify with a number of different units" do
|
69
|
-
date = Date.new(2010,10,10)
|
67
|
+
date = Date.new(2010, 10, 10)
|
70
68
|
loc_date = date.localize(:de)
|
71
|
-
loc_date.until(:base_time => base_time).to_s(:unit => :second).should match_normalized("In
|
72
|
-
loc_date.until(:base_time => base_time).to_s(:unit => :minute).should match_normalized("In
|
73
|
-
loc_date.until(:base_time => base_time).to_s(:unit => :hour).should match_normalized("In
|
74
|
-
loc_date.until(:base_time => base_time).to_s(:unit => :day).should match_normalized("In
|
69
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :second).should match_normalized("In 5616000 Sekunden")
|
70
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :minute).should match_normalized("In 93600 Minuten")
|
71
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :hour).should match_normalized("In 1560 Stunden")
|
72
|
+
loc_date.until(:base_time => base_time).to_s(:unit => :day).should match_normalized("In 65 Tagen")
|
75
73
|
loc_date.until(:base_time => base_time).to_s(:unit => :month).should match_normalized("In 2 Monaten")
|
76
74
|
loc_date.until(:base_time => base_time).to_s(:unit => :year).should match_normalized("In 0 Jahren")
|
77
75
|
end
|
@@ -81,7 +81,7 @@ describe LocalizedObject do
|
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'uses default locale and empty options hash by default' do
|
84
|
-
mock(LocalizedClass).new(localizable_object, TwitterCldr.
|
84
|
+
mock(LocalizedClass).new(localizable_object, TwitterCldr.locale, {})
|
85
85
|
localizable_object.localize
|
86
86
|
end
|
87
87
|
end
|
@@ -90,6 +90,39 @@ describe LocalizedString do
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
+
describe "#to_f" do
|
94
|
+
it "should correctly parse a number with a thousands separator" do
|
95
|
+
"1,300".localize.to_f.should == 1300.0
|
96
|
+
"1.300".localize(:es).to_f.should == 1300.0
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should correctly parse a number with a decimal separator" do
|
100
|
+
"1.300".localize.to_f.should == 1.3
|
101
|
+
"1,300".localize(:es).to_f.should == 1.3
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should correctly parse a number with a thousands and a decimal separator" do
|
105
|
+
"1,300.05".localize.to_f.should == 1300.05
|
106
|
+
"1.300,05".localize(:es).to_f.should == 1300.05
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return zero if the string contains no numbers" do
|
110
|
+
"abc".localize.to_f.should == 0.0
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should return only the numbers at the beginning of the string if the string contains any non-numeric characters" do
|
114
|
+
"1abc".localize.to_f.should == 1.0
|
115
|
+
"a1bc".localize.to_f.should == 0.0
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#to_i" do
|
120
|
+
it "should chop off the decimal" do
|
121
|
+
"1,300.05".localize.to_i.should == 1300
|
122
|
+
"1.300,05".localize(:es).to_i.should == 1300
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
93
126
|
describe "#normalize" do
|
94
127
|
let(:string) { 'string' }
|
95
128
|
let(:normalized_string) { 'normalized' }
|
@@ -12,7 +12,7 @@ describe LocalizedSymbol do
|
|
12
12
|
describe "#as_language_code" do
|
13
13
|
it "returns the correct localized language from the symbol" do
|
14
14
|
:es.localize.as_language_code.should == "Spanish"
|
15
|
-
|
15
|
+
TwitterCldr.locale = :es
|
16
16
|
:es.localize.as_language_code.should == "español"
|
17
17
|
end
|
18
18
|
|
@@ -0,0 +1,189 @@
|
|
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
|
+
require 'pry'
|
8
|
+
require 'pry-nav'
|
9
|
+
|
10
|
+
include TwitterCldr::Parsers
|
11
|
+
|
12
|
+
describe TwitterCldr::Parsers::NumberParser do
|
13
|
+
let(:separators) { ["\\.", ","] }
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
@parser = NumberParser.new(:es)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#group_separator" do
|
20
|
+
it "returns the correct group separator" do
|
21
|
+
@parser.send(:group_separator).should == "\\."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#decimal_separator" do
|
26
|
+
it "returns the correct decimal separator" do
|
27
|
+
@parser.send(:decimal_separator).should == ","
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#identify" do
|
32
|
+
it "properly identifies a numeric value" do
|
33
|
+
@parser.send(:identify, "7841", *separators).should == { :value => "7841", :type => :numeric }
|
34
|
+
end
|
35
|
+
|
36
|
+
it "properly identifies a decimal separator" do
|
37
|
+
@parser.send(:identify, ",", *separators).should == { :value => ",", :type => :decimal }
|
38
|
+
end
|
39
|
+
|
40
|
+
it "properly identifies a group separator" do
|
41
|
+
@parser.send(:identify, ".", *separators).should == { :value => ".", :type => :group }
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns nil if the text doesn't match a number or either separators" do
|
45
|
+
@parser.send(:identify, "abc", *separators).should == { :value => "abc", :type => nil }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#tokenize" do
|
50
|
+
it "splits text by numericality and group/decimal separators" do
|
51
|
+
@parser.send(:tokenize, "1,33.00", *separators).should == [
|
52
|
+
{ :value => "1", :type => :numeric },
|
53
|
+
{ :value => ",", :type => :decimal },
|
54
|
+
{ :value => "33", :type => :numeric },
|
55
|
+
{ :value => ".", :type => :group },
|
56
|
+
{ :value => "00", :type => :numeric }
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns an empty array for a non-numeric string" do
|
61
|
+
@parser.send(:tokenize, "abc", *separators).should be_empty
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#separators" do
|
66
|
+
it "returns all separators when strict mode is off" do
|
67
|
+
group, decimal = @parser.send(:separators, false)
|
68
|
+
group.should == '\.,\s'
|
69
|
+
decimal.should == '\.,\s'
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns only locale-specific separators when strict mode is on" do
|
73
|
+
group, decimal = @parser.send(:separators, true)
|
74
|
+
group.should == '\.'
|
75
|
+
decimal.should == ','
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#punct_valid" do
|
80
|
+
it "correctly validates a number with no decimal" do
|
81
|
+
tokens = @parser.send(:tokenize, "1.337", *separators).reject { |t| t[:type] == :numeric }
|
82
|
+
@parser.send(:punct_valid?, tokens).should be_true
|
83
|
+
end
|
84
|
+
|
85
|
+
it "correctly validates a number with a decimal" do
|
86
|
+
tokens = @parser.send(:tokenize, "1.337,00", *separators).reject { |t| t[:type] == :numeric }
|
87
|
+
@parser.send(:punct_valid?, tokens).should be_true
|
88
|
+
end
|
89
|
+
|
90
|
+
it "reports on an invalid number when it has more than one decimal" do
|
91
|
+
tokens = @parser.send(:tokenize, "1,337,00", *separators).reject { |t| t[:type] == :numeric }
|
92
|
+
@parser.send(:punct_valid?, tokens).should be_false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#is_numeric?" do
|
97
|
+
it "returns true if the text is numeric" do
|
98
|
+
NumberParser.is_numeric?("4839", "").should be_true
|
99
|
+
NumberParser.is_numeric?("1", "").should be_true
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns false if the text is not purely numeric" do
|
103
|
+
NumberParser.is_numeric?("abc", "").should be_false
|
104
|
+
NumberParser.is_numeric?("123abc", "").should be_false
|
105
|
+
end
|
106
|
+
|
107
|
+
it "returns false if the text is blank" do
|
108
|
+
NumberParser.is_numeric?("", "").should be_false
|
109
|
+
end
|
110
|
+
|
111
|
+
it "accepts the given characters as valid numerics" do
|
112
|
+
NumberParser.is_numeric?("a123a", "a").should be_true
|
113
|
+
NumberParser.is_numeric?("1.234,56").should be_true # default separator chars used here
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#valid?" do
|
118
|
+
it "correctly identifies a series of valid cases" do
|
119
|
+
["5", "5,0", "1.337", "1.337,0", "0,05", ",5", "1.337.000,00"].each do |num|
|
120
|
+
@parser.valid?(num).should be_true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "correctly identifies a series of invalid cases" do
|
125
|
+
["12,0,0", "5,", "5."].each do |num|
|
126
|
+
@parser.valid?(num).should be_false
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#parse" do
|
132
|
+
it "correctly parses a series of valid numbers" do
|
133
|
+
cases = {
|
134
|
+
"5" => 5,
|
135
|
+
"5,0" => 5.0,
|
136
|
+
"1.337" => 1337,
|
137
|
+
"1.337,0" => 1337.0,
|
138
|
+
"0,05" => 0.05,
|
139
|
+
",5" => 0.5,
|
140
|
+
"1.337.000,00" => 1337000.0
|
141
|
+
}
|
142
|
+
|
143
|
+
cases.each do |text, expected|
|
144
|
+
@parser.parse(text).should == expected
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it "correctly raises an error when asked to parse invalid numbers" do
|
149
|
+
cases = ["12,0,0", "5,", "5."]
|
150
|
+
cases.each do |text|
|
151
|
+
lambda { @parser.parse(text) }.should raise_error(InvalidNumberError)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "non-strict" do
|
156
|
+
it "succeeds in parsing even if inexact punctuation is used" do
|
157
|
+
@parser.parse("5 100", :strict => false).should == 5100
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "#try_parse" do
|
163
|
+
it "parses correctly with a valid number" do
|
164
|
+
@parser.try_parse("1.234").should == 1234
|
165
|
+
end
|
166
|
+
|
167
|
+
it "parses correctly with a valid number and yields to the given block" do
|
168
|
+
pre_result = nil
|
169
|
+
@parser.try_parse("1.234") do |result|
|
170
|
+
pre_result = result
|
171
|
+
9
|
172
|
+
end.should == 9
|
173
|
+
pre_result.should == 1234
|
174
|
+
end
|
175
|
+
|
176
|
+
it "falls back on the default value if the number is invalid" do
|
177
|
+
@parser.try_parse("5,").should be_nil
|
178
|
+
@parser.try_parse("5,", 0).should == 0
|
179
|
+
end
|
180
|
+
|
181
|
+
it "falls back on the block if the number is invalid" do
|
182
|
+
@parser.try_parse("5,") { |result| 9 }.should == 9
|
183
|
+
end
|
184
|
+
|
185
|
+
it "doesn't catch anything but an InvalidNumberError" do
|
186
|
+
lambda { @parser.try_parse(Object.new) }.should raise_error(NoMethodError)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
data/spec/readme_spec.rb
CHANGED
@@ -26,7 +26,6 @@ describe "README" do
|
|
26
26
|
1337.localize(:es).to_s.should == "1.337"
|
27
27
|
spaces(1337.localize(:es).to_currency.to_s).should == "1.337,00 $"
|
28
28
|
spaces(1337.localize(:es).to_currency.to_s(:currency => "EUR").to_s).should == "1.337,00 €"
|
29
|
-
spaces(1337.localize(:es).to_currency.to_s(:currency => "Peru").to_s).should == "1.337,00 PEN"
|
30
29
|
1337.localize(:es).to_percent.to_s.should == "1.337%"
|
31
30
|
1337.localize(:es).to_percent.to_s(:precision => 2).should == "1.337,00%"
|
32
31
|
1337.localize(:es).to_decimal.to_s(:precision => 3).should == "1.337,000"
|
@@ -36,18 +35,17 @@ describe "README" do
|
|
36
35
|
end
|
37
36
|
|
38
37
|
it "verifies extra currency data" do
|
39
|
-
countries = TwitterCldr::Shared::Currencies.countries
|
40
|
-
countries.should be_a(Array)
|
41
|
-
countries.should include("Lithuania")
|
42
|
-
countries.should include("Philippines")
|
43
|
-
|
44
38
|
currency_codes = TwitterCldr::Shared::Currencies.currency_codes
|
45
39
|
currency_codes.should be_a(Array)
|
46
40
|
currency_codes.should include("LTL")
|
47
41
|
currency_codes.should include("PHP")
|
48
|
-
|
49
|
-
|
50
|
-
|
42
|
+
TwitterCldr::Shared::Currencies.for_code("CAD").should == {
|
43
|
+
:currency => :CAD,
|
44
|
+
:cldr_symbol => "CA$",
|
45
|
+
:symbol => "$",
|
46
|
+
:name => "Canadian dollar",
|
47
|
+
:code_points => [36]
|
48
|
+
}
|
51
49
|
end
|
52
50
|
|
53
51
|
it "verifies short and long decimals" do
|
@@ -275,8 +273,9 @@ describe "README" do
|
|
275
273
|
end
|
276
274
|
|
277
275
|
it "verifies locale defaults" do
|
278
|
-
TwitterCldr.
|
276
|
+
TwitterCldr.locale.should == :en
|
277
|
+
TwitterCldr.locale = nil
|
279
278
|
FastGettext.locale = "ru"
|
280
|
-
TwitterCldr.
|
279
|
+
TwitterCldr.locale.should == :ru
|
281
280
|
end
|
282
281
|
end
|
@@ -43,7 +43,7 @@ describe Loader do
|
|
43
43
|
lambda { loader.get_resource(:foo, :bar) }.should raise_error(ArgumentError, "Resource 'foo/bar.yml' not found.")
|
44
44
|
end
|
45
45
|
|
46
|
-
context
|
46
|
+
context 'custom resources' do
|
47
47
|
it "doesn't merge the custom resource if it doesn't exist" do
|
48
48
|
mock(loader).read_resource_file('foo/bar.yml') { ":foo: bar" }
|
49
49
|
loader.get_resource(:foo, :bar).should == { :foo => "bar" }
|
@@ -85,6 +85,80 @@ describe Loader do
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
+
describe '#resource_loaded' do
|
89
|
+
it 'should return true if the resource is cached, false otherwise' do
|
90
|
+
loader.preload_resources_for_locale(:de, :numbers)
|
91
|
+
loader.resource_loaded?(:locales, :de, :numbers).should be_true
|
92
|
+
loader.resource_loaded?(:locales, :de, :calendars).should be_false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#locale_resource_loaded' do
|
97
|
+
it 'should return true if the locale resource is cached, false otherwise' do
|
98
|
+
loader.preload_resources_for_locale(:de, :numbers)
|
99
|
+
loader.locale_resource_loaded?(:de, :numbers).should be_true
|
100
|
+
loader.locale_resource_loaded?(:de, :calendars).should be_false
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#resource_types' do
|
105
|
+
it 'returns the list of available resource types' do
|
106
|
+
types = loader.resource_types
|
107
|
+
types.should be_a(Array)
|
108
|
+
types.should include(:calendars)
|
109
|
+
types.should include(:numbers)
|
110
|
+
types.should include(:units)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '#preload_resources_for_locale' do
|
115
|
+
it 'loads potentially multiple resources into the cache' do
|
116
|
+
loader.preload_resources_for_locale(:ar, :calendars, :units)
|
117
|
+
loader.locale_resource_loaded?(:ar, :calendars).should be_true
|
118
|
+
loader.locale_resource_loaded?(:ar, :units).should be_true
|
119
|
+
loader.locale_resource_loaded?(:en, :units).should be_false
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'loads all resources for the locale if the :all resource type is specified' do
|
123
|
+
loader.preload_resources_for_locale(:ar, :all)
|
124
|
+
loader.resource_types.each do |resource_type|
|
125
|
+
loader.locale_resource_loaded?(:ar, resource_type).should be_true
|
126
|
+
loader.locale_resource_loaded?(:en, resource_type).should be_false
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#preload_resource_for_locales' do
|
132
|
+
it 'loads a single resource for potentially multiple locales into the cache' do
|
133
|
+
loader.preload_resource_for_locales(:calendars, :sv, :bn)
|
134
|
+
loader.locale_resource_loaded?(:sv, :calendars).should be_true
|
135
|
+
loader.locale_resource_loaded?(:bn, :calendars).should be_true
|
136
|
+
loader.locale_resource_loaded?(:sv, :units).should be_false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#preload_resources_for_all_locales' do
|
141
|
+
it 'loads potentially multiple resources for all locales' do
|
142
|
+
loader.preload_resources_for_all_locales(:plurals, :lists)
|
143
|
+
TwitterCldr.supported_locales.each do |locale|
|
144
|
+
loader.locale_resource_loaded?(locale, :plurals).should be_true
|
145
|
+
loader.locale_resource_loaded?(locale, :lists).should be_true
|
146
|
+
loader.locale_resource_loaded?(locale, :calendars).should be_false
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#preload_all_resources' do
|
152
|
+
it 'loads all resources for all locales' do
|
153
|
+
loader.preload_all_resources
|
154
|
+
TwitterCldr.supported_locales.each do |locale|
|
155
|
+
loader.resource_types.each do |resource_type|
|
156
|
+
loader.locale_resource_loaded?(locale, resource_type).should be_true
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
88
162
|
def stub_resource_file(resource_path, content)
|
89
163
|
file_path = File.join(TwitterCldr::RESOURCES_DIR, resource_path)
|
90
164
|
stub(File).read(file_path) { content }
|
@@ -11,9 +11,14 @@ describe Calendar do
|
|
11
11
|
|
12
12
|
let(:calendar) { Calendar.new(:de) }
|
13
13
|
|
14
|
+
before(:each) do
|
15
|
+
# clear cache for each test
|
16
|
+
Calendar.send(:class_variable_set, :@@calendar_cache, {})
|
17
|
+
end
|
18
|
+
|
14
19
|
describe '#initialize' do
|
15
20
|
it 'returns calendar for default locale and type' do
|
16
|
-
stub(TwitterCldr).
|
21
|
+
stub(TwitterCldr).locale { :fr }
|
17
22
|
cal = Calendar.new
|
18
23
|
|
19
24
|
cal.locale.should == :fr
|
@@ -130,4 +135,121 @@ describe Calendar do
|
|
130
135
|
end
|
131
136
|
end
|
132
137
|
|
138
|
+
describe '#fields' do
|
139
|
+
it 'returns the list of fields for the locale (eg. weekday, month, etc)' do
|
140
|
+
fields = calendar.fields
|
141
|
+
fields[:hour].should match_normalized("Stunde")
|
142
|
+
fields[:dayperiod].should match_normalized("Tageshälfte")
|
143
|
+
fields[:weekday].should match_normalized("Wochentag")
|
144
|
+
|
145
|
+
fields = Calendar.new(:ja).fields
|
146
|
+
fields[:hour].should match_normalized("時")
|
147
|
+
fields[:dayperiod].should match_normalized("午前/午後")
|
148
|
+
fields[:weekday].should match_normalized("曜日")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe '#quarters' do
|
153
|
+
it 'returns default quarters' do
|
154
|
+
calendar.quarters.should == {
|
155
|
+
1 => "1. Quartal",
|
156
|
+
2 => "2. Quartal",
|
157
|
+
3 => "3. Quartal",
|
158
|
+
4 => "4. Quartal"
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'returns quarters with other name forms' do
|
163
|
+
calendar.quarters(:abbreviated).should == {
|
164
|
+
1 => "Q1", 2 => "Q2",
|
165
|
+
3 => "Q3", 4 => "Q4"
|
166
|
+
}
|
167
|
+
|
168
|
+
calendar.quarters(:narrow).should == {
|
169
|
+
1 => 1, 2 => 2,
|
170
|
+
3 => 3, 4 => 4
|
171
|
+
}
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe '#periods' do
|
176
|
+
it 'returns default periods' do
|
177
|
+
periods = calendar.periods
|
178
|
+
periods[:am].should == "vorm."
|
179
|
+
periods[:pm].should == "nachm."
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'returns quarters with other name forms' do
|
183
|
+
periods = calendar.periods(:abbreviated)
|
184
|
+
periods[:am].should == "vorm."
|
185
|
+
periods[:pm].should == "nachm."
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe '#eras' do
|
190
|
+
it 'returns default eras' do
|
191
|
+
calendar.eras.should == {
|
192
|
+
0 => "v. Chr.",
|
193
|
+
1 => "n. Chr."
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'returns eras with other name forms' do
|
198
|
+
calendar.eras(:abbr).should == {
|
199
|
+
0 => "v. Chr.",
|
200
|
+
1 => "n. Chr."
|
201
|
+
}
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe '#date_order' do
|
206
|
+
it 'should return the correct date order for a few different locales' do
|
207
|
+
Calendar.new(:en).date_order.should == [:month, :day, :year]
|
208
|
+
Calendar.new(:ja).date_order.should == [:year, :month, :day]
|
209
|
+
Calendar.new(:ar).date_order.should == [:day, :month, :year]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe '#time_order' do
|
214
|
+
it 'should return the correct time order for a few different locales' do
|
215
|
+
Calendar.new(:en).time_order.should == [:hour, :minute, :second, :period]
|
216
|
+
Calendar.new(:ja).time_order.should == [:hour, :minute, :second]
|
217
|
+
Calendar.new(:ar).time_order.should == [:hour, :minute, :second, :period]
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe '#datetime_order' do
|
222
|
+
it 'should return the correct date and time order for a few different locales' do
|
223
|
+
Calendar.new(:en).datetime_order.should == [:month, :day, :year, :hour, :minute, :second, :period]
|
224
|
+
Calendar.new(:ja).datetime_order.should == [:year, :month, :day, :hour, :minute, :second]
|
225
|
+
Calendar.new(:ar).datetime_order.should == [:day, :month, :year, :hour, :minute, :second, :period]
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe '#methods_for_tokens' do
|
230
|
+
it 'converts pattern tokens into their corresponding method names' do
|
231
|
+
tokens = [TwitterCldr::Tokenizers::Token.new(:value => "YYYY", :type => :pattern)]
|
232
|
+
calendar.send(:methods_for_tokens, tokens).should == [:year_of_week_of_year]
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'ignores plaintext tokens' do
|
236
|
+
tokens = [TwitterCldr::Tokenizers::Token.new(:value => "blarg", :type => :plaintext)]
|
237
|
+
calendar.send(:methods_for_tokens, tokens).should == []
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe '#resolve_methods' do
|
242
|
+
it 'converts certain method names to their basic equivalents' do
|
243
|
+
calendar.send(:resolve_methods, [:year_of_week_of_year]).should == [:year]
|
244
|
+
calendar.send(:resolve_methods, [:weekday_local]).should == [:weekday]
|
245
|
+
calendar.send(:resolve_methods, [:day_of_month, :second_fraction]).should == [:day, :second]
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'does not convert basic method names' do
|
249
|
+
calendar.send(:resolve_methods, [:year]).should == [:year]
|
250
|
+
calendar.send(:resolve_methods, [:day, :month]).should == [:day, :month]
|
251
|
+
calendar.send(:resolve_methods, [:minute, :hour, :second]).should == [:minute, :hour, :second]
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
133
255
|
end
|