r18n-core 0.2.3 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README.rdoc +157 -35
  2. data/base/cs.yml +34 -0
  3. data/base/de.yml +24 -0
  4. data/base/en.yml +24 -0
  5. data/base/fr.yml +24 -0
  6. data/base/pl.yml +24 -0
  7. data/base/ru.yml +30 -0
  8. data/lib/r18n-core/filters.rb +245 -0
  9. data/lib/r18n-core/i18n.rb +57 -40
  10. data/lib/r18n-core/locale.rb +116 -19
  11. data/lib/r18n-core/translated.rb +186 -0
  12. data/lib/r18n-core/translation.rb +33 -73
  13. data/lib/r18n-core/unsupported_locale.rb +27 -9
  14. data/lib/r18n-core/utils.rb +49 -0
  15. data/lib/r18n-core/version.rb +1 -1
  16. data/lib/r18n-core.rb +3 -15
  17. data/locales/cs.rb +23 -0
  18. data/locales/cs.yml +26 -0
  19. data/locales/de.yml +3 -8
  20. data/locales/en-us.rb +8 -0
  21. data/locales/en-us.yml +9 -0
  22. data/locales/en.rb +26 -0
  23. data/locales/en.yml +3 -8
  24. data/locales/eo.yml +3 -8
  25. data/locales/fr.rb +14 -0
  26. data/locales/fr.yml +3 -8
  27. data/locales/kk.yml +3 -8
  28. data/locales/pl.yml +4 -11
  29. data/locales/ru.yml +3 -8
  30. data/spec/filters_spec.rb +167 -0
  31. data/spec/i18n_spec.rb +61 -16
  32. data/spec/locale_spec.rb +46 -19
  33. data/spec/locales/cs_spec.rb +22 -0
  34. data/spec/locales/en-us_spec.rb +14 -0
  35. data/spec/locales/en_spec.rb +14 -0
  36. data/spec/locales/fr_spec.rb +10 -0
  37. data/spec/locales/pl_spec.rb +17 -17
  38. data/spec/locales/ru_spec.rb +2 -2
  39. data/spec/r18n_spec.rb +7 -3
  40. data/spec/spec_helper.rb +2 -0
  41. data/spec/translated_spec.rb +108 -0
  42. data/spec/translation_spec.rb +24 -56
  43. data/spec/translations/extension/{no_TR.yml → no-tr.yml} +0 -0
  44. data/spec/translations/general/en.yml +15 -2
  45. data/spec/translations/general/{no_LC.yml → no-lc.yml} +0 -0
  46. metadata +46 -31
  47. data/locales/en_US.yml +0 -14
data/README.rdoc CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  R18n is a i18n tool to translate your Ruby application in several languages.
4
4
 
5
- Use <tt>merb_r18n</tt> to localize Merb Web application and
5
+ Use <tt>sinatra-r18n</tt> or teamon’s +merb_i18n+ to localize Web applications and
6
6
  <tt>r18n-desktop</tt> to localize desktop application.
7
7
 
8
8
  == Features
@@ -15,36 +15,14 @@ Use <tt>merb_r18n</tt> to localize Merb Web application and
15
15
  month and week days name and give other locale information.
16
16
  * It has translation for commons words, like “OK”, “Cancel”, etc.
17
17
  * It storage translation in rich YAML format. You can put procedures and
18
- pluralization (“1 comment”, “5 comments”) in your translation.
18
+ pluralization (“1 comment”, “5 comments”) or create you own filters.
19
19
  * It can translate Web and desktop applications.
20
20
 
21
21
  == Usage
22
22
 
23
- === Locale
24
- All supported locales are storage in R18n gem at +locales+ dir. If you want to
25
- add your locale, please write me to andrey@sitnik.ru.
26
-
27
- To get information about locale create R18n::Locale instance:
28
-
29
- locale = R18n::Locale.load('en')
30
-
31
- You can get from locale:
32
- * Locale title and RFC 3066 code:
33
-
34
- locale['title'] #=> "English"
35
- locale['code'] #=> "en"
36
-
37
- * Language direction (left to right, or right to left for Arabic and Hebrew):
38
-
39
- locale['direction'] #=> "ltr"
40
-
41
- * Week start day ("sunday" or "monday")
42
-
43
- locale['week']['start'] #=> "sunday"
44
-
45
23
  === Translation
46
24
  Translation files use YAML format and has name like en.yml (English) or
