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.
Files changed (128) hide show
  1. data/History.txt +9 -0
  2. data/NOTICE +29 -1
  3. data/README.md +4 -11
  4. data/lib/twitter_cldr/formatters/calendars/date_formatter.rb +6 -1
  5. data/lib/twitter_cldr/formatters/calendars/datetime_formatter.rb +10 -1
  6. data/lib/twitter_cldr/formatters/calendars/time_formatter.rb +6 -1
  7. data/lib/twitter_cldr/formatters/calendars/timespan_formatter.rb +12 -2
  8. data/lib/twitter_cldr/formatters/numbers/currency_formatter.rb +12 -3
  9. data/lib/twitter_cldr/formatters/numbers/number_formatter.rb +9 -1
  10. data/lib/twitter_cldr/formatters/plurals/rules.rb +8 -3
  11. data/lib/twitter_cldr/localized/localized_date.rb +13 -0
  12. data/lib/twitter_cldr/localized/localized_datetime.rb +20 -7
  13. data/lib/twitter_cldr/localized/localized_object.rb +1 -1
  14. data/lib/twitter_cldr/localized/localized_string.rb +14 -0
  15. data/lib/twitter_cldr/localized/localized_time.rb +12 -0
  16. data/lib/twitter_cldr/localized/localized_timespan.rb +1 -1
  17. data/lib/twitter_cldr/parsers/number_parser.rb +113 -0
  18. data/lib/twitter_cldr/parsers.rb +10 -0
  19. data/lib/twitter_cldr/resources/loader.rb +49 -2
  20. data/lib/twitter_cldr/resources/locales_resources_importer.rb +22 -2
  21. data/lib/twitter_cldr/shared/calendar.rb +95 -12
  22. data/lib/twitter_cldr/shared/currencies.rb +18 -15
  23. data/lib/twitter_cldr/shared/languages.rb +4 -4
  24. data/lib/twitter_cldr/shared/numbers.rb +1 -1
  25. data/lib/twitter_cldr/shared/territories.rb +63 -0
  26. data/lib/twitter_cldr/shared.rb +2 -1
  27. data/lib/twitter_cldr/tokenizers/base.rb +10 -15
  28. data/lib/twitter_cldr/tokenizers/calendars/additional_date_format_selector.rb +6 -1
  29. data/lib/twitter_cldr/tokenizers/calendars/datetime_tokenizer.rb +11 -2
  30. data/lib/twitter_cldr/tokenizers/calendars/timespan_tokenizer.rb +12 -9
  31. data/lib/twitter_cldr/tokenizers/numbers/number_tokenizer.rb +2 -2
  32. data/lib/twitter_cldr/utils/territories.rb +56 -0
  33. data/lib/twitter_cldr/utils.rb +4 -3
  34. data/lib/twitter_cldr/version.rb +1 -1
  35. data/lib/twitter_cldr.rb +60 -8
  36. data/resources/collation/tailoring/hr.yml +32 -0
  37. data/resources/collation/tailoring/is.yml +30 -0
  38. data/resources/collation/tries/hr.dump +0 -0
  39. data/resources/collation/tries/is.dump +0 -0
  40. data/resources/custom/locales/he/units.yml +150 -13
  41. data/resources/custom/locales/hr/units.yml +9 -0
  42. data/resources/locales/af/territories.yml +262 -0
  43. data/resources/locales/ar/territories.yml +262 -0
  44. data/resources/locales/be/territories.yml +239 -0
  45. data/resources/locales/bg/territories.yml +262 -0
  46. data/resources/locales/bn/territories.yml +262 -0
  47. data/resources/locales/ca/territories.yml +262 -0
  48. data/resources/locales/cs/territories.yml +262 -0
  49. data/resources/locales/cy/territories.yml +5 -0
  50. data/resources/locales/da/territories.yml +262 -0
  51. data/resources/locales/de/territories.yml +262 -0
  52. data/resources/locales/el/territories.yml +262 -0
  53. data/resources/locales/en/territories.yml +262 -0
  54. data/resources/locales/es/territories.yml +262 -0
  55. data/resources/locales/eu/territories.yml +262 -0
  56. data/resources/locales/fa/territories.yml +262 -0
  57. data/resources/locales/fi/territories.yml +262 -0
  58. data/resources/locales/fil/territories.yml +262 -0
  59. data/resources/locales/fr/territories.yml +262 -0
  60. data/resources/locales/ga/territories.yml +251 -0
  61. data/resources/locales/gl/territories.yml +262 -0
  62. data/resources/locales/he/territories.yml +262 -0
  63. data/resources/locales/hi/territories.yml +262 -0
  64. data/resources/locales/hr/calendars.yml +299 -0
  65. data/resources/locales/hr/currencies.yml +1490 -0
  66. data/resources/locales/hr/languages.yml +576 -0
  67. data/resources/locales/hr/layout.yml +4 -0
  68. data/resources/locales/hr/lists.yml +7 -0
  69. data/resources/locales/hr/numbers.yml +59 -0
  70. data/resources/locales/hr/plurals.yml +5 -0
  71. data/resources/locales/hr/territories.yml +262 -0
  72. data/resources/locales/hr/units.yml +164 -0
  73. data/resources/locales/hu/territories.yml +262 -0
  74. data/resources/locales/id/territories.yml +262 -0
  75. data/resources/locales/is/calendars.yml +243 -0
  76. data/resources/locales/is/currencies.yml +478 -0
  77. data/resources/locales/is/languages.yml +495 -0
  78. data/resources/locales/is/layout.yml +4 -0
  79. data/resources/locales/is/lists.yml +7 -0
  80. data/resources/locales/is/numbers.yml +57 -0
  81. data/resources/locales/is/plurals.yml +3 -0
  82. data/resources/locales/is/territories.yml +262 -0
  83. data/resources/locales/is/units.yml +108 -0
  84. data/resources/locales/it/territories.yml +262 -0
  85. data/resources/locales/ja/territories.yml +262 -0
  86. data/resources/locales/ko/territories.yml +262 -0
  87. data/resources/locales/lv/territories.yml +262 -0
  88. data/resources/locales/ms/territories.yml +262 -0
  89. data/resources/locales/nb/territories.yml +262 -0
  90. data/resources/locales/nl/territories.yml +262 -0
  91. data/resources/locales/pl/territories.yml +262 -0
  92. data/resources/locales/pt/territories.yml +262 -0
  93. data/resources/locales/ro/territories.yml +262 -0
  94. data/resources/locales/ru/territories.yml +262 -0
  95. data/resources/locales/sk/territories.yml +262 -0
  96. data/resources/locales/sq/territories.yml +159 -0
  97. data/resources/locales/sr/territories.yml +262 -0
  98. data/resources/locales/sv/territories.yml +262 -0
  99. data/resources/locales/ta/territories.yml +262 -0
  100. data/resources/locales/th/territories.yml +262 -0
  101. data/resources/locales/tr/territories.yml +262 -0
  102. data/resources/locales/uk/territories.yml +262 -0
  103. data/resources/locales/ur/territories.yml +262 -0
  104. data/resources/locales/vi/territories.yml +262 -0
  105. data/resources/locales/zh/territories.yml +262 -0
  106. data/resources/locales/zh-Hant/territories.yml +262 -0
  107. data/resources/shared/iso_currency_symbols.yml +475 -0
  108. data/spec/formatters/numbers/currency_formatter_spec.rb +11 -2
  109. data/spec/formatters/plurals/rules_spec.rb +1 -1
  110. data/spec/localized/localized_date_spec.rb +22 -24
  111. data/spec/localized/localized_object_spec.rb +1 -1
  112. data/spec/localized/localized_string_spec.rb +33 -0
  113. data/spec/localized/localized_symbol_spec.rb +1 -1
  114. data/spec/normalization/base_spec.rb +1 -0
  115. data/spec/parsers/number_parser_spec.rb +189 -0
  116. data/spec/readme_spec.rb +10 -11
  117. data/spec/resources/loader_spec.rb +75 -1
  118. data/spec/shared/calendar_spec.rb +123 -1
  119. data/spec/shared/currencies_spec.rb +20 -24
  120. data/spec/shared/languages_spec.rb +27 -27
  121. data/spec/shared/numbers_spec.rb +1 -1
  122. data/spec/shared/territories_spec.rb +120 -0
  123. data/spec/spec_helper.rb +19 -2
  124. data/spec/twitter_cldr_spec.rb +234 -9
  125. data/spec/utils/territories_spec.rb +16 -0
  126. data/spec/utils_spec.rb +1 -1
  127. metadata +131 -37
  128. data/resources/shared/currencies.yml +0 -448
