ruby-cldr 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -2
  3. data/Gemfile.lock +55 -5
  4. data/VERSION +1 -1
  5. data/lib/cldr/download.rb +15 -11
  6. data/lib/cldr/export.rb +64 -16
  7. data/lib/cldr/export/data.rb +18 -10
  8. data/lib/cldr/export/data/calendars/gregorian.rb +45 -22
  9. data/lib/cldr/export/data/currencies.rb +6 -1
  10. data/lib/cldr/export/data/currency_digits_and_rounding.rb +22 -0
  11. data/lib/cldr/export/data/layout.rb +22 -0
  12. data/lib/cldr/export/data/lists.rb +28 -0
  13. data/lib/cldr/export/data/metazones.rb +45 -0
  14. data/lib/cldr/export/data/numbering_systems.rb +41 -0
  15. data/lib/cldr/export/data/numbers.rb +9 -0
  16. data/lib/cldr/export/data/plurals.rb +8 -7
  17. data/lib/cldr/export/data/plurals/rules.rb +114 -31
  18. data/lib/cldr/export/data/rbnf.rb +64 -0
  19. data/lib/cldr/export/data/rbnf_root.rb +19 -0
  20. data/lib/cldr/export/data/timezones.rb +29 -6
  21. data/lib/cldr/export/data/units.rb +23 -6
  22. data/lib/cldr/export/data/windows_zones.rb +23 -0
  23. data/lib/cldr/export/yaml.rb +2 -1
  24. data/lib/cldr/format/datetime/base.rb +1 -1
  25. data/lib/cldr/format/time.rb +1 -1
  26. data/lib/cldr/thor.rb +1 -1
  27. data/lib/core_ext/string/camelize.rb +1 -1
  28. data/test/export/data/calendars_test.rb +23 -18
  29. data/test/export/data/currencies_test.rb +24 -24
  30. data/test/export/data/languages_test.rb +52 -48
  31. data/test/export/data/metazones_test.rb +17 -0
  32. data/test/export/data/numbers_test.rb +34 -3
  33. data/test/export/data/plurals_test.rb +133 -32
  34. data/test/export/data/territories_test.rb +22 -22
  35. data/test/export/data/timezones_test.rb +49 -26
  36. data/test/export/data/units_test.rb +16 -17
  37. data/test/export/data/windows_zones_test.rb +12 -0
  38. data/test/export_test.rb +4 -1
  39. data/test/format/date_test.rb +2 -2
  40. data/test/test_autotest.rb +1 -1
  41. metadata +94 -32
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 81ab6a59909b72f15381d80ca49053ca46bc54fb
4
+ data.tar.gz: 32e6c9fcd5291e54460abaeafc0f12189cc541e6
5
+ SHA512:
6
+ metadata.gz: fd2828beca0c9f5828cfcf9b25c5e973d8183ab17b7b93e5dfab4d6b1e92002fa5706d52f8a8ada8b840b18043bdb5bfb4a14379993753b4c536abd411f2139a
7
+ data.tar.gz: e51615436d0dfb6718627014defbdeff88093345aa00467e325cad301ac6a5b9c868a85ad8d4c72eacf872f898a4dacfae7e71e81fbf0f2608c47d10e82b3af7
data/Gemfile CHANGED
@@ -1,7 +1,13 @@
1
- source :gemcutter
1
+ source "http://rubygems.org"
2
2
 
3
3
  gem 'thor'
4
4
  gem 'i18n'
5
5
  gem 'ya2yaml'
6
6
  gem 'nokogiri'
7
- gem 'jeweler', :group => :development
7
+
8
+ group :development do
9
+ gem 'rubyzip'
10
+ gem 'jeweler'
11
+ gem 'pry'
12
+ gem 'pry-nav'
13
+ end
data/Gemfile.lock CHANGED
@@ -1,14 +1,61 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- git (1.2.5)
4
+ addressable (2.3.5)
5
+ builder (3.2.2)
6
+ coderay (1.0.9)
7
+ descendants_tracker (0.0.3)
8
+ faraday (0.9.0)
9
+ multipart-post (>= 1.2, < 3)
10
+ git (1.2.6)
11
+ github_api (0.11.2)
12
+ addressable (~> 2.3)
13
+ descendants_tracker (~> 0.0.1)
14
+ faraday (~> 0.8, < 0.10)
15
+ hashie (>= 1.2)
16
+ multi_json (>= 1.7.5, < 2.0)
17
+ nokogiri (~> 1.6.0)
18
+ oauth2
19
+ hashie (2.0.5)
20
+ highline (1.6.20)
5
21
  i18n (0.6.0)