47
- en_US.yml (USA English dialect) with language/country code (RFC 3066).
25
+ en-us.yml (USA English dialect) with language/country code (RFC 3066).
48
26
 
49
27
  In translation you can use:
50
28
  * Strings
@@ -58,8 +36,9 @@ In translation you can use:
58
36
  0: No robots
59
37
  1: One robot
60
38
  n: %1 robots
61
- * Procedures
62
- sum: !!proc |x, y| x + y
39
+ * Filters
40
+ filtered: !!custom_type
41
+ This content will be processed by filter
63
42
 
64
43
  To get translated string use method with key name or square brackets [] for
65
44
  keys, which is same with Object methods (+class+, +inspect+, etc):
@@ -105,6 +84,77 @@ See <tt>base/</tt> in dir in gem.
105
84
  i18n.cancel #=> "Cancel"
106
85
  i18n.delete #=> "Delete"
107
86
 
87
+ === Filters
88
+ You can also add you own filter for translations: escape HTML entries, convert
89
+ from Markdown syntax, etc.
90
+
91
+ R18n::Filters.add('custom_type', :filter_name) do |content, config, replace|
92
+ content.gsub(' ', replace)
93
+ end
94
+ R18n::Filters.add('custom_type') do |content, config, replace|
95
+ content + '!'
96
+ end
97
+
98
+ i18n.filtered('_') #=> "This_content_will_be_processed_by_filter!"
99
+
100
+ You can also add global filters for all translated strings:
101
+
102
+ R18n::Filters.add(String, :capitalize_ruby) do |content, config|
103
+ content.gsub(/ruby/i) { |i| i.swapcase }
104
+ end
105
+
106
+ ==== HTML Escape
107
+ R18n contain 2 filters to escape HTML entries: by YAML type and global. If you
108
+ need to escape HTML in some translations, just set <tt>!!escape</tt> YAML type:
109
+
110
+ greater: !!escape
111
+ 1 < 2 is true
112
+
113
+ i18n.greater #=> "1 &lt; 2 is true"
114
+
115
+ If you develop web application and want to escape HTML in all translations, just
116
+ activate global escape filter:
117
+
118
+ R18n::Filters.on(:global_escape_html)
119
+
120
+ If you enable global HTML escape, you may use <tt>!!html</tt> YAML type to
121
+ disable escaping in some special value.
122
+
123
+ warning: !!html
124
+ <b>Warning</b>
125
+
126
+ R18n::Filters.on(:global_escape_html)
127
+ i18n.warning #=> "<b>Warning</b>"
128
+
129
+ ==== Markdown
130
+ To use Markdown in your translations you must install maruku gem:
131
+
132
+ hi: !!markdown
133
+ **Hi**, people!
134
+
135
+ i18n.hi #=> "<p><strong>Hi</strong>, people!</p>"
136
+
137
+
138
+ ==== Textile
139
+ To use Textile in your translations you must install RedCloth gem:
140
+
141
+ alarm: !!textile
142
+ It will delete _all_ users!
143
+
144
+ i18n.alarm #=> "<p>It will delete <em>all</em> users!</p>"
145
+
146
+ ==== Lambdas
147
+ You can use lambdas in your translations.
148
+
149
+ sum: !!proc |x, y| x + y
150
+
151
+ i18n.sum(1, 2) #=> 3
152
+
153
+ If it isn’t secure in your application (for example, user can change
154
+ translations), you can disable it:
155
+
156
+ R18n::Filters.off(:procedure)
157
+
108
158
  === Localization
109
159
  You can print number and float according to the rules of the user locale:
110
160
 
@@ -116,18 +166,90 @@ non-break thin spaces (for locale, which use it as digit separator).
116
166
  You can translate months and week days names in Time, Date and DateTime by
117
167
  +strftime+ method:
118
168
 
119
- i18n.l Time.now, "%B" #=> "September"
169
+ i18n.l Time.now, '%B' #=> "September"
170
+
171
+ R18n has some time formats for locales: <tt>:human</tt>, <tt>:full</tt> and
172
+ <tt>:standard</tt> (by default):
173
+
174
+ i18n.l Time.now, :human #=> "now"
175
+ i18n.l Time.now, :full #=> "August 9th, 2009 21:47"
176
+ i18n.l Time.now #=> "08/09/2009 21:41"
177
+ i18n.l Time.now.to_date #=> "08/09/2009"
178
+
179
+ === Model
180
+ You can add i18n support to any classes, including ORM models:
181
+
182
+ require 'r18n-core/translated'
183
+
184
+ class Product
185
+ include DataMapper::Resource
186
+ property :title_ru, String
187
+ property :title_en, String
188
+
189
+ include R18n::Translated
190
+ translations :title
191
+ end
192
+
193
+ # For example, user know only Russian
194
+
195
+ # Set value to English (default) title
196
+ product.title_en = "Anthrax"
197
+ product.title #=> "Anthrax"
198
+
199
+ # Set value to title on user locale (Russian)
200
+ product.title = "Сибирская язва"
201
+ product.title #=> "Сибирская язва"
202
+
203
+ product.title_en #=> "Anthrax"
204
+ product.title_ru #=> "Сибирская язва"
205
+
206
+ See R18n::Translated for documentation.
120
207
 
