i18n-inflector 1.0.11 → 2.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.
@@ -2,168 +2,159 @@
2
2
  #
3
3
  # Author:: Paweł Wilk (mailto:pw@gnu.org)
4
4
  # Copyright:: (c) 2011 by Paweł Wilk
5
- # License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
5
+ # License:: This program is licensed under the terms of {file:LGPL GNU Lesser General Public License} or {file:COPYING Ruby License}.
6
6
  #
7
- # This file contains I18n::Backend::Inflector module,
8
- # which extends I18n::Backend::Simple by adding the ability
7
+ # This file contains I18n::Inflector module,
8
+ # which extends I18n by adding the ability
9
9
  # to interpolate patterns containing inflection tokens
10
- # defined in translation data.
10
+ # defined in translation data and manipulate on that data.
11
11
 
12
12
  module I18n
13
- module Backend
14
- module Inflector
15
13
 
16
- # Contains <tt>@{</tt> string that is used to quickly fallback
17
- # to standard +translate+ method if it's not found.
18
- FAST_MATCHER = '@{'
14
+ class <<self
15
+ # This is proxy method that returns an inflector
16
+ # object used by the current I18n backend.
17
+ #
18
+ # @return [I18n::Inflector::Core] inflector the inflector
19
+ # used by the current backend
20
+ def inflector
21
+ I18n.backend.inflector
22
+ end
23
+ end
24
+
25
+ module Inflector
26
+ # Contains <tt>@{</tt> string that is used to quickly fallback
27
+ # to standard +translate+ method if it's not found.
28
+ FAST_MATCHER = '@{'
29
+
30
+ # Contains a regular expression that catches patterns.
31
+ PATTERN = /(.?)@\{([^\}]+)\}/
19
32
 
20
- # Contains a regular expression that catches patterns.
21
- PATTERN = /(.?)@\{([^\}]+)\}/
33
+ # Contains a regular expression that catches tokens.
34
+ TOKENS = /(?:([^\:\|]+):+([^\|]+)\1?)|([^:\|]+)/
22
35
 
23
- # Contains a regular expression that catches tokens.
24
- TOKENS = /(?:([^\:\|]+):+([^\|]+)\1?)|([^:\|]+)/
36
+ # Contains a symbol that indicates an alias.
37
+ ALIAS_MARKER = '@'
25
38
 
26
- # Contains a symbol that indicates an alias.
27
- ALIAS_MARKER = '@'
39
+ # Conatins a symbol used to separate multiple tokens.
40
+ OPERATOR_MULTI = ','
28
41
 
29
- # Contains a list of escape symbols that cause pattern to be escaped.
30
- ESCAPES = { '@' => true, '\\' => true }
42
+ # Conatins a symbol used to mark tokens as negative.
43
+ OPERATOR_NOT = '!'
31
44
 
32
- # Reserved keys
33
- INFLECTOR_RESERVED_KEYS = defined?(RESERVED_KEYS) ?
34
- RESERVED_KEYS : I18n::Backend::Base::RESERVED_KEYS
45
+ # Contains a list of escape symbols that cause pattern to be escaped.
46
+ ESCAPES = { '@' => true, '\\' => true }
35
47
 
36
- attr_accessor :inflector_raises
37
- attr_accessor :inflector_unknown_defaults
38
- attr_accessor :inflector_excluded_defaults
48
+ # Reserved keys
49
+ INFLECTOR_RESERVED_KEYS = defined?(RESERVED_KEYS) ?
50
+ RESERVED_KEYS : I18n::Backend::Base::RESERVED_KEYS
39
51
 
40
- # Checks the state of the switch that enables extended error reporting.
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.
41
69
  #
42
70
  # @api public
43
- # @note This is a helper method, you can use {#inflector_raises accessor} instead.
44
- # @return [Boolean] the value of the global switch or the passed variable
45
- # @see I18n::Inflector.raises? Short name: I18n::Inflector.raises?
46
- # @see #inflector_raises=
47
- # @overload inflector_raises?
48
- # Checks the state of the switch that enables extended error reporting.
49
- # @return [Boolean] the value of the global switch
50
- # @overload inflector_raises?(value)
51
- # Returns the given value.
52
- # @param [Boolean] value the value to be returned
53
- # @return [Boolean] +true+ if the passed +value+ is not +false+
54
- def inflector_raises?(option=nil)
55
- option.nil? ? @inflector_raises : option!=false
56
- end
57
-
58
- # Checks the state of the switch that that enables falling back
59
- # to the default token of a kind when the inflection option
60
- # is unknown or empty.
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.
61
90
  #
62
91
  # @api public
63
- # @note This is a helper method, you can use {#inflector_unknown_defaults accessor} instead.
64
- # @return [Boolean] the value of the global switch or the passed variable
65
- # @see I18n::Inflector.unknown_defaults? Short name: I18n::Inflector.unknown_defaults?
66
- # @see #inflector_unknown_defaults=
67
- # @overload inflector_unknown_defaults?
68
- # Checks the state of the switch that that enables falling back
69
- # to the default token for a kind when the inflection option
70
- # is unknown or empty.
71
- # @return [Boolean] the value of the global switch
72
- # @overload inflector_unknown_defaults?(value)
73
- # Returns the given value.
74
- # @param [Boolean] value the value to be returned
75
- # @return [Boolean] +true+ if the passed +value+ is not +false+
76
- def inflector_unknown_defaults?(option=nil)
77
- option.nil? ? @inflector_unknown_defaults : option!=false
92
+ def initialize
93
+ @idb = {}
94
+ @options = I18n::Inflector::InflectionOptions.new
78
95
  end
79
-
80
- # Checks the state of the switch that that enables falling back
81
- # to the default token when the inflection option is not found in a pattern.
96
+
97
+ # Adds database for the specified locale.
82
98
  #
83
99
  # @api public
