i18n-inflector 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,7 +15,7 @@ module I18n
15
15
  # This is proxy method that returns an inflector
16
16
  # object used by the current I18n backend.
17
17
  #
18
- # @return [I18n::Inflector::Core] inflector the inflector
18
+ # @return [I18n::Inflector::API] inflector the inflector
19
19
  # used by the current backend
20
20
  def inflector
21
21
  I18n.backend.inflector
@@ -23,12 +23,23 @@ module I18n
23
23
  end
24
24
 
25
25
  module Inflector
26
- # Contains <tt>@{</tt> string that is used to quickly fallback
26
+
27
+ # @private
28
+ def get_reserved_keys
29
+ return I18n::RESERVED_KEYS if defined?(I18n::RESERVED_KEYS)
30
+ return I18n::Backend::Base::RESERVED_KEYS if defined?(I18n::Backend::Base::RESERVED_KEYS)
31
+ return I18n::Backend::Simple::RESERVED_KEYS if defined?(I18n::Backend::Simple::RESERVED_KEYS)
32
+ return RESERVED_KEYS if defined?(RESERVED_KEYS)
33
+ []
34
+ end
35
+ module_function :get_reserved_keys
36
+
37
+ # Contains <tt>@</tt> string that is used to quickly fallback
27
38
  # to standard +translate+ method if it's not found.
28
- FAST_MATCHER = '@{'
39
+ FAST_MATCHER = '@'
29
40
 
30
41
  # Contains a regular expression that catches patterns.
31
- PATTERN = /(.?)@\{([^\}]+)\}/
42
+ PATTERN = /(.?)@([^\{]*)\{([^\}]+)\}/
32
43
 
33
44
  # Contains a regular expression that catches tokens.
34
45
  TOKENS = /(?:([^\:\|]+):+([^\|]+)\1?)|([^:\|]+)/
@@ -36,6 +47,9 @@ module I18n
36
47
  # Contains a symbol that indicates an alias.
37
48
  ALIAS_MARKER = '@'
38
49
 
50
+ # Contains a symbol that indicates a named pattern.
51
+ NAMED_MARKER = '@'
52
+
39
53
  # Conatins a symbol used to separate multiple tokens.
40
54
  OPERATOR_MULTI = ','
41
55
 
@@ -46,661 +60,8 @@ module I18n
46
60
  ESCAPES = { '@' => true, '\\' => true }
47
61
 
48
62
  # Reserved keys
