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.
Files changed (39) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +56 -46
  4. data/README.textile +6 -0
  5. data/Rakefile +2 -2
  6. data/VERSION +1 -1
  7. data/lib/cldr/download.rb +1 -1
  8. data/lib/cldr/export.rb +70 -16
  9. data/lib/cldr/export/data.rb +31 -21
  10. data/lib/cldr/export/data/aliases.rb +47 -0
  11. data/lib/cldr/export/data/base.rb +4 -0
  12. data/lib/cldr/export/data/characters.rb +30 -0
  13. data/lib/cldr/export/data/fields.rb +60 -0
  14. data/lib/cldr/export/data/languages.rb +1 -1
  15. data/lib/cldr/export/data/likely_subtags.rb +29 -0
  16. data/lib/cldr/export/data/numbers.rb +48 -6
  17. data/lib/cldr/export/data/parent_locales.rb +23 -0
  18. data/lib/cldr/export/data/plural_rules.rb +70 -0
  19. data/lib/cldr/export/data/rbnf.rb +12 -4
  20. data/lib/cldr/export/data/region_currencies.rb +45 -0
  21. data/lib/cldr/export/data/segments_root.rb +13 -3
  22. data/lib/cldr/export/data/territories.rb +1 -1
  23. data/lib/cldr/export/data/territories_containment.rb +30 -0
  24. data/lib/cldr/export/data/timezones.rb +18 -2
  25. data/lib/cldr/export/data/transforms.rb +76 -0
  26. data/lib/cldr/export/data/variables.rb +42 -0
  27. data/lib/cldr/export/yaml.rb +5 -21
  28. data/lib/cldr/thor.rb +2 -2
  29. data/test/export/data/calendars_test.rb +85 -51
  30. data/test/export/data/currencies_test.rb +29 -25
  31. data/test/export/data/languages_test.rb +69 -51
  32. data/test/export/data/numbers_test.rb +61 -62
  33. data/test/export/data/plurals_test.rb +4 -3
  34. data/test/export/data/territories_containment_test.rb +10 -0
  35. data/test/export/data/territories_test.rb +12 -5
  36. data/test/export/data/timezones_test.rb +5 -8
  37. data/test/export_test.rb +57 -5
  38. data/test/format/time_test.rb +5 -5
  39. 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/#{type}Format").inject({}) do |format_result, format_node|
48
- format_key = format_node.parent.attribute('type')
49
- format_result[format_key ? format_key.value : :default] = select(format_node, "pattern").inject({}) do |pattern_result, pattern_node|
50
- pattern_key = pattern_node.attribute('type')
51
- pattern_result[pattern_key ? pattern_key.value : :default] = pattern_node.content unless draft?(pattern_node)
52
- pattern_result
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
- update(:timezones => timezones, :metazones => metazones)
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