84
- # @note This is a helper method, you can use {#inflector_excluded_defaults accessor} instead.
85
- # @return [Boolean] the value of the global switch or the passed variable
86
- # @see I18n::Inflector.excluded_defaults? Short name: I18n::Inflector.excluded_defaults?
87
- # @see #inflector_excluded_defaults=
88
- # @overload inflector_excluded_defaults?
89
- # Checks the state of the switch that enables falling back
90
- # to the default token for a kind when token name from
91
- # the inflection option is not found in a pattern.
92
- # @return [Boolean] the value of the global switch
93
- # @overload inflector_excluded_defaults?(value)
94
- # Returns the given value
95
- # @param [Boolean] value the value to be returned
96
- # @return [Boolean] +true+ if the passed +value+ is not +false+
97
- def inflector_excluded_defaults?(option=nil)
98
- option.nil? ? @inflector_excluded_defaults : option!=false
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)
99
107
  end
100
-
101
- # Cleans up internal hashes containg kinds, inflections and aliases.
102
- #
108
+
109
+ # Attaches {I18n::Inflector::InflectionData} instance to the
110
+ # current collection.
111
+ #
103
112
  # @api public
104
- # @note It calls {I18n::Backend::Simple#reload! I18n::Backend::Simple#reload!}
105
- # @return [Boolean] the result of calling ancestor's method
106
- # @see I18n::Inflector.reload! Short name: I18n::Inflector.reload!
107
- def reload!
108
- @inflection_tokens = nil
109
- @inflection_aliases = nil
110
- @inflection_defaults = nil
111
- super
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
112
123
  end
113
124
 
114
- # Translates given key taking care of inflections.
125
+ # Deletes a database for the specified locale.
115
126
  #
116
127
  # @api public
117
- # @param [Symbol] locale locale
118
- # @param [Symbol,String] key translation key
119
- # @param [Hash] options a set of options to pass to the translation routines.
120
- # @note Inflector requires at least one of the +options+ to have a value that
121
- # corresponds with token present in a pattern (or its alias). The name of that
122
- # particular option should be the same as the name of a kind of tokens from a pattern.
123
- # All +options+ along with a +string+ and +locale+ are passed to
124
- # {I18n::Backend::Simple#translate I18n::Backend::Simple#translate}
125
- # and the result is processed by {#interpolate_inflections}
126
- # @return [String] the translated string with interpolated patterns
127
- def translate(locale, key, options = {})
128
- translated_string = super
129
- return translated_string if locale.to_s.empty?
130
-
131
- unless translated_string.include?(I18n::Backend::Inflector::FAST_MATCHER)
132
- return translated_string
133
- end
134
-
135
- inflection_tokens = @inflection_tokens[locale]
136
- if (inflection_tokens.nil? || inflection_tokens.empty?)
137
- return clear_inflection_patterns(translated_string)
138
- end
139
-
140
- interpolate_inflections(translated_string, locale, options.dup)
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
141
137
  end
142
-
138
+
143
139
  # Reads default token for the given +kind+.
144
140
  #
145
141
  # @api public
146
142
  # @return [Symbol,nil] the default token for the given kind or +nil+
147
- # @raise [I18n::InvalidLocale] if the given +locale+ name is invalid
148
- # @see I18n::Inflector.default_token Short name: I18n::Inflector.default_token
149
- # @overload inflection_default_token(kind)
143
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
144
+ # @overload default_token(kind)
150
145
  # This method reads default token for the given +kind+ and current locale.
151
- # @param [Symbol] kind the kind of tokens
146
+ # @param [Symbol,String] kind the kind of tokens
152
147
  # @return [Symbol,nil] the default token for the given kind or +nil+ if
153
148
  # there is no default token
154
- # @overload inflection_default_token(kind, locale)
149
+ # @overload default_token(kind, locale)
155
150
  # This method reads default token for the given +kind+ and the given +locale+.
156
- # @param [Symbol] kind the kind of tokens
151
+ # @param [Symbol,String] kind the kind of tokens
157
152
  # @param [Symbol] locale the locale to use
158
153
  # @return [Symbol,nil] the default token for the given kind or +nil+ if
159
154
  # there is no default token
160
- def inflection_default_token(kind, locale=nil)
161
- locale = inflector_prep_locale(locale)
155
+ def default_token(kind, locale=nil)
162
156
  return nil if kind.to_s.empty?
163
- init_translations unless initialized?
164
- inflections = @inflection_defaults[locale]
165
- return nil if inflections.nil?
166
- inflections[kind.to_sym]
157
+ data_safe(locale).get_default_token(kind)
167
158
  end
168
159
 
169
160
  # Checks if the given +token+ is an alias.
@@ -171,268 +162,320 @@ module I18n
171
162
  # @api public
172
163
  # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise
173
164
  # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
174
- # @see I18n::Inflector.is_alias? Short name: I18n::Inflector.is_alias?
175
- # @overload inflection_is_alias?(token)
176
- # Uses current locale to check if the given +token+ is an alias
177
- # or a regular token.
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.
178
172
  # @param [Symbol,String] token name of the checked token
173
+ # @param [Symbol] locale the locale to use
179
174
  # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise
180
- # @overload inflection_is_alias?(token, locale)
181
- # Uses the given +locale+ to check if the given +token+ is an alias
182
- # or a regular token.
175
+ # @overload has_alias?(token, kind, locale)
176
+ # Uses the given +locale+ and +kind+ to check if the given +token+ is an alias.
183
177
  # @param [Symbol,String] token name of the checked token
178
+ # @param [Symbol,String] kind the kind used to narrow the check
184
179
  # @param [Symbol] locale the locale to use
185
180
  # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise
186
- def inflection_is_alias?(token, locale=nil)
181
+ def has_alias?(*args)
182
+ token, kind, locale = tkl_args(args)
187
183
  return false if token.to_s.empty?
