ruby-cldr 0.1.1 → 0.2.0

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