@@ -8,39 +8,122 @@ module TwitterCldr
8
8
  class Calendar
9
9
 
10
10
  DEFAULT_FORMAT = :'stand-alone'
11
+ DEFAULT_PERIOD_FORMAT = :format
11
12
 
12
13
  NAMES_FORMS = [:wide, :narrow, :abbreviated]
14
+ ERAS_NAMES_FORMS = [:abbr, :name]
15
+
16
+ DATETIME_METHOD_MAP = {
17
+ :year_of_week_of_year => :year,
18
+ :quarter_stand_alone => :quarter,
19
+ :month_stand_alone => :month,
20
+ :day_of_month => :day,
21
+ :day_of_week_in_month => :day,
22
+ :weekday_local => :weekday,
23
+ :weekday_local_stand_alone => :weekday,
24
+ :second_fraction => :second,
25
+ :timezone_generic_non_location => :timezone,
26
+ :timezone_metazone => :timezone
27
+ }
28
+
29
+ REDIRECT_CONVERSIONS = {
30
+ :dayPeriods => :periods
31
+ }
13
32
 
14
33
  attr_reader :locale, :calendar_type
15
34
 
16
- def initialize(locale = TwitterCldr.get_locale, calendar_type = TwitterCldr::DEFAULT_CALENDAR_TYPE)
35
+ def initialize(locale = TwitterCldr.locale, calendar_type = TwitterCldr::DEFAULT_CALENDAR_TYPE)
17
36
  @locale = TwitterCldr.convert_locale(locale)
