twitter_cldr_js 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/Gemfile +12 -0
  2. data/History.txt +3 -0
  3. data/LICENSE +177 -0
  4. data/NOTICE +120 -0
  5. data/README.md +161 -0
  6. data/Rakefile +66 -0
  7. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_af.js +887 -0
  8. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_ar.js +887 -0
  9. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_ca.js +887 -0
  10. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_cs.js +887 -0
  11. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_da.js +887 -0
  12. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_de.js +887 -0
  13. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_el.js +887 -0
  14. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_en.js +887 -0
  15. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_es.js +887 -0
  16. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_eu.js +887 -0
  17. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_fa.js +887 -0
  18. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_fi.js +887 -0
  19. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_fil.js +887 -0
  20. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_fr.js +887 -0
  21. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_he.js +887 -0
  22. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_hi.js +887 -0
  23. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_hu.js +887 -0
  24. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_id.js +887 -0
  25. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_it.js +887 -0
  26. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_ja.js +887 -0
  27. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_ko.js +887 -0
  28. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_msa.js +887 -0
  29. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_nl.js +887 -0
  30. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_no.js +887 -0
  31. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_pl.js +887 -0
  32. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_pt.js +887 -0
  33. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_ru.js +887 -0
  34. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_sv.js +887 -0
  35. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_th.js +887 -0
  36. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_tr.js +887 -0
  37. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_uk.js +887 -0
  38. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_ur.js +887 -0
  39. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_zh-cn.js +887 -0
  40. data/lib/assets/javascripts/twitter_cldr/twitter_cldr_zh-tw.js +887 -0
  41. data/lib/twitter_cldr/js/compiler.rb +49 -0
  42. data/lib/twitter_cldr/js/mustache/bundle.coffee +15 -0
  43. data/lib/twitter_cldr/js/mustache/calendars/datetime.coffee +240 -0
  44. data/lib/twitter_cldr/js/mustache/calendars/timespan.coffee +52 -0
  45. data/lib/twitter_cldr/js/mustache/numbers/numbers.coffee +179 -0
  46. data/lib/twitter_cldr/js/mustache/plurals/rules.coffee +14 -0
  47. data/lib/twitter_cldr/js/mustache/shared/currencies.coffee +27 -0
  48. data/lib/twitter_cldr/js/renderers/base.rb +18 -0
  49. data/lib/twitter_cldr/js/renderers/bundle.rb +18 -0
  50. data/lib/twitter_cldr/js/renderers/calendars/datetime_renderer.rb +34 -0
  51. data/lib/twitter_cldr/js/renderers/calendars/timespan_renderer.rb +39 -0
  52. data/lib/twitter_cldr/js/renderers/numbers/numbers_renderer.rb +31 -0
  53. data/lib/twitter_cldr/js/renderers/plurals/rules/plural_rules_compiler.rb +93 -0
  54. data/lib/twitter_cldr/js/renderers/plurals/rules/plural_rules_renderer.rb +26 -0
  55. data/lib/twitter_cldr/js/renderers/shared/currencies_renderer.rb +23 -0
  56. data/lib/twitter_cldr/js/renderers.rb +31 -0
  57. data/lib/twitter_cldr/js/tasks/tasks.rake +14 -0
  58. data/lib/twitter_cldr/js/tasks/tasks.rb +88 -0
  59. data/lib/twitter_cldr/js/version.rb +10 -0
  60. data/lib/twitter_cldr/js.rb +31 -0
  61. data/spec/js/calendars/datetime.spec.js +418 -0
  62. data/spec/js/calendars/timespan.spec.js +91 -0
  63. data/spec/js/numbers/currency.spec.js +34 -0
  64. data/spec/js/numbers/decimal.spec.js +24 -0
  65. data/spec/js/numbers/helpers/fraction.spec.js +23 -0
  66. data/spec/js/numbers/helpers/integer.spec.js +100 -0
  67. data/spec/js/numbers/number.spec.js +70 -0
  68. data/spec/js/numbers/percent.spec.js +22 -0
  69. data/spec/js/plurals/plural_rules.spec.js +28 -0
  70. data/spec/ruby/renderers/plurals/plural_rules_compiler_spec.rb +56 -0
  71. data/spec/ruby/spec_helper.rb +11 -0
  72. data/twitter_cldr_js.gemspec +34 -0
  73. metadata +224 -0
