ruby-cldr 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. data/Gemfile +7 -0
  2. data/Gemfile.lock +23 -0
  3. data/README.textile +9 -6
  4. data/VERSION +1 -1
  5. data/lib/cldr.rb +1 -1
  6. data/lib/cldr/data.rb +9 -29
  7. data/lib/cldr/download.rb +2 -2
  8. data/lib/cldr/export.rb +8 -2
  9. data/lib/cldr/export/code.rb +34 -0
  10. data/lib/cldr/export/code/numbers.rb +29 -0
  11. data/lib/cldr/export/data.rb +36 -0
  12. data/lib/cldr/export/data/base.rb +61 -0
  13. data/lib/cldr/export/data/calendars.rb +14 -0
  14. data/lib/cldr/export/data/calendars/gregorian.rb +142 -0
  15. data/lib/cldr/export/data/currencies.rb +28 -0
  16. data/lib/cldr/export/data/delimiters.rb +29 -0
  17. data/lib/cldr/export/data/languages.rb +19 -0
  18. data/lib/cldr/export/data/numbers.rb +67 -0
  19. data/lib/cldr/export/data/plurals.rb +41 -0
  20. data/lib/cldr/{data → export/data}/plurals/cldr_grammar.treetop +0 -0
  21. data/lib/cldr/export/data/plurals/grammar.rb +538 -0
  22. data/lib/cldr/export/data/plurals/rules.rb +119 -0
  23. data/lib/cldr/export/data/territories.rb +19 -0
  24. data/lib/cldr/export/data/timezones.rb +27 -0
  25. data/lib/cldr/export/data/units.rb +29 -0
  26. data/lib/cldr/export/ruby.rb +1 -1
  27. data/lib/cldr/export/yaml.rb +1 -1
  28. data/lib/cldr/format.rb +1 -97
  29. data/lib/cldr/format/currency.rb +1 -1
  30. data/lib/cldr/format/date.rb +1 -1
  31. data/lib/cldr/format/datetime.rb +14 -18
  32. data/lib/cldr/format/datetime/base.rb +1 -1
  33. data/lib/cldr/format/decimal.rb +1 -1
  34. data/lib/cldr/format/decimal/base.rb +1 -1
  35. data/lib/cldr/format/decimal/fraction.rb +1 -1
  36. data/lib/cldr/format/decimal/integer.rb +1 -1
  37. data/lib/cldr/format/decimal/number.rb +1 -1
  38. data/lib/cldr/format/percent.rb +1 -1
  39. data/lib/cldr/format/time.rb +1 -1
  40. data/lib/cldr/thor.rb +3 -3
  41. data/test/all.rb +1 -1
  42. data/test/export/code/numbers_test.rb +11 -0
  43. data/test/{data → export/data}/all.rb +1 -1
  44. data/test/{data → export/data}/calendars_test.rb +18 -18
  45. data/test/{data → export/data}/currencies_test.rb +6 -6
  46. data/test/{data → export/data}/delimiters_test.rb +6 -6
  47. data/test/{data → export/data}/languages_test.rb +6 -6
  48. data/test/{data → export/data}/numbers_test.rb +8 -8
  49. data/test/export/data/plurals_test.rb +141 -0
  50. data/test/{data → export/data}/territories_test.rb +6 -6
  51. data/test/{data → export/data}/timezones_test.rb +6 -6
  52. data/test/{data → export/data}/units_test.rb +6 -6
  53. data/test/export_test.rb +8 -8
  54. data/test/{formats → format}/all.rb +1 -1
  55. data/test/format/currency_test.rb +0 -0
  56. data/test/format/date_test.rb +265 -0
  57. data/test/format/datetime_test.rb +18 -0
  58. data/test/{formats → format}/decimal/fraction_test.rb +4 -4
  59. data/test/{formats → format}/decimal/integer_test.rb +17 -17
  60. data/test/{formats → format}/decimal/number_test.rb +19 -19
  61. data/test/{formats → format}/decimal_test.rb +5 -5
  62. data/test/format/percent_test.rb +0 -0
  63. data/test/format/time_test.rb +195 -0
  64. data/test/test_autotest.rb +36 -0
  65. data/test/test_helper.rb +16 -1
  66. metadata +124 -114
  67. data/lib/cldr/data/base.rb +0 -66
  68. data/lib/cldr/data/calendars.rb +0 -12
  69. data/lib/cldr/data/calendars/gregorian.rb +0 -124
  70. data/lib/cldr/data/currencies.rb +0 -26
  71. data/lib/cldr/data/delimiters.rb +0 -21
  72. data/lib/cldr/data/languages.rb +0 -17
  73. data/lib/cldr/data/numbers.rb +0 -60
  74. data/lib/cldr/data/plurals.rb +0 -39
  75. data/lib/cldr/data/plurals/grammar.rb +0 -536
  76. data/lib/cldr/data/plurals/rules.rb +0 -113
  77. data/lib/cldr/data/territories.rb +0 -17
  78. data/lib/cldr/data/timezones.rb +0 -25
  79. data/lib/cldr/data/units.rb +0 -25
  80. data/test/data/plurals_test.rb +0 -132
  81. data/test/formats/datetime/all.rb +0 -3
  82. data/test/formats/datetime/date_test.rb +0 -31
  83. data/test/formats/datetime/datetime_test.rb +0 -18
  84. data/test/formats/datetime/day_test.rb +0 -41
  85. data/test/formats/datetime/hour_test.rb +0 -79
  86. data/test/formats/datetime/minute_test.rb +0 -25
  87. data/test/formats/datetime/month_test.rb +0 -76
  88. data/test/formats/datetime/period_test.rb +0 -20
  89. data/test/formats/datetime/quarter_test.rb +0 -118
  90. data/test/formats/datetime/second_test.rb +0 -80
  91. data/test/formats/datetime/time_test.rb +0 -33
  92. data/test/formats/datetime/timezone_test.rb +0 -23
  93. data/test/formats/datetime/year_test.rb +0 -57
  94. data/test/formats/format_test.rb +0 -66
  95. data/test/formats/rails_compat/all.rb +0 -3
  96. data/test/formats/rails_compat/format_integer_test.rb +0 -56
  97. data/test/formats/rails_compat/format_number_test.rb +0 -134
