twitter_cldr 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/NOTICE +29 -1
- data/README.md +4 -11
- data/lib/twitter_cldr/formatters/calendars/date_formatter.rb +6 -1
- data/lib/twitter_cldr/formatters/calendars/datetime_formatter.rb +10 -1
- data/lib/twitter_cldr/formatters/calendars/time_formatter.rb +6 -1
- data/lib/twitter_cldr/formatters/calendars/timespan_formatter.rb +12 -2
- data/lib/twitter_cldr/formatters/numbers/currency_formatter.rb +12 -3
- data/lib/twitter_cldr/formatters/numbers/number_formatter.rb +9 -1
- data/lib/twitter_cldr/formatters/plurals/rules.rb +8 -3
- data/lib/twitter_cldr/localized/localized_date.rb +13 -0
- data/lib/twitter_cldr/localized/localized_datetime.rb +20 -7
- data/lib/twitter_cldr/localized/localized_object.rb +1 -1
- data/lib/twitter_cldr/localized/localized_string.rb +14 -0
- data/lib/twitter_cldr/localized/localized_time.rb +12 -0
- data/lib/twitter_cldr/localized/localized_timespan.rb +1 -1
- data/lib/twitter_cldr/parsers/number_parser.rb +113 -0
- data/lib/twitter_cldr/parsers.rb +10 -0
- data/lib/twitter_cldr/resources/loader.rb +49 -2
- data/lib/twitter_cldr/resources/locales_resources_importer.rb +22 -2
- data/lib/twitter_cldr/shared/calendar.rb +95 -12
- data/lib/twitter_cldr/shared/currencies.rb +18 -15
- data/lib/twitter_cldr/shared/languages.rb +4 -4
- data/lib/twitter_cldr/shared/numbers.rb +1 -1
- data/lib/twitter_cldr/shared/territories.rb +63 -0
- data/lib/twitter_cldr/shared.rb +2 -1
- data/lib/twitter_cldr/tokenizers/base.rb +10 -15
- data/lib/twitter_cldr/tokenizers/calendars/additional_date_format_selector.rb +6 -1
- data/lib/twitter_cldr/tokenizers/calendars/datetime_tokenizer.rb +11 -2
- data/lib/twitter_cldr/tokenizers/calendars/timespan_tokenizer.rb +12 -9
- data/lib/twitter_cldr/tokenizers/numbers/number_tokenizer.rb +2 -2
- data/lib/twitter_cldr/utils/territories.rb +56 -0
- data/lib/twitter_cldr/utils.rb +4 -3
- data/lib/twitter_cldr/version.rb +1 -1
- data/lib/twitter_cldr.rb +60 -8
- data/resources/collation/tailoring/hr.yml +32 -0
- data/resources/collation/tailoring/is.yml +30 -0
- data/resources/collation/tries/hr.dump +0 -0
- data/resources/collation/tries/is.dump +0 -0
- data/resources/custom/locales/he/units.yml +150 -13
- data/resources/custom/locales/hr/units.yml +9 -0
- data/resources/locales/af/territories.yml +262 -0
- data/resources/locales/ar/territories.yml +262 -0
- data/resources/locales/be/territories.yml +239 -0
- data/resources/locales/bg/territories.yml +262 -0
- data/resources/locales/bn/territories.yml +262 -0
- data/resources/locales/ca/territories.yml +262 -0
- data/resources/locales/cs/territories.yml +262 -0
- data/resources/locales/cy/territories.yml +5 -0
- data/resources/locales/da/territories.yml +262 -0
- data/resources/locales/de/territories.yml +262 -0
- data/resources/locales/el/territories.yml +262 -0
- data/resources/locales/en/territories.yml +262 -0
- data/resources/locales/es/territories.yml +262 -0
- data/resources/locales/eu/territories.yml +262 -0
- data/resources/locales/fa/territories.yml +262 -0
- data/resources/locales/fi/territories.yml +262 -0
- data/resources/locales/fil/territories.yml +262 -0
- data/resources/locales/fr/territories.yml +262 -0
- data/resources/locales/ga/territories.yml +251 -0
- data/resources/locales/gl/territories.yml +262 -0
- data/resources/locales/he/territories.yml +262 -0
- data/resources/locales/hi/territories.yml +262 -0
- data/resources/locales/hr/calendars.yml +299 -0
- data/resources/locales/hr/currencies.yml +1490 -0
- data/resources/locales/hr/languages.yml +576 -0
- data/resources/locales/hr/layout.yml +4 -0
- data/resources/locales/hr/lists.yml +7 -0
- data/resources/locales/hr/numbers.yml +59 -0
- data/resources/locales/hr/plurals.yml +5 -0
- data/resources/locales/hr/territories.yml +262 -0
- data/resources/locales/hr/units.yml +164 -0
- data/resources/locales/hu/territories.yml +262 -0
- data/resources/locales/id/territories.yml +262 -0
- data/resources/locales/is/calendars.yml +243 -0
- data/resources/locales/is/currencies.yml +478 -0
- data/resources/locales/is/languages.yml +495 -0
- data/resources/locales/is/layout.yml +4 -0
- data/resources/locales/is/lists.yml +7 -0
- data/resources/locales/is/numbers.yml +57 -0
- data/resources/locales/is/plurals.yml +3 -0
- data/resources/locales/is/territories.yml +262 -0
- data/resources/locales/is/units.yml +108 -0
- data/resources/locales/it/territories.yml +262 -0
- data/resources/locales/ja/territories.yml +262 -0
- data/resources/locales/ko/territories.yml +262 -0
- data/resources/locales/lv/territories.yml +262 -0
- data/resources/locales/ms/territories.yml +262 -0
- data/resources/locales/nb/territories.yml +262 -0
- data/resources/locales/nl/territories.yml +262 -0
- data/resources/locales/pl/territories.yml +262 -0
- data/resources/locales/pt/territories.yml +262 -0
- data/resources/locales/ro/territories.yml +262 -0
- data/resources/locales/ru/territories.yml +262 -0
- data/resources/locales/sk/territories.yml +262 -0
- data/resources/locales/sq/territories.yml +159 -0
- data/resources/locales/sr/territories.yml +262 -0
- data/resources/locales/sv/territories.yml +262 -0
- data/resources/locales/ta/territories.yml +262 -0
- data/resources/locales/th/territories.yml +262 -0
- data/resources/locales/tr/territories.yml +262 -0
- data/resources/locales/uk/territories.yml +262 -0
- data/resources/locales/ur/territories.yml +262 -0
- data/resources/locales/vi/territories.yml +262 -0
- data/resources/locales/zh/territories.yml +262 -0
- data/resources/locales/zh-Hant/territories.yml +262 -0
- data/resources/shared/iso_currency_symbols.yml +475 -0
- data/spec/formatters/numbers/currency_formatter_spec.rb +11 -2
- data/spec/formatters/plurals/rules_spec.rb +1 -1
- data/spec/localized/localized_date_spec.rb +22 -24
- data/spec/localized/localized_object_spec.rb +1 -1
- data/spec/localized/localized_string_spec.rb +33 -0
- data/spec/localized/localized_symbol_spec.rb +1 -1
- data/spec/normalization/base_spec.rb +1 -0
- data/spec/parsers/number_parser_spec.rb +189 -0
- data/spec/readme_spec.rb +10 -11
- data/spec/resources/loader_spec.rb +75 -1
- data/spec/shared/calendar_spec.rb +123 -1
- data/spec/shared/currencies_spec.rb +20 -24
- data/spec/shared/languages_spec.rb +27 -27
- data/spec/shared/numbers_spec.rb +1 -1
- data/spec/shared/territories_spec.rb +120 -0
- data/spec/spec_helper.rb +19 -2
- data/spec/twitter_cldr_spec.rb +234 -9
- data/spec/utils/territories_spec.rb +16 -0
- data/spec/utils_spec.rb +1 -1
- metadata +131 -37
- data/resources/shared/currencies.yml +0 -448
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 2.1.0
|
2
|
+
|
3
|
+
* Significant performance improvements (memoization, resource preloading).
|
4
|
+
* Number parsing.
|
5
|
+
* Custom Hebrew units (thanks @yarons!)
|
6
|
+
* Icelandic and Croatian support.
|
7
|
+
* Global locale setter and fallbacks.
|
8
|
+
* Support for territories from CLDR.
|
9
|
+
|
1
10
|
== 2.0.2
|
2
11
|
|
3
12
|
* Added support for Vietnamese.
|
data/NOTICE
CHANGED
@@ -151,4 +151,32 @@ OR PERFORMANCE OF THIS SOFTWARE.
|
|
151
151
|
|
152
152
|
Except as contained in this notice, the name of a copyright holder shall not be
|
153
153
|
used in advertising or otherwise to promote the sale, use or other dealings in
|
154
|
-
this Software without prior written authorization of the copyright holder.
|
154
|
+
this Software without prior written authorization of the copyright holder.
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
|
159
|
+
|
160
|
+
The currencies data in twitter-cldr-rb has been adapted from the currencies gem.
|
161
|
+
Here's the license that accompanied that code:
|
162
|
+
|
163
|
+
Copyright (c) 2009 hexorx
|
164
|
+
|
165
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
166
|
+
a copy of this software and associated documentation files (the
|
167
|
+
"Software"), to deal in the Software without restriction, including
|
168
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
169
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
170
|
+
permit persons to whom the Software is furnished to do so, subject to
|
171
|
+
the following conditions:
|
172
|
+
|
173
|
+
The above copyright notice and this permission notice shall be
|
174
|
+
included in all copies or substantial portions of the Software.
|
175
|
+
|
176
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
177
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
178
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
179
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
180
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
181
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
182
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -42,7 +42,6 @@ TwitterCldr patches core Ruby objects like `Fixnum` and `Date` to make localizat
|
|
42
42
|
# currencies, default USD
|
43
43
|
1337.localize(:es).to_currency.to_s # 1.337,00 $
|
44
44
|
1337.localize(:es).to_currency.to_s(:currency => "EUR") # 1.337,00 €
|
45
|
-
1337.localize(:es).to_currency.to_s(:currency => "Peru") # 1.337,00 S/.
|
46
45
|
|
47
46
|
# percentages
|
48
47
|
1337.localize(:es).to_percent.to_s # 1.337%
|
@@ -63,20 +62,14 @@ num.to_currency.to_s # ...etc
|
|
63
62
|
|
64
63
|
#### More on Currencies
|
65
64
|
|
66
|
-
If you're looking for a list of supported
|
65
|
+
If you're looking for a list of supported currencies, use the `TwitterCldr::Shared::Currencies` class:
|
67
66
|
|
68
67
|
```ruby
|
69
|
-
# all supported countries
|
70
|
-
TwitterCldr::Shared::Currencies.countries # ["Lithuania", "Philippines", ... ]
|
71
|
-
|
72
68
|
# all supported currency codes
|
73
69
|
TwitterCldr::Shared::Currencies.currency_codes # ["LTL", "PHP" ... ]
|
74
70
|
|
75
|
-
# data for a specific country
|
76
|
-
TwitterCldr::Shared::Currencies.for_country("Canada") # { :currency => "Dollar", :symbol => "$", :code => "CAD" }
|
77
|
-
|
78
71
|
# data for a specific currency code
|
79
|
-
TwitterCldr::Shared::Currencies.for_code("CAD") # { :currency => "
|
72
|
+
TwitterCldr::Shared::Currencies.for_code("CAD") # { :currency => "Canadian dollar", :symbol => "$", :code_points => [36], :cldr_symbol => "CA$", :country => "Canada" }
|
80
73
|
```
|
81
74
|
|
82
75
|
#### Short / Long Decimals
|
@@ -126,7 +119,7 @@ dt.to_short_s # ...etc
|
|
126
119
|
Besides the default date formats, CLDR supports a number of additional ones. The list of available formats varys for each locale. To get a full list, use the `additional_formats_for` method:
|
127
120
|
|
128
121
|
```ruby
|
129
|
-
# ["EEEEd", "Ed", "GGGGyMd", "H", "Hm", "Hms", "M", "MEd", "MMM", "MMMEEEEd", "MMMEd", ... ]
|
122
|
+
# ["EEEEd", "Ed", "GGGGyMd", "H", "Hm", "Hms", "M", "MEd", "MMM", "MMMEEEEd", "MMMEd", ... ]
|
130
123
|
TwitterCldr::Formatters::DateTimeFormatter.additional_formats_for(:ja)
|
131
124
|
```
|
132
125
|
|
@@ -620,7 +613,7 @@ TwitterCldr.convert_locale(:msa) # :ms
|
|
620
613
|
TwitterCldr.convert_locale(:ms) # :ms
|
621
614
|
```
|
622
615
|
|
623
|
-
There are a few functions in TwitterCLDR that don't require a locale code, and instead use the default locale by calling `TwitterCldr.
|
616
|
+
There are a few functions in TwitterCLDR that don't require a locale code, and instead use the default locale by calling `TwitterCldr.locale`. The `locale` function defers to `FastGettext.locale` when the FastGettext library is available, and falls back on :en (English) when it's not. (Twitter uses the FastGettext gem to retrieve translations efficiently in Ruby).
|
624
617
|
|
625
618
|
```ruby
|
626
619
|
TwitterCldr.get_locale # will return :en
|
@@ -7,7 +7,12 @@ module TwitterCldr
|
|
7
7
|
module Formatters
|
8
8
|
class DateFormatter < DateTimeFormatter
|
9
9
|
def initialize(options = {})
|
10
|
-
|
10
|
+
locale = extract_locale(options)
|
11
|
+
cache_key = TwitterCldr::Utils.compute_cache_key("date", locale, options[:calendar_type])
|
12
|
+
@tokenizer = tokenizer_cache[cache_key] ||= TwitterCldr::Tokenizers::DateTokenizer.new(
|
13
|
+
:locale => locale,
|
14
|
+
:calendar_type => options[:calendar_type]
|
15
|
+
)
|
11
16
|
end
|
12
17
|
end
|
13
18
|
end
|
@@ -41,7 +41,12 @@ module TwitterCldr
|
|
41
41
|
}
|
42
42
|
|
43
43
|
def initialize(options = {})
|
44
|
-
|
44
|
+
locale = extract_locale(options)
|
45
|
+
cache_key = TwitterCldr::Utils.compute_cache_key("datetime", locale, options[:calendar_type])
|
46
|
+
@tokenizer = tokenizer_cache[cache_key] ||= TwitterCldr::Tokenizers::DateTimeTokenizer.new(
|
47
|
+
:locale => locale,
|
48
|
+
:calendar_type => options[:calendar_type]
|
49
|
+
)
|
45
50
|
end
|
46
51
|
|
47
52
|
def result_for_token(token, index, date)
|
@@ -58,6 +63,10 @@ module TwitterCldr
|
|
58
63
|
|
59
64
|
protected
|
60
65
|
|
66
|
+
def tokenizer_cache
|
67
|
+
@@tokenizer_cache ||= {}
|
68
|
+
end
|
69
|
+
|
61
70
|
# there is incomplete era data in CLDR for certain locales like Hindi
|
62
71
|
# fall back if that happens
|
63
72
|
def era(date, pattern, length)
|
@@ -7,7 +7,12 @@ module TwitterCldr
|
|
7
7
|
module Formatters
|
8
8
|
class TimeFormatter < DateTimeFormatter
|
9
9
|
def initialize(options = {})
|
10
|
-
|
10
|
+
locale = extract_locale(options)
|
11
|
+
cache_key = TwitterCldr::Utils.compute_cache_key("time", locale, options[:calendar_type])
|
12
|
+
@tokenizer = tokenizer_cache[cache_key] ||= TwitterCldr::Tokenizers::TimeTokenizer.new(
|
13
|
+
:locale => locale,
|
14
|
+
:calendar_type => options[:calendar_type]
|
15
|
+
)
|
11
16
|
end
|
12
17
|
end
|
13
18
|
end
|
@@ -21,14 +21,18 @@ module TwitterCldr
|
|
21
21
|
}
|
22
22
|
|
23
23
|
def initialize(options = {})
|
24
|
+
locale = extract_locale(options)
|
24
25
|
@direction = options[:direction]
|
25
|
-
|
26
|
+
cache_key = TwitterCldr::Utils.compute_cache_key(locale)
|
27
|
+
@tokenizer = tokenizer_cache[cache_key] ||= TwitterCldr::Tokenizers::TimespanTokenizer.new(
|
28
|
+
:locale => locale
|
29
|
+
)
|
26
30
|
end
|
27
31
|
|
28
32
|
def format(seconds, fmt_options = {})
|
29
33
|
options = fmt_options.dup
|
30
34
|
options[:type] ||= DEFAULT_TYPE
|
31
|
-
options[:direction] ||=
|
35
|
+
options[:direction] ||= (seconds < 0 ? :ago : :until)
|
32
36
|
options[:unit] ||= calculate_unit(seconds.abs, options)
|
33
37
|
|
34
38
|
options[:number] = calculate_time(seconds.abs, options[:unit])
|
@@ -38,6 +42,12 @@ module TwitterCldr
|
|
38
42
|
strings.join.gsub(/\{[0-9]\}/, options[:number].to_s)
|
39
43
|
end
|
40
44
|
|
45
|
+
protected
|
46
|
+
|
47
|
+
def tokenizer_cache
|
48
|
+
@@tokenizer_cache ||= {}
|
49
|
+
end
|
50
|
+
|
41
51
|
def calculate_unit(seconds, unit_options = {})
|
42
52
|
options = unit_options.dup
|
43
53
|
options[:approximate] = false if options[:approximate].nil?
|
@@ -12,17 +12,26 @@ module TwitterCldr
|
|
12
12
|
def format(number, options = {})
|
13
13
|
options[:currency] ||= "USD"
|
14
14
|
currency = TwitterCldr::Shared::Currencies.for_code(options[:currency])
|
15
|
-
currency ||=
|
16
|
-
|
15
|
+
currency ||= {
|
16
|
+
:currency => options[:currency],
|
17
|
+
:symbol => options[:currency],
|
18
|
+
:cldr_symbol => options[:currency]
|
19
|
+
}
|
20
|
+
|
21
|
+
# overwrite with explicit symbol if given
|
22
|
+
currency[:symbol] = options[:symbol] if options[:symbol]
|
17
23
|
|
18
24
|
digits_and_rounding = resource(options[:currency])
|
19
25
|
options[:precision] ||= digits_and_rounding[:digits]
|
20
26
|
options[:rounding] ||= digits_and_rounding[:rounding]
|
21
27
|
|
22
|
-
|
28
|
+
symbol = options[:use_cldr_symbol] ? currency[:cldr_symbol] : currency[:symbol]
|
29
|
+
symbol ||= currency[:currency].to_s
|
30
|
+
super(number, options).gsub('¤', symbol)
|
23
31
|
end
|
24
32
|
|
25
33
|
private
|
34
|
+
|
26
35
|
def resource(code)
|
27
36
|
@resource ||= TwitterCldr.get_resource(:shared, :currency_digits_and_rounding)
|
28
37
|
@resource[code.to_sym] || @resource[:DEFAULT]
|
@@ -11,7 +11,11 @@ module TwitterCldr
|
|
11
11
|
DEFAULT_SYMBOLS = { :group => ',', :decimal => '.', :plus_sign => '+', :minus_sign => '-' }
|
12
12
|
|
13
13
|
def initialize(options = {})
|
14
|
-
|
14
|
+
locale = extract_locale(options)
|
15
|
+
cache_key = TwitterCldr::Utils.compute_cache_key(locale)
|
16
|
+
@tokenizer = tokenizer_cache[cache_key] ||= TwitterCldr::Tokenizers::NumberTokenizer.new(
|
17
|
+
:locale => locale
|
18
|
+
)
|
15
19
|
@symbols = DEFAULT_SYMBOLS.merge(tokenizer.symbols)
|
16
20
|
end
|
17
21
|
|
@@ -28,6 +32,10 @@ module TwitterCldr
|
|
28
32
|
|
29
33
|
protected
|
30
34
|
|
35
|
+
def tokenizer_cache
|
36
|
+
@@tokenizer_cache ||= {}
|
37
|
+
end
|
38
|
+
|
31
39
|
def transform_number(number)
|
32
40
|
number # noop for base class
|
33
41
|
end
|
@@ -11,7 +11,7 @@ module TwitterCldr
|
|
11
11
|
class << self
|
12
12
|
|
13
13
|
def all
|
14
|
-
all_for(TwitterCldr.
|
14
|
+
all_for(TwitterCldr.locale)
|
15
15
|
end
|
16
16
|
|
17
17
|
def all_for(locale)
|
@@ -20,7 +20,7 @@ module TwitterCldr
|
|
20
20
|
nil
|
21
21
|
end
|
22
22
|
|
23
|
-
def rule_for(number, locale = TwitterCldr.
|
23
|
+
def rule_for(number, locale = TwitterCldr.locale)
|
24
24
|
get_resource(locale)[:rule].call(number)
|
25
25
|
rescue
|
26
26
|
:other
|
@@ -30,7 +30,12 @@ module TwitterCldr
|
|
30
30
|
|
31
31
|
def get_resource(locale)
|
32
32
|
locale = TwitterCldr.convert_locale(locale)
|
33
|
-
|
33
|
+
cache_key = TwitterCldr::Utils.compute_cache_key(locale)
|
34
|
+
locale_cache[cache_key] ||= eval(TwitterCldr.get_locale_resource(locale, :plurals)[locale])[locale][:i18n][:plural]
|
35
|
+
end
|
36
|
+
|
37
|
+
def locale_cache
|
38
|
+
@locale_cache ||= {}
|
34
39
|
end
|
35
40
|
|
36
41
|
end
|
@@ -12,6 +12,19 @@ module TwitterCldr
|
|
12
12
|
LocalizedDateTime.new(DateTime.parse("#{@base_obj.strftime("%Y-%m-%d")}T#{time_obj.strftime("%H:%M:%S%z")}"), @locale, :calendar_type => @calendar_type)
|
13
13
|
end
|
14
14
|
|
15
|
+
def to_time(base = Time.now)
|
16
|
+
time = Time.gm(
|
17
|
+
@base_obj.year,
|
18
|
+
@base_obj.month,
|
19
|
+
@base_obj.day,
|
20
|
+
base.hour,
|
21
|
+
base.min,
|
22
|
+
base.sec
|
23
|
+
)
|
24
|
+
|
25
|
+
LocalizedTime.new(time, @locale, :calendar_type => @calendar_type)
|
26
|
+
end
|
27
|
+
|
15
28
|
protected
|
16
29
|
|
17
30
|
def formatter_const
|
@@ -27,15 +27,15 @@ module TwitterCldr
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def ago(options = {})
|
30
|
-
base_time = options[:base_time] || Time.now
|
31
|
-
seconds = self.to_time.base_obj.to_i - base_time.to_i
|
30
|
+
base_time = (options[:base_time] || Time.now).gmtime
|
31
|
+
seconds = self.to_time(base_time).base_obj.gmtime.to_i - base_time.to_i
|
32
32
|
raise ArgumentError.new('Start date is after end date. Consider using "until" function.') if seconds > 0
|
33
33
|
TwitterCldr::Localized::LocalizedTimespan.new(seconds, options.merge(:locale => @locale))
|
34
34
|
end
|
35
35
|
|
36
36
|
def until(options = {})
|
37
|
-
base_time = options[:base_time] || Time.now
|
38
|
-
seconds = self.to_time.base_obj.to_i - base_time.to_i
|
37
|
+
base_time = (options[:base_time] || Time.now).gmtime
|
38
|
+
seconds = self.to_time(base_time).base_obj.gmtime.to_i - base_time.to_i
|
39
39
|
raise ArgumentError.new('End date is before start date. Consider using "ago" function.') if seconds < 0
|
40
40
|
TwitterCldr::Localized::LocalizedTimespan.new(seconds, options.merge(:locale => @locale))
|
41
41
|
end
|
@@ -49,11 +49,24 @@ module TwitterCldr
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def to_date
|
52
|
-
|
52
|
+
date = Date.new(@base_obj.year, @base_obj.month, @base_obj.day)
|
53
|
+
LocalizedDate.new(date, @locale, :calendar_type => @calendar_type)
|
53
54
|
end
|
54
55
|
|
55
|
-
def to_time
|
56
|
-
|
56
|
+
def to_time(base = Time.now)
|
57
|
+
utc_dt = @base_obj.new_offset(0)
|
58
|
+
|
59
|
+
time = Time.gm(
|
60
|
+
utc_dt.year,
|
61
|
+
utc_dt.month,
|
62
|
+
utc_dt.day,
|
63
|
+
utc_dt.hour,
|
64
|
+
utc_dt.min,
|
65
|
+
utc_dt.sec,
|
66
|
+
utc_dt.sec_fraction * (RUBY_VERSION < '1.9' ? 86400000000 : 1000000)
|
67
|
+
)
|
68
|
+
|
69
|
+
LocalizedTime.new(time, @locale, :calendar_type => @calendar_type)
|
57
70
|
end
|
58
71
|
|
59
72
|
protected
|
@@ -27,7 +27,7 @@ module TwitterCldr
|
|
27
27
|
|
28
28
|
def self.localize(klass)
|
29
29
|
klass.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
|
30
|
-
def localize(locale = TwitterCldr.
|
30
|
+
def localize(locale = TwitterCldr.locale, options = {})
|
31
31
|
#{self}.new(self, locale, options)
|
32
32
|
end
|
33
33
|
LOCALIZE
|
@@ -36,6 +36,20 @@ module TwitterCldr
|
|
36
36
|
@base_obj.dup
|
37
37
|
end
|
38
38
|
|
39
|
+
def to_i(options = {})
|
40
|
+
to_f(options).to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_f(options = {})
|
44
|
+
if TwitterCldr::Parsers::NumberParser.is_numeric?(@base_obj)
|
45
|
+
TwitterCldr::Parsers::NumberParser.new(@locale).try_parse(@base_obj, options) do |result|
|
46
|
+
result || @base_obj.to_f
|
47
|
+
end
|
48
|
+
else
|
49
|
+
@base_obj.to_f
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
39
53
|
def size
|
40
54
|
code_points.size
|
41
55
|
end
|
@@ -12,6 +12,18 @@ module TwitterCldr
|
|
12
12
|
LocalizedDateTime.new(DateTime.parse("#{date_obj.strftime("%Y-%m-%d")}T#{@base_obj.strftime("%H:%M:%S%z")}"), @locale, :calendar_type => @calendar_type)
|
13
13
|
end
|
14
14
|
|
15
|
+
def to_time(base_time = Time.now)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def gmtime
|
20
|
+
LocalizedTime.new(@base_obj.gmtime, @locale, :calendar_type => @calendar_type)
|
21
|
+
end
|
22
|
+
|
23
|
+
def localtime
|
24
|
+
LocalizedTime.new(@base_obj.localtime, @locale, :calendar_type => @calendar_type)
|
25
|
+
end
|
26
|
+
|
15
27
|
protected
|
16
28
|
|
17
29
|
def formatter_const
|
@@ -8,7 +8,7 @@ module TwitterCldr
|
|
8
8
|
|
9
9
|
class LocalizedTimespan < LocalizedObject
|
10
10
|
def initialize(seconds, options = {})
|
11
|
-
super(seconds, options[:locale] || TwitterCldr.
|
11
|
+
super(seconds, options[:locale] || TwitterCldr.locale, options)
|
12
12
|
end
|
13
13
|
|
14
14
|
def to_s(options = {})
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2012 Twitter, Inc
|
4
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
5
|
+
|
6
|
+
module TwitterCldr
|
7
|
+
module Parsers
|
8
|
+
|
9
|
+
class InvalidNumberError < StandardError; end
|
10
|
+
|
11
|
+
class NumberParser
|
12
|
+
|
13
|
+
SEPARATOR_CHARS = ['.', ',', ' '].map do |char|
|
14
|
+
char == ' ' ? '\s' : Regexp.escape(char)
|
15
|
+
end.join
|
16
|
+
|
17
|
+
def initialize(locale = TwitterCldr.locale)
|
18
|
+
@locale = locale
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(number_text, options = {})
|
22
|
+
options[:strict] = true unless options.include?(:strict)
|
23
|
+
group, decimal = separators(options[:strict])
|
24
|
+
tokens = tokenize(number_text, group, decimal)
|
25
|
+
|
26
|
+
num_list, punct_list = tokens.partition { |t| t[:type] == :numeric }
|
27
|
+
raise InvalidNumberError unless punct_valid?(punct_list)
|
28
|
+
raise InvalidNumberError unless tokens.last && tokens.last[:type] == :numeric
|
29
|
+
|
30
|
+
if punct_list.last && punct_list.last[:type] == :decimal
|
31
|
+
result = num_list[0..-2].map { |num| num[:value] }.join.to_i
|
32
|
+
result + num_list.last[:value].to_i / (10.0 ** num_list.last[:value].size)
|
33
|
+
else
|
34
|
+
num_list.map { |num| num[:value] }.join.to_i
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def try_parse(number_text, default = nil, options = {})
|
39
|
+
begin
|
40
|
+
result = parse(number_text, options)
|
41
|
+
rescue InvalidNumberError
|
42
|
+
result = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
if block_given?
|
46
|
+
yield(result)
|
47
|
+
else
|
48
|
+
result || default
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def valid?(number_text, options = {})
|
53
|
+
parse(number_text, options)
|
54
|
+
true
|
55
|
+
rescue
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.is_numeric?(text, separators = SEPARATOR_CHARS)
|
60
|
+
!!(text =~ /\A[0-9#{separators}]+\Z/)
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
def punct_valid?(punct_list)
|
66
|
+
# all group, allowed one decimal at end
|
67
|
+
punct_list.each_with_index.all? do |punct, index|
|
68
|
+
punct[:type] == :group || (index == (punct_list.size - 1) && punct[:type] == :decimal)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def separators(strict = false)
|
73
|
+
group = strict ? group_separator : SEPARATOR_CHARS
|
74
|
+
decimal = strict ? decimal_separator : SEPARATOR_CHARS
|
75
|
+
[group, decimal]
|
76
|
+
end
|
77
|
+
|
78
|
+
def tokenize(number_text, group, decimal)
|
79
|
+
match_data = number_text.scan(/([\d]*)([#{group}]{0,1})([\d]*)([#{decimal}]{0,1})([\d]*)/)
|
80
|
+
(match_data.flatten || []).reject(&:empty?).map { |match| identify(match, group, decimal) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def identify(text, group, decimal)
|
84
|
+
result = { :value => text }
|
85
|
+
result[:type] = if self.class.is_numeric?(result[:value], "")
|
86
|
+
:numeric
|
87
|
+
else
|
88
|
+
if result[:value] =~ /[#{group}]/
|
89
|
+
:group
|
90
|
+
elsif result[:value] =~ /[#{decimal}]/
|
91
|
+
:decimal
|
92
|
+
else
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
result
|
97
|
+
end
|
98
|
+
|
99
|
+
def decimal_separator
|
100
|
+
@decimal_separator ||= Regexp.escape(resource[:symbols][:decimal])
|
101
|
+
end
|
102
|
+
|
103
|
+
def group_separator
|
104
|
+
@group_separator ||= Regexp.escape(resource[:symbols][:group])
|
105
|
+
end
|
106
|
+
|
107
|
+
def resource
|
108
|
+
@resource ||= TwitterCldr.get_locale_resource(@locale, "numbers")[@locale][:numbers]
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -13,11 +13,58 @@ module TwitterCldr
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def get_locale_resource(locale, resource_name)
|
16
|
-
get_resource(
|
16
|
+
get_resource(*locale_resource_path(locale, resource_name))
|
17
|
+
end
|
18
|
+
|
19
|
+
def resource_loaded?(*path)
|
20
|
+
resources_cache.include?(resource_file_path(path))
|
21
|
+
end
|
22
|
+
|
23
|
+
def locale_resource_loaded?(locale, resource_name)
|
24
|
+
resource_loaded?(*locale_resource_path(locale, resource_name))
|
25
|
+
end
|
26
|
+
|
27
|
+
def resource_types
|
28
|
+
@resource_types ||= Dir.glob(File.join(RESOURCES_DIR, 'locales/en', '*')).map do |file|
|
29
|
+
File.basename(file).chomp(File.extname(file)).to_sym
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def preload_resources_for_locale(locale, *resources)
|
34
|
+
if resources.size > 0
|
35
|
+
resources = resource_types if resources.first == :all
|
36
|
+
resources.each { |res| get_locale_resource(locale, res) }
|
37
|
+
end
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def preload_resource_for_locales(resource, *locales)
|
42
|
+
locales.each do |locale|
|
43
|
+
preload_resources_for_locale(locale, resource)
|
44
|
+
end
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def preload_resources_for_all_locales(*resources)
|
49
|
+
TwitterCldr.supported_locales.each do |locale|
|
50
|
+
preload_resources_for_locale(locale, *resources)
|
51
|
+
end
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def preload_all_resources
|
56
|
+
TwitterCldr.supported_locales.each do |locale|
|
57
|
+
preload_resources_for_locale(locale, :all)
|
58
|
+
end
|
59
|
+
nil
|
17
60
|
end
|
18
61
|
|
19
62
|
private
|
20
63
|
|
64
|
+
def locale_resource_path(locale, resource_name)
|
65
|
+
[:locales, TwitterCldr.convert_locale(locale), resource_name]
|
66
|
+
end
|
67
|
+
|
21
68
|
def resources_cache
|
22
69
|
@resources_cache ||= Hash.new { |hash, path| hash[path] = load_resource(path) }
|
23
70
|
end
|
@@ -54,4 +101,4 @@ module TwitterCldr
|
|
54
101
|
end
|
55
102
|
|
56
103
|
end
|
57
|
-
end
|
104
|
+
end
|
@@ -12,7 +12,7 @@ module TwitterCldr
|
|
12
12
|
|
13
13
|
class LocalesResourcesImporter
|
14
14
|
|
15
|
-
COMPONENTS = %w[calendars languages numbers units plurals lists layout currencies]
|
15
|
+
COMPONENTS = %w[calendars languages numbers units plurals lists layout currencies territories]
|
16
16
|
|
17
17
|
# Arguments:
|
18
18
|
#
|
@@ -49,6 +49,7 @@ module TwitterCldr
|
|
49
49
|
Cldr::Export.export(:locales => TwitterCldr.supported_locales, :components => COMPONENTS, :target => File.join(@output_path, 'locales')) do |component, locale, path|
|
50
50
|
add_buddhist_calendar(component, locale, path)
|
51
51
|
process_plurals(component, locale, path)
|
52
|
+
downcase_territory_codes(component, locale, path)
|
52
53
|
deep_symbolize(component, locale, path)
|
53
54
|
end
|
54
55
|
|
@@ -68,6 +69,25 @@ module TwitterCldr
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
72
|
+
# CLDR stores territory codes uppercase. For consistency with how we
|
73
|
+
# handle territory codes in methods relating to phone and postal codes,
|
74
|
+
# we downcase them here.
|
75
|
+
#
|
76
|
+
# (There is also some trickery relating to three-digit UN "area codes"
|
77
|
+
# used by CLDR; see comment of Utils::Territories::deep_normalize_territory_code_keys.)
|
78
|
+
def downcase_territory_codes(component, locale, path)
|
79
|
+
return unless component == 'Territories'
|
80
|
+
|
81
|
+
data = YAML.load(File.read(path))
|
82
|
+
data.keys.each do |l|
|
83
|
+
data[l] = TwitterCldr::Utils::Territories.deep_normalize_territory_code_keys(data[l])
|
84
|
+
end
|
85
|
+
|
86
|
+
File.open(path, 'w:utf-8') do |output|
|
87
|
+
output.write(YAML.dump(data))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
71
91
|
def process_plurals(component, locale, path)
|
72
92
|
return unless component == 'Plurals'
|
73
93
|
|
@@ -106,4 +126,4 @@ module TwitterCldr
|
|
106
126
|
end
|
107
127
|
|
108
128
|
end
|
109
|
-
end
|
129
|
+
end
|