18
37
  @calendar_type = calendar_type
19
38
  end
20
39
 
21
- def months(names_form = :wide)
22
- data = get_with_names_form(:months, names_form)
23
- data && data.sort_by{ |m| m.first }.map { |m| m.last }
40
+ def months(names_form = :wide, format = DEFAULT_FORMAT)
41
+ data = get_with_names_form(:months, names_form, format)
42
+ data && data.sort_by { |m| m.first }.map { |m| m.last }
24
43
  end
25
44
 
26
- def weekdays(names_form = :wide)
27
- get_with_names_form(:days, names_form)
45
+ def weekdays(names_form = :wide, format = DEFAULT_FORMAT)
46
+ get_with_names_form(:days, names_form, format)
47
+ end
48
+
49
+ def fields
50
+ get_data(:fields)
51
+ end
52
+
53
+ def quarters(names_form = :wide, format = DEFAULT_FORMAT)
54
+ get_with_names_form(:quarters, names_form, format)
55
+ end
56
+
57
+ def periods(names_form = :wide, format = DEFAULT_PERIOD_FORMAT)
58
+ get_with_names_form(:periods, names_form, format)
59
+ end
60
+
61
+ def eras(names_form = :name)
62
+ get_data(:eras)[names_form]
63
+ end
64
+
65
+ def date_order(options = {})
66
+ get_order_for(TwitterCldr::Tokenizers::DateTokenizer, options)
67
+ end
68
+
69
+ def time_order(options = {})
70
+ get_order_for(TwitterCldr::Tokenizers::TimeTokenizer, options)
71
+ end
72
+
73
+ def datetime_order(options = {})
74
+ get_order_for(TwitterCldr::Tokenizers::DateTimeTokenizer, options)
28
75
  end
29
76
 
30
77
  private
31
78
 
32
- def get_with_names_form(data_type, names_form)
33
- get_data(data_type, DEFAULT_FORMAT, names_form) if NAMES_FORMS.include?(names_form.to_sym)
79
+ def calendar_cache
80
+ @@calendar_cache ||= {}
81
+ end
82
+
83
+ def get_order_for(const, options)
84
+ opts = options.merge(:locale => @locale)
85
+ cache_key = TwitterCldr::Utils.compute_cache_key([const.to_s] + opts.keys.sort + opts.values.sort)
86
+ calendar_cache.fetch(cache_key) do |key|
87
+ tokens = const.new(opts).tokens
88
+ calendar_cache[cache_key] = resolve_methods(methods_for_tokens(tokens))
89
+ end
90
+ end
91
+
92
+ def resolve_methods(methods)
93
+ methods.map { |method| DATETIME_METHOD_MAP.fetch(method, method) }
94
+ end
95
+
96
+ def methods_for_tokens(tokens)
97
+ tokens.inject([]) do |ret, token|
98
+ if token.type == :pattern
99
+ ret << TwitterCldr::Formatters::DateTimeFormatter::METHODS[token.value[0].chr]
100
+ end
101
+ ret
102
+ end
103
+ end
104
+
105
+ def get_with_names_form(data_type, names_form, format)
106
+ get_data(data_type, format, names_form) if NAMES_FORMS.include?(names_form.to_sym)
34
107
  end
