r18n-core 0.4.14 → 1.0.0

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