188
- locale = inflector_prep_locale(locale)
189
- init_translations unless initialized?
190
- aliases = @inflection_aliases[locale]
191
- return false if aliases.nil?
192
- aliases.has_key?(token.to_sym)
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)
193
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?
194
252
 
195
253
  # Gets true token for the given +token+ (which may be an alias).
196
254
  #
197
255
  # @api public
198
256
  # @return [Symbol,nil] the true token if the given +token+ is an alias, token if
199
257
  # the token is a real token or +nil+ otherwise
200
- # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
201
- # @see I18n::Inflector.true_token Short name: I18n::Inflector.true_token
202
- # @overload inflection_true_token(token)
258
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
259
+ # @overload true_token(token)
203
260
  # Uses current locale to get a real token for the given +token+.
204
261
  # @param [Symbol,String] token name of the checked token
205
262
  # @return [Symbol,nil] the true token if the given +token+ is an alias, token if
206
263
  # the token is a real token or +nil+ otherwise
207
- # @overload inflection_true_token(token, locale)
264
+ # @overload true_token(token, locale)
208
265
  # Uses the given +locale+ to get a real token for the given +token+.
209
266
  # @param [Symbol,String] token name of the checked token
210
267
  # @param [Symbol] locale the locale to use
211
268
  # @return [Symbol,nil] the true token if the given +token+ is an alias, token if
212
269
  # the token is a real token or +nil+ otherwise
213
- def inflection_true_token(token, locale=nil)
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)
214
279
  return nil if token.to_s.empty?
215
- locale = inflector_prep_locale(locale)
216
- init_translations unless initialized?
217
- inflections = @inflection_tokens[locale]
218
- return nil if inflections.nil?
219
- entry = inflections[token]
220
- return token unless entry.nil?
221
- inflections = @inflection_aliases[locale]
222
- return nil if inflections.nil?
223
- entry = inflections[token]
224
- return nil if entry.nil?
225
- entry[:target]
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)
226
284
  end
285
+ alias_method :resolve_alias, :true_token
227
286
 
228
287
  # Gets a kind for the given +token+ (which may be an alias).
229
288
  #
230
289
  # @api public
231
- # @return [Symbol,nil] the kind of the given +token+ or alias or +nil+
232
- # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
233
- # @see I18n::Inflector.kind Short name: I18n::Inflector.kind
234
- # @overload inflection_true_token(token)
235
- # Uses current locale to get a kind for the given +token+ which may be an alias.
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).
236
294
  # @param [Symbol,String] token name of the token or alias
237
295
  # @return [Symbol,nil] the kind of the given +token+
238
296
  # for the current locale
239
- # @overload inflection_true_token(token, locale)
240
- # Uses the given +locale+ to get a kind for the given +token+ which may be an alias.
297
+ # @overload kind(token, locale)
298
+ # Uses the given +locale+ to get a kind of the given +token+ (which may be an alias).
241
299
  # @param [Symbol,String] token name of the token or alias
242
300
  # @param [Symbol] locale the locale to use
243
301
  # @return [Symbol,nil] the kind of the given +token+
244
302
  # for the given +locale+
245
- def inflection_kind(token, locale=nil)
303
+ def kind(token, locale=nil)
246
304
  return nil if token.to_s.empty?
247
- locale = inflector_prep_locale(locale)
248
- init_translations unless initialized?
249
- inflections = @inflection_tokens[locale]
250
- return nil if inflections.nil?
251
- entry = inflections[token]
252
- return entry[:kind] unless entry.nil?
253
- inflections = @inflection_aliases[locale]
254
- return nil if inflections.nil?
255
- entry = inflections[token]
256
- return nil if entry.nil?
257
- entry[:kind]
305
+ data_safe(locale).get_kind(token.to_sym)
258
306
  end
259
307
 
260
308
  # Gets available inflection tokens and their descriptions.
261
309
  #
262
310
  # @api public
263
- # @see I18n::Inflector.tokens Short name: I18n::Inflector.tokens
264
- # @raise [I18n::InvalidLocale] if a used locale is invalid
311
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
265
312
  # @return [Hash] the hash containing available inflection tokens and descriptions
266
313
  # @note You cannot deduce where aliases are pointing to, since the information
267
314
  # about a target is replaced by the description. To get targets use the
268
315
  # {#inflection_raw_tokens} method. To simply list aliases and their targets use
269
316
  # the {#inflection_aliases} method.
270
- # @overload inflection_tokens
317
+ # @overload tokens
271
318
  # Gets available inflection tokens and their descriptions.
272
319
  # @return [Hash] the hash containing available inflection tokens as keys
273
320
  # and their descriptions as values, including aliases,
274
321
  # for all kinds and current locale.
275
- # @overload inflection_tokens(kind)
322
+ # @overload tokens(kind)
276
323
  # Gets available inflection tokens and their descriptions for some +kind+.
277
- # @param [Symbol] kind the kind of inflection tokens to be returned
324
+ # @param [Symbol,String] kind the kind of inflection tokens to be returned
278
325
  # @return [Hash] the hash containing available inflection tokens as keys
279
326
  # and their descriptions as values, including aliases, for current locale.
280
- # @overload inflection_tokens(kind, locale)
327
+ # @overload tokens(kind, locale)
281
328
  # Gets available inflection tokens and their descriptions for some +kind+ and +locale+.
282
- # @param [Symbol] kind the kind of inflection tokens to be returned
329
+ # @param [Symbol,String] kind the kind of inflection tokens to be returned
283
330
  # @param [Symbol] locale the locale to use
284
331
  # @return [Hash] the hash containing available inflection tokens as keys
285
332
  # and their descriptions as values, including aliases, for current locale