35
108
 
36
109
  def get_data(*path)
37
- data = TwitterCldr::Utils.traverse_hash(calendar_data, path)
38
- redirect = parse_redirect(data)
39
- redirect ? get_data(*redirect) : data
110
+ cache_key = TwitterCldr::Utils.compute_cache_key([@locale] + path)
111
+ calendar_cache.fetch(cache_key) do |key|
112
+ data = TwitterCldr::Utils.traverse_hash(calendar_data, path)
113
+ redirect = parse_redirect(data)
114
+ calendar_cache[key] = if redirect
115
+ get_data(*redirect)
116
+ else
117
+ data
118
+ end
119
+ end
40
120
  end
41
121
 
42
122
  def parse_redirect(data)
43
- $1.split('.').map(&:to_sym) if data.is_a?(Symbol) && data.to_s =~ redirect_regexp
123
+ if data.is_a?(Symbol) && data.to_s =~ redirect_regexp
124
+ result = $1.split('.').map(&:to_sym)
125
+ result.map { |leg| REDIRECT_CONVERSIONS.fetch(leg, leg) }
126
+ end
44
127
  end
45
128
 
46
129
  def redirect_regexp
@@ -7,32 +7,35 @@ module TwitterCldr
7
7
  module Shared
8
8
  module Currencies
9
9
  class << self
10
- def countries
11
- Kernel.warn("Currencies#countries will be deprecated. Please use Currencies#for_code.")
12
- resource_countries.keys.map(&:to_s)
13
- end
14
-
15
10
  def currency_codes(locale = :en)
16
11
  resource(locale).keys.map { |c| c.to_s }
17
12
  end
18
13
 
19
- def for_country(country_name, locale = :en)
20
- Kernel.warn("Currencies#for_country will be deprecated. Please use Currencies#for_code.")
21
- for_code(resource_countries[country_name.to_sym][:code], locale) if resource_countries[country_name.to_sym]
22
- end
23
-
24
14
  def for_code(currency_code, locale = :en)
25
15
  currency_code = currency_code.to_sym
26
16
  data = resource(locale)[currency_code]
27
- { :currency => currency_code,
28
- :name => data[:one],
29
- :symbol => data[:symbol] } if data
17
+ symbol_data = iso_currency_symbols[currency_code]
18
+
19
+ if data
20
+ result = {
21
+ :currency => currency_code,
22
+ :name => data[:one],
23
+ :cldr_symbol => data[:symbol] || currency_code.to_s,
24
+ :symbol => data[:symbol] || currency_code.to_s,
25
+ :code_points => (data[:symbol] || currency_code.to_s).unpack("U*")
26
+ }
27
+
28
+ result.merge!(symbol_data) if symbol_data
29
+ end
30
+
31
+ result
30
32
  end
31
33
 
32
34
  private
33
35
 
34
- def resource_countries
35
- @resource_countries ||= TwitterCldr.get_resource(:shared, :currencies)
36
+ # ISO 4217 to be precise
37
+ def iso_currency_symbols
38
+ @iso_currency_symbols ||= TwitterCldr.get_resource(:shared, :iso_currency_symbols)
36
39
  end
37
40
 
38
41
  def resource(locale)
@@ -10,7 +10,7 @@ module TwitterCldr
10
10
  class << self
11
11
 
12
12
  def all
13
- all_for(TwitterCldr.get_locale)
13
+ all_for(TwitterCldr.locale)
14
14
  end
15
15
 
16
16
  def all_for(code)
@@ -20,16 +20,16 @@ module TwitterCldr
20
20
  end
21
21
 
22
22
  def from_code(code)
23
- from_code_for_locale(code, TwitterCldr.get_locale)
23
+ from_code_for_locale(code, TwitterCldr.locale)
24
24
  end
25
25
 
26
- def from_code_for_locale(code, locale = TwitterCldr.get_locale)
26
+ def from_code_for_locale(code, locale = TwitterCldr.locale)
27
27
  get_resource(locale)[:languages][TwitterCldr.convert_locale(code)]
28
28
  rescue
29
29
  nil
30
30
  end
31
31
 
32
- def translate_language(language, source_locale = :en, dest_locale = TwitterCldr.get_locale)
32
+ def translate_language(language, source_locale = :en, dest_locale = TwitterCldr.locale)
33
33
  lang_code = get_resource(source_locale)[:languages].detect { |_, val| val.downcase == language.downcase }.first
