i18n-inflector 1.0.11 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
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
7
  # This file contains inline documentation data
8
8
  # that would make the file with code less readable
@@ -10,414 +10,336 @@
10
10
  #
11
11
 
12
12
  module I18n
13
- module Backend
14
- # Overwrites the Simple backend translate method so that it will interpolate
15
- # additional inflection tokens present in translations. These tokens may
16
- # appear in *patterns* which are contained within <tt>@{</tt> and <tt>}</tt>
17
- # symbols.
18
- #
19
- # You can choose different kinds (gender, title, person, time, author, etc.)
20
- # of tokens to group them in a meaningful, semantical sets. That means you can
21
- # apply Inflector to do simple inflection by a gender or a person, when some
22
- # language requires it.
23
- #
24
- # To achieve similar functionality lambdas can be used but there might be
25
- # some areas of appliance that including proc objects in translations
26
- # is prohibited.
27
- # If you have a troop of happy translators that shouldn't have the
28
- # ability to execute any code yet you need some simple inflection
29
- # then you can make use of this module.
30
- # == Usage
31
- # require 'i18-inflector'
32
- #
33
- # i18n.translate('welcome')
34
- # # where welcome maps to: "Dear @{f:Madam|m:Sir}"
35
- #
36
- # == Inflection pattern
37
- # An example inflection pattern contained in a translation record looks like:
38
- # welcome: "Dear @{f:Madam|m:Sir|n:You|All}"
39
- #
40
- # The +f+, +m+ and +n+ are inflection *tokens* and +Madam+, +Sir+, +You+ and
41
- # +All+ are *values*. Only one value is going to replace the whole
42
- # pattern. To select which one an additional option is used. That option
43
- # must be passed to translate method.
44
- #
45
- # == Configuration
46
- # To recognize tokens present in patterns this module uses keys grouped
47
- # in the scope called `inflections` for a given locale. For instance
48
- # (YAML format):
49
- # en:
50
- # i18n:
51
- # inflections:
52
- # gender:
53
- # f: "female"
54
- # m: "male"
55
- # n: "neuter"
56
- # woman: @f
57
- # man: @m
58
- # default: n
59
- #
60
- # Elements in the example above are:
61
- # * +en+: language
62
- # * +i18n+: configuration scope
63
- # * +inflections+: inflections configuration scope
64
- # * +gender+: kind scope
65
- # * +f+, +m+, +n+: inflection tokens
66
- # * <tt>"male"</tt>, <tt>"female"</tt>, <tt>"neuter"</tt>: tokens' descriptions
67
- # * +woman+, +man+: inflection aliases
68
- # * <tt>@f</tt>, <tt>@m</tt>: pointers to real tokens
69
- # * +default+: default token for a kind +gender+
70
- #
71
- # === Kind
72
- # Note the fourth scope selector in the example above (+gender+). It's called
73
- # the *kind* and contains *tokens*. We have the kind
74
- # +gender+ to which the inflection tokens +f+, +m+ and +n+ are
75
- # assigned.
76
- #
77
- # You cannot assign the same token to more than one kind.
78
- # Trying to do that will raise DuplicatedInflectionToken exception.
79
- # This is required in order to keep patterns simple and tokens interpolation
80
- # fast.
81
- #
82
- # Kind is also used to instruct I18n.translate method which
83
- # token it should pick. This will be explained later.
84
- #
85
- # === Aliases
86
- # Aliases are special tokens that point to other tokens. They cannot
87
- # be used in inflection patterns but they are fully recognized values
88
- # of options while evaluating kinds.
89
- #
90
- # Aliases might be helpful in multilingual applications that are using
91
- # a fixed set of values passed through options to describe some properties
92
- # of messages, e.g. +masculine+ and +feminine+ for a grammatical gender.
93
- # Translators may then use their own tokens (like +f+ and +m+ for English)
94
- # to produce pretty and intuitive patterns.
95
- #
96
- # For example: if some application uses database with gender assigned
97
- # to a user which may be +male+, +female+ or +none+, then a translator
98
- # for some language may find it useful to map impersonal token (<tt>none</tt>)
99
- # to the +neuter+ token, since in translations for his language the
100
- # neuter gender is in use.
101
- #
102
- # Here is the example of such situation:
103
- #
104
- # en:
105
- # i18n:
106
- # inflections:
107
- # gender:
108
- # male: "male"
109
- # female: "female"
110
- # none: "impersonal form"
111
- # default: none
112
- #
113
- # pl:
114
- # i18n:
115
- # inflections:
116
- # gender:
117
- # k: "female"
118
- # m: "male"
119
- # n: "neuter"
120
- # male: @k
121
- # female: @m
122
- # none: @n
123
- # default: none
124
- #
125
- # In the case above Polish translator decided to use neuter
126
- # instead of impersonal form when +none+ token will be passed
127
- # through the option +:gender+ to the translate method. He
128
- # also decided that he will use +k+, +m+ or +n+ in patterns,
129
- # because the names are short and correspond to gender names in
130
- # Polish language.
131
- #
132
- # Aliases may point to other aliases. While loading inflections they
133
- # will be internally shortened and they will always point to real tokens,
134
- # not other aliases.
135
- #
136
- # === Default token
137
- # There is special token called the +default+, which points
138
- # to a token that should be used if translation routine cannot deduce
139
- # which one it should use because a proper option was not given.
140
- #
141
- # Default tokens may point to aliases and may use aliases' syntax, e.g.:
142
- # default: @man
143
- #
144
- # === Descriptions
145
- # The values of keys in the example (+female+, +male+ and +neuter+)
146
- # are *descriptions* which are not used by interpolation routines
147
- # but might be helpful (e.g. in UI). For obvious reasons you cannot
148
- # describe aliases.
149
- #
150
- # == Tokens
151
- # The token is an element of a pattern. A pattern may have many tokens
152
- # of the same kind separated by vertical bars. Each token name used in a
153
- # pattern should end with colon sign. After this colon a value should
154
- # appear (or an empty string).
155
- #
156
- # == Interpolation
157
- # The value of each token present in a pattern is to be picked by the interpolation
158
- # routine and will replace the whole pattern, when the token name from that
159
- # pattern matches the value of an option passed to {I18n.translate} method.
160
- # This option is called <b>the inflection option</b>. Its name should be
161
- # the same as a *kind* of tokens used within a pattern. The first token in a pattern
162
- # determines the kind of all tokens used in that pattern. You can pass
163
- # many inflection options, each one designated for keeping a token of a
164
- # different kind.
165
- #
166
- # ==== Examples:
167
- # # welcome is "Dear @{f:Madam|m:Sir|n:You|All}"
168
- #
169
- # I18n.translate('welcome', :gender => :m)
170
- # # => "Dear Sir"
171
- #
172
- # I18n.translate('welcome', :gender => :unknown)
173
- # # => "Dear All"
174
- #
175
- # I18n.translate('welcome')
176
- # # => "Dear You"
177
- #
178
- # In the second example the <b>fallback value</b> +All+ was interpolated
179
- # because the routine had been unable to find the token called +:unknown+.
180
- # That differs from the latest example, in which there was no option given,
181
- # so the default token for a kind had been applied (in this case +n+).
182
- #
183
- # == Local fallbacks (free text)
184
- # The fallback value will be used when any of the given tokens from
185
- # pattern cannot be interpolated.
186
- #
187
- # Be aware that enabling extended error reporting makes it unable
188
- # to use fallback values in most cases. Local fallbacks will then be
189
- # applied only when a given option contains a proper value for some
190
- # kind but it's just not present in a pattern, for example:
191
- #
192
- # I18n.locale = :en
193
- # I18n.backend.store_translations 'en', 'welcome' => 'Dear @{n:You|All}'
194
- # I18n.backend.store_translations 'en', :i18n => { :inflections => {
195
- # :gender => { :n => 'neuter', :o => 'other' }}}
196
- #
197
- # I18n.translate('welcome', :gender => :o, :inflector_raises => true)
198
- # # => "Dear All"
199
- #
200
- # # since the token :o was configured but not used in the pattern
201
- #
202
- # == Unknown and empty tokens in options
203
- # If an option containing token is not present at all then the interpolation
204
- # routine will try the default token for a processed kind if the default
205
- # token is present in a pattern. The same thing will happend if the option
206
- # is present but its value is unknown, empty or +nil+.
207
- # If the default token is not present in a pattern or is not defined in
208
- # a configuration data then the processed pattern will result in an empty
209
- # string or in a local fallback value if there is a free text placed
210
- # in a pattern.
211
- #
212
- # You can change this default behavior and force inflector
213
- # not to use a default token when a value of an option for a kind is unknown,
214
- # empty or +nil+ but only when it's not present.
215
- # To do that you should set option +:inflector_unknown_defaults+ to
216
- # +false+ and pass it to I18n.translate method. Other way is to set this
217
- # globally by using the method called inflector_unknown_defaults.
218
- # See #inflector_unknown_defaults for examples showing how the
219
- # translation results are changing when that switch is applied.
220
- #
221
- # == Mixing inflection and standard interpolation patterns
222
- # The Inflector module allows you to include standard <tt>%{}</tt>
223
- # patterns inside of inflection patterns. The value of a standard
224
- # interpolation variable will be evaluated and interpolated *before*
225
- # processing an inflection pattern. For example:
226
- #
227
- # I18n.backend.store_translations(:xx, 'hi' => 'Dear @{f:Lady|m:%{test}}!')
228
- #
229
- # I18n.t('hi', :gender => :m, :locale => :xx, :test => "Dude")
230
- # # => Dear Dude!
231
- #
232
- # == Escaping a pattern
233
- # If there is a need to translate something that matches an inflection
234
- # pattern the escape symbols can be used to disable the interpolation. These
235
- # symbols are <tt>\\</tt> and +@+ and they should be placed just before
236
- # a pattern that should be left untouched. For instance:
237
- #
238
- # I18n.backend.store_translations(:xx, 'hi' => 'This is the @@{pattern}!')
239
- #
240
- # I18n.t('hi', :gender => :m, :locale => :xx)
241
- # # => This is the @{pattern}!
242
- #
243
- # == Errors
244
- # By default the module will silently ignore any interpolation errors.
245
- # You can turn off this default behavior by passing +:inflector_raises+ option.
246
- #
247
- # === Usage of +:inflector_raises+ option
248
- #
249
- # I18n.locale = :en
250
- # I18n.backend.store_translations 'en', 'welcome' => 'Dear @{m:Sir|f:Madam|Fallback}'
251
- # I18n.backend.store_translations 'en', :i18n => { :inflections => {
252
- # :gender => {
253
- # :f => 'female',
254
- # :m => 'male'
255
- # }}}
256
- #
257
- # I18n.translate('welcome', :inflector_raises => true)
258
- #
259
- # # => I18n::InvalidOptionForKind: option :gender required by the pattern
260
- # # "@{m:Sir|f:Madam|Fallback}" was not found
261
- #
262
- # Here are the exceptions that may be raised when option +:inflector_raises+
263
- # is set to +true+:
264
- #
265
- # * {I18n::InvalidOptionForKind I18n::InvalidOptionForKind}
266
- # * {I18n::InvalidInflectionToken I18n::InvalidInflectionToken}
267
- # * {I18n::MisplacedInflectionToken I18n::MisplacedInflectionToken}
268
- #
269
- # There are also exceptions that are raised regardless of :+inflector_raises+
270
- # presence or value.
271
- # These are usually caused by critical errors encountered during processing
272
- # inflection data. Here is the list:
273
- #
274
- # * {I18n::InvalidLocale I18n::InvalidLocale}
275
- # * {I18n::DuplicatedInflectionToken I18n::DuplicatedInflectionToken}
276
- # * {I18n::BadInflectionToken I18n::BadInflectionToken}
277
- # * {I18n::BadInflectionAlias I18n::BadInflectionAlias}
278
- #
279
- module Inflector
280
- # When this switch is set to +true+ then inflector falls back to the default
281
- # token for a kind if an inflection option passed to the {#translate} is unknown
282
- # or +nil+. Note that the value of the default token will be
283
- # interpolated only when this token is present in a pattern. This switch
284
- # is by default set to +true+.
285
- #
286
- # @note Local option +:inflector_unknown_defaults+ passed to translation method
287
- # overrides this setting.
288
- #
289
- # @api public
290
- # @see #inflector_unknown_defaults?
291
- # @see I18n::Inflector.unknown_defaults Short name: I18n::Inflector.unknown_defaults
292
- # @return [Boolean] the state of the switch
293
- #
294
- # @example Usage of +:inflector_unknown_defaults+ option preparation
295
- #
296
- # I18n.locale = :en
297
- # I18n.backend.store_translations 'en', :i18n => { :inflections => {
298
- # :gender => {
299
- # :n => 'neuter',
300
- # :o => 'other',
301
- # :default => 'n' }}}
302
- #
303
- # I18n.backend.store_translations 'en', 'welcome' => 'Dear @{n:You|o:Other}'
304
- # I18n.backend.store_translations 'en', 'welcome_free' => 'Dear @{n:You|o:Other|Free}'
305
- #
306
- # @example Example 1
307
- #
308
- # # :gender option is not present,
309
- # # unknown tokens in options are falling back to default
310
- #
311
- # I18n.t('welcome')
312
- # # => "Dear You"
313
- #
314
- # # :gender option is not present,
315
- # # unknown tokens from options are not falling back to default
316
- #
317
- # I18n.t('welcome', :inflector_unknown_defaults => false)
318
- # # => "Dear You"
319
- #
320
- # # :gender option is not present, free text is present,
321
- # # unknown tokens from options are not falling back to default
322
- #
323
- # I18n.t('welcome_free', :inflector_unknown_defaults => false)
324
- # # => "Dear You"
325
- #
326
- # @example Example 2
327
- #
328
- # # :gender option is nil,
329
- # # unknown tokens from options are falling back to default token for a kind
330
- #
331
- # I18n.t('welcome', :gender => nil)
332
- # # => "Dear You"
333
- #
334
- # # :gender option is nil
335
- # # unknown tokens from options are not falling back to default token for a kind
336
- #
337
- # I18n.t('welcome', :gender => nil, :inflector_unknown_defaults => false)
338
- # # => "Dear "
339
- #
340
- # # :gender option is nil, free text is present
341
- # # unknown tokens from options are not falling back to default token for a kind
342
- #
343
- # I18n.t('welcome_free', :gender => nil, :inflector_unknown_defaults => false)
344
- # # => "Dear Free"
345
- #
346
- # @example Example 3
347
- #
348
- # # :gender option is unknown,
349
- # # unknown tokens from options are falling back to default token for a kind
350
- #
351
- # I18n.t('welcome', :gender => :unknown_blabla)
352
- # # => "Dear You"
353
- #
354
- # # :gender option is unknown,
355
- # # unknown tokens from options are not falling back to default token for a kind
356
- #
357
- # I18n.t('welcome', :gender => :unknown_blabla, :inflector_unknown_defaults => false)
358
- # # => "Dear "
359
- #
360
- # # :gender option is unknown, free text is present
361
- # # unknown tokens from options are not falling back to default token for a kind
362
- #
363
- # I18n.t('welcome_free', :gender => :unknown_blabla, :inflector_unknown_defaults => false)
364
- # # => "Dear Free"
365
- attr_accessor :inflector_unknown_defaults
13
+ # @version 2.0
14
+ # This module contains inflection classes and modules for enabling
15
+ # the inflection support in I18n translations.
16
+ # Its submodule overwrites the Simple backend translate method
17
+ # so that it will interpolate additional inflection tokens present
18
+ # in translations. These tokens may appear in *patterns* which
19
+ # are contained within <tt>@{</tt> and <tt>}</tt> symbols.
20
+ #
21
+ # == Usage
22
+ # require 'i18-inflector'
23
+ #
24
+ # i18n.translate('welcome', :gender => :f)
25
+ # # => Dear Madam
26
+ #
27
+ # i18n.inflector.kinds
28
+ # # => [:gender]
29
+ #
30
+ # i18n.inflector.true_tokens.keys
31
+ # # => [:f, :m, :n]
32
+ #
33
+ # == Inflection pattern
34
+ # An example inflection pattern contained in a translation record looks like:
35
+ # welcome: "Dear @{f:Madam|m:Sir|n:You|All}"
36
+ #
37
+ # The +f+, +m+ and +n+ are inflection *tokens* and +Madam+, +Sir+, +You+ and
38
+ # +All+ are *values*. Only one value is going to replace the whole
39
+ # pattern. To select which one an additional option is used. That option
40
+ # must be passed to translate method.
41
+ #
42
+ # == Configuration
43
+ # To recognize tokens present in patterns this module uses keys grouped
44
+ # in the scope called `inflections` for a given locale. For instance
45
+ # (YAML format):
46
+ # en:
47
+ # i18n:
48
+ # inflections:
49
+ # gender:
50
+ # f: "female"
51
+ # m: "male"
52
+ # n: "neuter"
53
+ # woman: @f
54
+ # man: @m
55
+ # default: n
56
+ #
57
+ # Elements in the example above are:
58
+ # * +en+: language
59
+ # * +i18n+: configuration scope
60
+ # * +inflections+: inflections configuration scope
61
+ # * +gender+: kind scope
62
+ # * +f+, +m+, +n+: inflection tokens
63
+ # * <tt>"male"</tt>, <tt>"female"</tt>, <tt>"neuter"</tt>: tokens' descriptions
64
+ # * +woman+, +man+: inflection aliases
65
+ # * <tt>@f</tt>, <tt>@m</tt>: pointers to real tokens
66
+ # * +default+: default token for a kind +gender+
67
+ #
68
+ # === Kind
69
+ # Note the fourth scope selector in the example above (+gender+). It's called
70
+ # the *kind* and contains *tokens*. We have the kind
71
+ # +gender+ to which the inflection tokens +f+, +m+ and +n+ are
72
+ # assigned.
73
+ #
74
+ # You cannot assign the same token to more than one kind.
75
+ # Trying to do that will raise DuplicatedInflectionToken exception.
76
+ # This is required in order to keep patterns simple and tokens interpolation
77
+ # fast.
78
+ #
79
+ # Kind is also used to instruct I18n.translate method which
80
+ # token it should pick. This will be explained later.
81
+ #
82
+ # === Tokens
83
+ # The token is an element of a pattern. A pattern may have many tokens
84
+ # of the same kind separated by vertical bars. Each token name used in a
85
+ # pattern should end with colon sign. After this colon a value should
86
+ # appear (or an empty string).
87
+ #
88
+ # === Aliases
89
+ # Aliases are special tokens that point to other tokens. They cannot
90
+ # be used in inflection patterns but they are fully recognized values
91
+ # of options while evaluating kinds.
92
+ #
93
+ # Aliases might be helpful in multilingual applications that are using
94
+ # a fixed set of values passed through options to describe some properties
95
+ # of messages, e.g. +masculine+ and +feminine+ for a grammatical gender.
96
+ # Translators may then use their own tokens (like +f+ and +m+ for English)
97
+ # to produce pretty and intuitive patterns.
98
+ #
99
+ # For example: if some application uses database with gender assigned
100
+ # to a user which may be +male+, +female+ or +none+, then a translator
101
+ # for some language may find it useful to map impersonal token (<tt>none</tt>)
102
+ # to the +neuter+ token, since in translations for his language the
103
+ # neuter gender is in use.
104
+ #
105
+ # Here is the example of such situation:
106
+ #
107
+ # en:
108
+ # i18n:
109
+ # inflections:
110
+ # gender:
111
+ # male: "male"
112
+ # female: "female"
113
+ # none: "impersonal form"
114
+ # default: none
115
+ #
116
+ # pl:
117
+ # i18n:
118
+ # inflections:
119
+ # gender:
120
+ # k: "female"
121
+ # m: "male"
122
+ # n: "neuter"
123
+ # male: @k
124
+ # female: @m
125
+ # none: @n
126
+ # default: none
127
+ #
128
+ # In the case above Polish translator decided to use neuter
129
+ # instead of impersonal form when +none+ token will be passed
130
+ # through the option +:gender+ to the translate method. He
131
+ # also decided that he will use +k+, +m+ or +n+ in patterns,
132
+ # because the names are short and correspond to gender names in
133
+ # Polish language.
134
+ #
135
+ # Aliases may point to other aliases. While loading inflections they
136
+ # will be internally shortened and they will always point to real tokens,
137
+ # not other aliases.
138
+ #
139
+ # === Default token
140
+ # There is special token called the +default+, which points
141
+ # to a token that should be used if translation routine cannot deduce
142
+ # which one it should use because a proper option was not given.
143
+ #
144
+ # Default tokens may point to aliases and may use aliases' syntax, e.g.:
145
+ # default: @man
146
+ #
147
+ # === Descriptions
148
+ # The values of keys in the example (+female+, +male+ and +neuter+)
149
+ # are *descriptions* which are not used by interpolation routines
150
+ # but might be helpful (e.g. in UI). For obvious reasons you cannot
151
+ # describe aliases.
152
+ #
153
+ # == Interpolation
154
+ # The value of each token present in a pattern is to be picked by the interpolation
155
+ # routine and will replace the whole pattern, when the token name from that
156
+ # pattern matches the value of an option passed to {I18n.translate} method.
157
+ # This option is called <b>the inflection option</b>. Its name should be
158
+ # the same as a *kind* of tokens used within a pattern. The first token in a pattern
159
+ # determines the kind of all tokens used in that pattern. You can pass
160
+ # many inflection options, each one designated for keeping a token of a
161
+ # different kind.
162
+ #
163
+ # === Examples:
164
+ #
165
+ # ===== YAML:
166
+ # Let's assume that the translation data in YAML format listed
167
+ # below is used in any later example, unless other inflections
168
+ # are given.
169
+ # en:
170
+ # i18n:
171
+ # inflections:
172
+ # gender:
173
+ # m: "male"
174
+ # f: "female"
175
+ # n: "neuter"
176
+ # default: n
177
+ #
178
+ # welcome: "Dear @{f:Madam|m:Sir|n:You|All}"
179
+ # ===== Code:
180
+ # I18n.translate('welcome', :gender => :m)
181
+ # # => "Dear Sir"
182
+ #
183
+ # I18n.translate('welcome', :gender => :unknown)
184
+ # # => "Dear All"
185
+ #
186
+ # I18n.translate('welcome')
187
+ # # => "Dear You"
188
+ #
189
+ # In the second example the <b>fallback value</b> +All+ was interpolated
190
+ # because the routine had been unable to find the token called +:unknown+.
191
+ # That differs from the latest example, in which there was no option given,
192
+ # so the default token for a kind had been applied (in this case +n+).
193
+ #
194
+ # === Local fallbacks (free text)
195
+ # The fallback value will be used when any of the given tokens from
196
+ # pattern cannot be interpolated.
197
+ #
198
+ # Be aware that enabling extended error reporting makes it unable
199
+ # to use fallback values in most cases. Local fallbacks will then be
200
+ # applied only when a given option contains a proper value for some
201
+ # kind but it's just not present in a pattern, for example:
202
+ #
203
+ # ===== YAML:
204
+ # en:
205
+ # i18n:
206
+ # inflections:
207
+ # gender:
208
+ # n: 'neuter'
209
+ # o: 'other'
210
+ #
211
+ # welcome: "Dear @{n:You|All}"
212
+ #
213
+ # ===== Code:
214
+ # I18n.translate('welcome', :gender => :o, :raises => true)
215
+ # # => "Dear All"
216
+ # # since the token :o was configured but not used in the pattern
217
+ #
218
+ # === Unknown and empty tokens in options
219
+ # If an option containing token is not present at all then the interpolation
220
+ # routine will try the default token for a processed kind if the default
221
+ # token is present in a pattern. The same thing will happend if the option
222
+ # is present but its value is unknown, empty or +nil+.
223
+ # If the default token is not present in a pattern or is not defined in
224
+ # a configuration data then the processed pattern will result in an empty
225
+ # string or in a local fallback value if there is a free text placed
226
+ # in a pattern.
227
+ #
228
+ # You can change this default behavior and force inflector
229
+ # not to use a default token when a value of an option for a kind is unknown,
230
+ # empty or +nil+ but only when it's not present.
231
+ # To do that you should set option +:unknown_defaults+ to
232
+ # +false+ and pass it to I18n.translate method. Other way is to set this
233
+ # globally by using the method called unknown_defaults.
234
+ # See #unknown_defaults for examples showing how the
235
+ # translation results are changing when that switch is applied.
236
+ #
237
+ # === Mixing inflection and standard interpolation patterns
238
+ # The Inflector module allows you to include standard <tt>%{}</tt>
239
+ # patterns inside of inflection patterns. The value of a standard
240
+ # interpolation variable will be evaluated and interpolated *before*
241
+ # processing an inflection pattern. For example:
242
+ #
243
+ # ===== YAML:
244
+ # Note: <em>Uses inflection configuration given in the first example.</em>
245
+ # en:
246
+ # hi: "Dear @{f:Lady|m:%{test}}!"
247
+ # ===== Code:
248
+ # I18n.t('hi', :gender => :m, :locale => :xx, :test => "Dude")
249
+ # # => Dear Dude!
250
+ #
251
+ # === Token groups
252
+ # It is possible to assign some value to more than one token.
253
+ # You can create group of tokens by separating them using commas.
254
+ # The comma has the meaning of logical OR in such a token group.
255
+ #
256
+ # ===== YAML:
257
+ # Note: <em>Uses inflection configuration given in the first example.</em>
258
+ # en:
259
+ # welcome: "Hello @{m,f:Ladies and Gentlemen|n:You}!"
260
+ # ===== Code:
261
+ # I18n.t('welcome', :gender => :f)
262
+ # # => Hello Ladies and Gentlemen!
263
+ #
264
+ # === Inverse matching of tokens
265
+ # You can place exclamation mark before a token that should be
266
+ # matched negatively. It's value will be used for a pattern
267
+ # <b>if the given inflection option contains other token</b>.
268
+ # You can use inversed matching tokens in token groups but
269
+ # note that using more than one inversed token separated
270
+ # by a comma will cause the expression to mach every time.
271
+ #
272
+ # ===== YAML:
273
+ # Note: <em>Uses inflection configuration given in the first example.</em>
274
+ # en:
275
+ # welcome: "Hello @{!m:Ladies|n:You}!"
276
+ # ===== Code:
277
+ # I18n.t('welcome', :gender => :n)
278
+ # # => Hello Ladies!
279
+ #
280
+ # I18n.t('welcome', :gender => :f)
281
+ # # => Hello Ladies!
282
+ #
283
+ # I18n.t('welcome', :gender => :m)
284
+ # # => Hello !
285
+ #
286
+ # === Aliases in a pattern
287
+ # Normally it possible to use only true tokens in patterns, not aliases.
288
+ # However, if you feel lucky and you're not affraid of messy patterns
289
+ # you can use the switch {I18n::Inflector::InflectionOptions#aliased_patterns}
290
+ # or corresponding +:inflector_aliased_patterns+ option passed to translation
291
+ # method.
292
+ #
293
+ # === Escaping a pattern
294
+ # If there is a need to translate something that matches an inflection
295
+ # pattern the escape symbols can be used to disable the interpolation. These
296
+ # symbols are <tt>\\</tt> and +@+ and they should be placed just before
297
+ # a pattern that should be left untouched. For instance:
298
+ #
299
+ # ===== YAML:
300
+ # Note: <em>Uses inflection configuration given in the first example.</em>
301
+ # en:
302
+ # welcome: "This is the @@{pattern}!"
303
+ # ===== Code:
304
+ # I18n.t('welcome', :gender => :m, :locale => :xx)
305
+ # # => This is the @{pattern}!
306
+ #
307
+ # == Errors
308
+ # By default the module will silently ignore any interpolation errors.
309
+ # You can turn off this default behavior by passing +:raises+ option.
310
+ #
311
+ # === Usage of +:raises+ option
312
+ #
313
+ # ===== YAML
314
+ # Note: <em>Uses inflection configuration given in the first example.</em>
315
+ # en:
316
+ # welcome: "Dear @{m:Sir|f:Madam|Fallback}"
317
+ # ===== Code:
318
+ # I18n.t('welcome', :raises => true)
319
+ # # => I18n::InvalidOptionForKind: option :gender required by the pattern
320
+ # # "@{m:Sir|f:Madam|Fallback}" was not found
321
+ #
322
+ # Here are the exceptions that may be raised when option +:raises+
323
+ # is set to +true+:
324
+ #
325
+ # * {I18n::InvalidOptionForKind I18n::InvalidOptionForKind}
326
+ # * {I18n::InvalidInflectionToken I18n::InvalidInflectionToken}
327
+ # * {I18n::MisplacedInflectionToken I18n::MisplacedInflectionToken}
328
+ #
329
+ # There are also exceptions that are raised regardless of :+raises+
330
+ # presence or value.
331
+ # These are usually caused by critical errors encountered during processing
332
+ # inflection data. Here is the list:
333
+ #
334
+ # * {I18n::InvalidLocale I18n::InvalidLocale}
335
+ # * {I18n::DuplicatedInflectionToken I18n::DuplicatedInflectionToken}
336
+ # * {I18n::BadInflectionToken I18n::BadInflectionToken}
337
+ # * {I18n::BadInflectionAlias I18n::BadInflectionAlias}
338
+ #
339
+ module Inflector
366
340
 