286
- def inflection_tokens(kind=nil, locale=nil)
287
- locale = inflector_prep_locale(locale)
288
- true_tokens = inflection_true_tokens(kind, locale)
289
- aliases = @inflection_aliases[locale]
290
- return true_tokens if aliases.nil?
291
- aliases = aliases.reject{|k,v| v[:kind]!=kind} unless kind.nil?
292
- aliases = aliases.merge(aliases){|k,v| v[:description]}
293
- true_tokens.merge(aliases)
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)
294
337
  end
295
338
 
296
339
  # Gets available inflection tokens and their values.
297
340
  #
298
341
  # @api public
299
- # @see I18n::Inflector.raw_tokens Short name: I18n::Inflector.raw_tokens
300
342
  # @return [Hash] the hash containing available inflection tokens and descriptions (or alias pointers)
301
- # @raise [I18n::InvalidLocale] if a used locale is invalid
343
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
302
344
  # @note You may deduce whether the returned values are aliases or true tokens
303
- # by testing if a value is a type of Symbol or String.
304
- # @overload inflection_tokens_raw
345
+ # by testing if a value is a type of Symbol or String.
346
+ # @overload tokens_raw
305
347
  # Gets available inflection tokens and their values.
306
348
  # @return [Hash] the hash containing available inflection tokens as keys
307
349
  # and their descriptions as values. In case of aliases the returned
308
350
  # values are Symbols
309
- # @overload inflection_tokens_raw(kind)
351
+ # @overload tokens_raw(kind)
310
352
  # Gets available inflection tokens and their values for the given +kind+.
311
- # @param [Symbol] kind the kind of inflection tokens to be returned
353
+ # @param [Symbol,String] kind the kind of inflection tokens to be returned
312
354
  # @return [Hash] the hash containing available inflection tokens as keys
313
355
  # and their descriptions as values for the given +kind+. In case of
314
356
  # aliases the returned values are Symbols
315
- # @overload inflection_tokens_raw(kind, locale)
357
+ # @overload tokens_raw(kind, locale)
316
358
  # Gets available inflection tokens and their values for the given +kind+ and +locale+.
317
- # @param [Symbol] kind the kind of inflection tokens to be returned
359
+ # @param [Symbol,String] kind the kind of inflection tokens to be returned
318
360
  # @param [Symbol] locale the locale to use
319
361
  # @return [Hash] the hash containing available inflection tokens as keys
320
362
  # and their descriptions as values for the given +kind+ and +locale+.
321
363
  # In case of aliases the returned values are Symbols
322
- def inflection_tokens_raw(kind=nil, locale=nil)
323
- true_tokens = inflection_true_tokens(kind, locale)
324
- aliases = inflection_aliases(kind, locale)
325
- true_tokens.merge(aliases)
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)
326
368
  end
327
-
328
- alias_method :inflection_raw_tokens, :inflection_tokens_raw
369
+ alias_method :raw_tokens, :tokens_raw
329
370
 
330
371
  # Gets true inflection tokens and their values.
331
372
  #
332
373
  # @api public
333
374
  # @return [Hash] the hash containing available inflection tokens and descriptions
334
- # @see I18n::Inflector.true_tokens Short name: I18n::Inflector.true_tokens
335
- # @raise [I18n::InvalidLocale] if a used locale is invalid
375
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
336
376
  # @note It returns only true tokens, not aliases.
337
- # @overload inflection_tokens_true
377
+ # @overload tokens_true
338
378
  # Gets true inflection tokens and their values.
339
379
  # @return [Hash] the hash containing available inflection tokens as keys
340
380
  # and their descriptions as values
341
- # @overload inflection_tokens_true(kind)
381
+ # @overload tokens_true(kind)
342
382
  # Gets true inflection tokens and their values for the given +kind+.
343
- # @param [Symbol] kind the kind of inflection tokens to be returned
383
+ # @param [Symbol,String] kind the kind of inflection tokens to be returned
344
384
  # @return [Hash] the hash containing available inflection tokens as keys
345
385
  # and their descriptions as values for the given +kind+
346
- # @overload inflection_tokens_true(kind, locale)
386
+ # @overload tokens_true(kind, locale)
347
387
  # Gets true inflection tokens and their values for the given +kind+ and +value+.
348
- # @param [Symbol] kind the kind of inflection tokens to be returned
388
+ # @param [Symbol,String] kind the kind of inflection tokens to be returned
349
389
  # @param [Symbol] locale the locale to use
350
390
  # @return [Hash] the hash containing available inflection tokens as keys
351
391
  # and their descriptions as values for the given +kind+ and +locale+
352
- def inflection_tokens_true(kind=nil, locale=nil)
353
- locale = inflector_prep_locale(locale)
354
- init_translations unless initialized?
355
- inflections = @inflection_tokens[locale]
356
- return {} if inflections.nil?
357
- inflections = inflections.reject{|k,v| v[:kind]!=kind} unless kind.nil?
358
- inflections.merge(inflections){|k,v| v[:description]}
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)
359
396
  end
360
-
361
- alias_method :inflection_true_tokens, :inflection_tokens_true
397
+ alias_method :true_tokens, :tokens_true
362
398
 
363
399
  # Gets inflection aliases and their pointers.
364
400
  #
365
401
  # @api public
366
- # @see I18n::Inflector.aliases Short name: I18n::Inflector.aliases
367
- # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
402
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
368
403
  # @return [Hash] the Hash containing available inflection aliases (<tt>alias => target</tt>)
369
- # @overload inflection_aliases
404
+ # @overload aliases
370
405
  # Gets inflection aliases and their pointers.
371
406
  # @return [Hash] the Hash containing available inflection aliases
372
- # @overload inflection_aliases(kind)
407
+ # @overload aliases(kind)
373
408
  # Gets inflection aliases and their pointers for the given +kind+.
374
- # @param [Symbol] kind the kind of aliases to get
409
+ # @param [Symbol,String] kind the kind of aliases to get
375
410
  # @return [Hash] the Hash containing available inflection
376
411
  # aliases for the given +kind+ and current locale
