ruby-cldr 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.textile +104 -0
- data/Rakefile +18 -0
- data/TODO +68 -0
- data/VERSION +1 -0
- data/cldr.thor +5 -0
- data/lib/cldr/data/base.rb +66 -0
- data/lib/cldr/data/calendars/gregorian.rb +124 -0
- data/lib/cldr/data/calendars.rb +12 -0
- data/lib/cldr/data/currencies.rb +26 -0
- data/lib/cldr/data/delimiters.rb +21 -0
- data/lib/cldr/data/languages.rb +17 -0
- data/lib/cldr/data/numbers.rb +60 -0
- data/lib/cldr/data/plurals/cldr_grammar.treetop +50 -0
- data/lib/cldr/data/plurals/grammar.rb +536 -0
- data/lib/cldr/data/plurals/rules.rb +113 -0
- data/lib/cldr/data/plurals.rb +39 -0
- data/lib/cldr/data/territories.rb +17 -0
- data/lib/cldr/data/timezones.rb +25 -0
- data/lib/cldr/data/units.rb +25 -0
- data/lib/cldr/data.rb +34 -0
- data/lib/cldr/download.rb +20 -0
- data/lib/cldr/export/ruby.rb +16 -0
- data/lib/cldr/export/yaml.rb +39 -0
- data/lib/cldr/export.rb +69 -0
- data/lib/cldr/format/currency.rb +11 -0
- data/lib/cldr/format/date.rb +144 -0
- data/lib/cldr/format/datetime/base.rb +32 -0
- data/lib/cldr/format/datetime.rb +28 -0
- data/lib/cldr/format/decimal/base.rb +18 -0
- data/lib/cldr/format/decimal/fraction.rb +28 -0
- data/lib/cldr/format/decimal/integer.rb +46 -0
- data/lib/cldr/format/decimal/number.rb +44 -0
- data/lib/cldr/format/decimal.rb +32 -0
- data/lib/cldr/format/percent.rb +11 -0
- data/lib/cldr/format/time.rb +71 -0
- data/lib/cldr/format.rb +113 -0
- data/lib/cldr/thor.rb +33 -0
- data/lib/cldr.rb +7 -0
- data/lib/core_ext/hash/deep_merge.rb +7 -0
- data/lib/core_ext/hash/deep_stringify_keys.rb +11 -0
- data/lib/core_ext/hash/symbolize_keys.rb +10 -0
- data/lib/core_ext/string/camelize.rb +5 -0
- data/lib/core_ext/string/underscore.rb +9 -0
- data/test/all.rb +3 -0
- data/test/data/all.rb +3 -0
- data/test/data/calendars_test.rb +149 -0
- data/test/data/currencies_test.rb +47 -0
- data/test/data/delimiters_test.rb +31 -0
- data/test/data/languages_test.rb +67 -0
- data/test/data/numbers_test.rb +61 -0
- data/test/data/plurals_test.rb +132 -0
- data/test/data/territories_test.rb +51 -0
- data/test/data/timezones_test.rb +56 -0
- data/test/data/units_test.rb +36 -0
- data/test/export_test.rb +57 -0
- data/test/formats/all.rb +3 -0
- data/test/formats/datetime/all.rb +3 -0
- data/test/formats/datetime/date_test.rb +31 -0
- data/test/formats/datetime/datetime_test.rb +18 -0
- data/test/formats/datetime/day_test.rb +41 -0
- data/test/formats/datetime/hour_test.rb +79 -0
- data/test/formats/datetime/minute_test.rb +25 -0
- data/test/formats/datetime/month_test.rb +76 -0
- data/test/formats/datetime/period_test.rb +20 -0
- data/test/formats/datetime/quarter_test.rb +118 -0
- data/test/formats/datetime/second_test.rb +80 -0
- data/test/formats/datetime/time_test.rb +33 -0
- data/test/formats/datetime/timezone_test.rb +23 -0
- data/test/formats/datetime/year_test.rb +57 -0
- data/test/formats/decimal/fraction_test.rb +17 -0
- data/test/formats/decimal/integer_test.rb +67 -0
- data/test/formats/decimal/number_test.rb +77 -0
- data/test/formats/decimal_test.rb +19 -0
- data/test/formats/format_test.rb +66 -0
- data/test/formats/rails_compat/all.rb +3 -0
- data/test/formats/rails_compat/format_integer_test.rb +56 -0
- data/test/formats/rails_compat/format_number_test.rb +134 -0
- data/test/test_helper.rb +5 -0
- metadata +169 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Sven Fuchs
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
h1. Ruby library for exporting and using data from CLDR
|
2
|
+
|
3
|
+
CLDR ("Common Locale Data Repository":http://cldr.unicode.org) contains tons of high-quality locale data such as formatting rules for dates, times, numbers, currencies as well as language, country, calendar-specific names etc.
|
4
|
+
|
5
|
+
For localizing applications in Ruby we'll obviously be able to use this incredibly comprehensive and well-maintained resource.
|
6
|
+
|
7
|
+
This library is a first stab at that goal. You can:
|
8
|
+
|
9
|
+
* export CLDR data to YAML and Ruby formatted files which are supposed to be usable in an "I18n":http://github.com/svenfuchs/i18n context but might be usable elsewhere, too.
|
10
|
+
* use CLDR compliant formatters for the following types: number, percentage, currency, date, time, datetime.
|
11
|
+
|
12
|
+
h2. Requirements
|
13
|
+
|
14
|
+
* Ruby 1.9 (if you want well-ordered Hashes to be exported)
|
15
|
+
* Thor
|
16
|
+
|
17
|
+
h2. Installation
|
18
|
+
|
19
|
+
<pre>
|
20
|
+
gem install cldr (not there, yet. install locally)
|
21
|
+
thor install http://github.com/svenfuchs/cldr/raw/master/cldr.thor --as=cldr
|
22
|
+
</pre>
|
23
|
+
|
24
|
+
h2. Export
|
25
|
+
|
26
|
+
The following command will export all known components from all locales to the target directory ./data/[locale]/[component].{yml,rb}:
|
27
|
+
|
28
|
+
<pre>
|
29
|
+
$ thor cldr:export
|
30
|
+
</pre>
|
31
|
+
|
32
|
+
You can also optionally specify locales and/or components to export as well as the target directory:
|
33
|
+
|
34
|
+
<pre>
|
35
|
+
$ thor cldr:export --locales de fr en --components numbers plurals --target=./tmp/export
|
36
|
+
</pre>
|
37
|
+
|
38
|
+
This will export the components :numbers and :plurals from the locales :de, :fr and :en to the same target directory.
|
39
|
+
|
40
|
+
Also note that CLDR natively builds on a locale fallback concept where all locales eventually fall back to a :root locale. E.g. the :de-AT locale only contains a single format for numbers, which means that an application is supposed to use other formats from the :de locale (fallback). Particular bits of information are only present in the :root locale where all locales fall back to eventually.
|
41
|
+
|
42
|
+
By default this library just exports data that is present in CLDR for a given locale. If you do not want to use locale fallbacks in your application you'll need to "flatten" locale fallbacks and merge the data during export time. To do that you can use the --merge option:
|
43
|
+
|
44
|
+
<pre>
|
45
|
+
$ thor cldr:export --merge
|
46
|
+
</pre>
|
47
|
+
|
48
|
+
h2. Formatters
|
49
|
+
|
50
|
+
The library includes a bunch of formatter classes that can be used to format Ruby objects like Numerics, Date, Time, DateTime etc. using the format information provided by CLDR.
|
51
|
+
|
52
|
+
E.g.:
|
53
|
+
|
54
|
+
<pre>
|
55
|
+
options = { :decimal => ',', :group => ' ' }
|
56
|
+
format = Cldr::Format::Numeric.new('#,##0.##', options)
|
57
|
+
format.apply(1234.567)
|
58
|
+
# => "1 234,57"
|
59
|
+
|
60
|
+
calendar = Cldr::Data::Calendars.new(:de)[:calendars][:gregorian]
|
61
|
+
format = Cldr::Format::Date.new('EEEE, d. MMMM y', calendar)
|
62
|
+
format.apply(Date.new(2010, 1, 11))
|
63
|
+
# => "Montag, 11. Januar 2010"
|
64
|
+
|
65
|
+
calendar = Cldr::Data::Calendars.new(:de)[:calendars][:gregorian]
|
66
|
+
format = Cldr::Format::Time.new('HH:mm:ss z', calendar)
|
67
|
+
format.apply(Time.utc(2010, 1, 1, 13, 12, 11))
|
68
|
+
# => "13:12:11 UTC"
|
69
|
+
</pre>
|
70
|
+
|
71
|
+
In order to make these things easier to use the library provides a bunch of helpers defined in the module Cldr::Format. (This module is supposed to work as an extension to the Simple backend in the I18n gem but is included here to suggest a common API to formatters and make development easier for usecases outside of the I18n gem. If you want to include this module somewhere else you have to implement a few abstract methods to provide translations.)
|
72
|
+
|
73
|
+
E.g.:
|
74
|
+
|
75
|
+
<pre>
|
76
|
+
format(:de, 123456.78)
|
77
|
+
# => "123.456,78"
|
78
|
+
|
79
|
+
format(:de, 123456.78, :as => :percent)
|
80
|
+
# => "123.457 %"
|
81
|
+
|
82
|
+
format(:de, 123456.78, :currency => 'EUR')
|
83
|
+
# => "123.456,78 EUR"
|
84
|
+
|
85
|
+
format(:de, Date.new(2010, 1, 1), :format => :full)
|
86
|
+
# => "Freitag, 1. Januar 2010"
|
87
|
+
|
88
|
+
format(:de, Time.utc(2010, 1, 1, 13, 15, 17), :format => :long)
|
89
|
+
# => "13:15:17 UTC"
|
90
|
+
|
91
|
+
format(:de, DateTime.new(2010, 11, 12, 13, 14, 15), :format => :long)
|
92
|
+
# => "12. November 2010 13:14:15 +00:00"
|
93
|
+
|
94
|
+
format(:de, DateTime.new(2010, 11, 12, 13, 14, 15), :date_format => :long, :time_format => :short)
|
95
|
+
# => "12. November 2010 13:14"
|
96
|
+
</pre>
|
97
|
+
|
98
|
+
h2. Resources
|
99
|
+
|
100
|
+
For additional information on CLDR plural rules see:
|
101
|
+
|
102
|
+
* "http://unicode.org/draft/reports/tr35/tr35.html#Language_Plural_Rules":http://unicode.org/draft/reports/tr35/tr35.html#Language_Plural_Rules
|
103
|
+
* "http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html":http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html
|
104
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ruby-cldr"
|
8
|
+
gem.summary = %Q{Ruby library for exporting and using data from CLDR }
|
9
|
+
gem.description = %Q{Ruby library for exporting and using data from CLDR, see http://cldr.unicode.org}
|
10
|
+
gem.email = "svenfuchs@artweb-design.de"
|
11
|
+
gem.homepage = "http://github.com/svenfuchs/ruby-cldr"
|
12
|
+
gem.authors = ["Sven Fuchs"]
|
13
|
+
gem.files = FileList["*.thor", "[A-Z]*", "{lib,test}/**/*"]
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
- during export resolve links if :merge => true
|
2
|
+
- make sense of timezone data
|
3
|
+
- hook into Rails' select_month and DateTime helpers
|
4
|
+
|
5
|
+
extract:
|
6
|
+
|
7
|
+
- territoryContainment (groups territories)
|
8
|
+
- languageData (maps languages/scripts to territories)
|
9
|
+
- territoryInfo (?)
|
10
|
+
- calendarData
|
11
|
+
- weekData
|
12
|
+
|
13
|
+
what do the following tags in supplementalMetadata mean?
|
14
|
+
- variable
|
15
|
+
- defaultContent
|
16
|
+
|
17
|
+
|
18
|
+
Instead of exporting YAML, maybe by default export Ruby classes:
|
19
|
+
|
20
|
+
module Cldr
|
21
|
+
module Data
|
22
|
+
class De::Numbers
|
23
|
+
def currency_format
|
24
|
+
"#,##0.00 ¤"
|
25
|
+
end
|
26
|
+
|
27
|
+
def symbols
|
28
|
+
{ ... }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class De::Calendars::Gregorian
|
33
|
+
def months(context, type)
|
34
|
+
case context
|
35
|
+
when :format
|
36
|
+
case type
|
37
|
+
when :wide
|
38
|
+
{ :sat => "Samstag", :sun => "Sonntag", :mon => "Montag", ...}
|
39
|
+
end
|
40
|
+
when :'stand-alone'
|
41
|
+
case type
|
42
|
+
when :narrow
|
43
|
+
{ ... }
|
44
|
+
else
|
45
|
+
months(:format, :wide)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def date_format(type)
|
51
|
+
case type
|
52
|
+
when :full
|
53
|
+
"EEEE, d. MMMM y"
|
54
|
+
when :medium
|
55
|
+
"dd.MM.yyyy"
|
56
|
+
else
|
57
|
+
date_format(:medium)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class DeAt::Numbers < De::Numbers
|
63
|
+
end
|
64
|
+
|
65
|
+
class DeAt::Calendars::Gregorian < De::Calendars::Gregorian
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/cldr.thor
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'core_ext/string/underscore'
|
2
|
+
require 'core_ext/hash/deep_merge'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
class Cldr
|
6
|
+
module Data
|
7
|
+
class Base < Hash
|
8
|
+
attr_reader :locale
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
hash = args.last.is_a?(Hash) ? args.pop : {}
|
12
|
+
@locale = args.pop.to_sym unless args.empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(keys, value)
|
16
|
+
return if value.nil? || value.respond_to?(:empty?) && value.empty?
|
17
|
+
|
18
|
+
keys = keys.to_s.split('.')
|
19
|
+
last_key = keys.pop.to_sym
|
20
|
+
|
21
|
+
target = keys.inject(self) { |target, key| target[key.to_sym] || target.store(key.to_sym, {}) }
|
22
|
+
target.store(last_key, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def update(hash)
|
26
|
+
hash.each { |key, value| self[key] = value }
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def plural?(node)
|
32
|
+
!!node.attribute('count')
|
33
|
+
end
|
34
|
+
|
35
|
+
def draft?(node)
|
36
|
+
draft = node.attribute('draft')
|
37
|
+
draft && draft.value == 'unconfirmed'
|
38
|
+
end
|
39
|
+
|
40
|
+
def name(node)
|
41
|
+
node.name.underscore
|
42
|
+
end
|
43
|
+
|
44
|
+
def count(node)
|
45
|
+
node.attribute('count').value
|
46
|
+
end
|
47
|
+
|
48
|
+
def select(*sources)
|
49
|
+
doc.xpath(xpath(sources))
|
50
|
+
end
|
51
|
+
|
52
|
+
def xpath(sources)
|
53
|
+
path = sources.map { |source| source.respond_to?(:path) ? source.path : source }.join('/')
|
54
|
+
path =~ /^\/?\/ldml/ ? path : "//ldml/#{path}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def doc
|
58
|
+
@doc ||= Nokogiri::XML(File.read(path))
|
59
|
+
end
|
60
|
+
|
61
|
+
def path
|
62
|
+
@path ||= "#{Cldr::Data.dir}/main/#{locale.to_s.gsub('-', '_')}.xml"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
class Cldr
|
2
|
+
module Data
|
3
|
+
class Calendars
|
4
|
+
class Gregorian < Base
|
5
|
+
def initialize(locale)
|
6
|
+
super
|
7
|
+
update(
|
8
|
+
:months => contexts('month'),
|
9
|
+
:days => contexts('day'),
|
10
|
+
:eras => contexts('era'),
|
11
|
+
:quarters => contexts('quarter'),
|
12
|
+
:periods => periods,
|
13
|
+
:fields => fields,
|
14
|
+
:'formats.date' => formats('date'),
|
15
|
+
:'formats.time' => formats('time'),
|
16
|
+
:'formats.datetime' => formats('dateTime')
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def calendar
|
21
|
+
@calendar ||= select('dates/calendars/calendar[@type="gregorian"]').first
|
22
|
+
end
|
23
|
+
|
24
|
+
def contexts(kind)
|
25
|
+
select(calendar, "#{kind}s/#{kind}Context").inject({}) do |result, node|
|
26
|
+
context = node.attribute('type').value.to_sym
|
27
|
+
result[context] = widths(node, kind, context)
|
28
|
+
result
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def widths(node, kind, context)
|
33
|
+
select(node, "#{kind}Width").inject({}) do |result, node|
|
34
|
+
width = node.attribute('type').value.to_sym
|
35
|
+
result[width] = elements(node, kind, context, width)
|
36
|
+
result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def elements(node, kind, context, width)
|
41
|
+
aliased = select(node, 'alias').first
|
42
|
+
if aliased
|
43
|
+
xpath_to_key(aliased.attribute('path').value, kind, context, width)
|
44
|
+
else
|
45
|
+
select(node, kind).inject({}) do |result, node|
|
46
|
+
key = node.attribute('type').value
|
47
|
+
key = key =~ /^\d*$/ ? key.to_i : key.to_sym
|
48
|
+
result[key] = node.content
|
49
|
+
result
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def xpath_to_key(xpath, kind, context, width)
|
55
|
+
kind = (xpath =~ %r(/([^\/]*)Width) && $1) || kind
|
56
|
+
context = (xpath =~ %r(Context\[@type='([^\/]*)'\]) && $1) || context
|
57
|
+
width = (xpath =~ %r(Width\[@type='([^\/]*)'\]) && $1) || width
|
58
|
+
:"calendars.gregorian.#{kind}s.#{context}.#{width}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def xpath_width
|
62
|
+
end
|
63
|
+
|
64
|
+
def periods
|
65
|
+
am = select(calendar, "am").first
|
66
|
+
pm = select(calendar, "pm").first
|
67
|
+
|
68
|
+
result = {}
|
69
|
+
result[:am] = am.content if am
|
70
|
+
result[:pm] = pm.content if pm
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
def eras
|
75
|
+
base_path = calendar.path.gsub('/ldml/', '') + '/eras'
|
76
|
+
keys = select("#{base_path}/*").map { |node| node.name }
|
77
|
+
|
78
|
+
eras = keys.inject([]) do |result, name|
|
79
|
+
path = "#{base_path}/#{name}/*"
|
80
|
+
key = name.gsub('era', '').gsub(/s$/, '').downcase.to_sym
|
81
|
+
result << extract(path, :key => lambda { |node| node.attribute('type').value.to_i rescue 0 },
|
82
|
+
:value => lambda { |node| { key => node.content } })
|
83
|
+
end
|
84
|
+
eras.inject({}) { |result, data| result.deep_merge(data) }
|
85
|
+
end
|
86
|
+
|
87
|
+
def formats(type)
|
88
|
+
formats = select(calendar, "#{type}Formats/#{type}FormatLength").inject({}) do |result, node|
|
89
|
+
key = node.attribute('type').value.to_sym rescue :format
|
90
|
+
result[key] = pattern(node, type)
|
91
|
+
result
|
92
|
+
end
|
93
|
+
if default = default_format(type)
|
94
|
+
formats = default.merge(formats)
|
95
|
+
end
|
96
|
+
formats
|
97
|
+
end
|
98
|
+
|
99
|
+
def default_format(type)
|
100
|
+
if node = select(calendar, "#{type}Formats/default").first
|
101
|
+
key = node.attribute('choice').value.to_sym
|
102
|
+
{ :default => :"calendars.gregorian.formats.#{type.downcase}.#{key}" }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def pattern(node, type)
|
107
|
+
select(node, "#{type}Format/pattern").inject({}) do |result, node|
|
108
|
+
result[:pattern] = node.content
|
109
|
+
result
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def fields
|
114
|
+
select(calendar, "fields/field").inject({}) do |result, node|
|
115
|
+
key = node.attribute('type').value.to_sym
|
116
|
+
name = node.xpath('displayName').first
|
117
|
+
result[key] = name.content if name
|
118
|
+
result
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Cldr
|
2
|
+
module Data
|
3
|
+
class Currencies < Base
|
4
|
+
def initialize(locale)
|
5
|
+
super
|
6
|
+
self[:currencies] = currencies
|
7
|
+
end
|
8
|
+
|
9
|
+
def currencies
|
10
|
+
select('numbers/currencies/*').inject({}) do |result, node|
|
11
|
+
currency = self.currency(node)
|
12
|
+
result[node.attribute('type').value.to_sym] = currency unless currency.empty?
|
13
|
+
result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def currency(node)
|
18
|
+
select(node, 'displayName').inject({}) do |result, node|
|
19
|
+
count = node.attribute('count') ? node.attribute('count').value.to_sym : :one
|
20
|
+
result[count] = node.content unless draft?(node)
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Cldr
|
2
|
+
module Data
|
3
|
+
class Delimiters < Base
|
4
|
+
def initialize(locale)
|
5
|
+
super
|
6
|
+
self[:'delimiters.quotes.default'] = quotes('quotation')
|
7
|
+
self[:'delimiters.quotes.alternate'] = quotes('alternateQuotation')
|
8
|
+
end
|
9
|
+
|
10
|
+
def quotes(type)
|
11
|
+
start = select("delimiters/#{type}Start").first
|
12
|
+
end_ = select("delimiters/#{type}End").first
|
13
|
+
|
14
|
+
result = {}
|
15
|
+
result[:start] = start.content if start
|
16
|
+
result[:end] = end_.content if end_
|
17
|
+
result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Cldr
|
2
|
+
module Data
|
3
|
+
class Languages < Base
|
4
|
+
def initialize(locale)
|
5
|
+
super
|
6
|
+
self[:languages] = languages
|
7
|
+
end
|
8
|
+
|
9
|
+
def languages
|
10
|
+
@languages ||= select('localeDisplayNames/languages/language').inject({}) do |result, node|
|
11
|
+
result[node.attribute('type').value.gsub('_', '-').to_sym] = node.content unless draft?(node)
|
12
|
+
result
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class Cldr
|
2
|
+
module Data
|
3
|
+
class Numbers < Base
|
4
|
+
def initialize(locale)
|
5
|
+
super
|
6
|
+
self[:'numbers.symbols'] = symbols
|
7
|
+
self[:'numbers.formats'] = {
|
8
|
+
:decimal => {
|
9
|
+
:patterns => {
|
10
|
+
:default => format('decimal')
|
11
|
+
}
|
12
|
+
},
|
13
|
+
:scientific => {
|
14
|
+
:patterns => {
|
15
|
+
:default => format('scientific')
|
16
|
+
}
|
17
|
+
},
|
18
|
+
:percent => {
|
19
|
+
:patterns => {
|
20
|
+
:default => format('percent')
|
21
|
+
}
|
22
|
+
},
|
23
|
+
:currency => {
|
24
|
+
:patterns => {
|
25
|
+
:default => format('currency')
|
26
|
+
}
|
27
|
+
},
|
28
|
+
}
|
29
|
+
self[:'numbers.formats.currency.unit'] = unit
|
30
|
+
end
|
31
|
+
|
32
|
+
def currency
|
33
|
+
currency = format('currency')
|
34
|
+
currency.update(:unit => unit) unless unit.empty?
|
35
|
+
currency
|
36
|
+
end
|
37
|
+
|
38
|
+
def symbols
|
39
|
+
select('numbers/symbols/*').inject({}) do |result, node|
|
40
|
+
result[name(node).to_sym] = node.content unless draft?(node)
|
41
|
+
result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def format(type)
|
46
|
+
select("numbers/#{type}Formats/#{type}FormatLength/#{type}Format/pattern").inject({}) do |result, node|
|
47
|
+
node.content unless draft?(node)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def unit
|
52
|
+
@unit ||= select("numbers/currencyFormats/unitPattern").inject({}) do |result, node|
|
53
|
+
count = node.attribute('count').value rescue 'one'
|
54
|
+
result[count] = node.content
|
55
|
+
result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# http://unicode.org/draft/reports/tr35/tr35.html#Language_Plural_Rules
|
2
|
+
#
|
3
|
+
# condition = and_condition ('or' and_condition)*
|
4
|
+
# and_condition = relation ('and' relation)*
|
5
|
+
# relation = is_relation | in_relation | within_relation | 'n' <EOL>
|
6
|
+
# is_relation = expr 'is' ('not')? value
|
7
|
+
# in_relation = expr ('not')? 'in' range
|
8
|
+
# within_relation = expr ('not')? 'within' range
|
9
|
+
# expr = 'n' ('mod' value)?
|
10
|
+
# value = digit+
|
11
|
+
# digit = 0|1|2|3|4|5|6|7|8|9
|
12
|
+
# range = value'..'value
|
13
|
+
|
14
|
+
grammar CldrPluralGrammar
|
15
|
+
rule or_condition
|
16
|
+
and_condition (" or " and_condition)?
|
17
|
+
end
|
18
|
+
|
19
|
+
rule and_condition
|
20
|
+
relation (" and " relation)?
|
21
|
+
end
|
22
|
+
|
23
|
+
rule relation
|
24
|
+
is_relation / in_relation / within_relation / "n"
|
25
|
+
end
|
26
|
+
|
27
|
+
rule is_relation
|
28
|
+
expr " is " "not "? value
|
29
|
+
end
|
30
|
+
|
31
|
+
rule in_relation
|
32
|
+
expr " not"? " in " range
|
33
|
+
end
|
34
|
+
|
35
|
+
rule within_relation
|
36
|
+
expr " not"? " within " range
|
37
|
+
end
|
38
|
+
|
39
|
+
rule expr
|
40
|
+
"n" (" mod " value)?
|
41
|
+
end
|
42
|
+
|
43
|
+
rule range
|
44
|
+
value ".." value
|
45
|
+
end
|
46
|
+
|
47
|
+
rule value
|
48
|
+
[0-9]*
|
49
|
+
end
|
50
|
+
end
|