121
- R18n has some time formats for locales: <tt>:month</tt>, <tt>:time</tt>,
122
- <tt>:date</tt>, <tt>:short_data</tt>, <tt>:long_data</tt>, <tt>:datetime</tt>,
123
- <tt>:short_datetime</tt> and <tt>:long_datetime</tt>:
208
+ === Locale
209
+ All supported locales are storage in R18n gem at +locales+ dir. If you want to
210
+ add your locale, please write me to andrey@sitnik.ru.
124
211
 
125
- i18n.l Time.now, :date #=> "09/21/2008"
212
+ To get information about locale create R18n::Locale instance:
213
+
214
+ locale = R18n::Locale.load('en')
126
215
 
127
- By default +strftime+ will be use <tt>:datetime</tt> format for Time and
128
- DateTime and <tt>:date</tt> for Date:
216
+ You can get from locale:
217
+ * Locale title and RFC 3066 code:
218
+
219
+ locale.title #=> "English"
220
+ locale.code #=> "en"
221
+
222
+ * Language direction (left to right, or right to left for Arabic and Hebrew):
223
+
224
+ locale.ltr? #=> true
225
+
226
+ * Week start day ("sunday" or "monday"):
227
+
228
+ locale['week']['start'] #=> "sunday"
129
229
 