377
- # @overload inflection_aliases(kind, locale)
412
+ # @overload aliases(kind, locale)
378
413
  # Gets inflection aliases and their pointers for the given +kind+ and +locale+.
379
- # @param [Symbol] kind the kind of aliases to get
414
+ # @param [Symbol,String] kind the kind of aliases to get
380
415
  # @param [Symbol] locale the locale to use
381
416
  # @return [Hash] the Hash containing available inflection
382
417
  # aliases for the given +kind+ and +locale+
383
- def inflection_aliases(kind=nil, locale=nil)
384
- locale = inflector_prep_locale(locale)
385
- init_translations unless initialized?
386
- aliases = @inflection_aliases[locale]
387
- return {} if aliases.nil?
388
- aliases = aliases.reject{|k,v| v[:kind]!=kind} unless kind.nil?
389
- aliases.merge(aliases){|k,v| v[:target]}
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)
390
422
  end
391
423
 
392
424
  # Gets known inflection kinds.
393
425
  #
394
426
  # @api public
395
- # @see I18n::Inflector.kinds Short name: I18n::Inflector.kinds
396
427
  # @return [Array<Symbol>] the array containing known inflection kinds
397
- # @raise [I18n::InvalidLocale] if a used locale is invalid
398
- # @overload available_inflection_kinds
428
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
429
+ # @overload kinds
399
430
  # Gets known inflection kinds for the current locale.
400
431
  # @return [Array<Symbol>] the array containing known inflection kinds
401
- # @overload available_inflection_kinds(locale)
432
+ # @overload kinds(locale)
402
433
  # Gets known inflection kinds for the given +locale+.
403
434
  # @param [Symbol] locale the locale for which operation has to be done
404
435
  # @return [Array<Symbol>] the array containing known inflection kinds
405
- def available_inflection_kinds(locale=nil)
406
- locale = inflector_prep_locale(locale)
407
- init_translations unless initialized?
408
- subtree = inflection_subtree(locale)
409
- return [] if subtree.nil?
410
- subtree.keys
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)
411
457
  end
412
458
 
413
459
  # Gets locales which have configured inflection support.
414
460
  #
415
461
  # @api public
416
- # @see I18n::Inflector.locales Short name: I18n::Inflector.locales
417
462
  # @return [Array<Symbol>] the array containing locales that support inflection
418
463
  # @note If +kind+ is given it returns only these locales
419
- # that are inflected and support inflection by this kind.
464
+ # that support inflection by this kind.
420
465
  def inflected_locales(kind=nil)
421
- init_translations unless initialized?
422
- inflected_locales = (@inflection_tokens.keys || [])
423
- return inflected_locales if kind.to_s.empty?
466
+ return [] if (!kind.nil? && kind.to_s.empty?)
467
+ inflected_locales = (@idb.keys || [])
468
+ return inflected_locales if kind.nil?
424
469
  kind = kind.to_sym
425
- inflected_locales.select do |loc|
426
- kinds = inflection_subtree(loc)
427
- kinds.respond_to?(:has_key?) && kinds.has_key?(kind)
428
- end
470
+ inflected_locales.reject{|l| @idb[l].nil? || !@idb[l].has_kind?(kind)}
429
471
  end
472
+ alias_method :locales, :inflected_locales
473
+ alias_method :supported_locales, :inflected_locales
430
474
 
431
- # Checks if a locale was configured to support inflection.
475
+ # Checks if the given locale was configured to support inflection.
432
476
  #
433
477
  # @api public
434
- # @see I18n::Inflector.locale? Short name: I18n::Inflector.locale?
435
- # @raise [I18n::InvalidLocale] if a used locale is invalid
478
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
436
479
  # @return [Boolean] +true+ if a locale supports inflection
437
480
  # @overload inflected_locale?(locale)
438
481
  # Checks if the given locale was configured to support inflection.
@@ -442,87 +485,31 @@ module I18n
442
485
  # Checks if the current locale was configured to support inflection.
443
486
  # @return [Boolean] +true+ if the current locale supports inflection
444
487
  def inflected_locale?(locale=nil)
445
- locale = inflector_prep_locale(locale)
446
- init_translations unless initialized?
447
- @inflection_tokens.has_key?(locale)
448
- end
449
-
450
- # Stores translations in memory.
451
- #
452
- # @api public
453
- # @raise [I18n::InvalidLocale] if the given +locale+ is invalid
454
- # @raise [I18n::BadInflectionToken] if a name of some loaded token is invalid
455
- # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists
456
- # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration
457
- # @note If inflections are changed it will regenerate proper internal
458
- # structures.
459
- # @return [Hash] the stored translations
460
- def store_translations(locale, data, options = {})
461
- r = super
462
- locale = inflector_prep_locale(locale)
463
- inflector_try_init
464
- if data.respond_to?(:has_key?)
465
- subdata = (data[:i18n] || data['i18n'])
466
- unless subdata.nil?
467
- subdata = (subdata[:inflections] || subdata['inflections'])
468
- unless subdata.nil?
469
- @inflection_tokens.delete locale
470
- @inflection_aliases.delete locale
471
- @inflection_defaults.delete locale
472
- load_inflection_tokens(locale, r[:i18n][:inflections])
473
- end
474
- end
475
- end
476
- r
488
+ not @idb[prep_locale(locale)].nil? rescue false
477
489
  end
490
+ alias_method :locale?, :inflected_locale?
491
+ alias_method :locale_supported?, :inflected_locale?
478
492
 
479
493
  # Gets the description of the given inflection token.
480
494
  #
481
495
  # @api public
482
- # @see I18n::Inflector.description Short name: I18n::Inflector.description
483
496
  # @note If the given +token+ is really an alias it
484
497
  # returns the description of the true token that
485
498
  # it points to.
486
- # @raise [I18n::InvalidLocale] if a used locale is invalid
499
+ # @raise [I18n::InvalidLocale] if there is no proper locale name
487
500
  # @return [String,nil] the descriptive string or +nil+