6
- jeweler (1.6.4)
7
- bundler (~> 1.0)
22
+ jeweler (2.0.1)
23
+ builder
24
+ bundler (>= 1.0)
8
25
  git (>= 1.2.5)
26
+ github_api
27
+ highline (>= 1.6.15)
28
+ nokogiri (>= 1.5.10)
9
29
  rake
10
- nokogiri (1.5.0)
11
- rake (0.9.2.2)
30
+ rdoc
31
+ json (1.8.1)
32
+ jwt (0.1.11)
33
+ multi_json (>= 1.5)
34
+ method_source (0.8.1)
35
+ mini_portile (0.5.2)
36
+ multi_json (1.8.4)
37
+ multi_xml (0.5.5)
38
+ multipart-post (2.0.0)
39
+ nokogiri (1.6.1)
40
+ mini_portile (~> 0.5.0)
41
+ oauth2 (0.9.3)
42
+ faraday (>= 0.8, < 0.10)
43
+ jwt (~> 0.1.8)
44
+ multi_json (~> 1.3)
45
+ multi_xml (~> 0.5)
46
+ rack (~> 1.2)
47
+ pry (0.9.12)
48
+ coderay (~> 1.0.5)
49
+ method_source (~> 0.8)
50
+ slop (~> 3.4)
51
+ pry-nav (0.2.3)
52
+ pry (~> 0.9.10)
53
+ rack (1.5.2)
54
+ rake (10.1.1)
55
+ rdoc (4.1.1)
56
+ json (~> 1.4)
57
+ rubyzip (1.1.0)
58
+ slop (3.4.3)
12
59
  thor (0.14.6)
13
60
  ya2yaml (0.30)
14
61
 
@@ -19,5 +66,8 @@ DEPENDENCIES
19
66
  i18n
20
67
  jeweler
21
68
  nokogiri
69
+ pry
70
+ pry-nav
71
+ rubyzip
22
72
  thor
23
73
  ya2yaml
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.1.0
data/lib/cldr/download.rb CHANGED
@@ -1,20 +1,24 @@
1
- require 'fileutils'
2
- require 'net/http'
3
1
  require 'uri'
4
- require 'tempfile'
2
+ require 'open-uri'
3
+ require 'zip'
5
4
 
6
5
  module Cldr
7
6
  class << self
8
7
  def download(source = nil, target = nil)
9
- source ||= 'http://unicode.org/Public/cldr/21/core.zip'
8
+ source ||= 'http://unicode.org/Public/cldr/24/core.zip'
10
9
  target ||= File.expand_path('./vendor/cldr')
11
10
 
12
- source = URI.parse(source)
13
- tempfile = Tempfile.new('cldr-core')
14
-
15
- system("curl #{source} -o #{tempfile.path}")
16
- FileUtils.mkdir_p(target)
17
- system("unzip #{tempfile.path} -d #{target}")
11
+ URI.parse(source).open do |tempfile|
12
+ FileUtils.mkdir_p(target)
13
+ Zip.on_exists_proc = true
14
+ Zip::File.open(tempfile.path) do |file|
15
+ file.each do |entry|
16
+ path = target + '/' + entry.name
17
+ FileUtils.mkdir_p(File.dirname(path))
18
+ file.extract(entry, path)
19
+ end
20
+ end
21
+ end
18
22
  end
19
23
  end
20
- end
24
+ end
data/lib/cldr/export.rb CHANGED
@@ -3,6 +3,7 @@ require 'i18n/locale/fallbacks'
3
3
  require 'core_ext/string/camelize'
4
4
  require 'core_ext/string/underscore'
5
5
  require 'core_ext/hash/deep_stringify_keys'
6
+ require 'core_ext/hash/deep_merge'
6
7
 
7
8
  module Cldr
8
9
  module Export
@@ -11,6 +12,14 @@ module Cldr
11
12
  autoload :Ruby, 'cldr/export/ruby'
12
13
  autoload :Yaml, 'cldr/export/yaml'