34
34
  get_resource(dest_locale)[:languages][lang_code] if lang_code
35
35
  rescue
@@ -9,7 +9,7 @@ module TwitterCldr
9
9
 
10
10
  class << self
11
11
 
12
- def symbols(locale = TwitterCldr.get_locale)
12
+ def symbols(locale = TwitterCldr.locale)
13
13
  get_resource(TwitterCldr.convert_locale(locale))[:symbols] rescue nil
14
14
  end
15
15
 
@@ -0,0 +1,63 @@
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 Shared
8
+ module Territories
9
+
10
+ class << self
11
+
12
+ def all
13
+ all_for(TwitterCldr.locale)
14
+ end
15
+
16
+ def all_for(code)
17
+ get_resource(code)[:territories]
18
+ rescue
19
+ {}
20
+ end
21
+
22
+ def from_territory_code(territory_code)
23
+ from_territory_code_for_locale(territory_code, TwitterCldr.locale)
24
+ end
25
+
26
+ # Returns how to say a given territory in a given locale.
27
+ #
28
+ # This method does not work for three-digit United Nation "area
29
+ # codes" (UN M.49; for example, 014 for Eastern Africa and 419 for Latin
30
+ # America).
31
+ def from_territory_code_for_locale(territory_code, locale = TwitterCldr.locale)
32
+ get_resource(locale)[:territories][TwitterCldr::Utils::Territories.normalize_territory_code(territory_code)]
33
+ rescue
34
+ nil
35
+ end
36
+
37
+ # Translates territory_name from source_locale to dest_locale.
38
+ #
39
+ # This method does not work for three-digit United Nation "area
40
+ # codes" (UN M.49; for example, 014 for Eastern Africa and 419 for Latin
41
+ # America).
42
+ def translate_territory(territory_name, source_locale = :en, dest_locale = TwitterCldr.locale)
43
+ territory_code, _ = get_resource(source_locale)[:territories].find do |_, other_territory_name|
44
+ other_territory_name.downcase == territory_name.downcase
45
+ end
46
+ get_resource(dest_locale)[:territories][territory_code] if territory_code
47
+ rescue
48
+ nil
49
+ end
50
+
51
+ protected
52
+
53
+ def get_resource(locale)
54
+ locale = TwitterCldr.convert_locale(locale)
55
+ TwitterCldr.get_locale_resource(locale, :territories)[locale]
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+
@@ -14,5 +14,6 @@ module TwitterCldr
14
14
  autoload :PhoneCodes, 'twitter_cldr/shared/phone_codes'
15
15
  autoload :PostalCodes, 'twitter_cldr/shared/postal_codes'
16
16
  autoload :Bidi, 'twitter_cldr/shared/bidi'
17
+ autoload :Territories, 'twitter_cldr/shared/territories'
17
18
  end
18
- end
19
+ end
@@ -54,10 +54,9 @@ module TwitterCldr
54
54
  end
55
55
 
56
56
  def tokens_for_pattern(pattern, path, additional_cache_key_params = [])
57
- @@token_cache ||= {}
58
57
  cache_key = TwitterCldr::Utils.compute_cache_key(@locale, path.join('.'), type, format || "nil", *additional_cache_key_params)
59
58
 
60
- unless @@token_cache.include?(cache_key)
59
+ unless token_cache.include?(cache_key)
61
60
  result = []
62
61
  tokens = expand_pattern(pattern)
63
62
 
@@ -69,33 +68,29 @@ module TwitterCldr
69
68
  end
70
69
  end
71
70
 
72
- @@token_cache[cache_key] = result
71
+ token_cache[cache_key] = result
73
72
  end
74
73
 
75
- @@token_cache[cache_key]
74
+ token_cache[cache_key]
76
75
  end
77
76
 
78
77
  def tokens_with_placeholders_for(key)
79
- @@token_cache ||= {}
80
- cache_key = compute_cache_key(@locale, key, type)
78
+ cache_key = TwitterCldr::Utils.compute_cache_key(@locale, key, type)
81
79
 
82
- unless @@token_cache.include?(cache_key)
80
+ unless token_cache.include?(cache_key)
83
81
  result = []
84
82
  tokens = tokenize_pattern(pattern_for(traverse(key)))
85
83
  tokens.each do |token|
86
84
  result << token
87
85
  end
88
- @@token_cache[cache_key] = result
86
+ token_cache[cache_key] = result
89
87
  end
