ruby-cldr 0.1.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +53 -0
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +56 -46
  5. data/README.textile +8 -0
  6. data/Rakefile +2 -2
  7. data/VERSION +1 -1
  8. data/lib/cldr/download.rb +1 -1
  9. data/lib/cldr/export.rb +74 -16
  10. data/lib/cldr/export/data.rb +34 -21
  11. data/lib/cldr/export/data/aliases.rb +47 -0
  12. data/lib/cldr/export/data/base.rb +4 -0
  13. data/lib/cldr/export/data/characters.rb +30 -0
  14. data/lib/cldr/export/data/country_codes.rb +29 -0
  15. data/lib/cldr/export/data/currencies.rb +13 -3
  16. data/lib/cldr/export/data/fields.rb +60 -0
  17. data/lib/cldr/export/data/languages.rb +1 -1
  18. data/lib/cldr/export/data/likely_subtags.rb +29 -0
  19. data/lib/cldr/export/data/numbers.rb +48 -6
  20. data/lib/cldr/export/data/parent_locales.rb +23 -0
  21. data/lib/cldr/export/data/plural_rules.rb +70 -0
  22. data/lib/cldr/export/data/plurals/rules.rb +12 -1
  23. data/lib/cldr/export/data/rbnf.rb +12 -4
  24. data/lib/cldr/export/data/region_currencies.rb +45 -0
  25. data/lib/cldr/export/data/segments_root.rb +61 -0
  26. data/lib/cldr/export/data/subdivisions.rb +35 -0
  27. data/lib/cldr/export/data/territories.rb +1 -1
  28. data/lib/cldr/export/data/territories_containment.rb +30 -0
  29. data/lib/cldr/export/data/timezones.rb +18 -2
  30. data/lib/cldr/export/data/transforms.rb +76 -0
  31. data/lib/cldr/export/data/variables.rb +42 -0
  32. data/lib/cldr/export/yaml.rb +5 -21
  33. data/lib/cldr/thor.rb +2 -2
  34. data/ruby-cldr.gemspec +157 -0
  35. data/test/export/data/calendars_test.rb +102 -52
  36. data/test/export/data/country_codes_test.rb +21 -0
  37. data/test/export/data/currencies_test.rb +40 -26
  38. data/test/export/data/languages_test.rb +69 -51
  39. data/test/export/data/numbers_test.rb +61 -62
  40. data/test/export/data/plurals_test.rb +10 -3
  41. data/test/export/data/subdivisions_test.rb +33 -0
  42. data/test/export/data/territories_containment_test.rb +10 -0
  43. data/test/export/data/territories_test.rb +12 -5
  44. data/test/export/data/timezones_test.rb +5 -8
  45. data/test/export_test.rb +57 -5
  46. data/test/format/time_test.rb +5 -5
  47. 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
@@ -31,6 +31,10 @@ module Cldr
31
31
  draft && draft.value == 'unconfirmed'
32
32
  end
33
33
 
34
+ def alt?(node)
35
+ !node.attribute('alt').nil?
36
+ end
37
+
34
38
  def name(node)
35
39
  node.name.underscore
36
40
  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
- count = node.attribute('count') ? node.attribute('count').value.to_sym : :one
21
- result[count] = node.content unless draft?(node)
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/#{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(_ = 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