13
14
 
15
+ SHARED_COMPONENTS = [
16
+ 'CurrencyDigitsAndRounding',
17
+ 'RbnfRoot',
18
+ 'Metazones',
19
+ 'WindowsZones',
20
+ 'NumberingSystems'
21
+ ]
22
+
14
23
  class << self
15
24
  def base_path
16
25
  @@base_path ||= File.expand_path('./data')
@@ -22,11 +31,20 @@ module Cldr
22
31
 
23
32
  def export(options = {}, &block)
24
33
  locales = options[:locales] || Data.locales
25
- components = options[:components] || Data.components
34
+ components = (options[:components] || Data.components).map { |c| c.to_s.camelize }
26
35
  self.base_path = options[:target] if options[:target]
27
36
 
37
+ shared_components, locale_components = components.partition do |component|
38
+ is_shared_component?(component)
39
+ end
40
+
41
+ shared_components.each do |component|
42
+ ex = exporter(component, options[:format])
43
+ ex.export('', component, options, &block)
44
+ end
45
+
28
46
  locales.each do |locale|
29
- components.each do |component|
47
+ locale_components.each do |component|
30
48
  exporter(component, options[:format]).export(locale, component, options, &block)
31
49
  end
32
50
  end
@@ -38,26 +56,45 @@ module Cldr
38
56
  end
39
57
 
40
58
  def data(component, locale, options = {})
41
- if component.to_s == 'Plurals'
42
- Data.const_get(component.to_s.camelize).new(locale)
43
- else
44
- data = locales(locale, options).inject({}) do |result, locale|
45
- data = Data.const_get(component.to_s.camelize).new(locale)
46
- if data
47
- data.is_a?(Hash) ? data.deep_merge(result) : data
59
+ case component.to_s
60
+ when 'Plurals'
61
+ plural_data(component, locale, options)
62
+ else
63
+ if is_shared_component?(component)
64
+ shared_data(component, options)
48
65
  else
49
- result
66
+ locale_based_data(component, locale, options)
50
67
  end
68
+ end
69
+ end
70
+
71
+ def locale_based_data(component, locale, options = {})
72
+ data = locales(locale, component, options).inject({}) do |result, locale|
73
+ data = Data.const_get(component.to_s.camelize).new(locale)
74
+ if data
75
+ data.is_a?(Hash) ? data.deep_merge(result) : data
76
+ else
77
+ result
51
78
  end
52
- # data = resolve_links if options[:merge] TODO!!
53
- data
54
79
  end
80
+
81
+ # data = resolve_links if options[:merge] TODO!!
82
+ data
55
83
  end
56
84
 
57
- def locales(locale, options)
85
+ def plural_data(component, locale, options = {})
86
+ data = locale_based_data(component, locale, options)
87
+ "{ :'#{locale}' => { :i18n => { :plural => { :keys => #{data[:keys].inspect}, :rule => #{data[:rule]} } } } }"
88
+ end
89
+
90
+ def shared_data(component, options = {})
91
+ Data.const_get(component.to_s.camelize).new
92
+ end
93
+
94
+ def locales(locale, component, options)
58
95
  locale = locale.to_s.gsub('_', '-')
59
- locales = options[:merge] ? I18n::Locale::Fallbacks.new[locale.to_sym] : [locale.to_sym]
60
- locales << :root
96
+ locales = options[:merge] ? I18n::Locale::Fallbacks.new[locale.to_sym] : [locale.to_sym]
97
+ locales << :root if component_should_merge_root?(component)
61
98
  locales
62
99
  end
63
100
 
@@ -68,7 +105,18 @@ module Cldr
68
105
  end
69
106
 
70
107
  def path(locale, component, extension)
71
- "#{Export.base_path}/#{locale.to_s.gsub('_', '-')}/#{component.to_s.underscore}.#{extension}"
108
+ path = [Export.base_path]
109
+ path << locale.to_s.gsub('_', '-') unless is_shared_component?(component)
110
+ path << "#{component.to_s.underscore}.#{extension}"
111
+ File.join(*path)
112
+ end
113
+
114
+ def is_shared_component?(component)
115
+ SHARED_COMPONENTS.include?(component)
116
+ end
117
+
118
+ def component_should_merge_root?(component)
119
+ component != "Rbnf"
72
120
  end