90
- @@token_cache[cache_key]
88
+
89
+ token_cache[cache_key]
91
90
  end
92
91
 
93
- def compute_cache_key(*pieces)
94
- if pieces && pieces.size > 0
95
- pieces.join("|").hash
96
- else
97
- 0
98
- end
92
+ def token_cache
93
+ @@token_cache ||= {}
99
94
  end
100
95
 
101
96
  def init_placeholders
@@ -16,7 +16,8 @@ module TwitterCldr
16
16
  if !goal_pattern || goal_pattern.strip.empty?
17
17
  nil
18
18
  else
19
- rank(goal_pattern).min do |(p1, score1), (p2, score2)|
19
+ cache_key = TwitterCldr::Utils.compute_cache_key(goal_pattern)
20
+ pattern_cache[cache_key] ||= rank(goal_pattern).min do |(p1, score1), (p2, score2)|
20
21
  score1 <=> score2
21
22
  end.first
22
23
  end
@@ -28,6 +29,10 @@ module TwitterCldr
28
29
 
29
30
  protected
30
31
 
32
+ def pattern_cache
33
+ @pattern_cache ||= {}
34
+ end
35
+
31
36
  def separate(pattern_key)
32
37
  last_char = ""
33
38
  pattern_key.each_char.each_with_index.inject([]) do |ret, (char, index)|
@@ -20,7 +20,7 @@ module TwitterCldr
20
20
  DateTokenizer::TOKEN_SPLITTER_REGEX,
21
21
  TimeTokenizer::TOKEN_SPLITTER_REGEX
22
22
  ),
23
- :else => //
23
+ :else => /([^\s]+)/ # groups of non-space chars
24
24
  }
25
25
 
