i18n-inflector 2.0.1 → 2.1.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.
@@ -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