73
121
  end
74
122
  end
@@ -3,16 +3,24 @@ require 'core_ext/string/camelize'
3
3
  module Cldr
4
4
  module Export
5
5
  module Data
6
- autoload :Base, 'cldr/export/data/base'
7
- autoload :Calendars, 'cldr/export/data/calendars'
8
- autoload :Currencies, 'cldr/export/data/currencies'
9
- autoload :Delimiters, 'cldr/export/data/delimiters'
10
- autoload :Languages, 'cldr/export/data/languages'
11
- autoload :Numbers, 'cldr/export/data/numbers'
12
- autoload :Plurals, 'cldr/export/data/plurals'
13
- autoload :Territories, 'cldr/export/data/territories'
14
- autoload :Timezones, 'cldr/export/data/timezones'
15
- autoload :Units, 'cldr/export/data/units'
6
+ autoload :Base, 'cldr/export/data/base'
7
+ autoload :Calendars, 'cldr/export/data/calendars'
8
+ autoload :Currencies, 'cldr/export/data/currencies'
9
+ autoload :CurrencyDigitsAndRounding, 'cldr/export/data/currency_digits_and_rounding'
10
+ autoload :Delimiters, 'cldr/export/data/delimiters'
11
+ autoload :Languages, 'cldr/export/data/languages'
12
+ autoload :Numbers, 'cldr/export/data/numbers'
13
+ autoload :Plurals, 'cldr/export/data/plurals'
14
+ autoload :Territories, 'cldr/export/data/territories'
15
+ autoload :Timezones, 'cldr/export/data/timezones'
16
+ autoload :Metazones, 'cldr/export/data/metazones'
17
+ autoload :WindowsZones, 'cldr/export/data/windows_zones'
18
+ autoload :Units, 'cldr/export/data/units'
19
+ autoload :Lists, 'cldr/export/data/lists'
20
+ autoload :Layout, 'cldr/export/data/layout'
21
+ autoload :Rbnf, 'cldr/export/data/rbnf'
22
+ autoload :RbnfRoot, 'cldr/export/data/rbnf_root'
23
+ autoload :NumberingSystems, 'cldr/export/data/numbering_systems'
16
24
 
17
25
  class << self
18
26
  def dir
@@ -10,13 +10,14 @@ module Cldr
10
10
  :days => contexts('day'),
11
11
  :eras => eras,
12
12
  :quarters => contexts('quarter'),
13
- :periods => contexts('dayPeriod'),
13
+ :periods => contexts('dayPeriod', :group => "alt"),
14
14
  :fields => fields,
15
15
  :formats => {
16
16
  :date => formats('date'),
17
17
  :time => formats('time'),
18
18
  :datetime => formats('dateTime')
19
- }
19
+ },
20
+ :additional_formats => additional_formats
20
21
  )
21
22
  end
22
23
 
@@ -24,31 +25,39 @@ module Cldr
24
25
  @calendar ||= select('dates/calendars/calendar[@type="gregorian"]').first
25
26
  end
26
27
 
27
- def contexts(kind)
28
+ def contexts(kind, options = {})
28
29
  select(calendar, "#{kind}s/#{kind}Context").inject({}) do |result, node|
29
30
  context = node.attribute('type').value.to_sym
30
- result[context] = widths(node, kind, context)
31
+ result[context] = widths(node, kind, context, options)
31
32
  result
32
33
  end
33
34
  end
34
35
 
35
- def widths(node, kind, context)
36
+ def widths(node, kind, context, options = {})
36
37
  select(node, "#{kind}Width").inject({}) do |result, node|
37
- width = node.attribute('type').value.to_sym
38
- result[width] = elements(node, kind, context, width)
38
+ width = node.attribute('type').value.to_sym
39
+ result[width] = elements(node, kind, context, width, options)
39
40
  result
40
41
  end
41
42
  end
42
43
 
43
- def elements(node, kind, context, width)
44
+ def elements(node, kind, context, width, options = {})
44
45
  aliased = select(node, 'alias').first
46
+
45
47
  if aliased
46
48
  xpath_to_key(aliased.attribute('path').value, kind, context, width)
47
49
  else
48
50
  select(node, kind).inject({}) do |result, node|
49
51
  key = node.attribute('type').value