26
26
  @token_type_regexes = {
@@ -55,13 +55,18 @@ module TwitterCldr
55
55
  end
56
56
 
57
57
  def additional_format_selector
58
- @additional_format_selector ||= AdditionalDateFormatSelector.new(
58
+ cache_key = TwitterCldr::Utils.compute_cache_key(@locale, @calendar_type)
59
+ @additional_format_selector = format_selector_cache[cache_key] ||= AdditionalDateFormatSelector.new(
59
60
  @resource[:calendars][@calendar_type][:additional_formats]
60
61
  )
61
62
  end
62
63
 
63
64
  protected
64
65
 
66
+ def format_selector_cache
67
+ @@format_selector_cache ||= {}
68
+ end
69
+
65
70
  def merge_token_type_regexes(first, second)
66
71
  TwitterCldr::Utils.deep_merge_hash(first, second) do |left, right|
67
72
  if right.is_a?(Regexp) && left.is_a?(Regexp)
@@ -116,6 +121,10 @@ module TwitterCldr
116
121
  resource.is_a?(Hash) ? resource[:pattern] : resource
117
122
  end
118
123
  end
124
+
125
+ def pattern_cache
126
+ @@pattern_cache ||= {}
127
+ end
119
128
  end
120
129
  end
121
130
  end
@@ -56,25 +56,28 @@ module TwitterCldr
56
56
  end
57
57
 
58
58
  def tokens(options = {})
59
+ # tokens_with_placeholders_for(full_path(:none, :second, :short, :two))
59
60
  path = full_path(options[:direction], options[:unit], options[:type])
60
61
  pluralization = options[:rule] || TwitterCldr::Formatters::Plurals::Rules.rule_for(options[:number], @locale)
62
+ available = traverse(path)
61
63
 
62
64
  case pluralization # sometimes the plural rule will return ":one" when the resource only contains a path with "1"
63
65
  when :zero
64
- pluralization = 0 if token_exists(path + [0])
66
+ pluralization = 0 if available.include?(0)
65
67
  when :one
66
- pluralization = 1 if token_exists(path + [1])
68
+ pluralization = 1 if available.include?(1)
67
69
  when :two
68
- pluralization = 2 if token_exists(path + [2])
70
+ pluralization = 2 if available.include?(2)
69
71
  end
70
- path << pluralization
71
72
 
72
- tokens_with_placeholders_for(path) if token_exists(path)
73
- end
73
+ if available.include?(pluralization)
74
+ path << pluralization
75
+ else
76
+ return [] unless available.keys.first
77
+ path << available.keys.first
78
+ end
74
79
 
75
- def token_exists(path)
76
- cache_key = compute_cache_key(@locale, path.join('.'))
77
- token_cache.include?(cache_key) || !!traverse(path)
80
+ tokens_with_placeholders_for(path)
78
81
  end
79
82
 
80
83
  def all_types_for(unit, direction)
@@ -41,8 +41,8 @@ module TwitterCldr
41
41
  end
42
42
 
43
43
  def tokens(options = {})
44
- @type = options[:type] || @type || :default
45
- @format = options[:format] || @format || :default
44
+ @type = options[:type] || :default
45
+ @format = options[:format] || :default
46
46
 
47
47
  path = full_path
48
48
  positive, negative = traverse(path).to_s.split(/;/)
@@ -0,0 +1,56 @@
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 Utils
8
+ module Territories
9
+ class << self
10
+
11
+ # Normalizes a territory code to a symbol.
12
+ #
13
+ # 1) Converts to string.
14
+ # 2) Downcases.
15
+ # 3) Symbolizes.
16
+ #
17
+ # The downcasing is to convert ISO 3166-1 alpha-2 codes,
18
+ # used (upper-case) for territories in CLDR, to be lowercase, to be
19
+ # consistent with how territory codes are surfaced in TwitterCLDR
20
+ # methods relating to phone and postal codes.
21
+ def normalize_territory_code(territory_code)
22
+ return nil if territory_code.nil?
23
+ territory_code.to_s.downcase.gsub(/^0+/, '').to_sym
24
+ end
25
+
26
+ # Normalizes each key in the 'arg' hash or constituent hashes as
27
+ # if it were a territory code.
28
+ #
29
+ # In addition, removes entries in hashes where the key begins with a digit.
30
+ # Because of the way the twitter-cldr-rb YAML resource pipeline works,
31
+ # these three-digit codes get mangled (e.g. interpreted as octal then
32
+ # reinterpreted out in decimal), and translations for UN three-digit
33
+ # area codes cannot be trusted.
34
+ def deep_normalize_territory_code_keys(arg)
35
+ case arg
36
+ when Array
37
+ arg.map { |elem| deep_normalize_territory_code_keys(elem) }
38
+ when Hash
39
+ normalized = arg.inject({}) do |carry, (key, value)|
40
+ normalized_key = normalize_territory_code(key)
41
+ carry[normalized_key] = deep_normalize_territory_code_keys(value)
42
+ carry
43
+ end
44
+ normalized.delete_if do |key, _|
45
+ key.to_s =~ /^\d+$/
46
+ end
47
+ normalized
48
+ else
49
+ arg
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ end
@@ -6,8 +6,9 @@
6
6
  module TwitterCldr
7
7
  module Utils
8
8
 
9
- autoload :CodePoints, 'twitter_cldr/utils/code_points'
10
- autoload :YAML, 'twitter_cldr/utils/yaml'
9
+ autoload :CodePoints, 'twitter_cldr/utils/code_points'
10
+ autoload :Territories, 'twitter_cldr/utils/territories'
11
+ autoload :YAML, 'twitter_cldr/utils/yaml'
11
12
 
12
13
  class << self
13
14
 
@@ -70,4 +71,4 @@ module TwitterCldr
70
71
  end
71
72
  end
72
73
 
73
- require 'twitter_cldr/utils/interpolation'
74
+ require 'twitter_cldr/utils/interpolation'
@@ -4,5 +4,5 @@
4
4
  # http://www.apache.org/licenses/LICENSE-2.0
5
5
 
6
6
  module TwitterCldr
7
- VERSION = "2.0.2"
7
+ VERSION = "2.1.0"
8
8
  end
data/lib/twitter_cldr.rb CHANGED
@@ -23,6 +23,7 @@ module TwitterCldr
23
23
  autoload :Collation, 'twitter_cldr/collation'
24
24
  autoload :Localized, 'twitter_cldr/localized'
25
25
  autoload :Normalization, 'twitter_cldr/normalization'
26
+ autoload :Parsers, 'twitter_cldr/parsers'
26
27
  autoload :Resources, 'twitter_cldr/resources'
27
28
  autoload :Shared, 'twitter_cldr/shared'
28
29
  autoload :Tokenizers, 'twitter_cldr/tokenizers'
@@ -54,23 +55,53 @@ module TwitterCldr
54
55
 
55
56
  class << self
56
57
 
58
+ attr_writer :locale
59
+
57
60
  def resources
58
61
  @resources ||= TwitterCldr::Resources::Loader.new
59
62
  end
60
63
 
61
- def get_locale
62
- if defined?(FastGettext)
63
- locale = FastGettext.locale
64
- locale = DEFAULT_LOCALE if locale.to_s.empty?
65
- else
66
- locale = DEFAULT_LOCALE
64
+ def locale
65
+ locale = supported_locale?(@locale) ? @locale : find_fallback
66
+ locale = DEFAULT_LOCALE if locale.to_s.empty?
67
+ (supported_locale?(locale) ? locale : DEFAULT_LOCALE).to_sym
68
+ end
69
+
70
+ def with_locale(locale)
71
+ raise "Unsupported locale" unless supported_locale?(locale)
72
+
73
+ begin
74
+ old_locale = @locale
75
+ @locale = locale
76
+ result = yield
77
+ ensure
78
+ @locale = old_locale
79
+ result
67
80
  end
81
+ end
68
82
 
69
- (supported_locale?(locale) ? locale : DEFAULT_LOCALE).to_sym
83
+ def register_locale_fallback(proc_or_locale)
84
+ case proc_or_locale
85
+ when Symbol, String, Proc
86
+ locale_fallbacks << proc_or_locale
87
+ else
88
+ raise "A locale fallback must be of type String, Symbol, or Proc."
89
+ end
90
+ nil
91
+ end
92
+
93
+ def reset_locale_fallbacks
94
+ locale_fallbacks.clear
95
+ TwitterCldr.register_locale_fallback(lambda { I18n.locale if defined?(I18n) && I18n.respond_to?(:locale) })
96
+ TwitterCldr.register_locale_fallback(lambda { FastGettext.locale if defined?(FastGettext) && FastGettext.respond_to?(:locale) })
97
+ end
98
+
99
+ def locale_fallbacks
100
+ @locale_fallbacks ||= []
70
101
  end
71
102
 
72
103
  def convert_locale(locale)
73
- locale = locale.to_sym
104
+ locale = locale.to_sym if locale.respond_to?(:to_sym)
74
105
  TWITTER_LOCALE_MAP.fetch(locale, locale)
75
106
  end
76
107
 
@@ -86,8 +117,29 @@ module TwitterCldr
86
117
  def supported_locale?(locale)
87
118
  !!locale && supported_locales.include?(convert_locale(locale))
88
119
  end
120
+
121
+ protected
122
+
123
+ def find_fallback
124
+ locale_fallbacks.reverse_each do |fallback|
125
+ result = if fallback.is_a?(Proc)
126
+ begin
127
+ fallback.call
128
+ rescue
129
+ nil
130
+ end
131
+ else
132
+ fallback
133
+ end
134
+ return result if result
135
+ end
136
+ nil
137
+ end
138
+
89
139
  end
90
140
 
91
141
  end
92
142
 
143
+ TwitterCldr.reset_locale_fallbacks
144
+
93
145
  require 'twitter_cldr/core_ext'
@@ -0,0 +1,32 @@
1
+ ---
2
+ :collator_options: {}
3
+ :tailored_table: |-
4
+ 0063 030C; [2C04, 5, 5]
5
+ 0043 030C; [2C04, 5, 86]
6
+ 0063 0301; [2C05, 5, 5]
7
+ 0043 0301; [2C05, 5, 86]
8
+ 0064 007A 030C; [2E04, 5, 5]
9
+ 01C6; [2E04, 5, 6]
10
+ 0044 007A 030C; [2E04, 5, 47]
11
+ 01C5; [2E04, 5, 88]
12
+ 0044 005A 030C; [2E04, 5, 89]
13
+ 01C4; [2E04, 5, 8A]
14
+ 0111; [2E05, 5, 5]
15
+ 0110; [2E05, 5, 86]
16
+ 006C 006A; [3E04, 5, 5]
17
+ 01C9; [3E04, 5, 6]
18
+ 004C 006A; [3E04, 5, 47]
19
+ 01C8; [3E04, 5, 88]
20
+ 004C 004A; [3E04, 5, 89]
21
+ 01C7; [3E04, 5, 8A]
22
+ 006E 006A; [4204, 5, 5]
23
+ 01CC; [4204, 5, 6]
24
+ 004E 006A; [4204, 5, 47]
25
+ 01CB; [4204, 5, 88]
26
+ 004E 004A; [4204, 5, 89]
27
+ 01CA; [4204, 5, 8A]
28
+ 0073 030C; [4C04, 5, 5]
29
+ 0053 030C; [4C04, 5, 86]
30
+ 007A 030C; [5A04, 5, 5]
31
+ 005A 030C; [5A04, 5, 86]
32
+ :suppressed_contractions: ''