130
- i18n.l Time.now #=> "Sun Sep 21 19:50:04 GMT 2008"
230
+ == Add locale
231
+ If R18n hasn’t locale file for your language, please add it. It’s very simple:
232
+ * Create in locales/ file _code_.yml for your language and describe locale.
233
+ Just copy from another locale and change different values.
234
+ * If your language is dialect or base on another (as American English (en-US)
235
+ base on English (en)) write <tt>include: _base_locale_</tt> and similar
236
+ values can be deleted.
237
+ * If in your country people mostly know another language (like in exUSSR
238
+ countries people know Russian), write
239
+ <tt>sublocales: [_another_locale_, en]</tt>. Else write only:
240
+ <tt>sublocales: [en]</tt>. For dialect put base locale to +sublocales+ too.
241
+ * Create in base/ file _code_.yml for your language and translate base messages.
242
+ Just copy file from language, which you know, and rewrite values.
243
+ * If you language need some special logic (for example, different pluralization
244
+ or time formatters) you can change Locale class. Create in locales/ file
245
+ _code_.rb and write R18n::Locales::_Code_ class, which must extend
246
+ R18n::Locale.
247
+ * Push files by GitHub (http://github.com/ai/r18n) or just write e-mail with
248
+ this files to me (andrey@sitnik.ru).
249
+
250
+ _Code_ is RFC 3066 code for your language (for example, “en” for English and
251
+ “fr_CA” for Canadian French). You can send to my e-mail any questions (on
252
+ http://sitnik.ru you find another contact addresses).
131
253
 
132
254
  == License
133
255
  R18n is licensed under the GNU Lesser General Public License version 3.
data/base/cs.yml ADDED
@@ -0,0 +1,34 @@
1
+ ok: OK
2
+ save: Uložit
3
+ cancel: Zrušit
4
+ yes: Ano
5
+ no: Ne
6
+ exit: Konec
7
+ delete: Smazat
8
+
9
+ human_time:
10
+ after_days: !!pl
11
+ 1: za %1 den
12
+ 2: za %1 dny
13
+ n: za %1 dnů
14
+ tomorrow: zítra
15
+ after_hours: !!pl
16
+ 1: za %1 hodinu
17
+ 2: za %1 hodiny
18
+ n: za %1 hodin
19
+ after_minutes: !!pl
20
+ 1: za %1 minutu
21
+ 2: za %1 minuty
22
+ n: za %1 minut
23
+ now: teď
24
+ today: dnes
25
+ minutes_ago: !!pl
26
+ 1: před %1 minutou
27
+ n: před %1 minutami
28
+ hours_ago: !!pl
29
+ 1: před %1 hodinou
30
+ n: před %1 hodinami
31
+ yesterday: včera
32
+ days_ago: !!pl
33
+ 1: před %1 dnem
34
+ n: před %1 dny
data/base/de.yml CHANGED
@@ -5,3 +5,27 @@ yes: Ja
5
5
  no: Nein
6
6
  exit: Ausgang
7
7
  delete: Löschen
8
+
9
+ human_time:
10
+ after_days: !!pl
11
+ 1: nach %1 Tag
12
+ n: nach %1 Tagen
13
+ tomorrow: morgen
14
+ after_hours: !!pl
15
+ 1: nach %1 Stunde
16
+ n: nach %1 Stunden
17
+ after_minutes: !!pl
18
+ 1: nach %1 Minute
19
+ n: nach %1 Minuten
20
+ now: jetzt
21
+ today: heute
22
+ minutes_ago: !!pl
23
+ 1: %1 Minute vor
24
+ n: %1 Minuten vor
25
+ hours_ago: !!pl
26
+ 1: %1 Stunde vor
27
+ n: %1 Stunden vor
28
+ yesterday: gestern
29
+ days_ago: !!pl
30
+ 1: %1 Tag vor
31
+ n: %1 Tagen vor
data/base/en.yml CHANGED
@@ -5,3 +5,27 @@ yes: Yes
5
5
  no: No
6
6
  exit: Exit
7
7
  delete: Delete
8
+
9
+ human_time:
10
+ after_days: !!pl
11
+ 1: after %1 day
12
+ n: after %1 days
13
+ tomorrow: tomorrow
14
+ after_hours: !!pl
15
+ 1: after %1 hour
16
+ n: after %1 hours
17
+ after_minutes: !!pl
18
+ 1: after %1 minute
19
+ n: after %1 minutes
20
+ now: now
21
+ today: today
22
+ minutes_ago: !!pl
23
+ 1: %1 minute ago
24
+ n: %1 minutes ago
25
+ hours_ago: !!pl
26
+ 1: %1 hour ago
27
+ n: %1 hours ago
28
+ yesterday: yesterday
29
+ days_ago: !!pl
30
+ 1: %1 day ago
31
+ n: %1 days ago
data/base/fr.yml CHANGED
@@ -5,3 +5,27 @@ yes: Oui
5
5
  no: Non
6
6
  exit: Sortie
7
7
  delete: Supprimer
8
+
9
+ human_time:
10
+ after_days: !!pl
11
+ 1: dans une jour
12
+ n: dans %1 jours
13
+ tomorrow: demain
14
+ after_hours: !!pl
15
+ 1: dans une heure
16
+ n: dans %1 heures
17
+ after_minutes: !!pl
18
+ 1: dans une minute
19
+ n: dans %1 minutes
20
+ now: maintenant
21
+ today: "aujourd'hui"
22
+ minutes_ago: !!pl
23
+ 1: il ya une minute
24
+ n: il ya %1 minutes
25
+ hours_ago: !!pl
26
+ 1: il ya une heure
27
+ n: il ya %1 heures
28
+ yesterday: hier
29
+ days_ago: !!pl
30
+ 1: il ya une jour
31
+ n: il ya %1 jours
data/base/pl.yml CHANGED
@@ -5,3 +5,27 @@ yes: Tak
5
5
  no: Nie
6
6
  exit: Wyjście
7
7
  delete: Usuń
8
+
9
+ human_time:
10
+ after_days: !!pl
11
+ 1: po %1 dniu
12
+ n: po %1 dniach
13
+ tomorrow: jutro
14
+ after_hours: !!pl
15
+ 1: po %1 godzinie
16
+ n: po %1 godzinach
17
+ after_minutes: !!pl
18
+ 1: po %1 minucie
19
+ n: po %1 minutach
20
+ now: teraz
21
+ today: dzisiaj
22
+ minutes_ago: !!pl
23
+ 1: %1 minutę temu
24
+ n: %1 minut temu
25
+ hours_ago: !!pl
26
+ 1: %1 godzinę temu
27
+ n: %1 godzin temu
28
+ yesterday: wczoraj
29
+ days_ago: !!pl
30
+ 1: %1 dzień temu
31
+ n: %1 dni temu
data/base/ru.yml CHANGED
@@ -5,3 +5,33 @@ yes: Да
5
5
  no: Нет
6
6
  exit: Выход
7
7
  delete: Удалить
8
+
9
+ human_time:
10
+ after_days: !!pl
11
+ 1: через %1 день
12
+ 2: через %1 дня
13
+ n: через %1 дней
14
+ tomorrow: завтра
15
+ after_hours: !!pl
16
+ 1: через %1 час
17
+ 2: через %1 часа
18
+ n: через %1 часов
19
+ after_minutes: !!pl
20
+ 1: через %1 минуту
21
+ 2: через %1 минуты
22
+ n: через %1 минут
23
+ now: сейчас
24
+ today: сегодня
25
+ minutes_ago: !!pl
26
+ 1: %1 минуту назад
27
+ 2: %1 минуты назад
28
+ n: %1 минут назад
29
+ hours_ago: !!pl
30
+ 1: %1 час назад
31
+ 2: %1 часа назад
32
+ n: %1 часов назад
33
+ yesterday: вчера
34
+ days_ago: !!pl
35
+ 1: %1 день назад
36
+ 2: %1 дня назад
37
+ n: %1 дней назад
@@ -0,0 +1,245 @@
1
+ # encoding: utf-8
2
+ =begin
3
+ Filters for translations content.
4
+
5
+ Copyright (C) 2009 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ =end
20
+
21
+ require 'rubygems'
22
+
23
+ module R18n
24
+ # Filter is a way, to process translations: escape HTML entries, convert from
25
+ # Markdown syntax, etc.
26
+ #
27
+ # In translation file filtered content must be marked by YAML type:
28
+ #
29
+ # filtered: !!custom_type
30
+ # This content will be processed by filter
31
+ #
32
+ # Filter function will be receive filtered content as first argument, struct
33
+ # with filter config as second and filter parameters as next arguments.
34
+ #
35
+ # R18n::Filters.add('custom_type', :no_space) do |content, config, replace|
36
+ # content.gsub(' ', replace)
37
+ # end
38
+ # R18n::Filters.add('custom_type') do |content, config, replace|
39
+ # content + '!'
40
+ # end
41
+ #
42
+ # i18n.filtered('_') #=> "This_content_will_be_processed_by_filter!"
43
+ #
44
+ # Use String class as type to add global filter for all translated strings:
45
+ #
46
+ # R18n::Filters.add(String, :escape_html) do |content, config, params|
47
+ # escape_html(content)
48
+ # end
49
+ #
50
+ # Filter config contain two parameters: translation locale and path. But it is
51
+ # OpenStruct and you can add you own parameter to cross-filter communications:
52
+ #
53
+ # R18n::Filters.add(String, :hide_truth) do |content, config|
54
+ # return content if config.censorship_check
55
+ #
56
+ # if content.scan(CENSORSHIP_WORDS[config.locale]).empty?
57
+ # content
58
+ # else
59
+ # "Error in #{config.path}"
60
+ # end
61
+ # end
62
+ #
63
+ # R18n::Filters.add('passed', :show_lie) do |content, config|
64
+ # config.censorship_check = true
65
+ # content
66
+ # end
67
+ #
68
+ # You can disable, enabled and delete filters:
69
+ #
70
+ # R18n::Filters.off(:no_space))
71
+ # i18n.filtered('_') #=> "This content will be processed by filter!"
72
+ # R18n::Filters.on(:no_space)
73
+ # i18n.filtered('_') #=> "This_content_will_be_processed_by_filter!"
74
+ # R18n::Filters.delete(:no_space)
75
+ module Filters
76
+ Filter = Struct.new(:name, :type, :block, :enabled) do
77
+ def call(*params)
78
+ block.call(*params)
79
+ end
80
+
81
+ def enabled?
82
+ enabled
83
+ end
84
+ end
85
+
86
+ class << self
87
+ # Hash of filter names to Filters.
88
+ def defined
89
+ @defined ||= {}
90
+ end
91
+
92
+ # Hash of types to enabled Filters.
93
+ def enabled
94
+ @enabled ||= Hash.new([])
95
+ end
96
+
97
+ # Hash of types to all Filters.
98
+ def by_type
99
+ @by_type ||= Hash.new([])
100
+ end
101
+
102
+ # Process +translation+ by global filters and filters for special +type+.
103
+ def process(translation, locale, path, type, params)
104
+ case translation
105
+ when Numeric, NilClass, FalseClass, TrueClass, Symbol
106
+ else
107
+ translation = translation.clone
108
+ end
109
+ config = OpenStruct.new(:locale => locale, :path => path)
110
+
111
+ if type
112
+ filters = Filters.enabled[type]
113
+ filters.each { |f| translation = f.call(translation, config, *params)}
114
+ end
115
+
116
+ if translation.is_a? String
117
+ Filters.enabled[String].each do |f|
118
+ translation = f.call(translation, config, *params)
119
+ end
120
+ return TranslatedString.new(translation, locale, path)
121
+ else
122
+ translation
123
+ end
124
+ end
125
+
126
+ # Add new filter for +type+ with +name+ and return filter object. You
127
+ # can use String class as +type+ to add global filter for all translated
128
+ # string.
129
+ #
130
+ # Several filters for same type will be call consecutively, but you can
131
+ # set +position+ in call list.
132
+ #
133
+ # Filter content will be sent to +block+ as first argument, struct with
134
+ # config as second and filters parameters will be in next arguments.
135
+ def add(type, name = nil, position = nil, &block)
136
+ unless name
137
+ @last_auto_name ||= 0
138
+ begin
139
+ @last_auto_name += 1
140
+ name = @last_auto_name
141
+ end while defined.has_key? name
142
+ else
143
+ delete(name)
144
+ end
145
+
146
+ filter = Filter.new(name, type, block, true)
147
+ defined[name] = filter
148
+
149
+ unless enabled.has_key? type
150
+ enabled[type] = []
151
+ by_type[type] = []
152
+ end
153
+ if position
154
+ enabled[type].insert(position, filter)
155
+ by_type[type].insert(position, filter)
156
+ else
157
+ enabled[type] << filter
158
+ by_type[type] << defined[name]
159
+ end
160
+
161
+ filter
162
+ end
163
+
164
+ # Delete +filter+ by name or Filter object.
165
+ def delete(filter)
166
+ filter = defined[filter] unless filter.is_a? Filter
167
+ return unless filter
168
+
169
+ defined.delete(filter.name)
170
+ by_type[filter.type].delete(filter)
171
+ enabled[filter.type].delete(filter)
172
+ end
173
+
174
+ # Disable +filter+ by name or Filter object.
175
+ def off(filter)
176
+ filter = defined[filter] unless filter.is_a? Filter
177
+ return unless filter
178
+
179
+ filter.enabled = false
180
+ enabled[filter.type].delete(filter)
181
+ end
182
+
183
+ # Turn on disabled +filter+ by name or Filter object.
184
+ def on(filter)
185
+ filter = defined[filter] unless filter.is_a? Filter
186
+ return unless filter
187
+
188
+ filter.enabled = true
189
+ enabled[filter.type] = by_type[filter.type].reject { |i| !i.enabled? }
190
+ end
191
+ end
192
+ end
193
+
194
+ Filters.add('proc', :procedure) do |content, config, *params|
195
+ eval("proc { #{content} }").call(*params)
196
+ end
197
+
198
+ Filters.add('pl', :pluralization) do |content, config, param|
199
+ type = config.locale.pluralize(param)
200
+ type = 'n' if not content.include? type
201
+ content[type]
202
+ end
203
+
204
+ Filters.add(String, :variables) do |content, config, *params|
205
+ content = content.clone
206
+ params.each_with_index do |param, i|
207
+ if param.is_a? Float
208
+ param = config.locale.format_float(param)
209
+ elsif param.is_a? Integer
210
+ param = config.locale.format_integer(param)
211
+ end
212
+ content.gsub! "%#{i+1}", param.to_s
213
+ end
214
+ content
215
+ end
216
+
217
+ Filters.add('escape', :escape_html) do |content, config|
218
+ config.dont_escape_html = true
219
+ Utils.escape_html(content)
220
+ end
221
+
222
+ Filters.add('html', :dont_escape_html) do |content, config|
223
+ config.dont_escape_html = true
224
+ content
225
+ end
226
+
227
+ Filters.add(String, :global_escape_html) do |content, config|
228
+ if config.dont_escape_html
229
+ content
230
+ else
231
+ Utils.escape_html(content)
232
+ end
233
+ end
234
+ Filters.off(:global_escape_html)
235
+
236
+ Filters.add('markdown', :maruku) do |content, config|
237
+ require 'maruku'
238
+ ::Maruku.new(content).to_html
239
+ end
240
+
241
+ Filters.add('textile', :redcloth) do |content, config|
242
+ require 'redcloth'
243
+ ::RedCloth.new(content).to_html
244
+ end
245
+ end