r18n-core 0.4.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.yardopts +1 -1
  2. data/ChangeLog +21 -0
  3. data/LICENSE +2 -2
  4. data/README.md +456 -0
  5. data/Rakefile +2 -1
  6. data/base/gl.yml +31 -0
  7. data/base/it.yml +1 -1
  8. data/lib/r18n-core/filter_list.rb +157 -0
  9. data/lib/r18n-core/filters.rb +40 -36
  10. data/lib/r18n-core/i18n.rb +17 -9
  11. data/lib/r18n-core/locale.rb +5 -2
  12. data/lib/r18n-core/translated.rb +18 -15
  13. data/lib/r18n-core/translated_string.rb +14 -0
  14. data/lib/r18n-core/translation.rb +19 -20
  15. data/lib/r18n-core/untranslated.rb +8 -5
  16. data/lib/r18n-core/utils.rb +5 -1
  17. data/lib/r18n-core/version.rb +1 -1
  18. data/lib/r18n-core/yaml_loader.rb +2 -2
  19. data/lib/r18n-core.rb +60 -13
  20. data/locales/ca.rb +1 -0
  21. data/locales/cs.rb +0 -1
  22. data/locales/en-au.rb +0 -1
  23. data/locales/en-gb.rb +0 -1
  24. data/locales/en-us.rb +0 -1
  25. data/locales/en.rb +1 -1
  26. data/locales/fr.rb +1 -1
  27. data/locales/gl.rb +21 -0
  28. data/locales/hu.rb +1 -2
  29. data/locales/nb-no.rb +2 -3
  30. data/locales/nl.rb +4 -2
  31. data/locales/pt-br.rb +0 -1
  32. data/locales/pt.rb +0 -1
  33. data/locales/sv-se.rb +2 -3
  34. data/locales/th.rb +1 -1
  35. data/locales/tr.rb +2 -4
  36. data/locales/zh-cn.rb +7 -0
  37. data/locales/zh-tw.rb +7 -0
  38. data/r18n-core.gemspec +10 -10
  39. data/spec/filters_spec.rb +38 -7
  40. data/spec/i18n_spec.rb +15 -18
  41. data/spec/locale_spec.rb +19 -14
  42. data/spec/locales/cs_spec.rb +1 -1
  43. data/spec/locales/pl_spec.rb +1 -1
  44. data/spec/locales/ru_spec.rb +1 -1
  45. data/spec/locales/sk_spec.rb +1 -1
  46. data/spec/r18n_spec.rb +64 -22
  47. data/spec/spec_helper.rb +2 -3
  48. data/spec/translated_spec.rb +18 -4
  49. data/spec/translation_spec.rb +17 -6
  50. data/spec/translations/general/en.yml +1 -0
  51. data/spec/yaml_loader_spec.rb +10 -10
  52. metadata +163 -141
  53. data/Gemfile +0 -5
  54. data/Gemfile.lock +0 -35
  55. data/README.rdoc +0 -482
  56. data/spec/translations/empty/en.yml +0 -0
data/.yardopts CHANGED
@@ -1,4 +1,4 @@
1
1
  --charset utf-8
2
2
  -
3
- README.rdoc
3
+ README.md
4
4
  ChangeLog
data/ChangeLog CHANGED
@@ -1,3 +1,24 @@
1
+ == 1.0.0 (Bangkok)
2
+ * Add R18n.default_places.
3
+ * Rails SafeBuffer support.
4
+ * Allow in Rails app to put filters to app/i18n reload them in development.
5
+ * Move R18n::I18n.available_locales to R18n.available_locales.
6
+ * Rename _keys to translation_keys.
7
+ * Use Kramdown instead of Maruku for Markdown.
8
+ * Allow to use R18n for Rails without mailer.
9
+ * Allow to overwrite I18n object for models.
10
+ * Autoload R18n::Translated.
11
+ * Set default locale to R18n on Rails start to easy use in Rails console.
12
+ * Use env language in Rails console.
13
+ * Mark untranslated part as red in Rails console.
14
+ * Allow to temporary change locale by R18n.change.
15
+ * Add R18n.locale shortcut.
16
+ * Allow return from setter block locale code, instead of I18n object.
17
+ * Allow to set custom filters for I18n object.
18
+ * Add Galician locale (by Eduard Giménez).
19
+ * Add Traditional Chinese and Simplified Chinese (by Francis Chong).
20
+ * Fix Norsk locale (by Peter Haza).
21
+
1
22
  == 0.4.14 (üç)