488
- # @overload inflection_token_description(token)
501
+ # @overload token_description(token)
489
502
  # Uses current locale to get description of the given token.
490
503
  # @return [String,nil] the descriptive string or +nil+ if something
491
504
  # went wrong (e.g. token was not found)
492
- # @overload inflection_token_description(token, locale)
505
+ # @overload token_description(token, locale)
493
506
  # Uses the given +locale+ to get description of the given inflection token.
494
507
  # @param [Symbol] locale the locale to use
495
508
  # @return [String,nil] the descriptive string or +nil+ if something
496
509
  # went wrong (e.g. token was not found)
497
- def inflection_token_description(token, locale=nil)
498
- locale = inflector_prep_locale(locale)
510
+ def token_description(token, locale=nil)
499
511
  return nil if token.to_s.empty?
500
- init_translations unless initialized?
501
- inflections = @inflection_tokens[locale]
502
- aliases = @inflection_aliases[locale]
503
- return nil if (inflections.nil? || aliases.nil?)
504
- token = token.to_sym
505
- match = (inflections[token] || aliases[token])
506
- return nil if match.nil?
507
- match[:description]
508
- end
509
-
510
- protected
511
-
512
- # Processes +locale+ name and validates
513
- # if it's correct (not empty and not +nil+).
514
- #
515
- # @note If the +locale+ is not correct, it
516
- # tries to use locale from {I18n.locale} and validates it
517
- # as well.
518
- # @param [Symbol,String] locale the locale identifier
519
- # @raise [I18n::InvalidLocale] if there is no proper locale name
520
- # @return [Symbol] the given locale or the global locale
521
- # and usable or the global locale for I18n
522
- def inflector_prep_locale(locale=nil)
523
- locale ||= I18n.locale
524
- raise I18n::InvalidLocale.new(locale) if locale.to_s.empty?
525
- locale.to_sym
512
+ data_safe(locale).get_description(token.to_sym)
526
513
  end
527
514
 
528
515
  # Interpolates inflection values in a given +string+
@@ -533,39 +520,45 @@ module I18n
533
520
  # @param [String,Symbol] locale the locale identifier
534
521
  # @param [Hash] options the options
535
522
  # @option options [Boolean] :inflector_excluded_defaults (false) local switch
536
- # that overrides global setting (see: {#inflector_excluded_defaults})
523
+ # that overrides global setting (see: {I18n::Inflector::InflectionOptions#excluded_defaults})
537
524
  # @option options [Boolean] :inflector_unknown_defaults (true) local switch
538
- # that overrides global setting (see: {#inflector_unknown_defaults})
525
+ # that overrides global setting (see: {I18n::Inflector::InflectionOptions#unknown_defaults})
539
526
  # @option options [Boolean] :inflector_raises (false) local switch
540
- # that overrides global setting (see: {#inflector_raises})
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})
541
530
  # @return [String] the string with interpolated patterns
542
- def interpolate_inflections(string, locale, options = {})
543
- used_kinds = options.except(*I18n::Backend::Inflector::INFLECTOR_RESERVED_KEYS)
544
- raises = inflector_raises? options.delete(:inflector_raises)
545
- unknown_defaults = inflector_unknown_defaults? options.delete(:inflector_unknown_defaults)
546
- excluded_defaults = inflector_excluded_defaults? options.delete(:inflector_excluded_defaults)
547
- inflections = @inflection_tokens[locale]
548
- defaults = @inflection_defaults[locale]
549
- aliases = @inflection_aliases[locale]
550
-
551
- string.gsub(I18n::Backend::Inflector::PATTERN) do
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]
540
+
541
+ string.gsub(I18n::Inflector::PATTERN) do
552
542
  pattern_fix = $1
553
543
  pattern_content = $2
554
544
  ext_pattern = $&
555
545
  parsed_kind = nil
546
+ default_token = nil
556
547
  ext_value = nil
557
548
  ext_freetext = ''
558
549
  found = false
559
550
  parsed_default_v= nil
560
551
 
561
552
  # leave escaped pattern as is
562
- next ext_pattern[1..-1] if I18n::Backend::Inflector::ESCAPES.has_key?(pattern_fix)
553
+ next ext_pattern[1..-1] if I18n::Inflector::ESCAPES.has_key?(pattern_fix)
563
554
 
564
555
  # process pattern content's
565
- pattern_content.scan(I18n::Backend::Inflector::TOKENS) do
556
+ pattern_content.scan(I18n::Inflector::TOKENS) do
566
557
  ext_token = $1.to_s
567
558
  ext_value = $2.to_s
568
559
  ext_freetext = $3.to_s
560
+ tokens = Hash.new(false)
561
+ negatives = Hash.new(false)
569
562
  kind = nil
570
563
  option = nil
571
564
 
@@ -578,29 +571,54 @@ module I18n
578
571
  next
579
572
  end
580
573
 
581
- # set token and get current kind for it
582
- token = ext_token.to_sym
583
- t_entry = inflections[token]
584
-
585
- # kind not found for a given token?
586
- if t_entry.nil?
587
- raise I18n::InvalidInflectionToken.new(ext_pattern, ext_token) if raises
588
- next
589
- end
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
590
581
 
591
- # set kind
592
- kind = t_entry[:kind]
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
593
 
594
- # set processed kind after matching first token in pattern
595
- if parsed_kind.nil?
596
- parsed_kind = kind
597
- elsif parsed_kind != kind
598
- raise I18n::MisplacedInflectionToken.new(ext_pattern, token, parsed_kind) if raises
599
- next
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]
600
616
  end
601
617
 
602
- # memorize default option for further processing
603
- default_token = defaults[kind]
618
+ # self-explanatory
619
+ if (tokens.empty? && negatives.empty?)
620
+ raise I18n::InvalidInflectionToken.new(ext_pattern, ext_token) if raises
621
+ end
604
622
 
