ruby-cldr 0.0.2 → 0.1.0
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.
- checksums.yaml +7 -0
- data/Gemfile +8 -2
- data/Gemfile.lock +55 -5
- data/VERSION +1 -1
- data/lib/cldr/download.rb +15 -11
- data/lib/cldr/export.rb +64 -16
- data/lib/cldr/export/data.rb +18 -10
- data/lib/cldr/export/data/calendars/gregorian.rb +45 -22
- data/lib/cldr/export/data/currencies.rb +6 -1
- data/lib/cldr/export/data/currency_digits_and_rounding.rb +22 -0
- data/lib/cldr/export/data/layout.rb +22 -0
- data/lib/cldr/export/data/lists.rb +28 -0
- data/lib/cldr/export/data/metazones.rb +45 -0
- data/lib/cldr/export/data/numbering_systems.rb +41 -0
- data/lib/cldr/export/data/numbers.rb +9 -0
- data/lib/cldr/export/data/plurals.rb +8 -7
- data/lib/cldr/export/data/plurals/rules.rb +114 -31
- data/lib/cldr/export/data/rbnf.rb +64 -0
- data/lib/cldr/export/data/rbnf_root.rb +19 -0
- data/lib/cldr/export/data/timezones.rb +29 -6
- data/lib/cldr/export/data/units.rb +23 -6
- data/lib/cldr/export/data/windows_zones.rb +23 -0
- data/lib/cldr/export/yaml.rb +2 -1
- data/lib/cldr/format/datetime/base.rb +1 -1
- data/lib/cldr/format/time.rb +1 -1
- data/lib/cldr/thor.rb +1 -1
- data/lib/core_ext/string/camelize.rb +1 -1
- data/test/export/data/calendars_test.rb +23 -18
- data/test/export/data/currencies_test.rb +24 -24
- data/test/export/data/languages_test.rb +52 -48
- data/test/export/data/metazones_test.rb +17 -0
- data/test/export/data/numbers_test.rb +34 -3
- data/test/export/data/plurals_test.rb +133 -32
- data/test/export/data/territories_test.rb +22 -22
- data/test/export/data/timezones_test.rb +49 -26
- data/test/export/data/units_test.rb +16 -17
- data/test/export/data/windows_zones_test.rb +12 -0
- data/test/export_test.rb +4 -1
- data/test/format/date_test.rb +2 -2
- data/test/test_autotest.rb +1 -1
- metadata +94 -32
@@ -0,0 +1,22 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class Layout < Base
|
5
|
+
def initialize(locale)
|
6
|
+
super
|
7
|
+
update(:layout => layout)
|
8
|
+
end
|
9
|
+
|
10
|
+
def layout
|
11
|
+
result = { :orientation => { :character_order => nil } }
|
12
|
+
|
13
|
+
if node = select("layout/orientation/characterOrder/text()").first
|
14
|
+
result[:orientation][:character_order] = node.text
|
15
|
+
end
|
16
|
+
|
17
|
+
result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class Lists < Base
|
5
|
+
def initialize(locale)
|
6
|
+
super
|
7
|
+
update(:lists => lists)
|
8
|
+
end
|
9
|
+
|
10
|
+
def lists
|
11
|
+
select('listPatterns/listPattern').inject({}) do |list_pattern_ret, list_pattern|
|
12
|
+
pattern_type = if attribute = list_pattern.attribute('type')
|
13
|
+
attribute.value.to_sym
|
14
|
+
else
|
15
|
+
:default
|
16
|
+
end
|
17
|
+
|
18
|
+
list_pattern_ret[pattern_type] = select(list_pattern, 'listPatternPart').inject({}) do |part_ret, part|
|
19
|
+
part_ret[part.attribute('type').value.to_sym] = part.content
|
20
|
+
part_ret
|
21
|
+
end
|
22
|
+
list_pattern_ret
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Cldr
|
5
|
+
module Export
|
6
|
+
module Data
|
7
|
+
class Metazones < Hash
|
8
|
+
def initialize
|
9
|
+
path = "#{Cldr::Export::Data.dir}/supplemental/metaZones.xml"
|
10
|
+
doc = File.open(path) { |file| Nokogiri::XML(file) }
|
11
|
+
self[:timezones] = doc.xpath('//metaZones/metazoneInfo/timezone').inject({}) do |result, node|
|
12
|
+
timezone = node.attr('type').to_sym
|
13
|
+
result[timezone] = metazone(node.xpath('usesMetazone'))
|
14
|
+
result[timezone].sort_by! { |zone| [zone['from'] ? zone['from'] : DateTime.new, zone['to'] ? zone['to'] : DateTime.now] }
|
15
|
+
result
|
16
|
+
end
|
17
|
+
self[:primaryzones] = doc.xpath('//primaryZones/primaryZone').inject({}) do |result, node|
|
18
|
+
territory = node.attr('iso3166').to_sym
|
19
|
+
result[territory] = node.content
|
20
|
+
result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def metazone(nodes)
|
27
|
+
nodes.inject([]) do |result, node|
|
28
|
+
mzone = node.attr('mzone')
|
29
|
+
from = node.attr('from')
|
30
|
+
to = node.attr('to')
|
31
|
+
data = { 'metazone' => mzone }
|
32
|
+
data['from'] = parse_date(from) if from
|
33
|
+
data['to'] = parse_date(to) if to
|
34
|
+
result << data
|
35
|
+
result
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_date(date)
|
40
|
+
DateTime.strptime(date + ' UTC', '%F %R %Z')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Cldr
|
4
|
+
module Export
|
5
|
+
module Data
|
6
|
+
class NumberingSystems < Base
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
super(nil)
|
10
|
+
update(:numbering_systems => numbering_systems)
|
11
|
+
end
|
12
|
+
|
13
|
+
def numbering_systems
|
14
|
+
doc.xpath("supplementalData/numberingSystems/numberingSystem").inject({}) do |ret, numbering|
|
15
|
+
system_name = numbering.attribute("id").value
|
16
|
+
type = numbering.attribute("type").value
|
17
|
+
|
18
|
+
param = case type
|
19
|
+
when "numeric"
|
20
|
+
"digits"
|
21
|
+
when "algorithmic"
|
22
|
+
"rules"
|
23
|
+
end
|
24
|
+
|
25
|
+
ret[system_name] = {
|
26
|
+
:type => type,
|
27
|
+
param => numbering.attribute(param).value
|
28
|
+
}
|
29
|
+
|
30
|
+
ret
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def path
|
35
|
+
@path ||= "#{Cldr::Export::Data.dir}/supplemental/numberingSystems.xml"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -9,15 +9,19 @@ module Cldr
|
|
9
9
|
:symbols => symbols,
|
10
10
|
:formats => {
|
11
11
|
:decimal => {
|
12
|
+
:number_system => number_system('decimal'),
|
12
13
|
:patterns => format('decimal')
|
13
14
|
},
|
14
15
|
:scientific => {
|
16
|
+
:number_system => number_system('scientific'),
|
15
17
|
:patterns => format('scientific')
|
16
18
|
},
|
17
19
|
:percent => {
|
20
|
+
:number_system => number_system('percent'),
|
18
21
|
:patterns => format('percent')
|
19
22
|
},
|
20
23
|
:currency => {
|
24
|
+
:number_system => number_system('currency'),
|
21
25
|
:patterns => format('currency'),
|
22
26
|
:unit => unit
|
23
27
|
}
|
@@ -54,6 +58,11 @@ module Cldr
|
|
54
58
|
result
|
55
59
|
end
|
56
60
|
|
61
|
+
def number_system(type)
|
62
|
+
node = select("numbers/#{type}Formats").first
|
63
|
+
node.attribute('numberSystem').value rescue "latn"
|
64
|
+
end
|
65
|
+
|
57
66
|
def unit
|
58
67
|
@unit ||= select("numbers/currencyFormats/unitPattern").inject({}) do |result, node|
|
59
68
|
count = node.attribute('count').value rescue 'one'
|
@@ -3,7 +3,7 @@ require 'fileutils'
|
|
3
3
|
module Cldr
|
4
4
|
module Export
|
5
5
|
module Data
|
6
|
-
class Plurals <
|
6
|
+
class Plurals < Hash
|
7
7
|
autoload :Grammar, 'cldr/export/data/plurals/grammar'
|
8
8
|
autoload :Parser, 'cldr/export/data/plurals/grammar'
|
9
9
|
autoload :Rules, 'cldr/export/data/plurals/rules'
|
@@ -20,18 +20,19 @@ module Cldr
|
|
20
20
|
File.read("#{Cldr::Export::Data.dir}/supplemental/plurals.xml")
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
attr_reader :locale
|
25
25
|
|
26
26
|
def initialize(locale)
|
27
27
|
@locale = locale
|
28
|
-
|
28
|
+
self.merge!(rule ? to_hash : {})
|
29
29
|
end
|
30
|
-
|
31
|
-
def
|
32
|
-
|
30
|
+
|
31
|
+
def to_hash
|
32
|
+
rule_rb = rule ? rule.to_ruby : nil
|
33
|
+
{ :keys => (rule || {}).keys, :rule => rule_rb }
|
33
34
|
end
|
34
|
-
|
35
|
+
|
35
36
|
def rule
|
36
37
|
@rule = Plurals.rules.rule(locale)
|
37
38
|
end
|
@@ -17,15 +17,15 @@ module Cldr
|
|
17
17
|
rules
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def locales
|
22
22
|
@locales ||= map { |rule| rule.locales }.flatten.map(&:to_s).sort.map(&:to_sym)
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def rule(locale)
|
26
26
|
detect { |rule| rule.locales.include?(locale.to_sym) }
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def to_ruby(options = {})
|
30
30
|
namespaces = options[:namespaces] || [:i18n]
|
31
31
|
code = locales.map do |locale|
|
@@ -38,25 +38,44 @@ module Cldr
|
|
38
38
|
"{\n" + code + "\n}"
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
class Rule < Array
|
43
43
|
class << self
|
44
|
+
|
45
|
+
def parse_list(str)
|
46
|
+
values = []
|
47
|
+
ranges = []
|
48
|
+
str.split(',').each do |value|
|
49
|
+
parts = value.split('..')
|
50
|
+
if parts.count == 1
|
51
|
+
values << value.to_i
|
52
|
+
else
|
53
|
+
ranges << (parts.first.to_i..parts.last.to_i)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
[values, ranges]
|
57
|
+
end
|
58
|
+
|
44
59
|
def parse(code)
|
60
|
+
code = code.split('@').first.to_s
|
61
|
+
operand = /(n|i|f|t|v|w)/i
|
62
|
+
expr = /#{operand}(?:\s+(?:mod|%)\s+([\d]+))?/i
|
63
|
+
range = /(?:\d+\.\.\d+|\d+)/i
|
64
|
+
range_list = /(#{range}(?:\s*,\s*#{range})*)/i
|
45
65
|
case code
|
46
|
-
when /
|
47
|
-
code.split(/
|
48
|
-
when /
|
49
|
-
code.split(/
|
50
|
-
when
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
when /n/
|
66
|
+
when /or/i
|
67
|
+
code.split(/or/i).inject(Proposition.new('||')) { |rule, code| rule << parse(code) }
|
68
|
+
when /and/i
|
69
|
+
code.split(/and/i).inject(Proposition.new('&&')) { |rule, code| rule << parse(code) }
|
70
|
+
when /^\s*#{expr}\s+(?:is(\s+not)?|(not\s+)?in|(!)?=)\s+#{range_list}\s*$/i
|
71
|
+
list = parse_list($6)
|
72
|
+
Expression.new((list.first.count == 1 && list.last.count == 0) ? :is : :in, $2, !($3.nil? && $4.nil? && $5.nil?), (list.first.count == 1 && list.last.count == 0) ? list.first.first : list, $1)
|
73
|
+
when /^\s*#{expr}\s+(not\s+)?within\s+#{range_list}\s*$/i
|
74
|
+
Expression.new(:within, $2, !($3==nil), parse_list($4).last.first, $1)
|
75
|
+
when /^\s*$/
|
57
76
|
Expression.new
|
58
77
|
else
|
59
|
-
raise "can not parse #{code}"
|
78
|
+
raise "can not parse '#{code}'"
|
60
79
|
end
|
61
80
|
end
|
62
81
|
end
|
@@ -66,15 +85,19 @@ module Cldr
|
|
66
85
|
def initialize(locales)
|
67
86
|
@locales = locales.map { |locale| locale.gsub('_', '-').to_sym }
|
68
87
|
end
|
69
|
-
|
88
|
+
|
70
89
|
def keys
|
71
|
-
inject([]) { |keys, (key, code)| keys << key.to_sym }
|
90
|
+
inject([]) { |keys, (key, code)| keys << key.to_sym }
|
72
91
|
end
|
73
|
-
|
92
|
+
|
74
93
|
def to_ruby
|
75
|
-
@condition ||= 'lambda { |n| ' + reverse.inject(':other') do |result, (key, code)|
|
94
|
+
@condition ||= 'lambda { |n| n = n.respond_to?(:abs) ? n.abs : ((m = n.to_s)[0] == "-" ? m[1,m.length] : m); ' + reverse.inject(':other') do |result, (key, code)|
|
76
95
|
code = self.class.parse(code).to_ruby
|
77
|
-
|
96
|
+
if code
|
97
|
+
"#{code} ? :#{key} : #{result}"
|
98
|
+
else
|
99
|
+
':' << key.to_s
|
100
|
+
end
|
78
101
|
end + ' }'
|
79
102
|
end
|
80
103
|
end
|
@@ -85,30 +108,90 @@ module Cldr
|
|
85
108
|
end
|
86
109
|
|
87
110
|
def to_ruby
|
88
|
-
@ruby ||= map { |expr| expr.to_ruby }.join(" #{@type} ")
|
111
|
+
@ruby ||= '(' << map { |expr| expr.to_ruby }.join(" #{@type} ") << ')'
|
89
112
|
end
|
90
113
|
end
|
91
114
|
|
92
115
|
class Expression
|
93
|
-
attr_reader :operator, :operand, :mod, :negate
|
116
|
+
attr_reader :operator, :operand, :mod, :negate, :type
|
94
117
|
|
95
|
-
def initialize(operator = nil, mod = nil, negate = nil, operand = nil)
|
96
|
-
@operator, @mod, @negate, @operand = operator, mod, negate, operand
|
118
|
+
def initialize(operator = nil, mod = nil, negate = nil, operand = nil, type = nil)
|
119
|
+
@operator, @mod, @negate, @operand, @type = operator, mod, negate, operand, type
|
97
120
|
end
|
98
121
|
|
122
|
+
# Symbol Value
|
123
|
+
# n absolute value of the source number (integer and decimals).
|
124
|
+
# i integer digits of n.
|
125
|
+
# v number of visible fraction digits in n, with trailing zeros.
|
126
|
+
# w number of visible fraction digits in n, without trailing zeros.
|
127
|
+
# f visible fractional digits in n, with trailing zeros.
|
128
|
+
# t visible fractional digits in n, without trailing zeros.
|
129
|
+
#
|
130
|
+
# http://www.unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules
|
99
131
|
def to_ruby
|
100
132
|
@ruby ||= begin
|
101
|
-
|
102
|
-
|
133
|
+
return nil unless @operator
|
134
|
+
enclose = false
|
135
|
+
fraction = false
|
136
|
+
case @type
|
137
|
+
when 'i'
|
138
|
+
op = 'n.to_i'
|
139
|
+
when 'f'
|
140
|
+
op = '(f = n.to_s.split(".")[1]) ? f.to_i : 0'
|
141
|
+
enclose = true
|
142
|
+
when 't'
|
143
|
+
op = '(t = n.to_s.split(".")[1]) ? t.gsub(/0+$/, "").to_i : 0'
|
144
|
+
enclose = true
|
145
|
+
when 'v'
|
146
|
+
op = '(v = n.to_s.split(".")[1]) ? v.length : 0'
|
147
|
+
enclose = true
|
148
|
+
when 'w'
|
149
|
+
op = '(w = n.to_s.split(".")[1]) ? w.gsub(/0+$/, "").length : 0'
|
150
|
+
enclose = true
|
151
|
+
else
|
152
|
+
fraction = true
|
153
|
+
op = 'n.to_f'
|
154
|
+
end
|
155
|
+
if @mod
|
156
|
+
op = '(' << op << ')' if enclose
|
157
|
+
op << ' % ' << @mod.to_s
|
158
|
+
enclose = false
|
159
|
+
end
|
103
160
|
case @operator
|
104
161
|
when :is
|
105
|
-
op
|
162
|
+
op = '(' << op << ')' if enclose
|
163
|
+
op << (@negate ? ' != ' : ' == ') << @operand.to_s
|
106
164
|
when :in
|
107
|
-
|
165
|
+
values = @operand.first
|
166
|
+
ranges = @operand.last
|
167
|
+
prepend = (@negate ? '!' : '')
|
168
|
+
str = ''
|
169
|
+
bop = op
|
170
|
+
bop = '(' << bop << ')' if enclose || @mod
|
171
|
+
if values.count == 1
|
172
|
+
str = bop + (@negate ? ' != ' : ' == ') << values.first.to_s
|
173
|
+
elsif values.count > 1
|
174
|
+
str = prepend + "#{values.inspect}.include?(#{op})"
|
175
|
+
end
|
176
|
+
enclose = ranges.count > 1 || (values.count > 0 && ranges.count > 0)
|
177
|
+
if ranges.count > 0
|
178
|
+
str << ' || ' if values.count > 0
|
179
|
+
str << "((#{bop} % 1).zero? && " if fraction
|
180
|
+
str << '(' if ranges.count > 1
|
181
|
+
str << prepend + "(#{ranges.shift.inspect}).include?(#{op})"
|
182
|
+
ranges.each do |range|
|
183
|
+
str << ' || ' << prepend + "(#{range.inspect}).include?(#{op})"
|
184
|
+
end
|
185
|
+
str << ')' if ranges.count > 0
|
186
|
+
str << ')' if fraction
|
187
|
+
end
|
188
|
+
str = '(' << str << ')' if enclose
|
189
|
+
str
|
108
190
|
when :within
|
109
|
-
|
191
|
+
op = '(' << op << ')' if enclose || @mod
|
192
|
+
(@negate ? '!' : '') + "#{op}.between?(#{@operand.first}, #{@operand.last})"
|
110
193
|
else
|
111
|
-
|
194
|
+
raise "unknown operator '#{@operator}'"
|
112
195
|
end
|
113
196
|
end
|
114
197
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Cldr
|
4
|
+
module Export
|
5
|
+
module Data
|
6
|
+
class Rbnf < Base
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
super
|
10
|
+
update(:rbnf => { :grouping => rule_groups })
|
11
|
+
end
|
12
|
+
|
13
|
+
def rule_groups
|
14
|
+
if File.exist?(path)
|
15
|
+
select("rbnf/rulesetGrouping").map do |grouping_node|
|
16
|
+
{
|
17
|
+
:type => grouping_node.attribute("type").value,
|
18
|
+
:ruleset => (grouping_node / "ruleset").map do |ruleset_node|
|
19
|
+
rule_set(ruleset_node)
|
20
|
+
end
|
21
|
+
}
|
22
|
+
end
|
23
|
+
else
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def rule_set(ruleset_node)
|
29
|
+
attrs = {
|
30
|
+
:type => ruleset_node.attribute("type").value,
|
31
|
+
:rules => (ruleset_node / "rbnfrule").map do |rule_node|
|
32
|
+
radix = if radix_attr = rule_node.attribute("radix")
|
33
|
+
radix_attr.value
|
34
|
+
else
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
attrs = {
|
39
|
+
:value => rule_node.attribute("value").value,
|
40
|
+
:rule => fix_rule(rule_node.text)
|
41
|
+
}
|
42
|
+
|
43
|
+
attrs[:radix] = radix if radix
|
44
|
+
attrs
|
45
|
+
end
|
46
|
+
}
|
47
|
+
|
48
|
+
access = ruleset_node.attribute("access")
|
49
|
+
attrs[:access] = access.value if access
|
50
|
+
attrs
|
51
|
+
end
|
52
|
+
|
53
|
+
def fix_rule(rule)
|
54
|
+
rule.gsub(/\A'/, '').gsub("←", '<').gsub("→", '>')
|
55
|
+
end
|
56
|
+
|
57
|
+
def path
|
58
|
+
@path ||= "#{Cldr::Export::Data.dir}/rbnf/#{locale.to_s.gsub('-', '_')}.xml"
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|