2
23
  * Fix support for Ruby 1.9.3.
3
24
  * Added Turkish locale (by Ahmet Özkaya).
data/LICENSE CHANGED
@@ -10,7 +10,7 @@
10
10
  the terms and conditions of version 3 of the GNU General Public
11
11
  License, supplemented by the additional permissions listed below.
12
12
 
13
- 0. Additional Definitions.
13
+ 0. Additional Definitions.
14
14
 
15
15
  As used herein, "this License" refers to version 3 of the GNU Lesser
16
16
  General Public License, and the "GNU GPL" refers to version 3 of the GNU
@@ -111,7 +111,7 @@ the following:
111
111
  a copy of the Library already present on the user's computer
112
112
  system, and (b) will operate properly with a modified version
113
113
  of the Library that is interface-compatible with the Linked
114
- Version.
114
+ Version.
115
115
 
116
116
  e) Provide Installation Information, but only if you would otherwise
117
117
  be required to provide such information under section 6 of the
data/README.md ADDED
@@ -0,0 +1,456 @@
1
+ # R18n
2
+
3
+ R18n is an i18n tool to translate your Ruby application into several languages.
4
+
5
+ Use `r18n-rails` or `sinatra-r18n` to localize Web applications and
6
+ `r18n-desktop` to localize desktop application.
7
+
8
+ ## Features
9
+
10
+ * Nice Ruby-style syntax.
11
+ * Filters.
12
+ * Model Translation (or any Ruby object).
13
+ * Autodetect user locales.
14
+ * Flexible locales.
15
+ * Total flexibility.
16
+
17
+ See full features in [main README](https://github.com/ai/r18n/blob/master/README.md).
18
+
19
+ ## Usage
20
+
21
+ To add i18n support to your app, you can use the particular plugin for your
22
+ environment: `r18n-rails`, `sinatra-r18n` or `r18n-desktop`.
23
+
24
+ If you develop you own plugin or want to use only core gem, you will need to
25
+ set default translation places and current locale:
26
+
27
+ ```ruby
28
+ R18n.default_places = 'path/to/translations'
29
+ R18n.set('en')
30
+ ```
31
+
32
+ You can use `R18n.t` to get translations and `R18n.l` to localize times and
33
+ numbers. But more useful is to add helpers to fast access the R18n:
34
+
35
+ ```ruby
36
+ include R18n::Helpers
37
+
38
+ t.yes #=> "Yes"
39
+ l Time.now, :human #=> "now"
40
+
41
+ r18n.locale.code #=> "en"
42
+ ```
43
+
44
+ To set locale only for current thread use `R18n.thread_set`.
45
+
46
+ ### Translation
47
+
48
+ Translation files are in YAML format by default and have names like
49
+ `en.yml` (English) or `en-us.yml` (USA English dialect) with
50
+ language/country code (RFC 3066).
51
+
52
+ In your translation files you can use:
53
+
54
+ * Strings
55
+
56
+ ```yaml
57
+ robot: This is a robot
58
+ percent: "Percent sign (%)"
59
+ ```
60
+
61
+ * Numbers
62
+
63
+ ```yaml
64
+ number: 123
65
+ float: 12.45
66
+ ```
67
+
68
+ * Pluralizable messages
69
+
70
+ ```yaml
71
+ robots: !!pl
72
+ 0: No robots
73
+ 1: One robot
74
+ n: %1 robots
75
+ ```
76
+
77
+ * Filters
78
+
79
+ ```yaml
80
+ filtered: !!custom_type
81
+ This content will be processed by a filter
82
+ ```
83
+
84
+ To get the translated string use a method with the key name or square brackets
85
+ [] for keys, which is the same with Object methods (`class`, `inspect`, etc):
86
+
87
+ ```ruby
88
+ t.robot #=> "This is a robot"
89
+ t[:robot] #=> "This is a robot"
90
+ ```
91
+
92
+ Translation may be hierarchical:
93
+
94
+ ```ruby
95
+ t.post.add #=> "Add post"
96
+ t[:post][:add] #=> "Add post"
97
+ ```
98
+
99
+ If the locale isn’t found in the user’s requested locale, R18n will search for
100
+ it in sublocales or in another locale, which the user also can accept:
101
+
102
+ ```ruby
103
+ t.not.in.english #=> "В английском нет"
104
+ ```
105
+
106
+ The translated string has a `locale` method for determining its locale (Locale
107
+ instance or code string if locale is’t supported in R18n):
108
+
109
+ ```ruby
110
+ i18n.not.in.english.locale #=> Locale ru (Русский)
111
+ ```
112
+
113
+ You can include parameters in the translated string by specifying arguments:
114
+
115
+ ```yaml
116
+ name: My name is %1
117
+ ```
118
+
119
+ ```ruby
120
+ t.name('John') #=> "My name is John"
121
+ ```
122
+
123
+ Pluralizable messages get their item count from the first argument:
124
+
125
+ ```ruby
126
+ t.robots(0) #=> "No robots"
127
+ t.robots(1) #=> "One robot"
128
+ t.robots(50) #=> "50 robots"
129
+ ```
130
+
131
+ If there isn’t a pluralization for a particular number, translation will be use
132
+ `n`. If there isn’t a locale file for translation, it will use the English
133
+ pluralization rule (`0`, `1` and `n`).
134
+
135
+ You can check if the key has a translation:
136
+
137
+ ```ruby
138
+ t.post.add.translated? #=> true
139
+ t.not.exists.translated? #=> false
140
+ ```
141
+
142
+ You can set a default value for untranslated strings:
143
+
144
+ ```ruby
145
+ t.not.exists | 'default' #=> "default"
146
+ ```
147
+
148
+ You can query the translation keys:
149
+
150
+ ```ruby
151
+ t.counties.translation_keys.each do |county|
152
+ puts t.counties[county]
153
+ end
154
+ ```
155
+
156
+ R18n already has translations for common words for most built in locales.
157
+ See `base/` the source.
158
+
159
+ ```ruby
160
+ t.yes #=> "Yes"
161
+ t.cancel #=> "Cancel"
162
+ t.delete #=> "Delete"
163
+ ```
164
+
165
+ ### Filters
166
+
167
+ You can also add you own filters for translations: escape HTML entities, convert
168
+ from Markdown syntax, etc. Filters can be passive, only being processed when
169
+ loaded.
170
+
171
+ ```yaml
172
+ friendship: !!gender
173
+ f: She adds a friend
174
+ m: He adds a friend
175
+ ```
176
+
177
+ ```ruby
178
+ R18n::Filters.add('gender', :user_gender) do |content, config, user|
179
+ if user.female?
180
+ content['f']
181
+ else
182
+ content['m']
183
+ end
184
+ end
185
+
186
+ t.friendship(anne) #=> "She adds a friend"
187
+ ```
188
+
189
+ To create a filter you pass the following to `R18n::Filters.add`:
190
+
191
+ * Filter target. YAML type (`!!type`), `String` for all translations of
192
+ `R18n::Untranslated` for missing translations.
193
+ * Optional filter name, to disable, enable or delete it later by
194
+ `R18n::Filters.off`, `R18n::Filters.on` and
195
+ `R18n::Filters.delete`.
196
+ * Hash with options:
197
+ * `:passive => true` to filter translations only on load;
198
+ * `:position` within the list of current filters of this type
199
+ (by default a new filter will be inserted into last position).
200
+
201
+ The filter will receive at least two arguments:
202
+ * Translation (possibly already filtered by other filters for this type earlier
203
+ in the list).
204
+ * A Hash with translation `locale` and `path`.
205
+ * Parameters from translation request will be in the remaining arguments.
206
+
207
+ #### HTML Escape
208
+
209
+ R18n contains 2 filters to escape HTML entities: by YAML type and global. If you
210
+ need to escape HTML in some translations, just set `!!escape` YAML type:
211
+
212
+ ```yaml
213
+ greater: !!escape
214
+ 1 < 2 is true
215
+ ```
216
+
217
+ ```ruby
218
+ t.greater #=> "1 &lt; 2 is true"
219
+ ```
220
+
221
+ If you develop web application and want to escape HTML in all translations, just
222
+ activate the global escape filter:
223
+
224
+ ```ruby
225
+ R18n::Filters.on(:global_escape_html)
226
+ ```
227
+
228
+ If you enable global HTML escape, you may still use `!!html` YAML type to
229
+ disable escaping on some values:
230
+
231
+ ```yaml
232
+ warning: !!html
233
+ <b>Warning</b>
234
+ ```
235
+
236
+ ```ruby
237
+ R18n::Filters.on(:global_escape_html)
238
+ t.warning #=> "<b>Warning</b>"
239
+ ```
240
+
241
+ #### Markdown
242
+
243
+ To use Markdown in your translations you must install the Kramdown gem:
244
+
245
+ ```yaml
246
+ hi: !!markdown
247
+ **Hi**, people!
248
+ ```
249
+
250
+ ```ruby
251
+ t.hi #=> "<p><strong>Hi</strong>, people!</p>"
252
+ ```
253
+
254
+ #### Textile
255
+
256
+ To use Textile in your translations you must install the RedCloth gem:
257
+
258
+ ```yaml
259
+ alarm: !!textile
260
+ It will delete _all_ users!
261
+ ```
262
+
263
+ ```ruby
264
+ t.alarm #=> "<p>It will delete <em>all</em> users!</p>"
265
+ ```
266
+
267
+ #### Lambdas
268
+
269
+ You can use lambdas in your translations.
270
+
271
+ ```yaml
272
+ sum: !!proc |x, y| x + y
273
+ ```
274
+
275
+ ```ruby
276
+ t.sum(1, 2) #=> 3
277
+ ```
278
+
279
+ If this is unsafe in your application (for example, user can change
280
+ translations), you can disable it:
281
+
282
+ ```ruby
283
+ R18n::Filters.off(:procedure)
284
+ ```
285
+
286
+ ### Localization
287
+
288
+ You can print numbers and floats according to the rules of the user locale:
289
+
290
+ ```ruby
291
+ l -12000.5 #=> "−12,000.5"
292
+ ```
293
+
294
+ Number and float formatters will also put real typographic minus and put
295
+ non-breakable thin spaces (for locale, which use it as digit separator).
296
+
297
+ You can translate months and week day names in Time, Date and DateTime by the
298
+ `strftime` method:
299
+
300
+ ```ruby
301
+ l Time.now, '%B' #=> "September"
302
+ ```
303
+
304
+ R18n has some built-in time formats for locales: `:human`, `:full` and
305
+ `:standard` (the default):
306
+
307
+ ```ruby
308
+ l Time.now, :human #=> "now"
309
+ l Time.now, :full #=> "August 9th, 2009 21:47"
310
+ l Time.now #=> "08/09/2009 21:41"
311
+ l Time.now.to_date #=> "08/09/2009"
312
+ ```
313
+
314
+ ### Model
315
+
316
+ You can add i18n support to any classes, including ORM models (ActiveRecord,
317
+ DataMapper, MongoMapper, Mongoid or others):
318
+
319
+ ```ruby
320
+ class Product
321
+ include DataMapper::Resource
322
+ property :title_ru, String
323
+ property :title_en, String
324
+
325
+ include R18n::Translated
326
+ translations :title
327
+ end
328
+
329
+ # For example, user only knows Russian
330
+
331
+ # Set English (default) title
332
+ product.title_en = "Anthrax"
333
+ product.title #=> "Anthrax"
334
+
335
+ # Set value for user locale (Russian)
336
+ product.title = "Сибирская язва"
337
+ product.title #=> "Сибирская язва"
338
+
339
+ product.title_en #=> "Anthrax"
340
+ product.title_ru #=> "Сибирская язва"
341
+ ```
342
+
343
+ See `R18n::Translated` for documentation.
344
+
345
+ ### Locale
346
+
347
+ All supported locales are stored in R18n gem in `locales` directory. If you want
348
+ to add your locale, please fork this project and send a pull request or email me
349
+ at <andrey@sitnik.ru>.
350
+
351
+ To get information about a locale create an `R18n::Locale` instance:
352
+
353
+ ```ruby
354
+ locale = R18n.locale('en')
355
+ ```
356
+
357
+ You can then get the following from the locale:
358
+
359
+ * Locale title and RFC 3066 code:
360
+
361
+ ```ruby
362
+ locale.title #=> "English"
363
+ locale.code #=> "en"
364
+ ```
365
+
366
+ * Language direction (left to right, or right to left for Arabic and Hebrew):
367
+
368
+ ```ruby
369
+ locale.ltr? #=> true
370
+ ```
371
+
372
+ * Week start day (`:monday` or `:sunday`):
373
+
374
+ ```ruby
375
+ locale.week_start #=> :sunday
376
+ ```
377
+
378
+ ### Loaders
379
+
380
+ You can load translations from anywhere, not just from YAML files. To load
381
+ translation you must create loader class with 2 methods:
382
+
383
+ * `available` – return array of locales of available translations;
384
+ * `load(locale)` – return Hash of translation.
385
+
386
+ Pass its instance to `R18n.default_places` or `R18n.set(locales, loaders)`
387
+
388
+ ```ruby
389
+ R18n.default_places = MyLoader.new(loader_param)
390
+ R18n.set('en')
391
+ ```
392
+
393
+ You can set your default loader and pass it to `R18n.set` as the only
394
+ constructor argument:
395
+
396
+ ```ruby
397
+ R18n.default_loader = MyLoader
398
+ R18n.default_places = loader_param
399
+
400
+ R18n.set('en')
401
+ R18n.set('en', different_loader_param)
402
+ ```
403
+
404
+ If you want to load a translation with some type for filter, use
405
+ `R18n::Typed` struct:
406
+
407
+ ```ruby
408
+ # Loader will return something like:
409
+ { 'users' => R18n::Typed.new('pl', { 1 => '1 user', 'n' => '%1 users' }) }
410
+
411
+ # To use pluralization filter ("pl" type):
412
+ t.users(5) #=> "5 users"
413
+ ```
414
+
415
+ ### Extension Translations
416
+
417
+ For r18n plugin you can add loaders with translations, which will be used with
418
+ application translations. For example, DB plugin may place translations for
419
+ error messages in extension directory. R18n contain translations for base words
420
+ as extension directory too.
421
+
422
+ ```ruby
423
+ R18n.extension_places << R18n::Loader::YAML.new('./error_messages/')
424
+ ```
425
+
426
+ ## Add Locale
427
+
428
+ If R18n hasn’t got locale file for your language, please add it. It’s very
429
+ simple:
430
+
431
+ * Create the file <tt><i>code</i>.rb</tt> in the `locales/` directory for your
432
+ language and describe locale. Just copy from another locale and change the
433
+ values.
434
+ * If your country has alternate languages (for example, in exUSSR countries
435
+ most people also know Russian), add
436
+ <tt>sublocales %w{<i>another_locale</i> en}</tt>.
437
+ * Create in `base/` file <tt><i>code</i>.yml</tt> for your language and
438
+ translate the base messages. Just copy file from language, which you know,
439
+ and rewrite values.
440
+ * If your language needs some special logic (for example, different
441
+ pluralization or time formatters) you can extend `R18n::Locale` class methods.
442
+ * Send a pull request via GitHub <http://github.com/ai/r18n> or just write email
443
+ with the files to me <andrey@sitnik.ru>.
444
+
445
+ *Code* is RFC 3066 code for your language (for example, “en” for English and
446
+ “fr-CA” for Canadian French). Email me with any questions you may have, you will
447
+ find other contact addresses at http://sitnik.ru.
448
+
449
+ ## License
450
+
451
+ R18n is licensed under the GNU Lesser General Public License version 3.
452
+ See the LICENSE file or http://www.gnu.org/licenses/lgpl.html.
453
+
454
+ ## Author
455
+
456
+ Andrey “A.I.” Sitnik <andrey@sitnik.ru>
data/Rakefile CHANGED
@@ -27,7 +27,8 @@ YARD::Rake::YardocTask.new do |yard|
27
27
  end
28
28
 
29
29
  task :clobber_doc do
30
- rm_r 'doc' rescue nil
30
+ rm_r 'doc' rescue nil
31
+ rm_r '.yardoc' rescue nil
31
32
  end
32
33
  task :clobber_package do
33
34
  rm_r 'pkg' rescue nil
data/base/gl.yml ADDED
@@ -0,0 +1,31 @@
1
+ ok: 'OK'
2
+ save: 'Gardar'
3
+ cancel: 'Cancelar'
4
+ 'yes': 'Sí'
5
+ 'no': 'Non'
6
+ exit: 'Deixar'
7
+ delete: 'Borrar'
8
+
9
+ human_time:
10
+ after_days: !!pl
11
+ 1: 'despois do %1 día'
12
+ n: 'tras %1 días'
13
+ tomorrow: 'mañá'
14
+ after_hours: !!pl
15
+ 1: 'despois de %1 hora'
16
+ n: 'tras %1 horas'
17
+ after_minutes: !!pl
18
+ 1: 'despois de %1 minuto'
19
+ n: 'tras %1 minutos'
20
+ now: 'agora'
21
+ today: 'hoxe'
22
+ minutes_ago: !!pl
23
+ 1: '%1 minuto'
24
+ n: '%1 minutos'
25
+ hours_ago: !!pl
26
+ 1: '%1 hora'
27
+ n: '%1 horas'
28
+ yesterday: 'ayer'
29
+ days_ago: !!pl
30
+ 1: '%1 día'
31
+ n: '%1 días'
data/base/it.yml CHANGED
@@ -5,7 +5,7 @@ cancel: 'Annulla'
5
5
  'no': 'No'
6
6
  exit: 'Esci'
7
7
  delete: 'Cancella'
8
-
8
+
9
9
  human_time:
10
10
  after_days: !!pl
11
11
  1: 'dopo %1 giorno'
@@ -0,0 +1,157 @@
1
+ # encoding: utf-8
2
+ =begin
3
+ Filters for translations content.
4
+
5
+ Copyright (C) 2012 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
+ module R18n
22
+ # Superclass for +GlobalFilterList+ and +CustomFilterList+ with filters
23
+ # processing.
24
+ class FilterList
25
+ # Process +value+ by filters in +enabled+.
26
+ def process(filters_type, type, value, locale, path, params)
27
+ config = { :locale => locale, :path => path }
28
+
29
+ enabled(filters_type, type).each do |filter|
30
+ value = filter.call(value, config, *params)
31
+ end
32
+
33
+ if value.is_a? String
34
+ value = TranslatedString.new(value, locale, path)
35
+ process_string(filters_type, value, config, params)
36
+ else
37
+ value
38
+ end
39
+ end
40
+
41
+ # Shortcut ot process `R18n::Typed`.
42
+ def process_typed(filters_type, typed_value, params)
43
+ process(filters_type,
44
+ typed_value.type,
45
+ typed_value.value,
46
+ typed_value.locale,
47
+ typed_value.path,
48
+ params)
49
+ end
50
+
51
+ # Process +value+ by global filters in +enabled+.
52
+ def process_string(filters_type, value, config, params)
53
+ if config.is_a? String
54
+ config = { :locale => value.locale, :path => config }
55
+ end
56
+ enabled(filters_type, String).each do |f|
57
+ value = f.call(value, config, *params)
58
+ end
59
+ value
60
+ end
61
+
62
+ # Array of enabled filters with +filters_type+ for +type+.
63
+ def enabled(filters_type, type)
64
+ if filters_type == :passive
65
+ passive(type)
66
+ elsif filters_type == :active
67
+ active(type)
68
+ else
69
+ all(type)
70
+ end
71
+ end
72
+
73
+ # List of enable passive filters.
74
+ def passive(type)
75
+ []
76
+ end
77
+
78
+ # List of enable active filters.
79
+ def active(type)
80
+ []
81
+ end
82
+
83
+ # List of enable filters.
84
+ def all(type)
85
+ []
86
+ end
87
+ end
88
+
89
+ # Filter list for I18n object with only global filters.
90
+ class GlobalFilterList < FilterList
91
+ include Singleton
92
+
93
+ def passive(type)
94
+ Filters.passive_enabled[type]
95
+ end
96
+
97
+ def active(type)
98
+ Filters.active_enabled[type]
99
+ end
100
+
101
+ def all(type)
102
+ Filters.enabled[type]
103
+ end
104
+ end
105
+
106
+ # Filter list for I18n object with custom disabled/enabled filters.
107
+ class CustomFilterList < FilterList
108
+
109
+ def initialize(on, off)
110
+ @on = Array(on).map { |i| Filters.defined[i] }
111
+ @off = Array(off).map { |i| Filters.defined[i] }
112
+ @changed_types = (@on + @off).map { |i| i.types }.flatten.uniq
113
+
114
+ @changed_passive = (@on + @off).reject { |i| !i.passive? }.
115
+ map { |i| i.types }.flatten.uniq
116
+ @changed_active = (@on + @off).reject { |i| i.passive? }.
117
+ map { |i| i.types }.flatten.uniq
118
+
119
+ @on_by_type = {}
120
+ @on.each do |filter|
121
+ filter.types.each do |type|
122
+ @on_by_type[type] ||= []
123
+ @on_by_type[type] << filter
124
+ end
125
+ end
126
+ @off_by_type = {}
127
+ @off.each do |filter|
128
+ filter.types.each do |type|
129
+ @off_by_type[type] ||= []
130
+ @off_by_type[type] << filter
131
+ end
132
+ end
133
+ end
134
+
135
+ def passive(type)
136
+ enabled = Filters.passive_enabled[type]
137
+ return enabled unless @changed_passive.include? type
138
+ enabled = enabled.reject { |i| @off_by_type[type].include? i }
139
+ enabled += @on_by_type[type].reject { |i| !i.passive }
140
+ end
141
+
142
+ def active(type)
143
+ enabled = Filters.active_enabled[type]
144
+ return enabled unless @changed_active.include? type
145
+ enabled = enabled.reject { |i| @off_by_type[type].include? i }
146
+ enabled += @on_by_type[type].reject { |i| i.passive }
147
+ end
148
+
149
+ def all(type)
150
+ enabled = Filters.enabled[type]
151
+ return enabled unless @changed_types.include? type
152
+ enabled = enabled.reject { |i| @off_by_type[type].include? i }
153
+ enabled += @on_by_type[type]
154
+ end
155
+
156
+ end
157
+ end