49
- INFLECTOR_RESERVED_KEYS = defined?(RESERVED_KEYS) ?
50
- RESERVED_KEYS : I18n::Backend::Base::RESERVED_KEYS
51
-
52
- # Instances of this class, the inflectors, are attached
53
- # to I18n backends. This class contains common operations
54
- # that programmer can perform on inflections. It keeps the
55
- # database of {I18n::Inflector::InflectionData} instances
56
- # and has methods to access them in an easy way.
57
- #
58
- # ==== Usage
59
- # You can access the instance of this class attached to
60
- # default I18n backend by entering:
61
- # I18n.backend.inflector
62
- # or in a short form:
63
- # I18n.inflector
64
- class Core
65
-
66
- include I18n::Inflector::Util
67
-
68
- # Options controlling the engine.
69
- #
70
- # @api public
71
- # @return [I18n::Inflector::InflectionOptions] the set of options
72
- # controlling inflection engine
73
- # @see I18n::Inflector::InflectionOptions#raises
74
- # @see I18n::Inflector::InflectionOptions#unknown_defaults
75
- # @see I18n::Inflector::InflectionOptions#excluded_defaults
76
- # @see I18n::Inflector::InflectionOptions#aliased_patterns
77
- # @example Usage of +options+:
78
- # # globally set raises flag
79
- # I18n.inflector.options.raises = true
80
- #
81
- # # globally set raises flag (the same meaning as the example above)
82
- # I18n.backend.inflector.options.raises = true
83
- #
84
- # # set raises flag just for this translation
85
- # I18n.translate('welcome', :inflector_raises => true)
86
- attr_reader :options
87
-
88
- # Initilizes inflector by creating internal databases for storing
89
- # inflection hashes and options.
90
- #
91
- # @api public
92
- def initialize
93
- @idb = {}
94
- @options = I18n::Inflector::InflectionOptions.new
95
- end
96
-
97
- # Adds database for the specified locale.
98
- #
99
- # @api public
100
- # @raise [I18n::InvalidLocale] if there is no proper locale name
101
- # @param [Symbol] locale the locale for which the infleciton database is created
102
- # @return [I18n::Inflector::InflectionData] the new object for keeping inflection data
103
- # for the given +locale+
104
- def new_database(locale)
105
- locale = prep_locale(locale)
106
- @idb[locale] = I18n::Inflector::InflectionData.new(locale)
107
- end
108
-
109
- # Attaches {I18n::Inflector::InflectionData} instance to the
110
- # current collection.
111
- #
112
- # @api public
113
- # @raise [I18n::InvalidLocale] if there is no proper locale name
114
- # @note It doesn't create copy of inflection data, it registers the given object.
115
- # @param [I18n::Inflector::InflectionData] idb inflection data to add
116
- # @return [I18n::Inflector::InflectionData] the given +idb+ or +nil+ if something
117
- # went wrong (e.g. +nil+ was given as an argument)
118
- def add_database(idb)
119
- return nil if idb.nil?
120
- locale = prep_locale(idb.locale)
121
- delete_database(locale)
122
- @idb[locale] = idb
123
- end
124
-
125
- # Deletes a database for the specified locale.
126
- #
127
- # @api public
128
- # @note It detaches the database from {I18n::Inflector::Core} instance.
129
- # Other objects referring to it directly may still use it.
130
- # @raise [I18n::InvalidLocale] if there is no proper locale name
131
- # @param [Symbol] locale the locale for which the infleciton database is to be deleted.
132
- # @return [void]
133
- def delete_database(locale)
134
- locale = prep_locale(locale)
135
- return nil if @idb[locale].nil?
136
- @idb[locale] = nil
137
- end
138
-
139
- # Reads default token for the given +kind+.
140
- #
141
- # @api public
142
- # @return [Symbol,nil] the default token for the given kind or +nil+
143
- # @raise [I18n::InvalidLocale] if there is no proper locale name
144
- # @overload default_token(kind)
145
- # This method reads default token for the given +kind+ and current locale.
146
- # @param [Symbol,String] kind the kind of tokens
147
- # @return [Symbol,nil] the default token for the given kind or +nil+ if
148
- # there is no default token
149
- # @overload default_token(kind, locale)
150
- # This method reads default token for the given +kind+ and the given +locale+.
151
- # @param [Symbol,String] kind the kind of tokens
152
- # @param [Symbol] locale the locale to use
153
- # @return [Symbol,nil] the default token for the given kind or +nil+ if
154
- # there is no default token
155
- def default_token(kind, locale=nil)
156
- return nil if kind.to_s.empty?
157
- data_safe(locale).get_default_token(kind)
158
- end
159
-
160
- # Checks if the given +token+ is an alias.
161
- #
162
- # @api public
163
- # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise
164
- # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
165
- # @raise [ArgumentError] if the count of arguments is invalid
166
- # @overload has_alias?(token)
167
- # Uses current locale to check if the given +token+ is an alias.
168
- # @param [Symbol,String] token name of the checked token
169
- # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise
170
- # @overload has_alias?(token, locale)
171
- # Uses the given +locale+ to check if the given +token+ is an alias.
172
- # @param [Symbol,String] token name of the checked token
173
- # @param [Symbol] locale the locale to use
174
- # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise
175
- # @overload has_alias?(token, kind, locale)
176
- # Uses the given +locale+ and +kind+ to check if the given +token+ is an alias.
177
- # @param [Symbol,String] token name of the checked token
178
- # @param [Symbol,String] kind the kind used to narrow the check
179
- # @param [Symbol] locale the locale to use
180
- # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise
181
- def has_alias?(*args)
182
- token, kind, locale = tkl_args(args)
183
- return false if token.to_s.empty?
184
- return false if (!kind.nil? && kind.to_s.empty?)
185
- token = token.to_sym
186
- kind = kind.to_sym unless kind.nil?
187
- data_safe(locale).has_alias?(token, kind)
188
- end
189
- alias_method :token_has_alias?, :has_alias?
190
-
191
- # Checks if the given +token+ is a true token (not alias).
192
- #
193
- # @api public
194
- # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise
195
- # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
196
- # @raise [ArgumentError] if the count of arguments is invalid
197
- # @overload has_true_token?(token)
198
- # Uses current locale to check if the given +token+ is a true token.
199
- # @param [Symbol,String] token name of the checked token
200
- # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise
201
- # @overload has_true_token?(token, locale)
202
- # Uses the given +locale+ to check if the given +token+ is a true token.
203
- # @param [Symbol,String] token name of the checked token
204
- # @param [Symbol] locale the locale to use
205
- # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise
206
- # @overload has_true_token?(token, kind, locale)
207
- # Uses the given +locale+ and +kind+ to check if the given +token+ is a true token.
208
- # @param [Symbol,String] token name of the checked token
209
- # @param [Symbol,String] kind the kind used to narrow the check
210
- # @param [Symbol] locale the locale to use
211
- # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise
212
- def has_true_token?(*args)
213
- token, kind, locale = tkl_args(args)
214
- return false if token.to_s.empty?
215
- return false if (!kind.nil? && kind.to_s.empty?)
216
- token = token.to_sym
217
- kind = kind.to_sym unless kind.nil?
218
- data_safe(locale).has_true_token?(token, kind)
219
- end
220
- alias_method :token_has_true?, :has_true_token?
221
-
222
- # Checks if the given +token+ exists. It may be an alias or a true token.
223
- #
224
- # @api public
225
- # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise
226
- # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
227
- # @raise [ArgumentError] if the count of arguments is invalid
228
- # @overload has_token?(token)
229
- # Uses current locale to check if the given +token+ is a token.
230
- # @param [Symbol,String] token name of the checked token
231
- # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise
232
- # @overload has_token?(token, locale)
233
- # Uses the given +locale+ to check if the given +token+ exists.
234
- # @param [Symbol,String] token name of the checked token
235
- # @param [Symbol] locale the locale to use
236
- # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise
237
- # @overload has_token?(token, kind, locale)
238
- # Uses the given +locale+ and +kind+ to check if the given +token+ exists.
239
- # @param [Symbol,String] token name of the checked token
240
- # @param [Symbol,String] kind the kind used to narrow the check
241
- # @param [Symbol] locale the locale to use
242
- # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise
243
- def has_token?(*args)
244
- token, kind, locale = tkl_args(args)
245
- return false if token.to_s.empty?
246
- return false if (!kind.nil? && kind.to_s.empty?)
247
- token = token.to_sym
248
- kind = kind.to_sym unless kind.nil?
249
- data_safe(locale).has_token?(token, kind)
250
- end
251
- alias_method :token_exists?, :has_token?
252
-
253
- # Gets true token for the given +token+ (which may be an alias).
254
- #
255
- # @api public
256
- # @return [Symbol,nil] the true token if the given +token+ is an alias, token if
257
- # the token is a real token or +nil+ otherwise
258
- # @raise [I18n::InvalidLocale] if there is no proper locale name
259
- # @overload true_token(token)
260
- # Uses current locale to get a real token for the given +token+.
261
- # @param [Symbol,String] token name of the checked token
262
- # @return [Symbol,nil] the true token if the given +token+ is an alias, token if
263
- # the token is a real token or +nil+ otherwise
264
- # @overload true_token(token, locale)
265
- # Uses the given +locale+ to get a real token for the given +token+.
266
- # @param [Symbol,String] token name of the checked token
267
- # @param [Symbol] locale the locale to use
268
- # @return [Symbol,nil] the true token if the given +token+ is an alias, token if
269
- # the token is a real token or +nil+ otherwise
270
- # @overload true_token(token, kind, locale)
271
- # Uses the given +locale+ and +kind+ to get a real token for the given +token+.
272
- # @param [Symbol,String] token name of the checked token
273
- # @param [Symbol,String] kind the kind used to narrow the check
274
- # @param [Symbol] locale the locale to use
275
- # @return [Symbol,nil] the true token if the given +token+ is an alias, token if
276
- # the token is a real token or +nil+ otherwise
277
- def true_token(*args)
278
- token, kind, locale = tkl_args(args)
279
- return nil if token.to_s.empty?
280
- return nil if (!kind.nil? && kind.to_s.empty?)
281
- token = token.to_sym
282
- kind = kind.to_sym unless kind.nil?
283
- data_safe(locale).get_true_token(token, kind)
284
- end
285
- alias_method :resolve_alias, :true_token
286
-
287
- # Gets a kind for the given +token+ (which may be an alias).
288
- #
289
- # @api public
290
- # @return [Symbol,nil] the kind of the given +token+ or +nil+
291
- # @raise [I18n::InvalidLocale] if there is no proper locale name
292
- # @overload kind(token)
293
- # Uses current locale to get a kind of the given +token+ (which may be an alias).
294
- # @param [Symbol,String] token name of the token or alias
295
- # @return [Symbol,nil] the kind of the given +token+
296
- # for the current locale
297
- # @overload kind(token, locale)
298
- # Uses the given +locale+ to get a kind of the given +token+ (which may be an alias).
299
- # @param [Symbol,String] token name of the token or alias
300
- # @param [Symbol] locale the locale to use
301
- # @return [Symbol,nil] the kind of the given +token+
302
- # for the given +locale+
303
- def kind(token, locale=nil)
304
- return nil if token.to_s.empty?
305
- data_safe(locale).get_kind(token.to_sym)
306
- end
307
-
308
- # Gets available inflection tokens and their descriptions.
309
- #
310
- # @api public
311
- # @raise [I18n::InvalidLocale] if there is no proper locale name
312
- # @return [Hash] the hash containing available inflection tokens and descriptions
313
- # @note You cannot deduce where aliases are pointing to, since the information
314
- # about a target is replaced by the description. To get targets use the
315
- # {#inflection_raw_tokens} method. To simply list aliases and their targets use
316
- # the {#inflection_aliases} method.
317
- # @overload tokens
318
- # Gets available inflection tokens and their descriptions.
319
- # @return [Hash] the hash containing available inflection tokens as keys
320
- # and their descriptions as values, including aliases,
321
- # for all kinds and current locale.
322
- # @overload tokens(kind)
323
- # Gets available inflection tokens and their descriptions for some +kind+.
324
- # @param [Symbol,String] kind the kind of inflection tokens to be returned
325
- # @return [Hash] the hash containing available inflection tokens as keys
326
- # and their descriptions as values, including aliases, for current locale.
327
- # @overload tokens(kind, locale)
328
- # Gets available inflection tokens and their descriptions for some +kind+ and +locale+.
329
- # @param [Symbol,String] kind the kind of inflection tokens to be returned
330
- # @param [Symbol] locale the locale to use
331
- # @return [Hash] the hash containing available inflection tokens as keys
332
- # and their descriptions as values, including aliases, for current locale
333
- def tokens(kind=nil, locale=nil)
334
- return {} if (!kind.nil? && kind.to_s.empty?)
335
- kind = kind.to_sym unless kind.nil?
336
- data_safe(locale).get_tokens(kind)
337
- end
338
-
339
- # Gets available inflection tokens and their values.
340
- #
341
- # @api public
342
- # @return [Hash] the hash containing available inflection tokens and descriptions (or alias pointers)
343
- # @raise [I18n::InvalidLocale] if there is no proper locale name
344
- # @note You may deduce whether the returned values are aliases or true tokens
345
- # by testing if a value is a type of Symbol or String.
346
- # @overload tokens_raw
347
- # Gets available inflection tokens and their values.
348
- # @return [Hash] the hash containing available inflection tokens as keys
349
- # and their descriptions as values. In case of aliases the returned
350
- # values are Symbols
351
- # @overload tokens_raw(kind)
352
- # Gets available inflection tokens and their values for the given +kind+.
353
- # @param [Symbol,String] kind the kind of inflection tokens to be returned
354
- # @return [Hash] the hash containing available inflection tokens as keys
355
- # and their descriptions as values for the given +kind+. In case of
356
- # aliases the returned values are Symbols
357
- # @overload tokens_raw(kind, locale)
358
- # Gets available inflection tokens and their values for the given +kind+ and +locale+.
359
- # @param [Symbol,String] kind the kind of inflection tokens to be returned
360
- # @param [Symbol] locale the locale to use
361
- # @return [Hash] the hash containing available inflection tokens as keys
362
- # and their descriptions as values for the given +kind+ and +locale+.
363
- # In case of aliases the returned values are Symbols
364
- def tokens_raw(kind=nil, locale=nil)
365
- return {} if (!kind.nil? && kind.to_s.empty?)
366
- kind = kind.to_sym unless kind.nil?
367
- data_safe(locale).get_raw_tokens(kind)
368
- end
369
- alias_method :raw_tokens, :tokens_raw
370
-
371
- # Gets true inflection tokens and their values.
372
- #
373
- # @api public
374
- # @return [Hash] the hash containing available inflection tokens and descriptions
375
- # @raise [I18n::InvalidLocale] if there is no proper locale name
376
- # @note It returns only true tokens, not aliases.
377
- # @overload tokens_true
378
- # Gets true inflection tokens and their values.
379
- # @return [Hash] the hash containing available inflection tokens as keys
380
- # and their descriptions as values
381
- # @overload tokens_true(kind)
382
- # Gets true inflection tokens and their values for the given +kind+.
383
- # @param [Symbol,String] kind the kind of inflection tokens to be returned
384
- # @return [Hash] the hash containing available inflection tokens as keys
385
- # and their descriptions as values for the given +kind+
386
- # @overload tokens_true(kind, locale)
387
- # Gets true inflection tokens and their values for the given +kind+ and +value+.
388
- # @param [Symbol,String] kind the kind of inflection tokens to be returned
389
- # @param [Symbol] locale the locale to use
390
- # @return [Hash] the hash containing available inflection tokens as keys
391
- # and their descriptions as values for the given +kind+ and +locale+
392
- def tokens_true(kind=nil, locale=nil)
393
- return {} if (!kind.nil? && kind.to_s.empty?)
394
- kind = kind.to_sym unless kind.nil?
395
- data_safe(locale).get_true_tokens(kind)
396
- end
397
- alias_method :true_tokens, :tokens_true
398
-
399
- # Gets inflection aliases and their pointers.
400
- #
401
- # @api public
402
- # @raise [I18n::InvalidLocale] if there is no proper locale name
403
- # @return [Hash] the Hash containing available inflection aliases (<tt>alias => target</tt>)
404
- # @overload aliases
405
- # Gets inflection aliases and their pointers.
406
- # @return [Hash] the Hash containing available inflection aliases
407
- # @overload aliases(kind)
408
- # Gets inflection aliases and their pointers for the given +kind+.
409
- # @param [Symbol,String] kind the kind of aliases to get
410
- # @return [Hash] the Hash containing available inflection
411
- # aliases for the given +kind+ and current locale
412
- # @overload aliases(kind, locale)
413
- # Gets inflection aliases and their pointers for the given +kind+ and +locale+.
414
- # @param [Symbol,String] kind the kind of aliases to get
415
- # @param [Symbol] locale the locale to use
416
- # @return [Hash] the Hash containing available inflection
417
- # aliases for the given +kind+ and +locale+
418
- def aliases(kind=nil, locale=nil)
419
- return {} if (!kind.nil? && kind.to_s.empty?)
420
- kind = kind.to_sym unless kind.nil?
421
- data_safe(locale).get_aliases(kind)
422
- end
423
-
424
- # Gets known inflection kinds.
425
- #
426
- # @api public
427
- # @return [Array<Symbol>] the array containing known inflection kinds
428
- # @raise [I18n::InvalidLocale] if there is no proper locale name
429
- # @overload kinds
430
- # Gets known inflection kinds for the current locale.
431
- # @return [Array<Symbol>] the array containing known inflection kinds
432
- # @overload kinds(locale)
433
- # Gets known inflection kinds for the given +locale+.
434
- # @param [Symbol] locale the locale for which operation has to be done
435
- # @return [Array<Symbol>] the array containing known inflection kinds
436
- def kinds(locale=nil)
437
- data_safe(locale).get_kinds
438
- end
439
- alias_method :inflection_kinds, :kinds
440
-
441
- # Tests if a kind exists.
442
- #
443
- # @api public
444
- # @raise [I18n::InvalidLocale] if there is no proper locale name
445
- # @return [Boolean] +true+ if the given +kind+ exists, +false+ otherwise
446
- # @overload has_kind?(kind)
447
- # @param [Symbol] kind the identifier of a kind
448
- # @return [Boolean] +true+ if the given +kind+ exists for the current
449
- # locale, +false+ otherwise
450
- # @overload has_kind?(kind, locale)
451
- # @param [Symbol,String] kind the identifier of a kind
452
- # @param [Symbol] locale the locale identifier
453
- # @return [Boolean] +true+ if the given +kind+ exists, +false+ otherwise
454
- def has_kind?(kind, locale=nil)
455
- return false if kind.to_s.empty?
456
- data_safe(locale).has_kind?(kind)
457
- end
458
-
459
- # Gets locales which have configured inflection support.
460
- #
461
- # @api public
462
- # @return [Array<Symbol>] the array containing locales that support inflection
463
- # @note If +kind+ is given it returns only these locales
464
- # that support inflection by this kind.
465
- def inflected_locales(kind=nil)
466
- return [] if (!kind.nil? && kind.to_s.empty?)
467
- inflected_locales = (@idb.keys || [])
468
- return inflected_locales if kind.nil?
469
- kind = kind.to_sym
470
- inflected_locales.reject{|l| @idb[l].nil? || !@idb[l].has_kind?(kind)}
471
- end
472
- alias_method :locales, :inflected_locales
473
- alias_method :supported_locales, :inflected_locales
474
-
475
- # Checks if the given locale was configured to support inflection.
476
- #
477
- # @api public
478
- # @raise [I18n::InvalidLocale] if there is no proper locale name
479
- # @return [Boolean] +true+ if a locale supports inflection
480
- # @overload inflected_locale?(locale)
481
- # Checks if the given locale was configured to support inflection.
482
- # @param [Symbol] locale the locale to test
483
- # @return [Boolean] +true+ if the given locale supports inflection
484
- # @overload inflected_locale?
485
- # Checks if the current locale was configured to support inflection.
486
- # @return [Boolean] +true+ if the current locale supports inflection
487
- def inflected_locale?(locale=nil)
488
- not @idb[prep_locale(locale)].nil? rescue false
489
- end
490
- alias_method :locale?, :inflected_locale?
491
- alias_method :locale_supported?, :inflected_locale?
492
-
493
- # Gets the description of the given inflection token.
494
- #
495
- # @api public
496
- # @note If the given +token+ is really an alias it
497
- # returns the description of the true token that
498
- # it points to.
499
- # @raise [I18n::InvalidLocale] if there is no proper locale name
500
- # @return [String,nil] the descriptive string or +nil+
501
- # @overload token_description(token)
502
- # Uses current locale to get description of the given token.
503
- # @return [String,nil] the descriptive string or +nil+ if something
504
- # went wrong (e.g. token was not found)
505
- # @overload token_description(token, locale)
506
- # Uses the given +locale+ to get description of the given inflection token.
507
- # @param [Symbol] locale the locale to use
508
- # @return [String,nil] the descriptive string or +nil+ if something
509
- # went wrong (e.g. token was not found)
510
- def token_description(token, locale=nil)
511
- return nil if token.to_s.empty?
512
- data_safe(locale).get_description(token.to_sym)
513
- end
514
-
515
- # Interpolates inflection values in a given +string+
516
- # using kinds given in +options+ and a matching tokens.
517
- #
518
- # @param [String] string the translation string
519
- # containing patterns to interpolate
520
- # @param [String,Symbol] locale the locale identifier
521
- # @param [Hash] options the options
522
- # @option options [Boolean] :inflector_excluded_defaults (false) local switch
523
- # that overrides global setting (see: {I18n::Inflector::InflectionOptions#excluded_defaults})
524
- # @option options [Boolean] :inflector_unknown_defaults (true) local switch
525
- # that overrides global setting (see: {I18n::Inflector::InflectionOptions#unknown_defaults})
526
- # @option options [Boolean] :inflector_raises (false) local switch
527
- # that overrides global setting (see: {I18n::Inflector::InflectionOptions#raises})
528
- # @option options [Boolean] :inflector_aliased_patterns (false) local switch
529
- # that overrides global setting (see: {I18n::Inflector::InflectionOptions#aliased_patterns})
530
- # @return [String] the string with interpolated patterns
531
- def interpolate(string, locale, options = {})
532
- used_kinds = options.except(*I18n::Inflector::INFLECTOR_RESERVED_KEYS)
533
- sw, op = @options, options
534
- raises = (s=op.delete :inflector_raises).nil? ? sw.raises : s
535
- aliased_patterns = (s=op.delete :inflector_aliased_patterns).nil? ? sw.aliased_patterns : s
536
- unknown_defaults = (s=op.delete :inflector_unknown_defaults).nil? ? sw.unknown_defaults : s
537
- excluded_defaults = (s=op.delete :inflector_excluded_defaults).nil? ? sw.excluded_defaults : s
538
-
539
- idb = @idb[locale]
63
+ INFLECTOR_RESERVED_KEYS = I18n::Inflector.get_reserved_keys
540
64
 
