ruby-cldr 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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}/