twitter_cldr 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|