541
- string.gsub(I18n::Inflector::PATTERN) do
542
- pattern_fix = $1
543
- pattern_content = $2
544
- ext_pattern = $&
545
- parsed_kind = nil
546
- default_token = nil
547
- ext_value = nil
548
- ext_freetext = ''
549
- found = false
550
- parsed_default_v= nil
65
+ end # module Inflector
551
66
 
552
- # leave escaped pattern as is
553
- next ext_pattern[1..-1] if I18n::Inflector::ESCAPES.has_key?(pattern_fix)
554
-
555
- # process pattern content's
556
- pattern_content.scan(I18n::Inflector::TOKENS) do
557
- ext_token = $1.to_s
558
- ext_value = $2.to_s
559
- ext_freetext = $3.to_s
560
- tokens = Hash.new(false)
561
- negatives = Hash.new(false)
562
- kind = nil
563
- option = nil
564
-
565
- # token not found?
566
- if ext_token.empty?
567
- # free text not found too? that should never happend.
568
- if ext_freetext.empty?
569
- raise I18n::InvalidInflectionToken.new(ext_pattern, ext_token) if raises
570
- end
571
- next
572
- end
573
-
574
- # split tokens if comma is present and put into fast list
575
- ext_token.split(I18n::Inflector::OPERATOR_MULTI).each do |t|
576
- # token name corrupted
577
- if t.empty?
578
- raise I18n::InvalidInflectionToken.new(ext_pattern, t) if raises
579
- next
580
- end
581
-
582
- # mark negative-matching tokens and put them to negatives fast list
583
- if t[0..0] == I18n::Inflector::OPERATOR_NOT
584
- t = t[1..-1]
585
- if t.empty?
586
- raise I18n::InvalidInflectionToken.new(ext_pattern, t) if raises
587
- next
588
- end
589
- t = t.to_sym
590
- t = idb.get_true_token(t) if aliased_patterns
591
- negatives[t] = true
592
- end
593
-
594
- t = t.to_sym
595
- t = idb.get_true_token(t) if aliased_patterns
596
-
597
- # get kind for that token
598
- kind = idb.get_kind(t)
599
- if kind.nil?
600
- raise I18n::InvalidInflectionToken.new(ext_pattern, t) if raises
601
- next
602
- end
603
-
604
- # set processed kind after matching first token in a pattern
605
- if parsed_kind.nil?
606
- parsed_kind = kind
607
- default_token = idb.get_default_token(parsed_kind)
608
- elsif parsed_kind != kind
609
- # different kinds in one pattern are prohibited
610
- raise I18n::MisplacedInflectionToken.new(ext_pattern, t, parsed_kind) if raises
611
- next
612
- end
613
-
614
- # use that token
615
- tokens[t] = true unless negatives[t]
616
- end
617
-
618
- # self-explanatory
619
- if (tokens.empty? && negatives.empty?)
620
- raise I18n::InvalidInflectionToken.new(ext_pattern, ext_token) if raises
621
- end
622
-
623
- # fetch the kind's option or fetch default if an option does not exists
624
- option = options.has_key?(kind) ? options[kind] : default_token
625
-
626
- if option.to_s.empty?
627
- # if option is given but is unknown, empty or nil
628
- # then use default option for a kind if unknown_defaults is switched on
629
- option = unknown_defaults ? default_token : nil
630
- else
631
- # validate option and if it's unknown try in aliases
632
- option = idb.get_true_token(option.to_sym)
633
-
634
- # if still nothing then fall back to default value
635
- # for a kind in unknown_defaults switch is on
636
- if option.nil?
637
- option = unknown_defaults ? default_token : nil
638
- end
639
- end
640
-
641
- # if the option is still unknown
642
- if option.nil?
643
- raise I18n::InvalidOptionForKind.new(ext_pattern, kind, ext_token, nil) if raises
644
- next
645
- end
646
-
647
- # memorize default value for further processing
648
- # outside this block if excluded_defaults switch is on
649
- parsed_default_v = ext_value if (excluded_defaults && !default_token.nil?)
650
-
651
- # throw the value if a given option matches one of the tokens from group
652
- # or negatively matches one of the negated tokens
653
- case negatives.count
654
- when 0 then next unless tokens[option]
655
- when 1 then next if negatives[option]
656
- end
657
-
658
- # skip further evaluation of the pattern
659
- # since the right token has been found
660
- found = true
661
- break
662
-
663
- end # single token (or a group) processing
664
-
665
- result = nil
666
-
667
- # return value of a token that matches option's value
668
- # given for a kind or try to return a free text
669
- # if it's present
670
- if found
671
- result = ext_value
672
- elsif (excluded_defaults && !parsed_kind.nil?)
673
- # if there is excluded_defaults switch turned on
674
- # and a correct token was found in an inflection option but
675
- # has not been found in a pattern then interpolate
676
- # the pattern with a value picked for the default
677
- # token for that kind if a default token was present
678
- # in a pattern
679
- kind = nil
680
- token = options[parsed_kind]
681
- kind = idb.get_kind(token)
682
- result = parsed_default_v unless kind.nil?
683
- end
684
-
685
- pattern_fix + (result || ext_freetext)
686
-
687
- end # single pattern processing
688
-
689
- end
690
-
691
- protected
692
-
693
- # @private
694
- def data(locale=nil)
695
- @idb[prep_locale(locale)]
696
- end
697
-
698
- # @private
699
- def data_safe(locale=nil)
700
- @idb[prep_locale(locale)] || I18n::Inflector::InflecitonData.new
701
- end
702
-
703
- end
704
-
705
- end
706
- end
67
+ end # module I18n