50
52
  key = key =~ /^\d*$/ ? key.to_i : key.to_sym
51
- result[key] = node.content
53
+
54
+ if options[:group] && found_group = node.attribute(options[:group])
55
+ result[found_group.value] ||= {}
56
+ result[found_group.value][key] = node.content
57
+ else
58
+ result[key] = node.content
59
+ end
60
+
52
61
  result
53
62
  end
54
63
  end
@@ -75,18 +84,22 @@ module Cldr
75
84
  end
76
85
 
77
86
  def eras
78
- base_path = calendar.path.gsub('/ldml/', '') + '/eras'
79
- keys = select("#{base_path}/*").map { |node| node.name }
80
-
81
- keys.inject({}) do |result, name|
82
- path = "#{base_path}/#{name}/*"
83
- key = name.gsub('era', '').gsub(/s$/, '').downcase.to_sym
84
- result[key] = select(path).inject({}) do |ret, node|
85
- type = node.attribute('type').value.to_i rescue 0
86
- ret[type] = node.content
87
- ret
87
+ if calendar
88
+ base_path = calendar.path.gsub('/ldml/', '') + '/eras'
89
+ keys = select("#{base_path}/*").map { |node| node.name }
90
+
91
+ keys.inject({}) do |result, name|
92
+ path = "#{base_path}/#{name}/*"
93
+ key = name.gsub('era', '').gsub(/s$/, '').downcase.to_sym
94
+ result[key] = select(path).inject({}) do |ret, node|
95
+ type = node.attribute('type').value.to_i rescue 0
96
+ ret[type] = node.content
97
+ ret
98
+ end
99
+ result
88
100
  end
89
- result
101
+ else
102
+ {}
90
103
  end
91
104
  end
92
105
 
@@ -110,7 +123,15 @@ module Cldr
110
123
  end
111
124
  formats
112
125
  end
113
-
126
+
127
+ def additional_formats
128
+ select(calendar, "dateTimeFormats/availableFormats/dateFormatItem").inject({}) do |result, node|
129
+ key = node.attribute('id').value
130
+ result[key] = node.content
131
+ result
132
+ end
133
+ end
134
+
114
135
  def default_format(type)
115
136
  if node = select(calendar, "#{type}Formats/default").first
116
137
  key = node.attribute('choice').value.to_sym
@@ -127,8 +148,10 @@ module Cldr
127
148
  end
128
149
  end
129
150
 
151
+ # NOTE: As of CLDR 23, this data moved from inside each "calendar" tag to under its parent, the "dates" tag.
152
+ # That probably means this `fields` method should be moved up to the parent as well.
130
153
  def fields
131
- select(calendar, "fields/field").inject({}) do |result, node|
154
+ select("dates/fields/field").inject({}) do |result, node|
132
155
  key = node.attribute('type').value.to_sym
133
156
  name = node.xpath('displayName').first
134
157
  result[key] = name.content if name
@@ -16,11 +16,16 @@ module Cldr
16
16
  end
17
17
 
18
18
  def currency(node)
19
- select(node, 'displayName').inject({}) do |result, node|
19
+ data = select(node, 'displayName').inject({}) do |result, node|
20
20
  count = node.attribute('count') ? node.attribute('count').value.to_sym : :one
21
21
  result[count] = node.content unless draft?(node)
22
22
  result
23
23
  end
24
+
25
+ symbol = select(node, 'symbol')
26
+ data[:symbol] = symbol.first.content if symbol.length > 0
27
+
28
+ data
24
29
  end
25
30
  end
26
31
  end
@@ -0,0 +1,22 @@
1
+ require 'nokogiri'
2
+
3
+ module Cldr
4
+ module Export
5
+ module Data
6
+ class CurrencyDigitsAndRounding < Hash
7
+ def initialize
8
+ path = "#{Cldr::Export::Data.dir}/supplemental/supplementalData.xml"
9
+ doc = File.open(path) { |file| Nokogiri::XML(file) }
10
+
11
+ currency_digits_and_rounding = doc.xpath('//currencyData/fractions/info').each do |node|
12
+ code = node.attr('iso4217')
13
+ digits = node.attr('digits').to_i
14
+ rounding = node.attr('rounding').to_i
15
+
16
+ self[code.upcase.to_sym] = { :digits => digits, :rounding => rounding }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end