ruby-cldr 0.1.0 → 0.5.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/CHANGELOG.md +53 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +56 -46
- data/README.textile +8 -0
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/cldr/download.rb +1 -1
- data/lib/cldr/export.rb +74 -16
- data/lib/cldr/export/data.rb +34 -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/country_codes.rb +29 -0
- data/lib/cldr/export/data/currencies.rb +13 -3
- 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/plurals/rules.rb +12 -1
- 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 +61 -0
- data/lib/cldr/export/data/subdivisions.rb +35 -0
- 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/ruby-cldr.gemspec +157 -0
- data/test/export/data/calendars_test.rb +102 -52
- data/test/export/data/country_codes_test.rb +21 -0
- data/test/export/data/currencies_test.rb +40 -26
- 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 +10 -3
- data/test/export/data/subdivisions_test.rb +33 -0
- 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 +51 -33
@@ -0,0 +1,47 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class Aliases < Base
|
5
|
+
|
6
|
+
# only these aliases will be exported
|
7
|
+
ALIAS_TAGS = %w(languageAlias territoryAlias)
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
super(nil)
|
11
|
+
update(:aliases => aliases)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def aliases
|
17
|
+
ALIAS_TAGS.inject({}) do |ret, alias_tag|
|
18
|
+
ret[alias_tag.sub('Alias', '')] = alias_for(alias_tag)
|
19
|
+
ret
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def alias_for(alias_tag)
|
24
|
+
doc.xpath("//alias/#{alias_tag}").inject({}) do |ret, alias_data|
|
25
|
+
if replacement_attr = alias_data.attribute('replacement')
|
26
|
+
replacement = replacement_attr.value
|
27
|
+
|
28
|
+
if replacement.include?(' ')
|
29
|
+
replacement = replacement.split(' ')
|
30
|
+
end
|
31
|
+
|
32
|
+
type = alias_data.attribute('type').value
|
33
|
+
ret[type] = replacement
|
34
|
+
end
|
35
|
+
|
36
|
+
ret
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def path
|
41
|
+
@path ||= "#{Cldr::Export::Data.dir}/supplemental/supplementalMetadata.xml"
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class Characters < Base
|
5
|
+
def initialize(locale)
|
6
|
+
super
|
7
|
+
update(:characters => { :exemplars => exemplars })
|
8
|
+
end
|
9
|
+
|
10
|
+
def exemplars
|
11
|
+
select('/ldml/characters/exemplarCharacters').map do |node|
|
12
|
+
{
|
13
|
+
# remove enclosing brackets
|
14
|
+
characters: node.content[1..-2],
|
15
|
+
type: type_from(node)
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def type_from(node)
|
23
|
+
if attrib = node.attribute('type')
|
24
|
+
attrib.value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Cldr
|
2
|
+
module Export
|
3
|
+
module Data
|
4
|
+
class CountryCodes < Base
|
5
|
+
def initialize
|
6
|
+
super(nil)
|
7
|
+
update(:country_codes => country_codes)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def country_codes
|
13
|
+
doc.xpath("//codeMappings/*").each_with_object({}) do |node, hash|
|
14
|
+
if node.name == "territoryCodes"
|
15
|
+
type = node.attribute('type').to_s.to_sym
|
16
|
+
hash[type] = {}
|
17
|
+
hash[type]["numeric"] = node[:numeric] if node[:numeric]
|
18
|
+
hash[type]["alpha3"] = node[:alpha3] if node[:alpha3]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def path
|
24
|
+
@path ||= "#{Cldr::Export::Data.dir}/supplemental/supplementalData.xml"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -17,17 +17,27 @@ module Cldr
|
|
17
17
|
|
18
18
|
def currency(node)
|
19
19
|
data = select(node, 'displayName').inject({}) do |result, node|
|
20
|
-
|
21
|
-
|
20
|
+
unless draft?(node)
|
21
|
+
if node.attribute('count')
|
22
|
+
count = node.attribute('count').value.to_sym
|
23
|
+
result[count] = node.content
|
24
|
+
else
|
25
|
+
result[:one] = node.content if result[:one].nil?
|
26
|
+
result[:name] = node.content
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
22
30
|
result
|
23
31
|
end
|
24
32
|
|
25
33
|
symbol = select(node, 'symbol')
|
34
|
+
narrow_symbol = symbol.select { |child_node| child_node.values.include?('narrow') }.first
|
26
35
|
data[:symbol] = symbol.first.content if symbol.length > 0
|
36
|
+
data[:'narrow_symbol'] = narrow_symbol.content unless narrow_symbol.nil?
|
27
37
|
|
28
38
|
data
|
29
39
|
end
|
30
40
|
end
|
31
41
|
end
|
32
42
|
end
|
33
|
-
end
|
43
|
+
end
|
@@ -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(_ = nil)
|
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
|
@@ -57,6 +57,8 @@ module Cldr
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def parse(code)
|
60
|
+
code = scrub_code(code)
|
61
|
+
|
60
62
|
code = code.split('@').first.to_s
|
61
63
|
operand = /(n|i|f|t|v|w)/i
|
62
64
|
expr = /#{operand}(?:\s+(?:mod|%)\s+([\d]+))?/i
|
@@ -78,6 +80,15 @@ module Cldr
|
|
78
80
|
raise "can not parse '#{code}'"
|
79
81
|
end
|
80
82
|
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def scrub_code(code)
|
87
|
+
code
|
88
|
+
.gsub(/(n)%(\d+)/, '\1 % \2') # n%1000 -> n % 1000
|
89
|
+
.gsub(/(\d+)=(\d+)/, '\1 = \2') # 10=100-> 10 = 100
|
90
|
+
.gsub(/(n)!=(\d+)/, '\1 != \2') # n!=100 -> n != 100
|
91
|
+
end
|
81
92
|
end
|
82
93
|
|
83
94
|
attr_reader :locales
|
@@ -199,4 +210,4 @@ module Cldr
|
|
199
210
|
end
|
200
211
|
end
|
201
212
|
end
|
202
|
-
end
|
213
|
+
end
|