activesupport 2.3.5 → 2.3.6.pre

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (121) hide show
  1. data/CHANGELOG +23 -0
  2. data/lib/active_support.rb +1 -0
  3. data/lib/active_support/core_ext/date_time/conversions.rb +14 -3
  4. data/lib/active_support/core_ext/enumerable.rb +6 -0
  5. data/lib/active_support/core_ext/file/atomic.rb +2 -1
  6. data/lib/active_support/core_ext/numeric/conversions.rb +2 -2
  7. data/lib/active_support/core_ext/object.rb +1 -0
  8. data/lib/active_support/core_ext/object/metaclass.rb +6 -5
  9. data/lib/active_support/core_ext/object/singleton_class.rb +13 -0
  10. data/lib/active_support/core_ext/string.rb +0 -1
  11. data/lib/active_support/core_ext/string/output_safety.rb +148 -44
  12. data/lib/active_support/core_ext/time/calculations.rb +1 -1
  13. data/lib/active_support/inflector.rb +1 -1
  14. data/lib/active_support/json/backends/yajl.rb +40 -0
  15. data/lib/active_support/json/decoding.rb +16 -1
  16. data/lib/active_support/json/encoding.rb +11 -2
  17. data/lib/active_support/ordered_hash.rb +24 -1
  18. data/lib/active_support/vendor.rb +10 -2
  19. data/lib/active_support/vendor/i18n-0.3.3/CHANGELOG.textile +76 -0
  20. data/lib/active_support/vendor/{i18n-0.1.3 → i18n-0.3.3}/MIT-LICENSE +0 -0
  21. data/lib/active_support/vendor/i18n-0.3.3/README.textile +81 -0
  22. data/lib/active_support/vendor/i18n-0.3.3/Rakefile +24 -0
  23. data/lib/active_support/vendor/i18n-0.3.3/benchmark/example.yml +144 -0
  24. data/lib/active_support/vendor/i18n-0.3.3/benchmark/run.rb +71 -0
  25. data/lib/active_support/vendor/i18n-0.3.3/contributors.txt +17 -0
  26. data/lib/active_support/vendor/i18n-0.3.3/i18n.gemspec +165 -0
  27. data/lib/active_support/vendor/i18n-0.3.3/init.rb +1 -0
  28. data/lib/active_support/vendor/{i18n-0.1.3 → i18n-0.3.3}/lib/i18n.rb +99 -21
  29. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend.rb +17 -0
  30. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/active_record.rb +70 -0
  31. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/active_record/missing.rb +67 -0
  32. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/active_record/store_procs.rb +38 -0
  33. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/active_record/translation.rb +83 -0
  34. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/base.rb +259 -0
  35. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/cache.rb +75 -0
  36. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/cascade.rb +44 -0
  37. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/chain.rb +74 -0
  38. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/fallbacks.rb +52 -0
  39. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/fast.rb +68 -0
  40. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/gettext.rb +75 -0
  41. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/helpers.rb +80 -0
  42. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/interpolation_compiler.rb +119 -0
  43. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/metadata.rb +73 -0
  44. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/pluralization.rb +57 -0
  45. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/backend/simple.rb +22 -0
  46. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/core_ext/object/meta_class.rb +5 -0
  47. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/core_ext/string/interpolate.rb +99 -0
  48. data/lib/active_support/vendor/{i18n-0.1.3 → i18n-0.3.3}/lib/i18n/exceptions.rb +14 -6
  49. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/gettext.rb +25 -0
  50. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/helpers.rb +5 -0
  51. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/helpers/gettext.rb +64 -0
  52. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale.rb +6 -0
  53. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/fallbacks.rb +98 -0
  54. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/tag.rb +28 -0
  55. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/tag/parents.rb +24 -0
  56. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/tag/rfc4646.rb +76 -0
  57. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/locale/tag/simple.rb +41 -0
  58. data/lib/active_support/vendor/i18n-0.3.3/lib/i18n/version.rb +3 -0
  59. data/lib/active_support/vendor/i18n-0.3.3/test/all.rb +8 -0
  60. data/lib/active_support/vendor/i18n-0.3.3/test/api/basics.rb +15 -0
  61. data/lib/active_support/vendor/i18n-0.3.3/test/api/defaults.rb +40 -0
  62. data/lib/active_support/vendor/i18n-0.3.3/test/api/interpolation.rb +92 -0
  63. data/lib/active_support/vendor/i18n-0.3.3/test/api/link.rb +55 -0
  64. data/lib/active_support/vendor/i18n-0.3.3/test/api/localization/date.rb +91 -0
  65. data/lib/active_support/vendor/i18n-0.3.3/test/api/localization/date_time.rb +90 -0
  66. data/lib/active_support/vendor/i18n-0.3.3/test/api/localization/procs.rb +54 -0
  67. data/lib/active_support/vendor/i18n-0.3.3/test/api/localization/time.rb +84 -0
  68. data/lib/active_support/vendor/i18n-0.3.3/test/api/lookup.rb +45 -0
  69. data/lib/active_support/vendor/i18n-0.3.3/test/api/pluralization.rb +35 -0
  70. data/lib/active_support/vendor/i18n-0.3.3/test/api/procs.rb +40 -0
  71. data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/active_record_test.rb +29 -0
  72. data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/all_features_test.rb +40 -0
  73. data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/cascade_test.rb +31 -0
  74. data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/chain_test.rb +26 -0
  75. data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/fallbacks_test.rb +33 -0
  76. data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/fast_test.rb +31 -0
  77. data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/pluralization_test.rb +33 -0
  78. data/lib/active_support/vendor/i18n-0.3.3/test/cases/api/simple_test.rb +21 -0
  79. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/active_record/missing_test.rb +60 -0
  80. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/active_record_test.rb +52 -0
  81. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/cache_test.rb +72 -0
  82. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/cascade_test.rb +66 -0
  83. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/chain_test.rb +64 -0
  84. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/fallbacks_test.rb +57 -0
  85. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/fast_test.rb +50 -0
  86. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/helpers_test.rb +26 -0
  87. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/interpolation_compiler_test.rb +107 -0
  88. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/metadata_test.rb +67 -0
  89. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/pluralization_test.rb +43 -0
  90. data/lib/active_support/vendor/i18n-0.3.3/test/cases/backend/simple_test.rb +77 -0
  91. data/lib/active_support/vendor/i18n-0.3.3/test/cases/core_ext/string/interpolate_test.rb +94 -0
  92. data/lib/active_support/vendor/i18n-0.3.3/test/cases/gettext/api_test.rb +201 -0
  93. data/lib/active_support/vendor/i18n-0.3.3/test/cases/gettext/backend_test.rb +91 -0
  94. data/lib/active_support/vendor/{i18n-0.1.3/test → i18n-0.3.3/test/cases}/i18n_exceptions_test.rb +8 -10
  95. data/lib/active_support/vendor/i18n-0.3.3/test/cases/i18n_load_path_test.rb +23 -0
  96. data/lib/active_support/vendor/i18n-0.3.3/test/cases/i18n_test.rb +172 -0
  97. data/lib/active_support/vendor/i18n-0.3.3/test/cases/locale/fallbacks_test.rb +126 -0
  98. data/lib/active_support/vendor/i18n-0.3.3/test/cases/locale/tag/rfc4646_test.rb +143 -0
  99. data/lib/active_support/vendor/i18n-0.3.3/test/cases/locale/tag/simple_test.rb +33 -0
  100. data/lib/active_support/vendor/i18n-0.3.3/test/fixtures/locales/de.po +72 -0
  101. data/lib/active_support/vendor/i18n-0.3.3/test/fixtures/locales/en.rb +3 -0
  102. data/lib/active_support/vendor/i18n-0.3.3/test/fixtures/locales/en.yml +3 -0
  103. data/lib/active_support/vendor/i18n-0.3.3/test/fixtures/locales/plurals.rb +113 -0
  104. data/lib/active_support/vendor/i18n-0.3.3/test/test_helper.rb +100 -0
  105. data/lib/active_support/vendor/i18n-0.3.3/vendor/po_parser.rb +329 -0
  106. data/lib/active_support/version.rb +1 -1
  107. data/lib/active_support/whiny_nil.rb +1 -1
  108. data/lib/active_support/xml_mini/libxml.rb +23 -83
  109. data/lib/active_support/xml_mini/libxmlsax.rb +74 -0
  110. data/lib/active_support/xml_mini/nokogiri.rb +25 -22
  111. data/lib/active_support/xml_mini/nokogirisax.rb +73 -0
  112. metadata +108 -20
  113. data/lib/active_support/vendor/i18n-0.1.3/README.textile +0 -20
  114. data/lib/active_support/vendor/i18n-0.1.3/Rakefile +0 -5
  115. data/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec +0 -27
  116. data/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb +0 -214
  117. data/lib/active_support/vendor/i18n-0.1.3/test/all.rb +0 -5
  118. data/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +0 -124
  119. data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb +0 -1
  120. data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml +0 -3
  121. data/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +0 -567