605
623
  # fetch the kind's option or fetch default if an option does not exists
606
624
  option = options.has_key?(kind) ? options[kind] : default_token
@@ -611,38 +629,38 @@ module I18n
611
629
  option = unknown_defaults ? default_token : nil
612
630
  else
613
631
  # validate option and if it's unknown try in aliases
614
- option = option.to_sym
615
- unless inflections.has_key?(option)
616
- option = aliases[option]
617
- if option.nil?
618
- # if still nothing then fall back to default value
619
- # for a kind in unknown_defaults switch is on
620
- option = unknown_defaults ? default_token : nil
621
- else
622
- option = option[:target]
623
- end
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
624
638
  end
625
639
  end
626
640
 
627
641
  # if the option is still unknown
628
642
  if option.nil?
629
- raise I18n::InvalidOptionForKind.new(ext_pattern, kind, ext_token, option) if raises
643
+ raise I18n::InvalidOptionForKind.new(ext_pattern, kind, ext_token, nil) if raises
630
644
  next
631
645
  end
632
646
 
633
- # memorize default token's value for further processing
647
+ # memorize default value for further processing
634
648
  # outside this block if excluded_defaults switch is on
635
- parsed_default_v = ext_value if (excluded_defaults && token == default_token)
649
+ parsed_default_v = ext_value if (excluded_defaults && !default_token.nil?)
636
650
 
637
- # throw the value if a given option matches the token
638
- next unless option == token
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
639
657
 
640
658
  # skip further evaluation of the pattern
641
659
  # since the right token has been found
642
660
  found = true
643
661
  break
644
662
 
645
- end # single token:value processing
663
+ end # single token (or a group) processing
646
664
 
647
665
  result = nil
648
666
 
@@ -653,222 +671,36 @@ module I18n
653
671
  result = ext_value
654
672
  elsif (excluded_defaults && !parsed_kind.nil?)
655
673
  # if there is excluded_defaults switch turned on
656
- # and a correct token was found in options but
674
+ # and a correct token was found in an inflection option but
657
675
  # has not been found in a pattern then interpolate
658
676
  # the pattern with a value picked for the default
659
677
  # token for that kind if a default token was present
660
678
  # in a pattern
661
679
  kind = nil
662
680
  token = options[parsed_kind]
663
- kind = inflections[token] unless token.nil?
664
- result = parsed_default_v unless (kind.nil? || kind[:kind].nil?)
681
+ kind = idb.get_kind(token)
682
+ result = parsed_default_v unless kind.nil?
665
683
  end
666
684
 
667
685
  pattern_fix + (result || ext_freetext)
668
686
 
669
687
  end # single pattern processing
670
-
671
- end
672
-
673
- # Initializes internal hashes used for keeping inflections configuration.
674
- #
675
- # @return [void]
676
- def inflector_try_init
677
- return nil if defined? @inflector_initialized
678
- @inflection_tokens ||= {}
679
- @inflection_aliases ||= {}
680
- @inflection_defaults ||= {}
681
- @inflector_excluded_defaults = false
682
- @inflector_unknown_defaults = true
683
- @inflector_raises = false
684
- @inflector_initialized = true
685
- nil
686
- end
687
688
 
688
- # Takes care of loading inflection tokens
689
- # for all languages (locales) that have them
690
- # defined.
691
- #
692
- # @note It calls {I18n::Backend::Simple#init_translations I18n::Backend::Simple#init_translations}
693
- # @raise [I18n::BadInflectionToken] if a name of some loaded token is invalid
694
- # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists
695
- # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration
696
- # @return [Boolean] +true+ if everything went fine
697
- def init_translations
698
- inflector_try_init
699
- super
700
689
  end
701
690
 
702
- # Removes inflection patterns from the translated string.
703
- #
704
- # @param [String] translated_string the string that is translated
705
- # @return [String] the translation with any inflection patterns removed
706
- def clear_inflection_patterns(translated_string)
707
- translated_string.gsub(I18n::Backend::Inflector::PATTERN,'')
708
- end
691
+ protected
709
692
 
710
- # Gives access to the internal structure containing configuration data
711
- # for a given locale.
712
- #
713
- # @note Under some very rare conditions this method may be called while
714
- # translation data is loading. It must always return when translations
715
- # are not initialized. Otherwise it will cause loops and someone in Poland
716
- # will eat a kittien!
717
- # @param [Symbol] locale the locale to use
718
- # @return [Hash,nil] part of the translation data that
719
- # reflects inflections for a given locale or +nil+
720
- # if translations are not initialized
721
- def inflection_subtree(locale)
722
- return nil unless initialized?
723
- lookup(locale, :"i18n.inflections", [], :fallback => true, :raise => :false)
693
+ # @private
694
+ def data(locale=nil)
695
+ @idb[prep_locale(locale)]
724
696
  end
725
697
 
