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.
Files changed (128) hide show
  1. data/History.txt +9 -0
  2. data/NOTICE +29 -1
  3. data/README.md +4 -11
  4. data/lib/twitter_cldr/formatters/calendars/date_formatter.rb +6 -1
  5. data/lib/twitter_cldr/formatters/calendars/datetime_formatter.rb +10 -1
  6. data/lib/twitter_cldr/formatters/calendars/time_formatter.rb +6 -1
  7. data/lib/twitter_cldr/formatters/calendars/timespan_formatter.rb +12 -2
  8. data/lib/twitter_cldr/formatters/numbers/currency_formatter.rb +12 -3
  9. data/lib/twitter_cldr/formatters/numbers/number_formatter.rb +9 -1
  10. data/lib/twitter_cldr/formatters/plurals/rules.rb +8 -3
  11. data/lib/twitter_cldr/localized/localized_date.rb +13 -0
  12. data/lib/twitter_cldr/localized/localized_datetime.rb +20 -7
  13. data/lib/twitter_cldr/localized/localized_object.rb +1 -1
  14. data/lib/twitter_cldr/localized/localized_string.rb +14 -0
  15. data/lib/twitter_cldr/localized/localized_time.rb +12 -0
  16. data/lib/twitter_cldr/localized/localized_timespan.rb +1 -1
  17. data/lib/twitter_cldr/parsers/number_parser.rb +113 -0
  18. data/lib/twitter_cldr/parsers.rb +10 -0
  19. data/lib/twitter_cldr/resources/loader.rb +49 -2
  20. data/lib/twitter_cldr/resources/locales_resources_importer.rb +22 -2
  21. data/lib/twitter_cldr/shared/calendar.rb +95 -12
  22. data/lib/twitter_cldr/shared/currencies.rb +18 -15
  23. data/lib/twitter_cldr/shared/languages.rb +4 -4
  24. data/lib/twitter_cldr/shared/numbers.rb +1 -1
  25. data/lib/twitter_cldr/shared/territories.rb +63 -0
  26. data/lib/twitter_cldr/shared.rb +2 -1
  27. data/lib/twitter_cldr/tokenizers/base.rb +10 -15
  28. data/lib/twitter_cldr/tokenizers/calendars/additional_date_format_selector.rb +6 -1
  29. data/lib/twitter_cldr/tokenizers/calendars/datetime_tokenizer.rb +11 -2
  30. data/lib/twitter_cldr/tokenizers/calendars/timespan_tokenizer.rb +12 -9
  31. data/lib/twitter_cldr/tokenizers/numbers/number_tokenizer.rb +2 -2
  32. data/lib/twitter_cldr/utils/territories.rb +56 -0
  33. data/lib/twitter_cldr/utils.rb +4 -3
  34. data/lib/twitter_cldr/version.rb +1 -1
  35. data/lib/twitter_cldr.rb +60 -8
  36. data/resources/collation/tailoring/hr.yml +32 -0
  37. data/resources/collation/tailoring/is.yml +30 -0
  38. data/resources/collation/tries/hr.dump +0 -0
  39. data/resources/collation/tries/is.dump +0 -0
  40. data/resources/custom/locales/he/units.yml +150 -13
  41. data/resources/custom/locales/hr/units.yml +9 -0
  42. data/resources/locales/af/territories.yml +262 -0
  43. data/resources/locales/ar/territories.yml +262 -0
  44. data/resources/locales/be/territories.yml +239 -0
  45. data/resources/locales/bg/territories.yml +262 -0
  46. data/resources/locales/bn/territories.yml +262 -0
  47. data/resources/locales/ca/territories.yml +262 -0
  48. data/resources/locales/cs/territories.yml +262 -0
  49. data/resources/locales/cy/territories.yml +5 -0
  50. data/resources/locales/da/territories.yml +262 -0
  51. data/resources/locales/de/territories.yml +262 -0
  52. data/resources/locales/el/territories.yml +262 -0
  53. data/resources/locales/en/territories.yml +262 -0
  54. data/resources/locales/es/territories.yml +262 -0
  55. data/resources/locales/eu/territories.yml +262 -0
  56. data/resources/locales/fa/territories.yml +262 -0
  57. data/resources/locales/fi/territories.yml +262 -0
  58. data/resources/locales/fil/territories.yml +262 -0
  59. data/resources/locales/fr/territories.yml +262 -0
  60. data/resources/locales/ga/territories.yml +251 -0
  61. data/resources/locales/gl/territories.yml +262 -0
  62. data/resources/locales/he/territories.yml +262 -0
  63. data/resources/locales/hi/territories.yml +262 -0
  64. data/resources/locales/hr/calendars.yml +299 -0
  65. data/resources/locales/hr/currencies.yml +1490 -0
  66. data/resources/locales/hr/languages.yml +576 -0
  67. data/resources/locales/hr/layout.yml +4 -0
  68. data/resources/locales/hr/lists.yml +7 -0
  69. data/resources/locales/hr/numbers.yml +59 -0
  70. data/resources/locales/hr/plurals.yml +5 -0
  71. data/resources/locales/hr/territories.yml +262 -0
  72. data/resources/locales/hr/units.yml +164 -0
  73. data/resources/locales/hu/territories.yml +262 -0
  74. data/resources/locales/id/territories.yml +262 -0
  75. data/resources/locales/is/calendars.yml +243 -0
  76. data/resources/locales/is/currencies.yml +478 -0
  77. data/resources/locales/is/languages.yml +495 -0
  78. data/resources/locales/is/layout.yml +4 -0
  79. data/resources/locales/is/lists.yml +7 -0
  80. data/resources/locales/is/numbers.yml +57 -0
  81. data/resources/locales/is/plurals.yml +3 -0
  82. data/resources/locales/is/territories.yml +262 -0
  83. data/resources/locales/is/units.yml +108 -0
  84. data/resources/locales/it/territories.yml +262 -0
  85. data/resources/locales/ja/territories.yml +262 -0
  86. data/resources/locales/ko/territories.yml +262 -0
  87. data/resources/locales/lv/territories.yml +262 -0
  88. data/resources/locales/ms/territories.yml +262 -0
  89. data/resources/locales/nb/territories.yml +262 -0
  90. data/resources/locales/nl/territories.yml +262 -0
  91. data/resources/locales/pl/territories.yml +262 -0
  92. data/resources/locales/pt/territories.yml +262 -0
  93. data/resources/locales/ro/territories.yml +262 -0
  94. data/resources/locales/ru/territories.yml +262 -0
  95. data/resources/locales/sk/territories.yml +262 -0
  96. data/resources/locales/sq/territories.yml +159 -0
  97. data/resources/locales/sr/territories.yml +262 -0
  98. data/resources/locales/sv/territories.yml +262 -0
  99. data/resources/locales/ta/territories.yml +262 -0
  100. data/resources/locales/th/territories.yml +262 -0
  101. data/resources/locales/tr/territories.yml +262 -0
  102. data/resources/locales/uk/territories.yml +262 -0
  103. data/resources/locales/ur/territories.yml +262 -0
  104. data/resources/locales/vi/territories.yml +262 -0
  105. data/resources/locales/zh/territories.yml +262 -0
  106. data/resources/locales/zh-Hant/territories.yml +262 -0
  107. data/resources/shared/iso_currency_symbols.yml +475 -0
  108. data/spec/formatters/numbers/currency_formatter_spec.rb +11 -2
  109. data/spec/formatters/plurals/rules_spec.rb +1 -1
  110. data/spec/localized/localized_date_spec.rb +22 -24
  111. data/spec/localized/localized_object_spec.rb +1 -1
  112. data/spec/localized/localized_string_spec.rb +33 -0
  113. data/spec/localized/localized_symbol_spec.rb +1 -1
  114. data/spec/normalization/base_spec.rb +1 -0
  115. data/spec/parsers/number_parser_spec.rb +189 -0
  116. data/spec/readme_spec.rb +10 -11
  117. data/spec/resources/loader_spec.rb +75 -1
  118. data/spec/shared/calendar_spec.rb +123 -1
  119. data/spec/shared/currencies_spec.rb +20 -24
  120. data/spec/shared/languages_spec.rb +27 -27
  121. data/spec/shared/numbers_spec.rb +1 -1
  122. data/spec/shared/territories_spec.rb +120 -0
  123. data/spec/spec_helper.rb +19 -2
  124. data/spec/twitter_cldr_spec.rb +234 -9
  125. data/spec/utils/territories_spec.rb +16 -0
  126. data/spec/utils_spec.rb +1 -1
  127. metadata +131 -37
  128. 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, :currency => "S/.").should == "S/.12.00"
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).get_locale { :ru }
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("756시간 전")
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("2 days ago")
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("قبل 756 ساعة")
36
- loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("قبل 32 يومًا")
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("32 روز پیش")
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("32 days ago")
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 5314350 Sekunden")
51
- loc_date.ago(:base_time => base_time).to_s(:unit => :minute).should match_normalized("Vor 88573 Minuten")
52
- loc_date.ago(:base_time => base_time).to_s(:unit => :hour).should match_normalized("Vor 1476 Stunden")
53
- loc_date.ago(:base_time => base_time).to_s(:unit => :day).should match_normalized("Vor 62 Tagen")
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 5572050 Sekunden")
72
- loc_date.until(:base_time => base_time).to_s(:unit => :minute).should match_normalized("In 92868 Minuten")
73
- loc_date.until(:base_time => base_time).to_s(:unit => :hour).should match_normalized("In 1548 Stunden")
74
- loc_date.until(:base_time => base_time).to_s(:unit => :day).should match_normalized("In 64 Tagen")
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.get_locale, {})
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
- FastGettext.locale = :es
15
+ TwitterCldr.locale = :es
16
16
  :es.localize.as_language_code.should == "español"
17
17
  end
18
18
 
@@ -4,6 +4,7 @@
4
4
  # http://www.apache.org/licenses/LICENSE-2.0
5
5
 
6
6
  require 'spec_helper'
7
+ include TwitterCldr::Normalization
7
8
 
8
9
  describe Base do
9
10
  describe "#combining_class_for" do
@@ -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
- TwitterCldr::Shared::Currencies.for_country("Canada").should == { :currency => :CAD, :symbol => "CA$", :name => "Canadian dollar"}
50
- TwitterCldr::Shared::Currencies.for_code("CAD").should == { :currency => :CAD, :symbol => "CA$", :name => "Canadian dollar"}
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.get_locale.should == :en
276
+ TwitterCldr.locale.should == :en
277
+ TwitterCldr.locale = nil
279
278
  FastGettext.locale = "ru"
280
- TwitterCldr.get_locale.should == :ru
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 "custom resources" do
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).get_locale { :fr }
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