@@ -0,0 +1,49 @@
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 Js
8
+ class Compiler
9
+ attr_reader :locales
10
+
11
+ def initialize(options = {})
12
+ @locales = options[:locales] || TwitterCldr.supported_locales
13
+ @features = options[:features] || renderers.keys
14
+ end
15
+
16
+ def compile_each(options = {})
17
+ options[:minify] = true unless options.include?(:minify)
18
+
19
+ @locales.each do |locale|
20
+ contents = ""
21
+
22
+ @features.each do |feature|
23
+ renderer_const = renderers[feature]
24
+ contents << renderer_const.new(:locale => locale).render if renderer_const
25
+ end
26
+
27
+ bundle = TwitterCldr::Js::Renderers::Bundle.new
28
+ bundle[:contents] = contents
29
+ result = CoffeeScript.compile(bundle.render, :bare => true)
30
+ result = Uglifier.compile(result) if options[:minify]
31
+
32
+ yield result, TwitterCldr.twitter_locale(locale)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def renderers
39
+ @renderers ||= {
40
+ :plural_rules => TwitterCldr::Js::Renderers::PluralRules::PluralRulesRenderer,
41
+ :timespan => TwitterCldr::Js::Renderers::Calendars::TimespanRenderer,
42
+ :datetime => TwitterCldr::Js::Renderers::Calendars::DateTimeRenderer,
43
+ :numbers => TwitterCldr::Js::Renderers::Numbers::NumbersRenderer,
44
+ :currencies => TwitterCldr::Js::Renderers::Shared::CurrenciesRenderer
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ ###
2
+ // Copyright 2012 Twitter, Inc
3
+ // http://www.apache.org/licenses/LICENSE-2.0
4
+
5
+ // TwitterCLDR (JavaScript) v{{version}}
6
+ // Authors: Cameron Dutro [@camertron]
7
+ Kirill Lashuk [@KL_7]
8
+ portions by Sven Fuchs [@svenfuchs]
9
+ // Homepage: https://twitter.com
10
+ // Description: Provides date, time, number, and list formatting functionality for various Twitter-supported locales in Javascript.
11
+ ###
12
+
13
+ TwitterCldr = {}
14
+ {{{contents}}}
15
+ exports[key] = obj for key, obj of TwitterCldr if exports? # for node
@@ -0,0 +1,240 @@
1
+ # Copyright 2012 Twitter, Inc
2
+ # http://www.apache.org/licenses/LICENSE-2.0
3
+
4
+ TwitterCldr.DateTimeFormatter = class DateTimeFormatter
5
+ constructor: ->
6
+ @tokens = `{{{tokens}}}`
7
+ @calendar = `{{{calendar}}}`
8
+ @weekday_keys = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"]
9
+ @methods = # ignoring u, l, g, j, A
10
+ 'G': 'era'
11
+ 'y': 'year'
12
+ 'Y': 'year_of_week_of_year'
13
+ 'Q': 'quarter'
14
+ 'q': 'quarter_stand_alone'
15
+ 'M': 'month'
16
+ 'L': 'month_stand_alone'
17
+ 'w': 'week_of_year'
18
+ 'W': 'week_of_month'
19
+ 'd': 'day'
20
+ 'D': 'day_of_month'
21
+ 'F': 'day_of_week_in_month'
22
+ 'E': 'weekday'
23
+ 'e': 'weekday_local'
24
+ 'c': 'weekday_local_stand_alone'
25
+ 'a': 'period'
26
+ 'h': 'hour'
27
+ 'H': 'hour'
28
+ 'K': 'hour'
29
+ 'k': 'hour'
30
+ 'm': 'minute'
31
+ 's': 'second'
32
+ 'S': 'second_fraction'
33
+ 'z': 'timezone'
34
+ 'Z': 'timezone'
35
+ 'v': 'timezone_generic_non_location'
36
+ 'V': 'timezone_metazone'
37
+
38
+ format: (obj, options) ->
39
+ format_token = (token) =>
40
+ result = ""
41
+
42
+ switch token.type
43
+ when "pattern"
44
+ return this.result_for_token(token, obj)
45
+ else
46
+ if token.value.length > 0 && token.value[0] == "'" && token.value[token.value.length - 1] == "'"
47
+ return token.value.substring(1, token.value.length - 1)
48
+ else
49
+ return token.value
50
+
51
+ tokens = this.get_tokens(obj, options)
52
+ return (format_token(token) for token in tokens).join("")
53
+
54
+ get_tokens: (obj, options) ->
55
+ return @tokens[options.format || "date_time"][options.type || "default"]
56
+
57
+ result_for_token: (token, date) ->
58
+ return this[@methods[token.value[0]]](date, token.value, token.value.length)
59
+
60
+ era: (date, pattern, length) ->
61
+ switch length
62
+ when 1, 2, 3
63
+ choices = @calendar["eras"]["abbr"]
64
+ else
65
+ choices = @calendar["eras"]["name"]
66
+
67
+ index = if (date.getFullYear() < 0) then 0 else 1
68
+ return choices[index]
69
+
70
+ year: (date, pattern, length) ->
71
+ year = date.getFullYear().toString()
72
+
73
+ if length == 2
74
+ if year.length != 1
75
+ year = year.slice(-2)
76
+
77
+ if length > 1
78
+ year = ("0000" + year).slice(-length)
79
+
80
+ return year
81
+
82
+ year_of_week_of_year: (date, pattern, length) ->
83
+ throw 'not implemented'
84
+
85
+ day_of_week_in_month: (date, pattern, length) -> # e.g. 2nd Wed in July
86
+ throw 'not implemented'
87
+
88
+ quarter: (date, pattern, length) ->
89
+ # the bitwise OR is used here to truncate the decimal produced by the / 3
90
+ quarter = ((date.getMonth() / 3) | 0) + 1
91
+
92
+ switch length
93
+ when 1
94
+ return quarter.toString()
95
+ when 2
96
+ return ("0000" + quarter.toString()).slice(-length)
97
+ when 3
98
+ return @calendar.quarters.format.abbreviated[quarter]
99
+ when 4
100
+ return @calendar.quarters.format.wide[quarter]
101
+
102
+ quarter_stand_alone: (date, pattern, length) ->
103
+ quarter = (date.getMonth() - 1) / 3 + 1
104
+
105
+ switch length
106
+ when 1
107
+ return quarter.toString()
108
+ when 2
109
+ return ("0000" + quarter.toString()).slice(-length)
110
+ when 3
111
+ throw 'not yet implemented (requires cldr\'s "multiple inheritance")'
112
+ when 4
113
+ throw 'not yet implemented (requires cldr\'s "multiple inheritance")'
114
+ when 5
115
+ return @calendar.quarters['stand-alone'].narrow[quarter]
116
+
117
+ month: (date, pattern, length) ->
118
+ month_str = (date.getMonth() + 1).toString()
119
+
120
+ switch length
121
+ when 1
122
+ return month_str
123
+ when 2
124
+ return ("0000" + month_str).slice(-length)
125
+ when 3
126
+ return @calendar.months.format.abbreviated[month_str]
127
+ when 4
128
+ return @calendar.months.format.wide[month_str]
129
+ when 5
130
+ throw 'not yet implemented (requires cldr\'s "multiple inheritance")'
131
+ else
132
+ throw "Unknown date format"
133
+
134
+ month_stand_alone: (date, pattern, length) ->
135
+ switch length
136
+ when 1
137
+ return date.getMonth().toString()
138
+ when 2
139
+ return ("0000" + date.getMonth().toString()).slice(-length)
140
+ when 3
141
+ throw 'not yet implemented (requires cldr\'s "multiple inheritance")'
142
+ when 4
143
+ throw 'not yet implemented (requires cldr\'s "multiple inheritance")'
144
+ when 5
145
+ return @calendar.months['stand-alone'].narrow[date.month]
146
+ else
147
+ throw "Unknown date format"
148
+
149
+ day: (date, pattern, length) ->
150
+ switch length
151
+ when 1
152
+ return date.getDate().toString()
153
+ when 2
154
+ return ("0000" + date.getDate().toString()).slice(-length)
155
+
156
+ weekday: (date, pattern, length) ->
157
+ key = @weekday_keys[date.getDay()]
158
+
159
+ switch length
160
+ when 1, 2, 3
161
+ return @calendar.days.format.abbreviated[key]
162
+ when 4
163
+ return @calendar.days.format.wide[key]
164
+ when 5
165
+ return @calendar.days['stand-alone'].narrow[key]
166
+
167
+ weekday_local: (date, pattern, length) ->
168
+ # "Like E except adds a numeric value depending on the local starting day of the week"
169
+ # CLDR does not contain data as to which day is the first day of the week, so we will assume Monday (Ruby default)
170
+ switch length
171
+ when 1, 2
172
+ day = date.getDay()
173
+ return (if day == 0 then "7" else day.toString())
174
+ else
175
+ return this.weekday(date, pattern, length)
176
+
177
+ weekday_local_stand_alone: (date, pattern, length) ->
178
+ switch length
179
+ when 1
180
+ return this.weekday_local(date, pattern, length)
181
+ else
182
+ return this.weekday(date, pattern, length)
183
+
184
+ period: (time, pattern, length) ->
185
+ if time.getHours() > 11
186
+ return @calendar.periods.format.wide["pm"]
187
+ else
188
+ return @calendar.periods.format.wide["am"]
189
+
190
+ hour: (time, pattern, length) ->
191
+ hour = time.getHours()
192
+
193
+ switch pattern[0]
194
+ when 'h'
195
+ if hour > 12
196
+ hour = hour - 12
197
+ else if hour == 0
198
+ hour = 12
199
+ when 'K'
200
+ if hour > 11
201
+ hour = hour - 12
202
+ when 'k'
203
+ if hour == 0
204
+ hour = 24
205
+
206
+ if length == 1
207
+ return hour.toString()
208
+ else
209
+ return ("000000" + hour.toString()).slice(-length)
210
+
211
+ minute: (time, pattern, length) ->
212
+ if length == 1
213
+ return time.getMinutes().toString()
214
+ else
215
+ return ("000000" + time.getMinutes().toString()).slice(-length)
216
+
217
+ second: (time, pattern, length) ->
218
+ if length == 1
219
+ return time.getSeconds().toString()
220
+ else
221
+ return ("000000" + time.getSeconds().toString()).slice(-length)
222
+
223
+ second_fraction: (time, pattern, length) ->
224
+ if length > 6
225
+ throw 'can not use the S format with more than 6 digits'
226
+
227
+ return ("000000" + Math.round(Math.pow(time.getMilliseconds() * 100.0, 6 - length)).toString()).slice(-length)
228
+
229
+ timezone: (time, pattern, length) ->
230
+ hours = ("00" + (time.getTimezoneOffset() / 60).toString()).slice(-2)
231
+ minutes = ("00" + (time.getTimezoneOffset() % 60).toString()).slice(-2)
232
+
233
+ switch length
234
+ when 1, 2, 3
235
+ return "-" + hours + ":" + minutes
236
+ else
237
+ return "UTC -" + hours + ":" + minutes
238
+
239
+ timezone_generic_non_location: (time, pattern, length) ->
240
+ throw 'not yet implemented (requires timezone translation data")'
@@ -0,0 +1,52 @@
1
+ # Copyright 2012 Twitter, Inc
2
+ # http://www.apache.org/licenses/LICENSE-2.0
3
+
4
+ TwitterCldr.TimespanFormatter = class TimespanFormatter
5
+ constructor: ->
6
+ @default_type = "default"
7
+ @tokens = `{{{tokens}}}`
8
+ @time_in_seconds = {
9
+ "second": 1,
10
+ "minute": 60,
11
+ "hour": 3600,
12
+ "day": 86400,
13
+ "week": 604800,
14
+ "month": 2629743.83,
15
+ "year": 31556926
16
+ }
17
+
18
+ format: (seconds, options = {}) ->
19
+ options["direction"] ||= (if seconds < 0 then "ago" else "until")
20
+ options["unit"] = this.calculate_unit(Math.abs(seconds)) if options["unit"] is null or options["unit"] is undefined
21
+ options["type"] ||= @default_type
22
+ options["number"] = this.calculate_time(Math.abs(seconds), options["unit"])
23
+ number = this.calculate_time(Math.abs(seconds), options["unit"])
24
+ options["rule"] = TwitterCldr.PluralRules.rule_for(number)
25
+
26
+ strings = (token.value for token in @tokens[options["direction"]][options["unit"]][options["type"]][options["rule"]])
27
+ strings.join("").replace(/\{[0-9]\}/, number.toString())
28
+
29
+ calculate_unit: (seconds) ->
30
+ if seconds < 30
31
+ "second"
32
+ else if seconds < 2670
33
+ "minute"
34
+ else if seconds < 86369
35
+ "hour"
36
+ else if seconds < 604800
37
+ "day"
38
+ else if seconds < 2591969
39
+ "week"
40
+ else if seconds < 31556926
41
+ "month"
42
+ else
43
+ "year"
44
+
45
+ # 0 <-> 29 secs # => seconds
46
+ # 30 secs <-> 44 mins, 29 secs # => minutes
47
+ # 44 mins, 30 secs <-> 23 hrs, 59 mins, 29 secs # => hours
48
+ # 23 hrs, 59 mins, 29 secs <-> 29 days, 23 hrs, 59 mins, 29 secs # => days
49
+ # 29 days, 23 hrs, 59 mins, 29 secs <-> 1 yr minus 1 sec # => months
50
+ # 1 yr <-> max time or date # => years
51
+ calculate_time: (seconds, unit) ->
52
+ Math.round(seconds / @time_in_seconds[unit])
@@ -0,0 +1,179 @@
1
+ # Copyright 2012 Twitter, Inc
2
+ # http://www.apache.org/licenses/LICENSE-2.0
3
+
4
+ TwitterCldr.NumberFormatter = class NumberFormatter
5
+ constructor: ->
6
+ @all_tokens = `{{{tokens}}}`
7
+ @tokens = []
8
+ @symbols = `{{{symbols}}}`
9
+
10
+ @default_symbols =
11
+ 'group': ','
12
+ 'decimal': '.'
13
+ 'plus_sign': '+'
14
+ 'minus_sign': '-'
15
+
16
+ format: (number, options = {}) ->
17
+ opts = this.default_format_options_for(number)
18
+
19
+ for key, val of options
20
+ opts[key] = if options[key]? then options[key] else opts[key]
21
+
22
+ [prefix, suffix, integer_format, fraction_format] = this.partition_tokens(this.get_tokens(number, opts))
23
+ [int, fraction] = this.parse_number(number, opts)
24
+ result = integer_format.apply(parseFloat(int), opts)
25
+ result += fraction_format.apply(fraction, opts) if fraction
26
+ sign = if number < 0 && prefix != "-" then @symbols.minus_sign || @default_symbols.minus_sign else ""
27
+ "#{prefix}#{result}#{suffix}"
28
+
29
+ partition_tokens: (tokens) ->
30
+ [tokens[0] || "",
31
+ tokens[2] || "",
32
+ new IntegerHelper(tokens[1], @symbols),
33
+ new FractionHelper(tokens[1], @symbols)]
34
+
35
+ parse_number: (number, options = {}) ->
36
+ if options.precision?
37
+ precision = options.precision
38
+ else
39
+ precision = this.precision_from(number)
40
+
41
+ number = this.round_to(number, precision)
42
+ Math.abs(number).toFixed(precision).split(".")
43
+
44
+ precision_from: (num) ->
45
+ parts = num.toString().split(".")
46
+ if parts.length == 2 then parts[1].length else 0
47
+
48
+ round_to: (number, precision) ->
49
+ factor = Math.pow(10, precision)
50
+ Math.round(number * factor) / factor
51
+
52
+ get_tokens: ->
53
+ throw "get_tokens() not implemented - use a derived class like PercentFormatter."
54
+
55
+ TwitterCldr.PercentFormatter = class PercentFormatter extends NumberFormatter
56
+ constructor: (options = {}) ->
57
+ @default_percent_sign = "%"
58
+ super
59
+
60
+ format: (number, options = {}) ->
61
+ super(number, options).replace('¤', @symbols.percent_sign || @default_percent_sign)
62
+
63
+ default_format_options_for: (number) ->
64
+ precision: 0
65
+
66
+ get_tokens: (number, options) ->
67
+ if number < 0 then @all_tokens.percent.negative else @all_tokens.percent.positive
68
+
69
+ TwitterCldr.DecimalFormatter = class DecimalFormatter extends NumberFormatter
70
+ format: (number, options = {}) ->
71
+ try
72
+ super(number, options)
73
+ catch error
74
+ number
75
+
76
+ default_format_options_for: (number) ->
77
+ precision: this.precision_from(number)
78
+
79
+ get_tokens: (number, options = {}) ->
80
+ if number < 0 then @all_tokens.decimal.negative else @all_tokens.decimal.positive
81
+
82
+ TwitterCldr.CurrencyFormatter = class CurrencyFormatter extends NumberFormatter
83
+ constructor: (options = {}) ->
84
+ @default_currency_symbol = "$"
85
+ @default_precision = 2
86
+ super
87
+
88
+ format: (number, options = {}) ->
89
+ if options.currency
90
+ if TwitterCldr.Currencies?
91
+ currency = TwitterCldr.Currencies.for_code(options.currency)
92
+ currency ||= TwitterCldr.Currencies.for_country(options.currency)
93
+ currency ||= symbol: options.currency
94
+ else
95
+ currency = symbol: options.currency
96
+ else
97
+ currency = symbol: @default_currency_symbol
98
+
99
+ super(number, options).replace('¤', currency.symbol)
100
+
101
+ default_format_options_for: (number) ->
102
+ precision = this.precision_from(number)
103
+ if precision == 0 then precision = @default_precision
104
+ precision: precision
105
+
106
+ get_tokens: (number, options = {}) ->
107
+ if number < 0 then @all_tokens.currency.negative else @all_tokens.currency.positive
108
+
109
+ TwitterCldr.NumberFormatter.BaseHelper = class BaseHelper
110
+ interpolate: (string, value, orientation = "right") ->
111
+ value = value.toString()
112
+ length = value.length
113
+ start = if orientation == "left" then 0 else -length
114
+ string = (("#" for i in [0...length]).join("") + string).slice(-length) if string.length < length
115
+
116
+ if start < 0
117
+ string = string[0...(start + string.length)] + value
118
+ else
119
+ string = string[0...start] + value + string[(length)..-1]
120
+
121
+ string.replace(/#/g, "")
122
+
123
+ TwitterCldr.NumberFormatter.IntegerHelper = class IntegerHelper extends BaseHelper
124
+ constructor: (token, symbols = {}) ->
125
+ format = token.split('.')[0]
126
+ @format = this.prepare_format(format, symbols)
127
+ @groups = this.parse_groups(format)
128
+ @separator = symbols.group || ','
129
+
130
+ apply: (number, options = {}) ->
131
+ this.format_groups(this.interpolate(@format, parseInt(number)))
132
+
133
+ format_groups: (string) ->
134
+ return string if @groups.length == 0
135
+ tokens = []
136
+
137
+ cur_token = this.chop_group(string, @groups[0])
138
+ tokens.push(cur_token)
139
+ string = string[0...(string.length - cur_token.length)] if cur_token
140
+
141
+ while string.length > @groups[@groups.length - 1]
142
+ cur_token = this.chop_group(string, @groups[@groups.length - 1])
143
+ tokens.push(cur_token)
144
+ string = string[0...(string.length - cur_token.length)] if cur_token
145
+
146
+ tokens.push(string)
147
+ (token for token in tokens when token != null).reverse().join(@separator)
148
+
149
+ parse_groups: (format) ->
150
+ return [] unless index = format.lastIndexOf(',')
151
+ rest = format[0...index]
152
+ widths = [format.length - index - 1]
153
+ widths.push(rest.length - rest.lastIndexOf(',') - 1) if rest.lastIndexOf(',') > -1
154
+ widths = (width for width in widths when width != null) # compact
155
+ widths.reverse() # uniq
156
+ (widths[index] for index in [0...widths.length] when widths.indexOf(widths[index], index + 1) == -1).reverse()
157
+
158
+ chop_group: (string, size) ->
159
+ if string.length > size then string[-size..-1] else null
160
+
161
+ prepare_format: (format, symbols) ->
162
+ format.replace(",", "").replace("+", symbols.plus_sign).replace("-", symbols.minus_sign)
163
+
164
+ TwitterCldr.NumberFormatter.FractionHelper = class FractionHelper extends BaseHelper
165
+ constructor: (token, symbols = {}) ->
166
+ @format = if token then token.split('.').pop() else ""
167
+ @decimal = symbols.decimal || "."
168
+ @precision = @format.length
169
+
170
+ apply: (fraction, options = {}) ->
171
+ precision = if options.precision? then options.precision else @precision
172
+ if precision > 0
173
+ @decimal + this.interpolate(this.format_for(options), fraction, "left")
174
+ else
175
+ ""
176
+
177
+ format_for: (options) ->
178
+ precision = if options.precision? then options.precision else @precision
179
+ if precision then ("0" for i in [0...precision]).join("") else @format
@@ -0,0 +1,14 @@
1
+ # Copyright 2012 Twitter, Inc
2
+ # http://www.apache.org/licenses/LICENSE-2.0
3
+
4
+ TwitterCldr.PluralRules = class PluralRules
5
+ @rules = `{{{rules}}}`
6
+
7
+ @all: ->
8
+ return @rules.keys
9
+
10
+ @rule_for: (number) ->
11
+ try
12
+ return @rules.rule(number)
13
+ catch error
14
+ return "other"
@@ -0,0 +1,27 @@
1
+ # Copyright 2012 Twitter, Inc
2
+ # http://www.apache.org/licenses/LICENSE-2.0
3
+
4
+ TwitterCldr.Currencies = class Currencies
5
+ @currencies = `{{{currencies}}}`
6
+
7
+ @countries: ->
8
+ @names ||= (country_name for country_name, data of @currencies)
9
+
10
+ @currency_codes: ->
11
+ @codes ||= (data.code for country_name, data of @currencies)
12
+
13
+ @for_country: (country_name) ->
14
+ @currencies[country_name]
15
+
16
+ @for_code: (currency_code) ->
17
+ final = null
18
+ for country_name, data of @currencies
19
+ if data.code == currency_code
20
+ final =
21
+ country: country_name
22
+ code: data.code
23
+ symbol: data.symbol
24
+ currency: data.currency
25
+ break
26
+
27
+ final
@@ -0,0 +1,18 @@
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 Js
8
+ module Renderers
9
+ class Base < Mustache
10
+
11
+ def initialize(options = {})
12
+ @locale = options[:locale]
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
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 Js
8
+ module Renderers
9
+ class Bundle < Mustache
10
+ self.template_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "mustache/bundle.coffee"))
11
+
12
+ def version
13
+ TwitterCldr::VERSION
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
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 Js
8
+ module Renderers
9
+ module Calendars
10
+ class DateTimeRenderer < TwitterCldr::Js::Renderers::Base
11
+ self.template_file = File.expand_path(File.join(File.dirname(__FILE__), "../..", "mustache/calendars/datetime.coffee"))
12
+
13
+ def tokens
14
+ tokens = {}
15
+ { :date_time => TwitterCldr::Tokenizers::DateTimeTokenizer,
16
+ :time => TwitterCldr::Tokenizers::TimeTokenizer,
17
+ :date => TwitterCldr::Tokenizers::DateTokenizer }.each_pair do |name, const|
18
+ tokenizer = const.new(:locale => @locale)
19
+ tokens[name] = const::VALID_TYPES.inject({}) do |ret, type|
20
+ ret[type] = tokenizer.tokens(:type => type).map(&:to_hash)
21
+ ret
22
+ end
23
+ end
24
+ tokens.to_json
25
+ end
26
+
27
+ def calendar
28
+ TwitterCldr::Tokenizers::DateTimeTokenizer.new(:locale => @locale).calendar.to_json
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: UTF-8
2
+
3
+ # Copyright 2012 Twitter, Inc
4
+ # http://www.apache.org/licenses/LICENSE-2.0
5
+
6
+ include TwitterCldr::Tokenizers
7
+ include TwitterCldr::Formatters
8
+
9
+ module TwitterCldr
10
+ module Js
11
+ module Renderers
12
+ module Calendars
13
+
14
+ class TimespanRenderer < TwitterCldr::Js::Renderers::Base
15
+ self.template_file = File.expand_path(File.join(File.dirname(__FILE__), "../..", "mustache/calendars/timespan.coffee"))
16
+
17
+ def tokens
18
+ tokenizer = TimespanTokenizer.new(:locale => @locale)
19
+ [:ago, :until, :none].inject({}) do |final, direction|
20
+ final[direction] = TimespanTokenizer::VALID_UNITS.inject({}) do |unit_hash, unit|
21
+ unit_hash[unit] = tokenizer.all_types_for(unit, direction).inject({}) do |type_hash, type|
22
+ type_hash[type] = Plurals::Rules.all_for(@locale).inject({}) do |rule_hash, rule|
23
+ rule_hash[rule] = tokenizer.tokens(:direction => direction, :unit => unit, :rule => rule, :type => type)
24
+ rule_hash
25
+ end
26
+ type_hash
27
+ end
28
+ unit_hash
29
+ end
30
+ final
31
+ end.to_json
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+ end