726
- # Resolves an alias for a token if the given +token+ is an alias.
727
- #
728
- # @note It does take care of aliasing loops (max traverses is set to 64).
729
- # @raise [I18n::BadInflectionToken] if a name of the token that alias points to is corrupted
730
- # @raise [I18n::BadInflectionAlias] if an alias points to token that does not exists
731
- # @return [Symbol] the true token that alias points to if the given +token+
732
- # is an alias or the given +token+ if it is a true token
733
- # @overload shorten_inflection_alias(token, kind, locale)
734
- # Resolves an alias for a token if the given +token+ is an alias for the given +locale+ and +kind+.
735
- # @note This version uses internal subtree and needs the translation data to be initialized.
736
- # @param [Symbol] token the token name
737
- # @param [Symbol] kind the kind of the given token
738
- # @param [Symbol] locale the locale to use
739
- # @return [Symbol] the true token that alias points to if the given +token+
740
- # is an alias or the given +token+ if it is a true token
741
- # @overload shorten_inflection_alias(token, kind, locale, subtree)
742
- # Resolves an alias for a token if the given +token+ is an alias for the given +locale+ and +kind+.
743
- # @param [Symbol] token the token name
744
- # @param [Symbol] kind the kind of the given token
745
- # @param [Symbol] locale the locale to use
746
- # @param [Hash] subtree the tree (in a form of nested Hashes) containing inflection tokens to scan
747
- # @return [Symbol] the true token that alias points to if the given +token+
748
- # is an alias or the given +token+ if it is a true token
749
- def shorten_inflection_alias(token, kind, locale, subtree=nil, count=0)
750
- count += 1
751
- return nil if count > 64
752
-
753
- inflections_tree = subtree || inflection_subtree(locale)
754
- return nil if (inflections_tree.nil? || inflections_tree.empty?)
755
-
756
- kind_subtree = inflections_tree[kind]
757
- value = kind_subtree[token].to_s
758
-
759
- if value.slice(0,1) != I18n::Backend::Inflector::ALIAS_MARKER
760
- if kind_subtree.has_key?(token)
761
- return token
762
- else
763
- # that should never happend but who knows
764
- raise I18n::BadInflectionToken.new(locale, token, kind)
765
- end
766
- else
767
- orig_token = token
768
- token = value[1..-1]
769
- if token.to_s.empty?
770
- raise I18n::BadInflectionToken.new(locale, token, kind)
771
- end
772
- token = token.to_sym
773
- if kind_subtree[token].nil?
774
- raise BadInflectionAlias.new(locale, orig_token, kind, token)
775
- else
776
- shorten_inflection_alias(token, kind, locale, inflections_tree, count)
777
- end
778
- end
779
-
780
- end
781
-
782
- # Uses the inflections subtree and creates internal mappings
783
- # to resolve kinds assigned to inflection tokens and aliases, including defaults.
784
- # @return [Hash,nil] the internal Hash containing inflection tokens or +nil+ if something went wrong
785
- # @raise [I18n::BadInflectionToken] if a name of some loaded token is invalid
786
- # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists
787
- # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration
788
- # @overload load_inflection_tokens(locale)
789
- # @note That version calls the {inflection_subtree} method to obtain internal translations data.
790
- # Loads inflection tokens for the given locale using internal hash of stored translations. Requires
791
- # translations to be initialized.
792
- # @param [Symbol] locale the locale to use and work for
793
- # @return [Hash,nil] the internal Hash containing inflection tokens (<tt>token => kind</tt>)
794
- # or +nil+ if translations were not initialized
795
- # @overload load_inflection_tokens(locale, subtree)
796
- # Loads inflection tokens for the given locale using data given in an argument
797
- # @param [Symbol] locale the locale to use and work for
798
- # @param [Hash] subtree the tree (in a form of nested Hashes) containing inflection tokens to scan
799
- # @return [Hash,nil] the internal Hash containing inflection tokens (<tt>token => kind</tt>)
800
- # or +nil+ if the given subtree was wrong or empty
801
- def load_inflection_tokens(locale, subtree=nil)
802
- return @inflection_tokens[locale] if @inflection_tokens.has_key?(locale)
803
- inflections_tree = subtree || inflection_subtree(locale)
804
- return nil if (inflections_tree.nil? || inflections_tree.empty?)
805
- ivars = @inflection_tokens[locale] = {}
806
- aliases = @inflection_aliases[locale] = {}
807
- defaults = @inflection_defaults[locale] = {}
808
-
809
- inflections_tree.each_pair do |kind, tokens|
810
- tokens.each_pair do |token, description|
811
-
812
- # test for duplicate
813
- if ivars.has_key?(token)
814
- raise I18n::DuplicatedInflectionToken.new(ivars[token], kind, token)
815
- end
816
-
817
- # validate token's name
818
- if token.nil?
819
- raise I18n::BadInflectionToken.new(locale, token, kind)
820
- end
821
-
822
- # validate token's description
823
- if description.nil?
824
- raise I18n::BadInflectionToken.new(locale, token, kind, description)
825
- end
826
-
827
- # handle default token for a kind
828
- if token == :default
829
- if defaults.has_key?(kind) # should never happend unless someone is messing with @translations
830
- raise I18n::DuplicatedInflectionToken.new(kind, nil, token)
831
- end
832
- defaults[kind] = description.to_sym
833
- next
834
- end
835
-
836
- # handle alias
837
- if description.slice(0,1) == I18n::Backend::Inflector::ALIAS_MARKER
838
- real_token = shorten_inflection_alias(token, kind, locale, inflections_tree)
839
- unless real_token.nil?
840
- real_token = real_token.to_sym
841
- aliases[token] = {}
842
- aliases[token][:kind] = kind
843
- aliases[token][:target] = real_token
844
- aliases[token][:description] = inflections_tree[kind][real_token].to_s
845
- end
846
- next
847
- end
848
-
849
- ivars[token] = {}
850
- ivars[token][:kind] = kind.to_sym
851
- ivars[token][:description] = description.to_s
852
- end
853
- end
854
-
855
- # validate defaults
856
- defaults.each_pair do |kind, pointer|
857
- unless ivars.has_key?(pointer)
858
- # default may be an alias
859
- target = aliases[pointer]
860
- target = target[:target] unless target.nil?
861
- real_token = (target || shorten_inflection_alias(:default, kind, locale, inflections_tree))
862
- raise I18n::BadInflectionAlias.new(locale, :default, kind, pointer) if real_token.nil?
863
- defaults[kind] = real_token.to_sym
864
- end
865
- end
866
-
867
- ivars
698
+ # @private
699
+ def data_safe(locale=nil)
700
+ @idb[prep_locale(locale)] || I18n::Inflector::InflecitonData.new
868
701
  end
869
702
 
870
703
  end
704
+
871
705
  end
872
-
873
-
874
706
  end