@@ -0,0 +1,119 @@
1
+ require 'rubygems'
2
+ require 'rexml/document'
3
+
4
+ module Cldr
5
+ module Export
6
+ module Data
7
+ class Plurals
8
+ class Rules < Array
9
+ class << self
10
+ def parse(xml)
11
+ rules = new
12
+ REXML::Document.new(xml).elements.each('//pluralRules') do |tag|
13
+ rule = Rule.new(tag.attributes['locales'].split(/\s+/))
14
+ tag.elements.each('pluralRule') { |tag| rule << [tag.attributes['count'], tag.text] }
15
+ rules << rule
16
+ end
17
+ rules
18
+ end
19
+ end
20
+
21
+ def locales
22
+ @locales ||= map { |rule| rule.locales }.flatten.map(&:to_s).sort.map(&:to_sym)
23
+ end
24
+
25
+ def rule(locale)
26
+ detect { |rule| rule.locales.include?(locale.to_sym) }
27
+ end
28
+
29
+ def to_ruby(options = {})
30
+ namespaces = options[:namespaces] || [:i18n]
31
+ code = locales.map do |locale|
32
+ rule = self.rule(locale)
33
+ ruby = "{ :plural => { :keys => #{rule.keys.inspect}, :rule => #{rule.to_ruby} } }"
34
+ ruby = namespaces.reverse.inject(ruby) { |ruby, namespace| "{ #{namespace.inspect} => #{ruby} }"}
35
+ "#{locale.inspect} => #{ruby}"
36
+ end.join(",\n")
37
+ code = code.split("\n").map { |line| " #{line}" }.join("\n")
38
+ "{\n" + code + "\n}"
39
+ end
40
+ end
41
+
42
+ class Rule < Array
43
+ class << self
44
+ def parse(code)
45
+ case code
46
+ when /and/
47
+ code.split(/and/).inject(Proposition.new('&&')) { |rule, code| rule << parse(code) }
48
+ when /or/
49
+ code.split(/or/).inject(Proposition.new('||')) { |rule, code| rule << parse(code) }
50
+ when /n( mod ([\d]+))? is (not )?([\d]+)/
51
+ Expression.new(:is, $2, !!$3, $4)
52
+ when /n( mod ([\d]+))?( not)? in ([\d]+\.\.[\d]+)/
53
+ Expression.new(:in, $2, !!$3, eval($4).to_a.inspect)
54
+ when /n within ([\d]+)\.\.([\d]+)/
55
+ Expression.new(:within, nil, nil, [$1, $2])
56
+ when /n/
57
+ Expression.new
58
+ else
59
+ raise "can not parse #{code}"
60
+ end
61
+ end
62
+ end
63
+
64
+ attr_reader :locales
65
+
66
+ def initialize(locales)
67
+ @locales = locales.map { |locale| locale.gsub('_', '-').to_sym }
68
+ end
69
+
70
+ def keys
71
+ inject([]) { |keys, (key, code)| keys << key.to_sym } << :other
72
+ end
73
+
74
+ def to_ruby
75
+ @condition ||= 'lambda { |n| ' + reverse.inject(':other') do |result, (key, code)|
76
+ code = self.class.parse(code).to_ruby
77
+ "#{code} ? :#{key} : #{result}"
78
+ end + ' }'
79
+ end
80
+ end
81
+
82
+ class Proposition < Array
83
+ def initialize(type = nil)
84
+ @type = type
85
+ end
86
+
87
+ def to_ruby
88
+ @ruby ||= map { |expr| expr.to_ruby }.join(" #{@type} ")
89
+ end
90
+ end
91
+
92
+ class Expression
93
+ attr_reader :operator, :operand, :mod, :negate
94
+
95
+ def initialize(operator = nil, mod = nil, negate = nil, operand = nil)
96
+ @operator, @mod, @negate, @operand = operator, mod, negate, operand
97
+ end
98
+
99
+ def to_ruby
100
+ @ruby ||= begin
101
+ op = 'n'
102
+ op << " % #{@mod}" if mod
103
+ case @operator
104
+ when :is
105
+ op + (@negate ? ' != ' : ' == ') + @operand
106
+ when :in
107
+ (@negate ? '!' : '') + "#{@operand}.include?(#{op})"
108
+ when :within
109
+ "#{op}.between?(#{@operand.first}, #{@operand.last})"
110
+ else
111
+ op
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,19 @@
1
+ module Cldr
2
+ module Export
3
+ module Data
4
+ class Territories < Base
5
+ def initialize(locale)
6
+ super
7
+ update(:territories => territories)
8
+ end
9
+
10
+ def territories
11
+ @territories ||= select('localeDisplayNames/territories/territory').inject({}) do |result, node|
12
+ result[node.attribute('type').value.to_sym] = node.content unless draft?(node)
13
+ result
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # I probably don't really get timezones.
2
+
3
+ module Cldr
4
+ module Export
5
+ module Data
6
+ class Timezones < Base
7
+ def initialize(locale)
8
+ super
9
+ update(:timezones => timezones)
10
+ end
11
+
12
+ def timezones
13
+ @timezones ||= select('dates/timeZoneNames/zone').inject({}) do |result, zone|
14
+ type = zone.attribute('type').value.to_sym
15
+ city = select(zone, 'exemplarCity').first
16
+ result[type] = {}
17
+ # see en.xml, Europe/London, does not have an exemplarCity element
18
+ # instead it has long and short daylight names which otherwise only
19
+ # have metazones. (??)
20
+ result[type][:city] = city.content if city
21
+ result
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ module Cldr
2
+ module Export
3
+ module Data
4
+ class Units < Base
5
+ def initialize(locale)
6
+ super
7
+ update(:units => units)
8
+ end
9
+
10
+ def units
11
+ select('units/unit').inject({}) do |result, node|
12
+ result[node.attribute('type').value.to_sym] = unit(node)
13
+ result
14
+ end
15
+ end
16
+
17
+ def unit(node)
18
+ node.xpath('unitPattern').inject({}) do |result, node|
19
+ alt = node.attribute('alt') ? node.attribute('alt').value.to_sym : :default
20
+ count = node.attribute('count') ? node.attribute('count').value.to_sym : :one
21
+ result[alt] ||= {}
22
+ result[alt][count] = node.content unless draft?(node)
23
+ result
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Export
3
3
  class Ruby
