ruby-cldr 0.1.1 → 0.2.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 +5 -5
- data/Gemfile +1 -1
- data/Gemfile.lock +56 -46
- data/README.textile +6 -0
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/cldr/download.rb +1 -1
- data/lib/cldr/export.rb +70 -16
- data/lib/cldr/export/data.rb +31 -21
- data/lib/cldr/export/data/aliases.rb +47 -0
- data/lib/cldr/export/data/base.rb +4 -0
- data/lib/cldr/export/data/characters.rb +30 -0
- data/lib/cldr/export/data/fields.rb +60 -0
- data/lib/cldr/export/data/languages.rb +1 -1
- data/lib/cldr/export/data/likely_subtags.rb +29 -0
- data/lib/cldr/export/data/numbers.rb +48 -6
- data/lib/cldr/export/data/parent_locales.rb +23 -0
- data/lib/cldr/export/data/plural_rules.rb +70 -0
- data/lib/cldr/export/data/rbnf.rb +12 -4
- data/lib/cldr/export/data/region_currencies.rb +45 -0
- data/lib/cldr/export/data/segments_root.rb +13 -3
- data/lib/cldr/export/data/territories.rb +1 -1
- data/lib/cldr/export/data/territories_containment.rb +30 -0
- data/lib/cldr/export/data/timezones.rb +18 -2
- data/lib/cldr/export/data/transforms.rb +76 -0
- data/lib/cldr/export/data/variables.rb +42 -0
- data/lib/cldr/export/yaml.rb +5 -21
- data/lib/cldr/thor.rb +2 -2
- data/test/export/data/calendars_test.rb +85 -51
- data/test/export/data/currencies_test.rb +29 -25
- data/test/export/data/languages_test.rb +69 -51
- data/test/export/data/numbers_test.rb +61 -62
- data/test/export/data/plurals_test.rb +4 -3
- data/test/export/data/territories_containment_test.rb +10 -0
- data/test/export/data/territories_test.rb +12 -5
- data/test/export/data/timezones_test.rb +5 -8
- data/test/export_test.rb +57 -5
- data/test/format/time_test.rb +5 -5
- metadata +40 -29
@@ -0,0 +1,60 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class Fields < Base
|
5
|
+
def initialize(locale)
|
6
|
+
super
|
7
|
+
update(:fields => fields)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def fields
|
13
|
+
select('dates/fields/field').each_with_object({}) do |field_node, ret|
|
14
|
+
type = field_node.attribute('type').value
|
15
|
+
ret[type] = field(field_node)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def field(field_node)
|
20
|
+
result = {}
|
21
|
+
|
22
|
+
unless (display_name = (field_node / 'displayName').text).empty?
|
23
|
+
result[:display_name] = display_name
|
24
|
+
end
|
25
|
+
|
26
|
+
unless (forms = relative_forms(field_node)).empty?
|
27
|
+
result[:relative] = forms
|
28
|
+
end
|
29
|
+
|
30
|
+
unless (forms = relative_time_forms(field_node)).empty?
|
31
|
+
result[:relative_time] = forms
|
32
|
+
end
|
33
|
+
|
34
|
+
result
|
35
|
+
end
|
36
|
+
|
37
|
+
def relative_forms(field_node)
|
38
|
+
(field_node / 'relative').each_with_object({}) do |relative_node, ret|
|
39
|
+
type = relative_node.attribute('type').value.to_i
|
40
|
+
ret[type] = relative_node.text
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def relative_time_forms(field_node)
|
45
|
+
(field_node / 'relativeTime').each_with_object({}) do |relative_time_node, ret|
|
46
|
+
type = relative_time_node.attribute('type').value
|
47
|
+
ret[type] = relative_time_patterns(relative_time_node)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def relative_time_patterns(relative_time_node)
|
52
|
+
(relative_time_node / 'relativeTimePattern').each_with_object({}) do |relative_time_pattern_node, ret|
|
53
|
+
count = relative_time_pattern_node.attribute('count').value
|
54
|
+
ret[count] = relative_time_pattern_node.text
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -9,7 +9,7 @@ module Cldr
|
|
9
9
|
|
10
10
|
def languages
|
11
11
|
@languages ||= select('localeDisplayNames/languages/language').inject({}) do |result, node|
|
12
|
-
result[node.attribute('type').value.gsub('_', '-').to_sym] = node.content unless draft?(node)
|
12
|
+
result[node.attribute('type').value.gsub('_', '-').to_sym] = node.content unless draft?(node) or alt?(node)
|
13
13
|
result
|
14
14
|
end
|
15
15
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class LikelySubtags < Base
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super(nil)
|
8
|
+
update(:subtags => subtags)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def subtags
|
14
|
+
doc.xpath('//likelySubtag').inject({}) do |ret, subtag|
|
15
|
+
from = subtag.attribute('from').value
|
16
|
+
to = subtag.attribute('to').value
|
17
|
+
ret[from] = to
|
18
|
+
ret
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def path
|
23
|
+
@path ||= "#{Cldr::Export::Data.dir}/supplemental/likelySubtags.xml"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -44,13 +44,48 @@ module Cldr
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def format(type)
|
47
|
-
result = select("numbers/#{type}Formats/#{type}FormatLength
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
result = select("numbers/#{type}Formats/#{type}FormatLength").inject({}) do |format_result, format_length_node|
|
48
|
+
format_nodes = select(format_length_node, "#{type}Format")
|
49
|
+
|
50
|
+
format_key = format_length_node.attribute('type')
|
51
|
+
format_key = format_key ? format_key.value : :default
|
52
|
+
|
53
|
+
if format_nodes.size > 0
|
54
|
+
format_nodes.each do |format_node|
|
55
|
+
format_result[format_key] ||= select(format_node, "pattern").inject({}) do |pattern_result, pattern_node|
|
56
|
+
pattern_key_node = pattern_node.attribute('type')
|
57
|
+
|
58
|
+
pattern_count_node = pattern_node.attribute('count')
|
59
|
+
|
60
|
+
unless draft?(pattern_node)
|
61
|
+
pattern_key = pattern_key_node ? pattern_key_node.value : :default
|
62
|
+
|
63
|
+
if pattern_count_node
|
64
|
+
pattern_count = pattern_count_node.value
|
65
|
+
|
66
|
+
if pattern_result[pattern_key].nil?
|
67
|
+
pattern_result[pattern_key] ||= {}
|
68
|
+
elsif !pattern_result[pattern_key].is_a?(Hash)
|
69
|
+
raise "can't parse patterns with and without 'count' attribute in the same section"
|
70
|
+
end
|
71
|
+
|
72
|
+
pattern_result[pattern_key][pattern_count] = pattern_node.content
|
73
|
+
else
|
74
|
+
pattern_result[pattern_key] = pattern_node.content
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
pattern_result
|
79
|
+
end
|
80
|
+
end
|
81
|
+
else
|
82
|
+
aliased = select(format_length_node, 'alias').first
|
83
|
+
|
84
|
+
if aliased
|
85
|
+
format_result[format_key] = xpath_to_redirect(aliased.attribute('path').value)
|
86
|
+
end
|
53
87
|
end
|
88
|
+
|
54
89
|
format_result
|
55
90
|
end
|
56
91
|
|
@@ -58,6 +93,13 @@ module Cldr
|
|
58
93
|
result
|
59
94
|
end
|
60
95
|
|
96
|
+
def xpath_to_redirect(xpath)
|
97
|
+
length = xpath[/(\w+)FormatLength/, 1]
|
98
|
+
type = xpath[/@type='(\w+)'/, 1]
|
99
|
+
|
100
|
+
:"numbers.formats.#{length}.patterns.#{type}"
|
101
|
+
end
|
102
|
+
|
61
103
|
def number_system(type)
|
62
104
|
node = select("numbers/#{type}Formats").first
|
63
105
|
node.attribute('numberSystem').value rescue "latn"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Cldr
|
4
|
+
module Export
|
5
|
+
module Data
|
6
|
+
class ParentLocales < Hash
|
7
|
+
def initialize(_)
|
8
|
+
path = File.join(Cldr::Export::Data.dir, 'supplemental', 'supplementalData.xml')
|
9
|
+
doc = File.open(path) { |file| Nokogiri::XML(file) }
|
10
|
+
|
11
|
+
doc.xpath('//parentLocales/parentLocale').each do |node|
|
12
|
+
parent = node.attr('parent')
|
13
|
+
locales = node.attr('locales').split(' ')
|
14
|
+
|
15
|
+
locales.each do |locale|
|
16
|
+
self[locale] = parent
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Cldr
|
4
|
+
module Export
|
5
|
+
module Data
|
6
|
+
class PluralRules < Hash
|
7
|
+
attr_reader :locale
|
8
|
+
|
9
|
+
def initialize(locale)
|
10
|
+
find_rules(locale).each_pair do |rule_type, rule_data|
|
11
|
+
self[rule_type.to_sym] = rule_data.inject({}) do |ret, rule|
|
12
|
+
ret[rule.attributes['count'].text] = rule.text
|
13
|
+
ret
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def sources
|
21
|
+
@sources ||= ['plurals', 'ordinals'].inject({}) do |ret, source_name|
|
22
|
+
ret[source_name] = ::Nokogiri::XML(
|
23
|
+
File.read("#{Cldr::Export::Data.dir}/supplemental/#{source_name}.xml")
|
24
|
+
)
|
25
|
+
ret
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_rules(locale)
|
30
|
+
locale = locale.to_s
|
31
|
+
|
32
|
+
sources.inject({}) do |ret, (file, source)|
|
33
|
+
# try to find exact match, then fall back
|
34
|
+
node = find_rules_for_exact_locale(locale, source) ||
|
35
|
+
find_rules_for_exact_locale(base_locale(locale), source) ||
|
36
|
+
find_rules_for_base_locale(locale, source) ||
|
37
|
+
find_rules_for_base_locale(base_locale(locale), source)
|
38
|
+
|
39
|
+
if node
|
40
|
+
name = (source / 'plurals').first.attributes['type'].value
|
41
|
+
ret[name] = node / 'pluralRule'
|
42
|
+
end
|
43
|
+
|
44
|
+
ret
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_rules_for_exact_locale(locale, source)
|
49
|
+
(source / 'plurals/pluralRules').find do |node|
|
50
|
+
node.attributes['locales'].text
|
51
|
+
.split(' ').map(&:downcase)
|
52
|
+
.include?(locale.downcase)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_rules_for_base_locale(locale, source)
|
57
|
+
(source / 'plurals/pluralRules').find do |node|
|
58
|
+
node.attributes['locales'].text
|
59
|
+
.split(' ').map { |l| base_locale(l) }
|
60
|
+
.include?(locale.downcase)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def base_locale(locale)
|
65
|
+
locale.split(/[_-]/).first
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -30,13 +30,13 @@ module Cldr
|
|
30
30
|
:type => ruleset_node.attribute("type").value,
|
31
31
|
:rules => (ruleset_node / "rbnfrule").map do |rule_node|
|
32
32
|
radix = if radix_attr = rule_node.attribute("radix")
|
33
|
-
radix_attr.value
|
33
|
+
cast_value(radix_attr.value)
|
34
34
|
else
|
35
35
|
nil
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
attrs = {
|
39
|
-
:value => rule_node.attribute("value").value,
|
39
|
+
:value => cast_value(rule_node.attribute("value").value),
|
40
40
|
:rule => fix_rule(rule_node.text)
|
41
41
|
}
|
42
42
|
|
@@ -50,6 +50,14 @@ module Cldr
|
|
50
50
|
attrs
|
51
51
|
end
|
52
52
|
|
53
|
+
def cast_value(val)
|
54
|
+
if val =~ /\A[\d]+\z/
|
55
|
+
val.to_i
|
56
|
+
else
|
57
|
+
val
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
53
61
|
def fix_rule(rule)
|
54
62
|
rule.gsub(/\A'/, '').gsub("←", '<').gsub("→", '>')
|
55
63
|
end
|
@@ -61,4 +69,4 @@ module Cldr
|
|
61
69
|
end
|
62
70
|
end
|
63
71
|
end
|
64
|
-
end
|
72
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class RegionCurrencies < Base
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super(nil)
|
8
|
+
update(:region_currencies => currencies)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def currencies
|
14
|
+
doc.xpath('//currencyData/region').inject({}) do |ret, region|
|
15
|
+
name = region.attribute('iso3166').value
|
16
|
+
ret[name] = currency(region)
|
17
|
+
ret
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def currency(node)
|
22
|
+
(node / 'currency').map do |currency|
|
23
|
+
currency_code = currency.attribute('iso4217').value
|
24
|
+
result = { currency: currency_code }
|
25
|
+
|
26
|
+
if from_node = currency.attribute('from')
|
27
|
+
result[:from] = from_node.value
|
28
|
+
end
|
29
|
+
|
30
|
+
if to_node = currency.attribute('to')
|
31
|
+
result[:to] = to_node.value
|
32
|
+
end
|
33
|
+
|
34
|
+
result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def path
|
39
|
+
@path ||= "#{Cldr::Export::Data.dir}/supplemental/supplementalData.xml"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -26,7 +26,7 @@ module Cldr
|
|
26
26
|
def variables(node)
|
27
27
|
(node / "variables" / "variable").map do |variable|
|
28
28
|
{
|
29
|
-
:id => variable.attribute("id").value,
|
29
|
+
:id => cast_value(variable.attribute("id").value),
|
30
30
|
:value => variable.text
|
31
31
|
}
|
32
32
|
end
|
@@ -35,7 +35,7 @@ module Cldr
|
|
35
35
|
def rules(node)
|
36
36
|
(node / "segmentRules" / "rule").map do |rule|
|
37
37
|
{
|
38
|
-
:id => rule.attribute("id").value,
|
38
|
+
:id => cast_value(rule.attribute("id").value),
|
39
39
|
:value => rule.text
|
40
40
|
}
|
41
41
|
end
|
@@ -45,7 +45,17 @@ module Cldr
|
|
45
45
|
@path ||= "#{Cldr::Export::Data.dir}/segments/root.xml"
|
46
46
|
end
|
47
47
|
|
48
|
+
def cast_value(value)
|
49
|
+
if value =~ /\A[\d]+\z/
|
50
|
+
value.to_i
|
51
|
+
elsif value =~ /\A[\d.]+\z/
|
52
|
+
value.to_f
|
53
|
+
else
|
54
|
+
value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
48
58
|
end
|
49
59
|
end
|
50
60
|
end
|
51
|
-
end
|
61
|
+
end
|
@@ -9,7 +9,7 @@ module Cldr
|
|
9
9
|
|
10
10
|
def territories
|
11
11
|
@territories ||= select('localeDisplayNames/territories/territory').inject({}) do |result, node|
|
12
|
-
result[node.attribute('type').value.to_sym] = node.content unless draft?(node)
|
12
|
+
result[node.attribute('type').value.to_sym] = node.content unless draft?(node) or alt?(node)
|
13
13
|
result
|
14
14
|
end
|
15
15
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class TerritoriesContainment < Base
|
5
|
+
def initialize(*)
|
6
|
+
super(nil)
|
7
|
+
update(:territories => territories)
|
8
|
+
end
|
9
|
+
|
10
|
+
def territories
|
11
|
+
@territories ||= doc.xpath('supplementalData/territoryContainment/group').inject(
|
12
|
+
Hash.new { |h, k| h[k] = { :contains => [] } }
|
13
|
+
) do |memo, territory|
|
14
|
+
territory_id = territory.attribute('type').value
|
15
|
+
children = territory.attribute('contains').value.split(' ')
|
16
|
+
|
17
|
+
memo[territory_id][:contains].concat(children)
|
18
|
+
memo[territory_id][:contains].sort!
|
19
|
+
|
20
|
+
memo
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def path
|
25
|
+
@path ||= "#{Cldr::Export::Data.dir}/supplemental/supplementalData.xml"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -6,7 +6,23 @@ module Cldr
|
|
6
6
|
class Timezones < Base
|
7
7
|
def initialize(locale)
|
8
8
|
super
|
9
|
-
|
9
|
+
|
10
|
+
update(
|
11
|
+
:formats => formats,
|
12
|
+
:timezones => timezones,
|
13
|
+
:metazones => metazones
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def formats
|
18
|
+
@formats ||= select('dates/timeZoneNames/*').inject({}) do |result, format|
|
19
|
+
if format.name.end_with?('Format')
|
20
|
+
underscored_name = format.name.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
21
|
+
result[underscored_name] = format.text
|
22
|
+
end
|
23
|
+
|
24
|
+
result
|
25
|
+
end
|
10
26
|
end
|
11
27
|
|
12
28
|
def timezones
|
@@ -47,4 +63,4 @@ module Cldr
|
|
47
63
|
end
|
48
64
|
end
|
49
65
|
end
|
50
|
-
end
|
66
|
+
end
|