i18n-inflector 2.1.0 → 2.2.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.
- data/ChangeLog +412 -0
- data/Manifest.txt +3 -0
- data/README.rdoc +38 -17
- data/docs/EXAMPLES +111 -22
- data/docs/HISTORY +37 -0
- data/docs/TODO +3 -27
- data/lib/i18n-inflector/api.rb +22 -234
- data/lib/i18n-inflector/api_strict.rb +1 -1
- data/lib/i18n-inflector/backend.rb +78 -23
- data/lib/i18n-inflector/config.rb +297 -0
- data/lib/i18n-inflector/errors.rb +184 -58
- data/lib/i18n-inflector/hset.rb +28 -0
- data/lib/i18n-inflector/inflection_data.rb +3 -1
- data/lib/i18n-inflector/inflection_data_strict.rb +3 -1
- data/lib/i18n-inflector/inflector.rb +1 -39
- data/lib/i18n-inflector/interpolate.rb +404 -0
- data/lib/i18n-inflector/lazy_enum.rb +52 -6
- data/lib/i18n-inflector/long_comments.rb +463 -157
- data/lib/i18n-inflector/options.rb +116 -20
- data/lib/i18n-inflector/version.rb +1 -1
- data/lib/i18n-inflector.rb +4 -1
- data/test/inflector_test.rb +179 -22
- data.tar.gz.sig +0 -0
- metadata +7 -4
- metadata.gz.sig +0 -0
@@ -10,14 +10,15 @@
|
|
10
10
|
#
|
11
11
|
|
12
12
|
module I18n
|
13
|
-
# @version 2.
|
13
|
+
# @version 2.2
|
14
14
|
# This module contains inflection classes and modules for enabling
|
15
15
|
# the inflection support in I18n translations.
|
16
16
|
# It is used by the module called {I18n::Backend::Inflector}
|
17
17
|
# that overwrites the Simple backend translate method
|
18
|
-
# so that it will interpolate additional inflection
|
19
|
-
# in translations.
|
20
|
-
#
|
18
|
+
# so that it will interpolate additional inflection data present
|
19
|
+
# in translations. That data may appear in *patterns*
|
20
|
+
# contained within <tt>@{</tt> and <tt>}</tt> symbols. Each pattern
|
21
|
+
# consist of *tokens* and respective *values*.
|
21
22
|
#
|
22
23
|
# == Usage
|
23
24
|
# require 'i18-inflector'
|
@@ -168,133 +169,6 @@ module I18n
|
|
168
169
|
# but might be helpful (e.g. in UI). For obvious reasons you cannot
|
169
170
|
# describe aliases.
|
170
171
|
#
|
171
|
-
# == Named patterns
|
172
|
-
#
|
173
|
-
# A named pattern is a pattern that may contain special clause
|
174
|
-
# containing name of a kind that tokens from a pattern
|
175
|
-
# are assigned to. It looks like:
|
176
|
-
#
|
177
|
-
# welcome: "Dear @gender{f:Madam|m:Sir|n:You|All}"
|
178
|
-
#
|
179
|
-
# === Configuring named patterns
|
180
|
-
#
|
181
|
-
# To recognize tokens present in a named patterns,
|
182
|
-
# inflector uses keys grouped in the scope called +inflections+
|
183
|
-
# for the given locale. For instance (YAML format):
|
184
|
-
# en:
|
185
|
-
# i18n:
|
186
|
-
# inflections:
|
187
|
-
# @gender:
|
188
|
-
# f: "female"
|
189
|
-
# woman: @f
|
190
|
-
# default: f
|
191
|
-
#
|
192
|
-
# Elements in the example above are:
|
193
|
-
# * +en+: language
|
194
|
-
# * +i18n+: configuration scope
|
195
|
-
# * +inflections+: inflections configuration scope
|
196
|
-
# * +gender+: <bb>strict kind</bb> scope
|
197
|
-
# * +f+: inflection token
|
198
|
-
# * <tt>"female"</tt>: token's description
|
199
|
-
# * +woman+: inflection alias
|
200
|
-
# * <tt>@f</tt>: pointer to real token
|
201
|
-
# * +default+: default token for a strict kind +gender+
|
202
|
-
#
|
203
|
-
# === Strict kinds
|
204
|
-
#
|
205
|
-
# In order to handle named patterns properly a new data structure
|
206
|
-
# is used. It is called the <b>strict kind</b>. Strict kinds are defined
|
207
|
-
# in a configuration in a similar way the regular kinds are but
|
208
|
-
# tokens assigned to them may have the same names across a whole
|
209
|
-
# configuration. (Note that within a strict kind tokens should still
|
210
|
-
# be unique.) That implies a requirement of passing the
|
211
|
-
# identifier of a kind when referring to such tokens.
|
212
|
-
#
|
213
|
-
# Here is the example configuration using strict kinds:
|
214
|
-
#
|
215
|
-
# en:
|
216
|
-
# i18n:
|
217
|
-
# inflections:
|
218
|
-
# @gender:
|
219
|
-
# f: "female"
|
220
|
-
# m: "male"
|
221
|
-
# n: "neuter"
|
222
|
-
# woman: @f
|
223
|
-
# man: @m
|
224
|
-
# default: n
|
225
|
-
# @title:
|
226
|
-
# s: "sir"
|
227
|
-
# l: "lady"
|
228
|
-
# u: "you"
|
229
|
-
# m: @s
|
230
|
-
# f: @l
|
231
|
-
# default: u
|
232
|
-
#
|
233
|
-
# The only thing that syntactically distinguishes named kinds
|
234
|
-
# from regular kinds is a presence of the +@+ symbol.
|
235
|
-
#
|
236
|
-
# You can mix regular and strict kinds having the same names.
|
237
|
-
# The proper class of kind will be picked up by interpolation
|
238
|
-
# method easily, since the first mentioned class uses
|
239
|
-
# patterns that are not named, and the second uses named patterns.
|
240
|
-
#
|
241
|
-
# ==== Strict kinds in options
|
242
|
-
#
|
243
|
-
# The interpolation routine recognizes strict kinds passed as
|
244
|
-
# options in almost the same way that it does it for regular
|
245
|
-
# kinds. The only difference is that you can override usage
|
246
|
-
# of a regular kind inflection option (if there is any) by
|
247
|
-
# putting a strict kind option with name prefixed by +@+ symbol.
|
248
|
-
# The inflection options starting with this symbol have
|
249
|
-
# precedence over inflection options without it;
|
250
|
-
# that is of course only true for strict kinds and has any effect
|
251
|
-
# only when both options describing the same kind are present.
|
252
|
-
#
|
253
|
-
# In other words: interpolation routine is looking for
|
254
|
-
# strict kinds in inflection options using their names
|
255
|
-
# with +@+ in front. When that fails it falls back to
|
256
|
-
# trying an option named like the strict kind but without
|
257
|
-
# the +@+ symbol. Examples:
|
258
|
-
#
|
259
|
-
# I18n.translate(welcome, :gender => :m, :@gender => :f)
|
260
|
-
# # the :f will be picked for the strict kind gender
|
261
|
-
#
|
262
|
-
# I18n.translate(welcome, :@gender => :f)
|
263
|
-
# # the :f will be picked for the strict kind gender
|
264
|
-
#
|
265
|
-
# I18n.translate(welcome, :gender => :f)
|
266
|
-
# # the :f will be picked for the strict kind gender
|
267
|
-
#
|
268
|
-
# In the example above we assume that +welcome+ is defined
|
269
|
-
# like that:
|
270
|
-
#
|
271
|
-
# welcome: "Dear @gender{f:Madam|m:Sir|n:You|All}"
|
272
|
-
#
|
273
|
-
# Note that for regular kinds the option named <tt>:@gender</tt>
|
274
|
-
# will have no meaning.
|
275
|
-
#
|
276
|
-
# ==== Note for developers
|
277
|
-
#
|
278
|
-
# Strict kinds that are used to handle named patterns
|
279
|
-
# are internally stored in a different database and handled by
|
280
|
-
# similar but different API methods than regular kinds. However
|
281
|
-
# most of the {I18n::Inflector::API} methods are also aware of strict kinds
|
282
|
-
# and will call proper methods oprating on strict inflections
|
283
|
-
# data when the +@+ symbol is detected at the beginning of
|
284
|
-
# the identifier of a kind passed as an argument. For example:
|
285
|
-
#
|
286
|
-
# I18n.inflector.has_token?(:m, :@gender)
|
287
|
-
#
|
288
|
-
# will effectively call:
|
289
|
-
#
|
290
|
-
# I18n.inflector.strict.has_token?(:m, :gender)
|
291
|
-
#
|
292
|
-
# As you can see above, to access {API_Strict} methods for strict kinds
|
293
|
-
# (and strict kinds data) only, associated with default I18n backend,
|
294
|
-
# use:
|
295
|
-
#
|
296
|
-
# I18n.inflector.strict
|
297
|
-
#
|
298
172
|
# == Interpolation
|
299
173
|
# The value of each token present in a pattern is to be picked by the interpolation
|
300
174
|
# routine and will replace the whole pattern, when the token name from that
|
@@ -356,28 +230,39 @@ module I18n
|
|
356
230
|
# welcome: "Dear @{n:You|All}"
|
357
231
|
#
|
358
232
|
# ===== Code:
|
359
|
-
# I18n.translate('welcome', :gender => :o, :
|
233
|
+
# I18n.translate('welcome', :gender => :o, :inflector_raises => true)
|
360
234
|
# # => "Dear All"
|
361
235
|
# # since the token :o was configured but not used in the pattern
|
362
236
|
#
|
363
|
-
# === Unknown and empty tokens in options
|
237
|
+
# === Unknown, malformed and empty tokens in options
|
364
238
|
# If an option containing token is not present at all then the interpolation
|
365
239
|
# routine will try the default token for a processed kind if the default
|
366
240
|
# token is present in a pattern. The same thing will happend if the option
|
367
|
-
# is present but its value is unknown, empty or +nil+.
|
241
|
+
# is present but its value is malformed, unknown, empty or +nil+.
|
368
242
|
# If the default token is not present in a pattern or is not defined in
|
369
|
-
# a configuration data then the
|
370
|
-
# string or in a local fallback value if there is
|
371
|
-
# in a pattern.
|
243
|
+
# a configuration data then the processing of a pattern will result
|
244
|
+
# in an empty string or in a local fallback value if there is
|
245
|
+
# a free text placed in a pattern.
|
372
246
|
#
|
373
247
|
# You can change this default behavior and force inflector
|
374
|
-
# not to use a default token when a value of an option for
|
375
|
-
# empty or +nil+ but only when
|
376
|
-
# To do that you should set option +:
|
377
|
-
# +false+ and pass it to I18n.translate method. Other way is to set this
|
378
|
-
# globally
|
379
|
-
#
|
380
|
-
#
|
248
|
+
# not to use a default token when a value of an option for
|
249
|
+
# a kind is malformed, unknown, empty or +nil+ but only when
|
250
|
+
# it's not present. To do that you should set option +:inflector_unknown_defaults+
|
251
|
+
# to +false+ and pass it to I18n.translate method. Other way is to set this
|
252
|
+
# switch globally using the {I18n::Inflector::InflectionOptions#unknown_defaults}.
|
253
|
+
#
|
254
|
+
# === Unmatched tokens in options
|
255
|
+
# It might happend that there is a default token present in a pattern
|
256
|
+
# but the inflection option causes other token to be picked up
|
257
|
+
# which however is not present in this pattern although it's
|
258
|
+
# correct and assigned to the currently processed kind. In such
|
259
|
+
# situation the free text or an empty string will be generated.
|
260
|
+
# You may change that behavior by passing +:inflector_excluded_defaults+
|
261
|
+
# option set to +true+ or by setting the global option called
|
262
|
+
# {I18n::Inflector::InflectionOptions#excluded_defaults}. If this
|
263
|
+
# option is set then any unmatched (excluded) but correct token
|
264
|
+
# given in an inflection option will cause the default token
|
265
|
+
# to be picked up (if present in a pattern of course).
|
381
266
|
#
|
382
267
|
# === Mixing inflection and standard interpolation patterns
|
383
268
|
# The Inflector module allows you to include standard <tt>%{}</tt>
|
@@ -418,6 +303,7 @@ module I18n
|
|
418
303
|
# Note: <em>Uses inflection configuration given in the first example.</em>
|
419
304
|
# en:
|
420
305
|
# welcome: "Hello @{!m:Ladies|n:You}!"
|
306
|
+
#
|
421
307
|
# ===== Code:
|
422
308
|
# I18n.t('welcome', :gender => :n)
|
423
309
|
# # => Hello Ladies!
|
@@ -428,11 +314,33 @@ module I18n
|
|
428
314
|
# I18n.t('welcome', :gender => :m)
|
429
315
|
# # => Hello !
|
430
316
|
#
|
317
|
+
# === Loud tokens
|
318
|
+
# Sometimes there might be a need to use descriptions of
|
319
|
+
# matching tokens instead of some given values. Use <b>loud tokens</b>
|
320
|
+
# to achieve that. Any matching token in a pattern that has tilde symbol (+~+)
|
321
|
+
# set as its value will be replaced by its description. In case of
|
322
|
+
# undescribed aliases, the description from a target token will be used.
|
323
|
+
#
|
324
|
+
# ===== YAML:
|
325
|
+
# Note: <em>Uses inflection configuration given in the first example.</em>
|
326
|
+
# en:
|
327
|
+
# welcome: "Hello @{m:~|n:~}!"
|
328
|
+
#
|
329
|
+
# ===== Code:
|
330
|
+
# I18n.t('welcome', :gender => :n)
|
331
|
+
# # => Hello neuter!
|
332
|
+
#
|
333
|
+
# I18n.t('welcome', :gender => :f)
|
334
|
+
# # => Hello female!
|
335
|
+
#
|
336
|
+
# To use tilde symbol as the only value of a token you may esape it
|
337
|
+
# by putting a backslash in front of the symbol.
|
338
|
+
#
|
431
339
|
# === Aliases in a pattern
|
432
|
-
# Normally it possible to use only true tokens in patterns, not aliases.
|
340
|
+
# Normally it is possible to use only true tokens in patterns, not aliases.
|
433
341
|
# However, if you feel lucky and you're not affraid of messy patterns
|
434
342
|
# you can use the switch {I18n::Inflector::InflectionOptions#aliased_patterns}
|
435
|
-
# or corresponding
|
343
|
+
# or corresponding +:inflector_aliased_patterns+ option passed to translation
|
436
344
|
# method.
|
437
345
|
#
|
438
346
|
# It may seem very easy and attractive to use aliased patterns, especially
|
@@ -444,7 +352,7 @@ module I18n
|
|
444
352
|
# the aliases would be used. Note hovewer, that you can make use of
|
445
353
|
# <tt>I18n.inflector.true_token</tt> method (see {I18n::Inflector::API#true_token}
|
446
354
|
# that will resolve any alias and then use that data to feed some inflection option
|
447
|
-
# (e.g.
|
355
|
+
# (e.g. +:gender+). In such scenario you don't have to rely on aliases
|
448
356
|
# in patterns and you will gain some speed since resolving will occur just once,
|
449
357
|
# not each time translated text is interpolated.
|
450
358
|
#
|
@@ -462,37 +370,424 @@ module I18n
|
|
462
370
|
# I18n.t('welcome', :gender => :m, :locale => :xx)
|
463
371
|
# # => This is the @{pattern}!
|
464
372
|
#
|
373
|
+
# == Named patterns
|
374
|
+
#
|
375
|
+
# A named pattern is a pattern that contains name of a kind
|
376
|
+
# that tokens from a pattern are assigned to. It looks like:
|
377
|
+
#
|
378
|
+
# welcome: "Dear @gender{f:Madam|m:Sir|n:You|All}"
|
379
|
+
#
|
380
|
+
# === Configuring named patterns
|
381
|
+
# To recognize tokens present in named patterns,
|
382
|
+
# inflector uses keys grouped in the scope called +inflections+
|
383
|
+
# for the given locale. For instance (YAML format):
|
384
|
+
# en:
|
385
|
+
# i18n:
|
386
|
+
# inflections:
|
387
|
+
# @gender:
|
388
|
+
# f: "female"
|
389
|
+
# woman: @f
|
390
|
+
# default: f
|
391
|
+
#
|
392
|
+
# Elements in the example above are:
|
393
|
+
# * +en+: language
|
394
|
+
# * +i18n+: configuration scope
|
395
|
+
# * +inflections+: inflections configuration scope
|
396
|
+
# * +gender+: <bb>strict kind</bb> scope
|
397
|
+
# * +f+: inflection token
|
398
|
+
# * <tt>"female"</tt>: token's description
|
399
|
+
# * +woman+: inflection alias
|
400
|
+
# * <tt>@f</tt>: pointer to real token
|
401
|
+
# * +default+: default token for a strict kind +gender+
|
402
|
+
#
|
403
|
+
# === Strict kinds
|
404
|
+
#
|
405
|
+
# In order to handle named patterns properly a new data structure
|
406
|
+
# is used. It is called the <b>strict kind</b>. Strict kinds are defined
|
407
|
+
# in a configuration in a similar way the regular kinds are but
|
408
|
+
# tokens assigned to them may have the same names across a whole
|
409
|
+
# configuration. (Note that tokens of the same strict kind should still
|
410
|
+
# be unique.) That implies a requirement of passing the
|
411
|
+
# identifier of a kind when referring to such tokens.
|
412
|
+
#
|
413
|
+
# Here is the example configuration using strict kinds:
|
414
|
+
#
|
415
|
+
# en:
|
416
|
+
# i18n:
|
417
|
+
# inflections:
|
418
|
+
# @gender:
|
419
|
+
# f: "female"
|
420
|
+
# m: "male"
|
421
|
+
# n: "neuter"
|
422
|
+
# woman: @f
|
423
|
+
# man: @m
|
424
|
+
# default: n
|
425
|
+
# @title:
|
426
|
+
# s: "sir"
|
427
|
+
# l: "lady"
|
428
|
+
# u: "you"
|
429
|
+
# m: @s
|
430
|
+
# f: @l
|
431
|
+
# default: u
|
432
|
+
#
|
433
|
+
# The only thing that syntactically distinguishes strict kinds
|
434
|
+
# from regular kinds is a presence of the +@+ symbol.
|
435
|
+
#
|
436
|
+
# You can mix regular and strict kinds having the same names.
|
437
|
+
# The proper class of kind will be picked up by interpolation
|
438
|
+
# method easily, since the first mentioned class uses
|
439
|
+
# patterns that are not named, and the second uses named patterns.
|
440
|
+
#
|
441
|
+
# ==== Strict kinds in options
|
442
|
+
#
|
443
|
+
# The interpolation routine recognizes strict kinds passed as
|
444
|
+
# options in almost the same way that it does it for regular
|
445
|
+
# kinds. The only difference is that you can override usage
|
446
|
+
# of a regular kind inflection option (if there is any) by
|
447
|
+
# putting a strict kind option with name prefixed by +@+ symbol.
|
448
|
+
# The inflection options starting with this symbol have
|
449
|
+
# precedence over inflection options without it;
|
450
|
+
# that is of course only true for strict kinds and has any effect
|
451
|
+
# only when both options describing the same kind are present.
|
452
|
+
#
|
453
|
+
# In other words: interpolation routine is looking for
|
454
|
+
# strict kinds in inflection options using their names
|
455
|
+
# with +@+ in front. When that fails it falls back to
|
456
|
+
# trying an option named like the strict kind but without
|
457
|
+
# the +@+ symbol. Examples:
|
458
|
+
#
|
459
|
+
# I18n.translate(welcome, :gender => :m, :@gender => :f)
|
460
|
+
# # the :f will be picked for the strict kind gender
|
461
|
+
#
|
462
|
+
# I18n.translate(welcome, :@gender => :f)
|
463
|
+
# # the :f will be picked for the strict kind gender
|
464
|
+
#
|
465
|
+
# I18n.translate(welcome, :gender => :f)
|
466
|
+
# # the :f will be picked for the strict kind gender
|
467
|
+
#
|
468
|
+
# In the example above we assume that +welcome+ is defined
|
469
|
+
# like that:
|
470
|
+
#
|
471
|
+
# welcome: "Dear @gender{f:Madam|m:Sir|n:You|All}"
|
472
|
+
#
|
473
|
+
# Note that for regular kinds the option named +:@gender+
|
474
|
+
# will have no meaning.
|
475
|
+
#
|
476
|
+
# ==== Note for developers
|
477
|
+
#
|
478
|
+
# Strict kinds that are used to handle named patterns
|
479
|
+
# are internally stored in a different database and handled by
|
480
|
+
# similar but different API methods than regular kinds. However
|
481
|
+
# most of the {I18n::Inflector::API} methods are also aware of strict kinds
|
482
|
+
# and will call proper methods oprating on strict inflections
|
483
|
+
# data when the +@+ symbol is detected at the beginning of
|
484
|
+
# the identifier of a kind passed as an argument. For example:
|
485
|
+
#
|
486
|
+
# I18n.inflector.has_token?(:m, :@gender)
|
487
|
+
#
|
488
|
+
# will effectively call:
|
489
|
+
#
|
490
|
+
# I18n.inflector.strict.has_token?(:m, :gender)
|
491
|
+
#
|
492
|
+
# As you can see above, to access {API_Strict} methods for strict kinds
|
493
|
+
# (and strict kinds data) only, associated with default I18n backend,
|
494
|
+
# use:
|
495
|
+
#
|
496
|
+
# I18n.inflector.strict
|
497
|
+
#
|
498
|
+
# == Multiple patterns
|
499
|
+
# You can make use of some syntactic sugar when having more than
|
500
|
+
# one pattern (regular or named) in your string. To not repeat
|
501
|
+
# a kind identifier(s) you may join pattern contents as in the
|
502
|
+
# following example:
|
503
|
+
#
|
504
|
+
# welcome: "You are @gender{f:pretty|m,n:handsome}{ }{f:lady|m:sir|n:human}"
|
505
|
+
#
|
506
|
+
# As you can see there should be no spaces or any other characters
|
507
|
+
# between successive patterns. That's why in this example an
|
508
|
+
# empty pattern's content is used. This is in fact a pattern
|
509
|
+
# containing no tokens but just a free text consisting
|
510
|
+
# of single space character.
|
511
|
+
#
|
512
|
+
# == Complex patterns
|
513
|
+
# A <bb>complex pattern</bb> is a named pattern that uses more than
|
514
|
+
# one inflection kind and sets of a respective tokens. The given identifiers
|
515
|
+
# of kinds should be separated by the plus sign and instead of single
|
516
|
+
# tokens there should be token sets (a tokens separated by the plus
|
517
|
+
# sign too).
|
518
|
+
#
|
519
|
+
# Example:
|
520
|
+
#
|
521
|
+
# welcome: "Dear @gender+number{f+s:Lady|f+p:Ladies|m+s:Sir|m+p:Gentlemen|All}"
|
522
|
+
#
|
523
|
+
# In the example above the complex pattern uses +gender+ and +number+
|
524
|
+
# inflection kinds and a token set (e.g. <tt>f+s</tt>) matches when
|
525
|
+
# both tokens match interpolation options (e.g. <tt>:gender => :f</tt>,
|
526
|
+
# <tt>:number => :s</tt>). The order of tokens in sets has meaning
|
527
|
+
# and should reflect the order of declared kinds.
|
528
|
+
#
|
529
|
+
# Note, that the count of tokens in each set should reflect the count
|
530
|
+
# of kinds that are used. Otherwise the interpolation routine will
|
531
|
+
# interpolate a free text (if given) or an empty string. If the switch
|
532
|
+
# {InflectionOptions#raises} is on then the {I18n::ComplexPatternMalformed}
|
533
|
+
# exception will be raised.
|
534
|
+
#
|
535
|
+
# The inflection tokens used in sets may make use of any features mentioned
|
536
|
+
# before (defaults, excluded defaults, negative matching, token groups,
|
537
|
+
# aliases, aliased patterns, loud tokens).
|
538
|
+
#
|
539
|
+
# === Loud tokens in complex patterns
|
540
|
+
#
|
541
|
+
# In case of loud tokens (having values taken from their
|
542
|
+
# descriptions), the complex pattern will be replaced by
|
543
|
+
# the descriptions of matching tokens joined with a single space
|
544
|
+
# character. So, for instance, when the translation data looks like:
|
545
|
+
#
|
546
|
+
# i18n:
|
547
|
+
# inflections:
|
548
|
+
# @person:
|
549
|
+
# i: 'I'
|
550
|
+
# u: 'You'
|
551
|
+
# @tense:
|
552
|
+
# now: 'am'
|
553
|
+
# past: 'were'
|
554
|
+
# welcome: "@person+tense{i+now:~|u+past:~}"
|
555
|
+
#
|
556
|
+
# the translate method will give the following results:
|
557
|
+
#
|
558
|
+
# I18n.translate('welcome', :person => :i, :tense => :now)
|
559
|
+
# # => "I am"
|
560
|
+
#
|
561
|
+
# I18n.translate('welcome', :person => :you, :tense => :past)
|
562
|
+
# # => "You were"
|
563
|
+
#
|
564
|
+
# This example is abstract, since the combination of +:i+
|
565
|
+
# and +:past+ will result in <tt>i were</tt> string, which is
|
566
|
+
# probably something unexpected. To achieve that kind of logic
|
567
|
+
# simply use combined patterns with the given values instead
|
568
|
+
# of loud tokens.
|
569
|
+
#
|
570
|
+
# == Inflection keys
|
571
|
+
# There is a way of storing inflected strings in keys instead
|
572
|
+
# of patterns. To use it you should simply assign subkeys to
|
573
|
+
# some translation key instead of string containing a pattern.
|
574
|
+
# The key-based inflection group is contained within a key
|
575
|
+
# which name begins with the +@+ symbol.
|
576
|
+
#
|
577
|
+
# The translation key containing a pattern:
|
578
|
+
#
|
579
|
+
# welcome: "Dear @{f:Lady|m:Sir|n:You|All}!"
|
580
|
+
#
|
581
|
+
# Can be easily written as:
|
582
|
+
#
|
583
|
+
# @welcome:
|
584
|
+
# f: "Lady"
|
585
|
+
# m: "Sir"
|
586
|
+
# n: "You"
|
587
|
+
# @free: "All"
|
588
|
+
# @prefix: "Dear "
|
589
|
+
# @suffix: "!"
|
590
|
+
#
|
591
|
+
# You can also use strict kind or even the inflection sets, token
|
592
|
+
# groups, etc.:
|
593
|
+
#
|
594
|
+
# welcome: "@gender+tense{f+past:She was|m+present:He is|n+future:You will be}"
|
595
|
+
#
|
596
|
+
# Can be written as:
|
597
|
+
#
|
598
|
+
# @welcome:
|
599
|
+
# f+past: "She was"
|
600
|
+
# m+present: "He is"
|
601
|
+
# n+future: "You will be"
|
602
|
+
# @kind: "gender+tense"
|
603
|
+
#
|
604
|
+
# There are special, optional subkeys that may give you
|
605
|
+
# more control over inflection process. These are:
|
606
|
+
#
|
607
|
+
# * +@kind+: a kind or kinds in case of strict kinds
|
608
|
+
# * +@prefix+: a prefix to be put before the interpolated data
|
609
|
+
# * +@suffix+: a suffix to be put after the interpolated data
|
610
|
+
# * +@free+: a free text that is to be used when no token will match
|
611
|
+
#
|
612
|
+
# === Limitations
|
613
|
+
#
|
614
|
+
# Inflection keys look compact and clean but obviously
|
615
|
+
# you cannot use the key-based inflection to simply replace
|
616
|
+
# a string containing more than one inflection pattern.
|
617
|
+
#
|
618
|
+
# Also, <b>you have to be very careful when using this method
|
619
|
+
# with Ruby 1.8</b> because the order of processed token sets
|
620
|
+
# may change. That may break the logic in case of inflection
|
621
|
+
# sets where order has meaning (e.g. tokens with inverted
|
622
|
+
# matching).
|
623
|
+
#
|
465
624
|
# == Errors
|
466
|
-
# By default the module will silently ignore
|
467
|
-
# You can turn off this default behavior by passing +:
|
625
|
+
# By default the module will silently ignore non-critical interpolation
|
626
|
+
# errors. You can turn off this default behavior by passing +:inflector_raises+
|
627
|
+
# option set to +true+. Note that most errors is reported because of
|
628
|
+
# wrong data in patterns or in configuration. In case of inflection
|
629
|
+
# options only malformed, empty or +nil+ values are reported
|
630
|
+
# when the mentioned switch is turned on. For inflection options
|
631
|
+
# containing unknown tokens no errors are generated.
|
468
632
|
#
|
469
|
-
# === Usage of +:
|
633
|
+
# === Usage of +:inflector_raises+ option
|
470
634
|
#
|
471
635
|
# ===== YAML
|
472
636
|
# Note: <em>Uses inflection configuration given in the first example.</em>
|
473
637
|
# en:
|
474
638
|
# welcome: "Dear @{m:Sir|f:Madam|Fallback}"
|
475
639
|
# ===== Code:
|
476
|
-
# I18n.t('welcome', :
|
477
|
-
# # => I18n::
|
478
|
-
# #
|
640
|
+
# I18n.t('welcome', :inflector_raises => true)
|
641
|
+
# # => I18n::InflectionOptionNotFound: en.welcome:
|
642
|
+
# # @{m:Sir|f:Madam|Fallback}" - required option :gender was not found
|
479
643
|
#
|
480
|
-
#
|
644
|
+
# === Exception meanings
|
645
|
+
# Here are the exceptions that may be raised when the option +:inflector_raises+
|
481
646
|
# is set to +true+:
|
482
647
|
#
|
483
|
-
# * {I18n::InvalidOptionForKind I18n::InvalidOptionForKind}
|
484
648
|
# * {I18n::InvalidInflectionToken I18n::InvalidInflectionToken}
|
649
|
+
# * {I18n::InvalidInflectionKind I18n::InvalidInflectionKind}
|
650
|
+
# * {I18n::InvalidInflectionOption I18n::InvalidInflectionOption}
|
485
651
|
# * {I18n::MisplacedInflectionToken I18n::MisplacedInflectionToken}
|
652
|
+
# * {I18n::InflectionOptionNotFound I18n::InflectionOptionNotFound}
|
653
|
+
# * {I18n::InflectionOptionIncorrect I18n::InflectionOptionIncorrect}
|
654
|
+
# * {I18n::ComplexPatternMalformed I18n::ComplexPatternMalformed}
|
486
655
|
#
|
487
|
-
# There are also exceptions that are raised regardless of :+
|
656
|
+
# There are also exceptions that are raised regardless of :+inflector_raises+
|
488
657
|
# presence or value.
|
489
658
|
# These are usually caused by critical errors encountered during processing
|
490
|
-
# inflection data.
|
659
|
+
# inflection data or exceptions raised by I18n. Note that the pure I18n's
|
660
|
+
# exceptions are not described here.
|
491
661
|
#
|
662
|
+
# * {I18n::ArgumentError I18n::ArgumentError}
|
492
663
|
# * {I18n::InvalidLocale I18n::InvalidLocale}
|
493
664
|
# * {I18n::DuplicatedInflectionToken I18n::DuplicatedInflectionToken}
|
665
|
+
# * {I18n::BadInflectionKind I18n::BadInflectionKind}
|
494
666
|
# * {I18n::BadInflectionToken I18n::BadInflectionToken}
|
495
667
|
# * {I18n::BadInflectionAlias I18n::BadInflectionAlias}
|
668
|
+
#
|
669
|
+
# === Exception hierarchy
|
670
|
+
# I18n::ArgumentError
|
671
|
+
# |
|
672
|
+
# `-- I18n::InvalidLocale
|
673
|
+
# |
|
674
|
+
# `-- I18n::InflectionException
|
675
|
+
# |
|
676
|
+
# `-- I18n::InflectionPatternException
|
677
|
+
# | |
|
678
|
+
# | |-- I18n::InvalidInflectionToken
|
679
|
+
# | |-- I18n::InvalidInflectionKind
|
680
|
+
# | |-- I18n::MisplacedInflectionToken
|
681
|
+
# | |-- I18n::ComplexPatternMalformed
|
682
|
+
# | `-- I18n::InvalidOptionForKind
|
683
|
+
# | |-- I18n::InflectionOptionNotFound
|
684
|
+
# | `-- I18n::InflectionOptionIncorrect
|
685
|
+
# |
|
686
|
+
# `-- I18n::InflectionConfigurationException
|
687
|
+
# |
|
688
|
+
# |-- I18n::DuplicatedInflectionToken
|
689
|
+
# |-- I18n::BadInflectionAlias
|
690
|
+
# |-- I18n::BadInflectionToken
|
691
|
+
# `-- I18n::BadInflectionKind
|
692
|
+
#
|
693
|
+
# == Reserved names and characters
|
694
|
+
# Some strings cannot be used as names and/or identifiers of
|
695
|
+
# kinds and tokens. There are also some reserved characters
|
696
|
+
# that cannot be used within them.
|
697
|
+
#
|
698
|
+
# === Reserved keys
|
699
|
+
# Reserved keys, that cannot be used as names of inflection
|
700
|
+
# options and as names of kinds in the configuration
|
701
|
+
# are available after issuing:
|
702
|
+
#
|
703
|
+
# puts I18n.inflector.config::Reserved::KEYS.to_a
|
704
|
+
#
|
705
|
+
# Here is the current list: <tt>:scope, :default, :separator,
|
706
|
+
# :resolve, :object, :fallback, :format, :cascade,
|
707
|
+
# :raise, :rescue_format, :inflector_cache_aware,
|
708
|
+
# :inflector_raises, :inflector_aliased_patterns,
|
709
|
+
# :inflector_unknown_defaults, :inflector_excluded_defaults</tt>.
|
710
|
+
#
|
711
|
+
# Additionally all Symbols or Strings beginning with
|
712
|
+
# +inflector_+ are prohibited, since they are reserved as
|
713
|
+
# controlling options.
|
714
|
+
#
|
715
|
+
# === Reserved characters
|
716
|
+
# All characters that have special meaning (operators and
|
717
|
+
# markers) are not allowed in patterns, in configuration
|
718
|
+
# and in options.
|
719
|
+
#
|
720
|
+
# ==== Reserved characters in kinds
|
721
|
+
# ===== Passed as inflection options
|
722
|
+
# ====== Code
|
723
|
+
# puts I18n.inflector.config::Reserved::Kinds::OPTION
|
724
|
+
# ====== List
|
725
|
+
# <tt>+ | : ! { }</tt> and <tt>,</tt> (comma).
|
726
|
+
#
|
727
|
+
# ===== Given in a configuration
|
728
|
+
# ====== Code
|
729
|
+
# puts I18n.inflector.config::Reserved::Kinds::DB
|
730
|
+
# ====== List
|
731
|
+
# <tt>+ | : ! { }</tt> and <tt>,</tt> (comma).
|
732
|
+
#
|
733
|
+
# ===== Placed in patterns
|
734
|
+
# ====== Code
|
735
|
+
# puts I18n.inflector.config::Reserved::Kinds::PATTERN
|
736
|
+
# ====== List
|
737
|
+
# <tt>+ | : , ! @ { }</tt> and <tt>,</tt> (comma).
|
738
|
+
#
|
739
|
+
# ==== Reserved characters in tokens
|
740
|
+
# ===== Passed as values of inflection options
|
741
|
+
# ====== Code
|
742
|
+
# puts I18n.inflector.config::Reserved::Tokens::OPTION
|
743
|
+
# ====== List
|
744
|
+
# <tt>+ | : ! @ { }</tt> and <tt>,</tt> (comma).
|
745
|
+
#
|
746
|
+
# ===== Given in a configuration
|
747
|
+
# ====== Code
|
748
|
+
# puts I18n.inflector.config::Reserved::Tokens::DB
|
749
|
+
# ====== List
|
750
|
+
# <tt>+ | : ! @ { }</tt> and <tt>,</tt> (comma).
|
751
|
+
#
|
752
|
+
# ===== Placed in patterns
|
753
|
+
# ====== Code
|
754
|
+
# puts I18n.inflector.config::Reserved::Tokens::PATTERN
|
755
|
+
# ====== List
|
756
|
+
# <tt>+ | : ! @ { }</tt> and <tt>,</tt> (comma).
|
757
|
+
#
|
758
|
+
# == Operators and markers
|
759
|
+
# Here is more formal definition of operators and markers used in patterns.
|
760
|
+
#
|
761
|
+
# === Pattern
|
762
|
+
# @[kind][+kind ...]{token_set[|token_set ...][|free_text]}
|
763
|
+
#
|
764
|
+
# * +@+ is the pattern marker
|
765
|
+
# * +{+ and +}+ are pattern delimiters
|
766
|
+
# * +free_text+ is an optional free text value
|
767
|
+
# * +kind+ is a kind identifier
|
768
|
+
# * <tt>+</tt> is the +AND+ operator that joins kinds (produces complex kinds)
|
769
|
+
# ==== +token_set+
|
770
|
+
# token_group[+token_group ...]:value
|
771
|
+
#
|
772
|
+
# * +:+ is the +ASSIGNMENT+ operator
|
773
|
+
# * +value+ is a value to be picked up then a token set matches; value may also
|
774
|
+
# be the loud marker (+~+)
|
775
|
+
# * <tt>+</tt> is the +AND+ operator that joins many token groups into a set
|
776
|
+
# ===== +token_group+
|
777
|
+
# [!]token[,[!]token ...]
|
778
|
+
#
|
779
|
+
# * +token+ is a token identifier
|
780
|
+
# * +!+ is the +NOT+ operator
|
781
|
+
# * +,+ is the +OR+ operator
|
782
|
+
#
|
783
|
+
# === Operator precedence
|
784
|
+
# * +NOT+ operators for inversed matching of tokens (<tt>!</tt>)
|
785
|
+
# * +OR+ operators for joining tokens into token groups (<tt>,</tt>)
|
786
|
+
# * +AND+ operators for joining token groups into sets (<tt>+</tt>)
|
787
|
+
# * +ASSIGNMENT+ operator for assigning values to token sets (<tt>:</tt>)
|
788
|
+
# * +OR+ operators for token sets or for free texts (<tt>|</tt>)
|
789
|
+
# * +AND+ operators for kind identifiers (<tt>+</tt>)
|
790
|
+
# * Pattern marker and pattern delimiters
|
496
791
|
module Inflector
|
497
792
|
|
498
793
|
class API
|
@@ -506,6 +801,12 @@ module I18n
|
|
506
801
|
# database and operations for named patterns (strict kinds)
|
507
802
|
attr_reader :strict
|
508
803
|
|
804
|
+
# This reader allows to reach internal configuration
|
805
|
+
# of the engine. It is shared among all instances of
|
806
|
+
# the Inflector and also available as
|
807
|
+
# {I18n::Inflector::Config I18n::Inflector::Config}.
|
808
|
+
attr_reader :config
|
809
|
+
|
509
810
|
# Gets known regular inflection kinds.
|
510
811
|
#
|
511
812
|
# @api public
|
@@ -532,4 +833,9 @@ module I18n
|
|
532
833
|
# @abstract This exception class is defined in package I18n. It is raised when
|
533
834
|
# the given and/or processed locale parameter is invalid.
|
534
835
|
class InvalidLocale; end
|
836
|
+
|
837
|
+
# @abstract This exception class is defined in package I18n. It is raised when
|
838
|
+
# the given and/or processed translation data or parameter are invalid.
|
839
|
+
class ArgumentError; end
|
840
|
+
|
535
841
|
end
|