4
4
  def export(locale, component, options = {})
@@ -1,6 +1,6 @@
1
1
  require 'ya2yaml'
2
2
 
3
- class Cldr
3
+ module Cldr
4
4
  module Export
5
5
  class Yaml < Ya2YAML
6
6
  def initialize
data/lib/cldr/format.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require 'core_ext/string/camelize'
3
3
 
4
- class Cldr
4
+ module Cldr
5
5
  module Format
6
6
  autoload :Base, 'cldr/format/base'
7
7
  autoload :Currency, 'cldr/format/currency'
@@ -13,101 +13,5 @@ class Cldr
13
13
  autoload :Numeric, 'cldr/format/numeric'
14
14
  autoload :Percent, 'cldr/format/percent'
15
15
  autoload :Time, 'cldr/format/time'
16
-
17
- def format(locale, object, options = {})
18
- type = options.has_key?(:currency) ? :currency : options.delete(:as)
19
- type ||= guess_type(object)
20
-
21
- send(:"format_#{type}", locale, object, options)
22
- end
23
-
24
- def format_decimal(locale, number, options = {})
25
- formatter(locale, :decimal, options.delete(:format)).apply(number, options)
26
- end
27
- alias :format_number :format_decimal
28
-
29
- def format_integer(locale, number, options = {})
30
- format_number(number, options.merge(:precision => 0))
31
- end
32
- alias :format_int :format_integer
33
-
34
- def format_currency(locale, number, options = {})
35
- if options[:currency].is_a?(Symbol)
36
- options.merge!(:currency => lookup_currency(locale, options[:currency], number))
37
- end
38
- formatter(locale, :currency, options.delete(:format)).apply(number, options)
39
- end
40
-
41
- def format_percent(locale, number, options = {})
42
- formatter(locale, :percent, options.delete(:format)).apply(number, options)
43
- end
44
-
45
- def format_date(locale, date, options = {})
46
- formatter(locale, :date, options.delete(:format)).apply(date, options)
47
- end
48
-
49
- def format_time(locale, time, options = {})
50
- formatter(locale, :time, options.delete(:format)).apply(time, options)
51
- end
52
-
53
- def format_datetime(locale, datetime, options = {})
54
- format = options.delete(:format) || :default
55
- (@formatters ||= {})[:"#{locale}.datetime.#{format}"] ||= begin
56
- date = formatter(locale, :date, options.delete(:date_format) || format)
57
- time = formatter(locale, :time, options.delete(:time_format) || format)
58
- format = lookup_format(locale, :datetime, format)
59
- Cldr::Format::Datetime.new(format, date, time).apply(datetime, options)
60
- end
61
- end
62
-
63
- protected
64
-
65
- def guess_type(object)
66
- case object
67
- when ::Numeric
68
- :number
69
- when ::Date, ::DateTime, ::Time
70
- object.class.name.downcase
71
- else
72
- raise_unspecified_format_type!
73
- end
74
- end
75
-
76
- def formatter(locale, type, format)
77
- (@formatters ||= {})[:"#{locale}.#{type}.#{format}"] ||= begin
78
- format = lookup_format(locale, type, format)
79
- data = lookup_format_data(locale, type)
80
- Cldr::Format.const_get(type.to_s.camelize).new(format, data)
81
- end
82
- end
83
-
84
- def lookup_format(locale, type, format)
85
- # Lookup the format string for the given type (e.g. :number).
86
- raise_abstract!
87
- end
88
-
89
- def lookup_format_data(locale, type)
90
- # Lookup the format data required for the given type (e.g. number
91
- # symbols for type :number, calendar data for type :date etc.).
92
- raise_abstract!
93
- end
94
-
95
- def lookup_currency(locale, currency, count)
96
- # Lookup the currency representation for the given locale and amount.
97
- # This might be a translation.
98
- raise_abstract!
99
- end
100
-
101
- def raise_unspecified_format_type!
102
- raise ArgumentError.new("You have to specify a format type, e.g. :as => :number.")
103
- end
104
-
105
- def raise_unspecified_currency!
106
- raise ArgumentError.new("You have to specify a currency, e.g. :currency => 'EUR'.")
107
- end
108
-
109
- def raise_abstract!
110
- raise "you have to implement this method"
111
- end
112
16
  end