367
- # When this switch is set to +true+ then inflector falls back to the default
368
- # token for a kind if the given inflection option is correct but doesn't exist in a pattern.
369
- #
370
- # There might happend that the inflection option
371
- # given to {#translate} method will contain some proper token, but that token
372
- # will not be present in a processed pattern. Normally an empty string will
373
- # be generated from such a pattern or a free text (if a local fallback is present
374
- # in a pattern). You can change that behavior and tell interpolating routine to
375
- # use the default token for a processed kind in such cases.
376
- #
377
- # This switch is by default set to +false+.
378
- #
379
- # @note Local option +:inflector_excluded_defaults+ passed to the {#translate}
380
- # overrides this setting.
381
- #
382
- # @api public
383
- # @see #inflector_excluded_defaults?
384
- # @see I18n::Inflector.excluded_defaults Short name: I18n::Inflector.excluded_defaults
385
- # @return [Boolean] the state of the switch
386
- #
387
- # @example Usage of +:inflector_excluded_defaults+ option
388
- #
389
- # I18n.locale = :en
390
- # I18n.backend.store_translations 'en', :i18n => { :inflections => {
391
- # :gender => {
392
- # :n => 'neuter',
393
- # :m => 'male',
394
- # :o => 'other',
395
- # :default => 'n' }}}
396
- #
397
- # I18n.backend.store_translations 'en', 'welcome' => 'Dear @{n:You|m:Sir}'
398
- #
399
- # I18n.t('welcome', :gender => :o)
400
- # # => "Dear "
401
- #
402
- # I18n.t('welcome', :gender => :o, :inflector_excluded_defaults => true)
403
- # # => "Dear You"
404
- attr_accessor :inflector_excluded_defaults
405
-
406
- # This is a switch that enables extended error reporting. When it's enabled then
407
- # errors are raised in case of unknown or empty tokens present in a pattern
408
- # or in options. This switch is by default set to +false+.
409
- #
410
- # @note Local option +:inflector_raises+ passed to the {#translate} overrides this setting.
411
- #
412
- # @api public
413
- # @see #inflector_excluded_defaults?
414
- # @see I18n::Inflector.raises Short name: I18n::Inflector.raises
415
- # @return [Boolean] the state of the switch
416
- attr_accessor :inflector_raises
417
-
418
- end
419
341
  end
420
-
342
+
421
343
  # @abstract This exception class is defined in package I18n. It is raised when
422
344
  # the given and/or processed locale parameter is invalid.
423
345
  class InvalidLocale; end