@@ -0,0 +1,119 @@
1
+ # encoding: utf-8
2
+
3
+ # The InterpolationCompiler module contains optimizations that can tremendously
4
+ # speed up the interpolation process on the Simple backend.
5
+ #
6
+ # It works by defining a pre-compiled method on stored translation Strings that
7
+ # already bring all the knowledge about contained interpolation variables etc.
8
+ # so that the actual recurring interpolation will be very fast.
9
+ #
10
+ # To enable pre-compiled interpolations you can simply include the
11
+ # InterpolationCompiler module to the Simple backend:
12
+ #
13
+ # I18n::Backend::Simple.send(:include, I18n::Backend::InterpolationCompiler)
14
+ module I18n
15
+ module Backend
16
+ module InterpolationCompiler
17
+ module Compiler
18
+ extend self
19
+
20
+ TOKENIZER = /(\\\{\{[^\}]+\}\}|\{\{[^\}]+\}\})/
21
+ INTERPOLATION_SYNTAX_PATTERN = /(\\)?(\{\{([^\}]+)\}\})/
22
+
23
+ def compile_if_an_interpolation(string)
24
+ if interpolated_str?(string)
25
+ string.instance_eval <<-RUBY_EVAL, __FILE__, __LINE__
26
+ def i18n_interpolate(v = {})
27
+ "#{compiled_interpolation_body(string)}"
28
+ end
29
+ RUBY_EVAL
30
+ end
31
+
32
+ string
33
+ end
34
+
35
+ def interpolated_str?(str)
36
+ str.kind_of?(String) && str =~ INTERPOLATION_SYNTAX_PATTERN
37
+ end
38
+
39
+ protected
40
+ # tokenize("foo {{bar}} baz \\{{buz}}") # => ["foo ", "{{bar}}", " baz ", "\\{{buz}}"]
41
+ def tokenize(str)
42
+ str.split(TOKENIZER)
43
+ end
44
+
45
+ def compiled_interpolation_body(str)
46
+ tokenize(str).map do |token|
47
+ (matchdata = token.match(INTERPOLATION_SYNTAX_PATTERN)) ? handle_interpolation_token(token, matchdata) : escape_plain_str(token)
48
+ end.join
49
+ end
50
+
51
+ def handle_interpolation_token(interpolation, matchdata)
52
+ escaped, pattern, key = matchdata.values_at(1, 2, 3)
53
+ escaped ? pattern : compile_interpolation_token(key.to_sym)
54
+ end
55
+
56
+ def compile_interpolation_token(key)
57
+ "\#{#{interpolate_or_raise_missing(key)}}"
58
+ end
59
+
60
+ def interpolate_or_raise_missing(key)
61
+ escaped_key = escape_key_sym(key)
62
+ Base::RESERVED_KEYS.include?(key) ? reserved_key(escaped_key) : interpolate_key(escaped_key)
63
+ end
64
+
65
+ def interpolate_key(key)
66
+ [direct_key(key), nil_key(key), missing_key(key)].join('||')
67
+ end
68
+
69
+ def direct_key(key)
70
+ "((t = v[#{key}]) && t.respond_to?(:call) ? t.call : t)"
71
+ end
72
+
73
+ def nil_key(key)
74
+ "(v.has_key?(#{key}) && '')"
75
+ end
76
+
77
+ def missing_key(key)
78
+ "raise(MissingInterpolationArgument.new(#{key}, self))"
79
+ end
80
+
81
+ def reserved_key(key)
82
+ "raise(ReservedInterpolationKey.new(#{key}, self))"
83
+ end
84
+
85
+ def escape_plain_str(str)
86
+ str.gsub(/"|\\|#/) {|x| "\\#{x}"}
87
+ end
88
+
89
+ def escape_key_sym(key)
90
+ # rely on Ruby to do all the hard work :)
91
+ key.to_sym.inspect
92
+ end
93
+ end
94
+
95
+ def interpolate(locale, string, values)
96
+ if string.respond_to?(:i18n_interpolate)
97
+ string.i18n_interpolate(values)
98
+ elsif values
99
+ super
100
+ else
101
+ string
102
+ end
103
+ end
104
+
105
+ def merge_translations(locale, data)
106
+ compile_all_strings_in(data)
107
+ super
108
+ end
109
+
110
+ protected
111
+ def compile_all_strings_in(data)
112
+ data.each_value do |value|
113
+ Compiler.compile_if_an_interpolation(value)
114
+ compile_all_strings_in(value) if value.kind_of?(Hash)
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,73 @@
1
+ # I18n translation metadata is useful when you want to access information
2
+ # about how a translation was looked up, pluralized or interpolated in
3
+ # your application.
4
+ #
5
+ # msg = I18n.t(:message, :default => 'Hi!', :scope => :foo)
6
+ # msg.translation_metadata
7
+ # # => { :key => :message, :scope => :foo, :default => 'Hi!' }
8
+ #
9
+ # If a :count option was passed to #translate it will be set to the metadata.
10
+ # Likewise, if any interpolation variables were passed they will also be set.
11
+ #
12
+ # To enable translation metadata you can simply include the Metadata module
13
+ # into the Simple backend class - or whatever other backend you are using:
14
+ #
15
+ # I18n::Backend::Simple.send(:include, I18n::Backend::Metadata)
16
+
17
+ require 'i18n/core_ext/object/meta_class'
18
+
19
+ module I18n
20
+ module Backend
21
+ module Metadata
22
+ class << self
23
+ def included(base)
24
+ Object.class_eval do
25
+ def translation_metadata
26
+ @translation_metadata ||= {}
27
+ end
28
+
29
+ def translation_metadata=(translation_metadata)
30
+ @translation_metadata = translation_metadata
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def translate(locale, key, options = {})
37
+ metadata = {
38
+ :locale => locale,
39
+ :key => key,
40
+ :scope => options[:scope],
41
+ :default => options[:default],
42
+ :separator => options[:separator],
43
+ :values => options.reject { |name, value| Base::RESERVED_KEYS.include?(name) }
44
+ }
45
+ with_metadata(metadata) { super }
46
+ end
47
+
48
+ def interpolate(locale, string, values = {})
49
+ with_metadata(:original => string) do
50
+ preserve_translation_metadata(string) { super }
51
+ end if string
52
+ end
53
+
54
+ def pluralize(locale, entry, count)
55
+ with_metadata(:count => count) { super }
56
+ end
57
+
58
+ protected
59
+
60
+ def with_metadata(metadata, &block)
61
+ result = yield
62
+ result.translation_metadata = result.translation_metadata.merge(metadata) if result
63
+ result
64
+ end
65
+
66
+ def preserve_translation_metadata(object, &block)
67
+ result = yield
68
+ result.translation_metadata = object.translation_metadata if result
69
+ result
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+
3
+ # I18n locale fallbacks are useful when you want your application to use
4
+ # translations from other locales when translations for the current locale are
5
+ # missing. E.g. you might want to use :en translations when translations in
6
+ # your applications main locale :de are missing.
7
+ #
8
+ # To enable locale specific pluralizations you can simply include the
9
+ # Pluralization module to the Simple backend - or whatever other backend you
10
+ # are using.
11
+ #
12
+ # I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
13
+ #
14
+ # You also need to make sure to provide pluralization algorithms to the
15
+ # backend, i.e. include them to your I18n.load_path accordingly.
16
+ module I18n
17
+ module Backend
18
+ module Pluralization
19
+ # Overwrites the Base backend translate method so that it will check the
20
+ # translation meta data space (:i18n) for a locale specific pluralization
21
+ # rule and use it to pluralize the given entry. I.e. the library expects
22
+ # pluralization rules to be stored at I18n.t(:'i18n.plural.rule')
23
+ #
24
+ # Pluralization rules are expected to respond to #call(entry, count) and
25
+ # return a pluralization key. Valid keys depend on the translation data
26
+ # hash (entry) but it is generally recommended to follow CLDR's style,
27
+ # i.e., return one of the keys :zero, :one, :few, :many, :other.
28
+ #
29
+ # The :zero key is always picked directly when count equals 0 AND the
30
+ # translation data has the key :zero. This way translators are free to
31
+ # either pick a special :zero translation even for languages where the
32
+ # pluralizer does not return a :zero key.
33
+ def pluralize(locale, entry, count)
34
+ return entry unless entry.is_a?(Hash) and count
35
+
36
+ pluralizer = pluralizer(locale)
37
+ if pluralizer.respond_to?(:call)
38
+ key = count == 0 && entry.has_key?(:zero) ? :zero : pluralizer.call(count)
39
+ raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key)
40
+ entry[key]
41
+ else
42
+ super
43
+ end
44
+ end
45
+
46
+ protected
47
+
48
+ def pluralizers
49
+ @pluralizers ||= {}
50
+ end
51
+
52
+ def pluralizer(locale)
53
+ pluralizers[locale] ||= lookup(locale, :'i18n.plural.rule')
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ # Stub class for the Simple backend. The actual implementation is provided by
4
+ # the backend Base class. This makes it easier to extend the Simple backend's
5
+ # behaviour by including modules. E.g.:
6
+ #
7
+ # module I18n::Backend::Pluralization
8
+ # def pluralize(*args)
9
+ # # extended pluralization logic
10
+ # super
11
+ # end
12
+ # end
13
+ #
14
+ # I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
15
+
16
+ module I18n
17
+ module Backend
18
+ class Simple
19
+ include Base
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ Object.class_eval do
2
+ def meta_class
3
+ class << self; self; end
4
+ end
5
+ end unless Object.method_defined?(:meta_class)
@@ -0,0 +1,99 @@
1
+ # encoding: utf-8
2
+
3
+ =begin
4
+ heavily based on Masao Mutoh's gettext String interpolation extension
5
+ http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
6
+ Copyright (C) 2005-2009 Masao Mutoh
7
+ You may redistribute it and/or modify it under the same license terms as Ruby.
8
+ =end
9
+
10
+ if RUBY_VERSION < '1.9'
11
+
12
+ # KeyError is raised by String#% when the string contains a named placeholder
13
+ # that is not contained in the given arguments hash. Ruby 1.9 includes and
14
+ # raises this exception natively. We define it to mimic Ruby 1.9's behaviour
15
+ # in Ruby 1.8.x
16
+
17
+ class KeyError < IndexError
18
+ def initialize(message = nil)
19
+ super(message || "key not found")
20
+ end
21
+ end unless defined?(KeyError)
22
+
23
+ # Extension for String class. This feature is included in Ruby 1.9 or later but not occur TypeError.
24
+ #
25
+ # String#% method which accept "named argument". The translator can know
26
+ # the meaning of the msgids using "named argument" instead of %s/%d style.
27
+
28
+ class String
29
+ # For older ruby versions, such as ruby-1.8.5
30
+ alias :bytesize :size unless instance_methods.find {|m| m.to_s == 'bytesize'}
31
+ alias :interpolate_without_ruby_19_syntax :% # :nodoc:
32
+
33
+ INTERPOLATION_PATTERN = Regexp.union(
34
+ /%\{(\w+)\}/, # matches placeholders like "%{foo}"
35
+ /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%<foo>.d"
36
+ )
37
+
38
+ INTERPOLATION_PATTERN_WITH_ESCAPE = Regexp.union(
39
+ /%%/,
40
+ INTERPOLATION_PATTERN
41
+ )
42
+
43
+ # % uses self (i.e. the String) as a format specification and returns the
44
+ # result of applying it to the given arguments. In other words it interpolates
45
+ # the given arguments to the string according to the formats the string
46
+ # defines.
47
+ #
48
+ # There are three ways to use it:
49
+ #
50
+ # * Using a single argument or Array of arguments.
51
+ #
52
+ # This is the default behaviour of the String class. See Kernel#sprintf for
53
+ # more details about the format string.
54
+ #
55
+ # Example:
56
+ #
57
+ # "%d %s" % [1, "message"]
58
+ # # => "1 message"
59
+ #
60
+ # * Using a Hash as an argument and unformatted, named placeholders.
61
+ #
62
+ # When you pass a Hash as an argument and specify placeholders with %{foo}
63
+ # it will interpret the hash values as named arguments.
64
+ #
65
+ # Example:
66
+ #
67
+ # "%{firstname}, %{lastname}" % {:firstname => "Masao", :lastname => "Mutoh"}
68
+ # # => "Masao Mutoh"
69
+ #
70
+ # * Using a Hash as an argument and formatted, named placeholders.
71
+ #
72
+ # When you pass a Hash as an argument and specify placeholders with %<foo>d
73
+ # it will interpret the hash values as named arguments and format the value
74
+ # according to the formatting instruction appended to the closing >.
75
+ #
76
+ # Example:
77
+ #
78
+ # "%<integer>d, %<float>.1f" % { :integer => 10, :float => 43.4 }
79
+ # # => "10, 43.3"
80
+ def %(args)
81
+ if args.kind_of?(Hash)
82
+ dup.gsub(INTERPOLATION_PATTERN_WITH_ESCAPE) do |match|
83
+ if match == '%%'
84
+ '%'
85
+ else
86
+ key = ($1 || $2).to_sym
87
+ raise KeyError unless args.has_key?(key)
88
+ $3 ? sprintf("%#{$3}", args[key]) : args[key]
89
+ end
90
+ end
91
+ elsif self =~ INTERPOLATION_PATTERN
92
+ raise ArgumentError.new('one hash required')
93
+ else
94
+ result = gsub(/%([{<])/, '%%\1')
95
+ result.send :'interpolate_without_ruby_19_syntax', args
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,3 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ class KeyError < IndexError
4
+ def initialize(message = nil)
5
+ super(message || "key not found")
6
+ end
7
+ end unless defined?(KeyError)
8
+
1
9
  module I18n
2
10
  class ArgumentError < ::ArgumentError; end
3
11
 
@@ -11,8 +19,8 @@ module I18n
11
19
 
12
20
  class MissingTranslationData < ArgumentError
13
21
  attr_reader :locale, :key, :options
14
- def initialize(locale, key, options)
15
- @key, @locale, @options = key, locale, options
22
+ def initialize(locale, key, opts = nil)
23
+ @key, @locale, @options = key, locale, opts || {}
16
24
  keys = I18n.send(:normalize_translation_keys, locale, key, options[:scope])
17
25
  keys << 'no key' if keys.size < 2
18
26
  super "translation missing: #{keys.join(', ')}"
@@ -28,10 +36,10 @@ module I18n
28
36
  end
29
37
 
30
38
  class MissingInterpolationArgument < ArgumentError
31
- attr_reader :key, :string
32
- def initialize(key, string)
33
- @key, @string = key, string
34
- super "interpolation argument #{key} missing in #{string.inspect}"
39
+ attr_reader :values, :string
40
+ def initialize(values, string)
41
+ @values, @string = values, string
42
+ super "missing interpolation argument in #{string.inspect} (#{values.inspect} given)"
35
43
  end
36
44
  end
37
45
 
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ module I18n
4
+ module Gettext
5
+ PLURAL_SEPARATOR = "\001"
6
+ CONTEXT_SEPARATOR = "\004"
7
+
8
+ @@plural_keys = { :en => [:one, :other] }
9
+
10
+ class << self
11
+ # returns an array of plural keys for the given locale so that we can
12
+ # convert from gettext's integer-index based style
13
+ # TODO move this information to the pluralization module
14
+ def plural_keys(locale)
15
+ @@plural_keys[locale] || @@plural_keys[:en]
16
+ end
17
+
18
+ def extract_scope(msgid, separator)
19
+ scope = msgid.to_s.split(separator)
20
+ msgid = scope.pop
21
+ [scope, msgid]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module I18n
2
+ module Helpers
3
+ autoload :Gettext, 'i18n/helpers/gettext'
4
+ end
5
+ end