113
17
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- class Cldr
3
+ module Cldr
4
4
  module Format
5
5
  class Currency < Decimal
6
6
  def apply(number, options = {})
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Date < Datetime::Base
4
4
  PATTERN = /G{1,5}|y+|Y+|Q{1,4}|q{1,5}|M{1,5}|L{1,5}|d{1,2}|F{1}|E{1,5}|e{1,5}|c{1,5}/
@@ -1,28 +1,24 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Datetime
4
4
  autoload :Base, 'cldr/format/datetime/base'
5
5
 
6
- attr_reader :date, :time
7
-
6
+ attr_reader :format, :date, :time
7
+
8
8
  def initialize(format, date, time)
9
- @date, @time = date, time
10
- compile(format)
9
+ @format, @date, @time = format, date, time
11
10
  end
12
-
13
- protected
14
-
15
- def compile(format)
16
- (class << self; self; end).class_eval <<-code
17
- def apply(datetime, options = {}); #{compile_format(format)}; end
18
- code
19
- end
20
-
21
- def compile_format(format)
22
- "'" + format.gsub(%r(\{(0|1)\})) do |token|
23
- "' + #{token == '{0}' ? 'time' : 'date'}.apply(datetime, options) + '"
24
- end + "'"
11
+
12
+ def apply(datetime, options = {})
13
+ format.gsub(/(\{\{(date|time)\}\})/) do
14
+ case $2
15
+ when 'date'
16
+ options[:date] || date.apply(datetime, options)
17
+ when 'time'
18
+ options[:time] || time.apply(datetime, options)
19
+ end
25
20
  end
21
+ end
26
22
  end
27
23
  end
28
24
  end
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Datetime
4
4
  class Base
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Decimal
4
4
  autoload :Base, 'cldr/format/decimal/base'
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Decimal
4
4
  class Base
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Decimal
4
4
  class Fraction < Base
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Decimal
4
4
  class Integer < Base
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Decimal
4
4
  class Number
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- class Cldr
3
+ module Cldr
4
4
  module Format
5
5
  class Percent < Decimal
6
6
  def apply(number, options = {})
@@ -1,4 +1,4 @@
1
- class Cldr
1
+ module Cldr
2
2
  module Format
3
3
  class Time < Datetime::Base
4
4
  PATTERN = /a{1}|h{1,2}|H{1,2}|K{1,2}|k{1,2}|m{1,2}|s{1,2}|S+|z{1,4}|Z{1,4}/