activesupport 2.3.8 → 2.3.9.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.
- data/CHANGELOG +11 -0
- data/lib/active_support/core_ext/array/grouping.rb +1 -1
- data/lib/active_support/core_ext/array/random_access.rb +24 -4
- data/lib/active_support/core_ext/class.rb +1 -0
- data/lib/active_support/core_ext/class/attribute.rb +67 -0
- data/lib/active_support/core_ext/enumerable.rb +1 -1
- data/lib/active_support/core_ext/kernel/singleton_class.rb +13 -0
- data/lib/active_support/core_ext/module/remove_method.rb +6 -0
- data/lib/active_support/core_ext/object/misc.rb +3 -0
- data/lib/active_support/core_ext/range/blockless_step.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +0 -11
- data/lib/active_support/dependencies.rb +36 -12
- data/lib/active_support/deprecation.rb +7 -0
- data/lib/active_support/json/backends/yajl.rb +1 -1
- data/lib/active_support/ordered_hash.rb +6 -0
- data/lib/active_support/testing/performance.rb +1 -1
- data/lib/active_support/values/time_zone.rb +5 -1
- data/lib/active_support/vendor.rb +2 -2
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n.rb +92 -105
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend.rb +5 -4
- data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/active_record.rb +61 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/active_record/missing.rb +4 -6
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/active_record/store_procs.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/active_record/translation.rb +8 -3
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/base.rb +55 -84
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/cache.rb +1 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/cascade.rb +0 -1
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/chain.rb +3 -1
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/cldr.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/fallbacks.rb +0 -0
- data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/flatten.rb +113 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/gettext.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/interpolation_compiler.rb +8 -4
- data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/key_value.rb +102 -0
- data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/memoize.rb +48 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/metadata.rb +5 -13
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/pluralization.rb +0 -0
- data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/simple.rb +87 -0
- data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/transliterator.rb +98 -0
- data/lib/active_support/vendor/i18n-0.4.1/i18n/config.rb +84 -0
- data/lib/active_support/vendor/i18n-0.4.1/i18n/core_ext/hash.rb +29 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/core_ext/string/interpolate.rb +3 -4
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/exceptions.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/gettext.rb +2 -0
- data/lib/active_support/vendor/{i18n-0.3.7/i18n/helpers/gettext.rb → i18n-0.4.1/i18n/gettext/helpers.rb} +2 -2
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/gettext/po_parser.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/locale.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/locale/fallbacks.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/locale/tag.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/locale/tag/parents.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/locale/tag/rfc4646.rb +0 -0
- data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/locale/tag/simple.rb +0 -0
- data/lib/active_support/vendor/i18n-0.4.1/i18n/version.rb +3 -0
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/whiny_nil.rb +1 -1
- metadata +48 -43
- data/lib/active_support/vendor/i18n-0.3.7/i18n/backend/active_record.rb +0 -66
- data/lib/active_support/vendor/i18n-0.3.7/i18n/backend/fast.rb +0 -69
- data/lib/active_support/vendor/i18n-0.3.7/i18n/backend/helpers.rb +0 -68
- data/lib/active_support/vendor/i18n-0.3.7/i18n/backend/links.rb +0 -34
- data/lib/active_support/vendor/i18n-0.3.7/i18n/backend/simple.rb +0 -22
- data/lib/active_support/vendor/i18n-0.3.7/i18n/core_ext/hash/except.rb +0 -8
- data/lib/active_support/vendor/i18n-0.3.7/i18n/core_ext/hash/slice.rb +0 -8
- data/lib/active_support/vendor/i18n-0.3.7/i18n/core_ext/object/meta_class.rb +0 -5
- data/lib/active_support/vendor/i18n-0.3.7/i18n/helpers.rb +0 -5
- data/lib/active_support/vendor/i18n-0.3.7/i18n/version.rb +0 -3
@@ -2,18 +2,19 @@ module I18n
|
|
2
2
|
module Backend
|
3
3
|
autoload :ActiveRecord, 'i18n/backend/active_record'
|
4
4
|
autoload :Base, 'i18n/backend/base'
|
5
|
+
autoload :InterpolationCompiler, 'i18n/backend/interpolation_compiler'
|
5
6
|
autoload :Cache, 'i18n/backend/cache'
|
6
7
|
autoload :Cascade, 'i18n/backend/cascade'
|
7
8
|
autoload :Chain, 'i18n/backend/chain'
|
8
9
|
autoload :Cldr, 'i18n/backend/cldr'
|
9
10
|
autoload :Fallbacks, 'i18n/backend/fallbacks'
|
10
|
-
autoload :
|
11
|
+
autoload :Flatten, 'i18n/backend/flatten'
|
11
12
|
autoload :Gettext, 'i18n/backend/gettext'
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
autoload :InterpolationCompiler, 'i18n/backend/interpolation_compiler'
|
13
|
+
autoload :KeyValue, 'i18n/backend/key_value'
|
14
|
+
autoload :Memoize, 'i18n/backend/memoize'
|
15
15
|
autoload :Metadata, 'i18n/backend/metadata'
|
16
16
|
autoload :Pluralization, 'i18n/backend/pluralization'
|
17
17
|
autoload :Simple, 'i18n/backend/simple'
|
18
|
+
autoload :Transliterator, 'i18n/backend/transliterator'
|
18
19
|
end
|
19
20
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'i18n/backend/base'
|
2
|
+
require 'i18n/backend/active_record/translation'
|
3
|
+
|
4
|
+
module I18n
|
5
|
+
module Backend
|
6
|
+
class ActiveRecord
|
7
|
+
autoload :Missing, 'i18n/backend/active_record/missing'
|
8
|
+
autoload :StoreProcs, 'i18n/backend/active_record/store_procs'
|
9
|
+
autoload :Translation, 'i18n/backend/active_record/translation'
|
10
|
+
|
11
|
+
module Implementation
|
12
|
+
include Base, Flatten
|
13
|
+
|
14
|
+
def available_locales
|
15
|
+
begin
|
16
|
+
Translation.available_locales
|
17
|
+
rescue ::ActiveRecord::StatementInvalid
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def store_translations(locale, data, options = {})
|
23
|
+
escape = options.fetch(:escape, true)
|
24
|
+
flatten_translations(locale, data, escape, false).each do |key, value|
|
25
|
+
Translation.locale(locale).lookup(expand_keys(key)).delete_all
|
26
|
+
Translation.create(:locale => locale.to_s, :key => key.to_s, :value => value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def lookup(locale, key, scope = [], options = {})
|
33
|
+
key = normalize_flat_keys(locale, key, scope, options[:separator])
|
34
|
+
result = Translation.locale(locale).lookup(key).all
|
35
|
+
|
36
|
+
if result.empty?
|
37
|
+
nil
|
38
|
+
elsif result.first.key == key
|
39
|
+
result.first.value
|
40
|
+
else
|
41
|
+
chop_range = (key.size + FLATTEN_SEPARATOR.size)..-1
|
42
|
+
result = result.inject({}) do |hash, r|
|
43
|
+
hash[r.key.slice(chop_range)] = r.value
|
44
|
+
hash
|
45
|
+
end
|
46
|
+
result.deep_symbolize_keys
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# For a key :'foo.bar.baz' return ['foo', 'foo.bar', 'foo.bar.baz']
|
51
|
+
def expand_keys(key)
|
52
|
+
key.to_s.split(FLATTEN_SEPARATOR).inject([]) do |keys, key|
|
53
|
+
keys << [keys.last, key].compact.join(FLATTEN_SEPARATOR)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
include Implementation
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/active_record/missing.rb
RENAMED
@@ -40,7 +40,7 @@ module I18n
|
|
40
40
|
keys = I18n.normalize_keys(locale, key, scope, separator)[1..-1]
|
41
41
|
key = keys.join(separator || I18n.default_separator)
|
42
42
|
|
43
|
-
unless ActiveRecord::Translation.locale(locale).lookup(key
|
43
|
+
unless ActiveRecord::Translation.locale(locale).lookup(key).exists?
|
44
44
|
interpolations = options.reject { |name, value| Base::RESERVED_KEYS.include?(name) }.keys
|
45
45
|
keys = count ? I18n.t('i18n.plural.keys', :locale => locale).map { |k| [key, k].join(separator) } : [key]
|
46
46
|
keys.each { |key| store_default_translation(locale, key, interpolations) }
|
@@ -55,11 +55,9 @@ module I18n
|
|
55
55
|
|
56
56
|
def translate(locale, key, options = {})
|
57
57
|
super
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
raise e
|
58
|
+
rescue I18n::MissingTranslationData => e
|
59
|
+
self.store_default_translations(locale, key, options)
|
60
|
+
raise e
|
63
61
|
end
|
64
62
|
end
|
65
63
|
end
|
data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/active_record/store_procs.rb
RENAMED
File without changes
|
data/lib/active_support/vendor/{i18n-0.3.7 → i18n-0.4.1}/i18n/backend/active_record/translation.rb
RENAMED
@@ -60,9 +60,14 @@ module I18n
|
|
60
60
|
|
61
61
|
send scope_method, :lookup, lambda { |keys, *separator|
|
62
62
|
column_name = connection.quote_column_name('key')
|
63
|
-
keys
|
64
|
-
|
65
|
-
|
63
|
+
keys = Array(keys).map! { |key| key.to_s }
|
64
|
+
|
65
|
+
unless separator.empty?
|
66
|
+
warn "[DEPRECATION] Giving a separator to Translation.lookup is deprecated. " <<
|
67
|
+
"You can change the internal separator by overwriting FLATTEN_SEPARATOR."
|
68
|
+
end
|
69
|
+
|
70
|
+
namespace = "#{keys.last}#{I18n::Backend::Flatten::FLATTEN_SEPARATOR}%"
|
66
71
|
{ :conditions => ["#{column_name} IN (?) OR #{column_name} LIKE ?", keys, namespace] }
|
67
72
|
}
|
68
73
|
|
@@ -1,50 +1,52 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'yaml'
|
4
|
-
require 'i18n/core_ext/hash
|
4
|
+
require 'i18n/core_ext/hash'
|
5
5
|
|
6
6
|
module I18n
|
7
7
|
module Backend
|
8
8
|
module Base
|
9
|
-
include I18n::Backend::
|
9
|
+
include I18n::Backend::Transliterator
|
10
10
|
|
11
11
|
RESERVED_KEYS = [:scope, :default, :separator, :resolve]
|
12
|
-
|
12
|
+
RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/
|
13
|
+
DEPRECATED_INTERPOLATION_SYNTAX_PATTERN = /(\\)?\{\{([^\}]+)\}\}/
|
14
|
+
INTERPOLATION_SYNTAX_PATTERN = /%\{([^\}]+)\}/
|
13
15
|
|
14
16
|
# Accepts a list of paths to translation files. Loads translations from
|
15
17
|
# plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml
|
16
18
|
# for details.
|
17
19
|
def load_translations(*filenames)
|
20
|
+
filenames = I18n.load_path.flatten if filenames.empty?
|
18
21
|
filenames.each { |filename| load_file(filename) }
|
19
22
|
end
|
20
23
|
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# translations will be overwritten by new ones only at the deepest
|
24
|
-
# level of the hash.
|
24
|
+
# This method receives a locale, a data hash and options for storing translations.
|
25
|
+
# Should be implemented
|
25
26
|
def store_translations(locale, data, options = {})
|
26
|
-
|
27
|
+
raise NotImplementedError
|
27
28
|
end
|
28
29
|
|
29
30
|
def translate(locale, key, options = {})
|
30
31
|
raise InvalidLocale.new(locale) unless locale
|
31
32
|
return key.map { |k| translate(locale, k, options) } if key.is_a?(Array)
|
32
33
|
|
34
|
+
entry = key && lookup(locale, key, options[:scope], options)
|
35
|
+
|
33
36
|
if options.empty?
|
34
|
-
entry = resolve(locale, key,
|
35
|
-
raise(I18n::MissingTranslationData.new(locale, key, options)) if entry.nil?
|
37
|
+
entry = resolve(locale, key, entry, options)
|
36
38
|
else
|
37
|
-
count,
|
38
|
-
values = options.
|
39
|
-
|
40
|
-
|
41
|
-
entry = entry.nil? && default ? default(locale, key, default, options) : resolve(locale, key, entry, options)
|
42
|
-
raise(I18n::MissingTranslationData.new(locale, key, options)) if entry.nil?
|
43
|
-
|
44
|
-
entry = pluralize(locale, entry, count) if count
|
45
|
-
entry = interpolate(locale, entry, values) if values
|
39
|
+
count, default = options.values_at(:count, :default)
|
40
|
+
values = options.except(*RESERVED_KEYS)
|
41
|
+
entry = entry.nil? && default ?
|
42
|
+
default(locale, key, default, options) : resolve(locale, key, entry, options)
|
46
43
|
end
|
47
44
|
|
45
|
+
raise(I18n::MissingTranslationData.new(locale, key, options)) if entry.nil?
|
46
|
+
entry = entry.dup if entry.is_a?(String)
|
47
|
+
|
48
|
+
entry = pluralize(locale, entry, count) if count
|
49
|
+
entry = interpolate(locale, entry, values) if values
|
48
50
|
entry
|
49
51
|
end
|
50
52
|
|
@@ -57,7 +59,7 @@ module I18n
|
|
57
59
|
if Symbol === format
|
58
60
|
key = format
|
59
61
|
type = object.respond_to?(:sec) ? 'time' : 'date'
|
60
|
-
format = I18n.t(:"#{type}.formats.#{key}", :
|
62
|
+
format = I18n.t(:"#{type}.formats.#{key}", options.merge(:raise => true, :object => object, :locale => locale))
|
61
63
|
end
|
62
64
|
|
63
65
|
# format = resolve(locale, object, format, options)
|
@@ -74,51 +76,21 @@ module I18n
|
|
74
76
|
object.strftime(format)
|
75
77
|
end
|
76
78
|
|
77
|
-
def initialized?
|
78
|
-
@initialized ||= false
|
79
|
-
end
|
80
|
-
|
81
79
|
# Returns an array of locales for which translations are available
|
82
80
|
# ignoring the reserved translation meta data key :i18n.
|
83
81
|
def available_locales
|
84
|
-
|
85
|
-
translations.inject([]) do |locales, (locale, data)|
|
86
|
-
locales << locale unless (data.keys - [:i18n]).empty?
|
87
|
-
locales
|
88
|
-
end
|
82
|
+
raise NotImplementedError
|
89
83
|
end
|
90
84
|
|
91
85
|
def reload!
|
92
|
-
@
|
93
|
-
@translations = nil
|
86
|
+
@skip_syntax_deprecation = false
|
94
87
|
end
|
95
88
|
|
96
89
|
protected
|
97
|
-
def init_translations
|
98
|
-
load_translations(*I18n.load_path.flatten)
|
99
|
-
@initialized = true
|
100
|
-
end
|
101
|
-
|
102
|
-
def translations
|
103
|
-
@translations ||= {}
|
104
|
-
end
|
105
90
|
|
106
|
-
#
|
107
|
-
# eiher key is nil, or locale, scope or key do not exist as a key in the
|
108
|
-
# nested translations hash. Splits keys or scopes containing dots
|
109
|
-
# into multiple keys, i.e. <tt>currency.format</tt> is regarded the same as
|
110
|
-
# <tt>%w(currency format)</tt>.
|
91
|
+
# The method which actually looks up for the translation in the store.
|
111
92
|
def lookup(locale, key, scope = [], options = {})
|
112
|
-
|
113
|
-
init_translations unless initialized?
|
114
|
-
keys = I18n.normalize_keys(locale, key, scope, options[:separator])
|
115
|
-
keys.inject(translations) do |result, key|
|
116
|
-
key = key.to_sym
|
117
|
-
return nil unless result.is_a?(Hash) && result.has_key?(key)
|
118
|
-
result = result[key]
|
119
|
-
result = resolve(locale, key, result, options) if result.is_a?(Symbol)
|
120
|
-
String === result ? result.dup : result
|
121
|
-
end
|
93
|
+
raise NotImplementedError
|
122
94
|
end
|
123
95
|
|
124
96
|
# Evaluates defaults.
|
@@ -147,7 +119,8 @@ module I18n
|
|
147
119
|
when Symbol
|
148
120
|
I18n.translate(subject, (options || {}).merge(:locale => locale, :raise => true))
|
149
121
|
when Proc
|
150
|
-
|
122
|
+
date_or_time = options.delete(:object) || object
|
123
|
+
resolve(locale, object, subject.call(date_or_time, options), options = {})
|
151
124
|
else
|
152
125
|
subject
|
153
126
|
end
|
@@ -160,7 +133,7 @@ module I18n
|
|
160
133
|
# and the second translation if it is equal to 1. Other backends can
|
161
134
|
# implement more flexible or complex pluralization rules.
|
162
135
|
def pluralize(locale, entry, count)
|
163
|
-
return entry unless entry.is_a?(Hash)
|
136
|
+
return entry unless entry.is_a?(Hash) && count
|
164
137
|
|
165
138
|
key = :zero if count == 0 && entry.has_key?(:zero)
|
166
139
|
key ||= count == 1 ? :one : :other
|
@@ -170,38 +143,48 @@ module I18n
|
|
170
143
|
|
171
144
|
# Interpolates values into a given string.
|
172
145
|
#
|
173
|
-
# interpolate "file {
|
174
|
-
# # => "file test.txt opened by {
|
146
|
+
# interpolate "file %{file} opened by %%{user}", :file => 'test.txt', :user => 'Mr. X'
|
147
|
+
# # => "file test.txt opened by %{user}"
|
175
148
|
#
|
176
149
|
# Note that you have to double escape the <tt>\\</tt> when you want to escape
|
177
150
|
# the <tt>{{...}}</tt> key in a string (once for the string and once for the
|
178
151
|
# interpolation).
|
179
152
|
def interpolate(locale, string, values = {})
|
180
153
|
return string unless string.is_a?(::String) && !values.empty?
|
154
|
+
original_values = values.dup
|
181
155
|
|
182
156
|
preserve_encoding(string) do
|
183
|
-
|
157
|
+
string = string.gsub(DEPRECATED_INTERPOLATION_SYNTAX_PATTERN) do
|
184
158
|
escaped, key = $1, $2.to_sym
|
185
159
|
if escaped
|
186
160
|
"{{#{key}}}"
|
187
|
-
elsif RESERVED_KEYS.include?(key)
|
188
|
-
raise ReservedInterpolationKey.new(key, string)
|
189
161
|
else
|
162
|
+
warn_syntax_deprecation!
|
190
163
|
"%{#{key}}"
|
191
164
|
end
|
192
165
|
end
|
193
166
|
|
167
|
+
keys = string.scan(INTERPOLATION_SYNTAX_PATTERN).flatten
|
168
|
+
return string if keys.empty?
|
169
|
+
|
194
170
|
values.each do |key, value|
|
195
|
-
|
196
|
-
|
197
|
-
|
171
|
+
if keys.include?(key.to_s)
|
172
|
+
value = value.call(values) if interpolate_lambda?(value, string, key)
|
173
|
+
value = value.to_s unless value.is_a?(::String)
|
174
|
+
values[key] = value
|
175
|
+
else
|
176
|
+
values.delete(key)
|
177
|
+
end
|
198
178
|
end
|
199
179
|
|
200
|
-
|
180
|
+
string % values
|
201
181
|
end
|
202
|
-
|
203
182
|
rescue KeyError => e
|
204
|
-
|
183
|
+
if string =~ RESERVED_KEYS_PATTERN
|
184
|
+
raise ReservedInterpolationKey.new($1.to_sym, string)
|
185
|
+
else
|
186
|
+
raise MissingInterpolationArgument.new(original_values, string)
|
187
|
+
end
|
205
188
|
end
|
206
189
|
|
207
190
|
def preserve_encoding(string)
|
@@ -229,7 +212,7 @@ module I18n
|
|
229
212
|
type = File.extname(filename).tr('.', '').downcase
|
230
213
|
raise UnknownFileType.new(type, filename) unless respond_to?(:"load_#{type}")
|
231
214
|
data = send(:"load_#{type}", filename) # TODO raise a meaningful exception if this does not yield a Hash
|
232
|
-
data.each { |locale, d|
|
215
|
+
data.each { |locale, d| store_translations(locale, d) }
|
233
216
|
end
|
234
217
|
|
235
218
|
# Loads a plain Ruby translations file. eval'ing the file must yield
|
@@ -244,22 +227,10 @@ module I18n
|
|
244
227
|
YAML::load(IO.read(filename))
|
245
228
|
end
|
246
229
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
translations[locale] ||= {}
|
252
|
-
separator = options[:separator] || I18n.default_separator
|
253
|
-
data = unwind_keys(data, separator)
|
254
|
-
data = deep_symbolize_keys(data)
|
255
|
-
|
256
|
-
# deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
|
257
|
-
merger = proc do |key, v1, v2|
|
258
|
-
# TODO should probably be:
|
259
|
-
# raise TypeError.new("can't merge #{v1.inspect} and #{v2.inspect}") unless Hash === v1 && Hash === v2
|
260
|
-
Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : (v2 || v1)
|
261
|
-
end
|
262
|
-
translations[locale].merge!(data, &merger)
|
230
|
+
def warn_syntax_deprecation! #:nodoc:
|
231
|
+
return if @skip_syntax_deprecation
|
232
|
+
warn "The {{key}} interpolation syntax in I18n messages is deprecated. Please use %{key} instead.\n#{caller.join("\n")}"
|
233
|
+
@skip_syntax_deprecation = true
|
263
234
|
end
|
264
235
|
end
|
265
236
|
end
|
@@ -16,7 +16,9 @@ module I18n
|
|
16
16
|
#
|
17
17
|
# The implementation assumes that all backends added to the Chain implement
|
18
18
|
# a lookup method with the same API as Simple backend does.
|
19
|
-
class Chain
|
19
|
+
class Chain
|
20
|
+
include Base
|
21
|
+
|
20
22
|
attr_accessor :backends
|
21
23
|
|
22
24
|
def initialize(*backends)
|
File without changes
|
File without changes
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module I18n
|
2
|
+
module Backend
|
3
|
+
# This module contains several helpers to assist flattening translations.
|
4
|
+
# You may want to flatten translations for:
|
5
|
+
#
|
6
|
+
# 1) speed up lookups, as in the Memoize backend;
|
7
|
+
# 2) In case you want to store translations in a data store, as in ActiveRecord backend;
|
8
|
+
#
|
9
|
+
# You can check both backends above for some examples.
|
10
|
+
# This module also keeps all links in a hash so they can be properly resolved when flattened.
|
11
|
+
module Flatten
|
12
|
+
SEPARATOR_ESCAPE_CHAR = "\001"
|
13
|
+
FLATTEN_SEPARATOR = "."
|
14
|
+
|
15
|
+
# normalize_keys the flatten way. This method is significantly faster
|
16
|
+
# and creates way less objects than the one at I18n.normalize_keys.
|
17
|
+
# It also handles escaping the translation keys.
|
18
|
+
def self.normalize_flat_keys(locale, key, scope, separator)
|
19
|
+
keys = [scope, key].flatten.compact
|
20
|
+
separator ||= I18n.default_separator
|
21
|
+
|
22
|
+
if separator != FLATTEN_SEPARATOR
|
23
|
+
keys.map! do |k|
|
24
|
+
k.to_s.tr("#{FLATTEN_SEPARATOR}#{separator}",
|
25
|
+
"#{SEPARATOR_ESCAPE_CHAR}#{FLATTEN_SEPARATOR}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
keys.join(".")
|
30
|
+
end
|
31
|
+
|
32
|
+
# Receives a string and escape the default separator.
|
33
|
+
def self.escape_default_separator(key) #:nodoc:
|
34
|
+
key.to_s.tr(FLATTEN_SEPARATOR, SEPARATOR_ESCAPE_CHAR)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Shortcut to I18n::Backend::Flatten.normalize_flat_keys
|
38
|
+
# and then resolve_links.
|
39
|
+
def normalize_flat_keys(locale, key, scope, separator)
|
40
|
+
key = I18n::Backend::Flatten.normalize_flat_keys(locale, key, scope, separator)
|
41
|
+
resolve_link(locale, key)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Store flattened links.
|
45
|
+
def links
|
46
|
+
@links ||= Hash.new { |h,k| h[k] = {} }
|
47
|
+
end
|
48
|
+
|
49
|
+
# Flatten keys for nested Hashes by chaining up keys:
|
50
|
+
#
|
51
|
+
# >> { "a" => { "b" => { "c" => "d", "e" => "f" }, "g" => "h" }, "i" => "j"}.wind
|
52
|
+
# => { "a.b.c" => "d", "a.b.e" => "f", "a.g" => "h", "i" => "j" }
|
53
|
+
#
|
54
|
+
def flatten_keys(hash, escape, prev_key=nil, &block)
|
55
|
+
hash.each_pair do |key, value|
|
56
|
+
key = escape_default_separator(key) if escape
|
57
|
+
curr_key = [prev_key, key].compact.join(FLATTEN_SEPARATOR).to_sym
|
58
|
+
yield curr_key, value
|
59
|
+
flatten_keys(value, escape, curr_key, &block) if value.is_a?(Hash)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Receives a hash of translations (where the key is a locale and
|
64
|
+
# the value is another hash) and return a hash with all
|
65
|
+
# translations flattened.
|
66
|
+
#
|
67
|
+
# Nested hashes are included in the flattened hash just if subtree
|
68
|
+
# is true and Symbols are automatically stored as links.
|
69
|
+
def flatten_translations(locale, data, escape, subtree)
|
70
|
+
hash = {}
|
71
|
+
flatten_keys(data, escape) do |key, value|
|
72
|
+
if value.is_a?(Hash)
|
73
|
+
hash[key] = value if subtree
|
74
|
+
else
|
75
|
+
store_link(locale, key, value) if value.is_a?(Symbol)
|
76
|
+
hash[key] = value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
hash
|
80
|
+
end
|
81
|
+
|
82
|
+
protected
|
83
|
+
|
84
|
+
def store_link(locale, key, link)
|
85
|
+
links[locale.to_sym][key.to_s] = link.to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
def resolve_link(locale, key)
|
89
|
+
key, locale = key.to_s, locale.to_sym
|
90
|
+
links = self.links[locale]
|
91
|
+
|
92
|
+
if links.key?(key)
|
93
|
+
links[key]
|
94
|
+
elsif link = find_link(locale, key)
|
95
|
+
store_link(locale, key, key.gsub(*link))
|
96
|
+
else
|
97
|
+
key
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def find_link(locale, key) #:nodoc:
|
102
|
+
links[locale].each do |from, to|
|
103
|
+
return [from, to] if key[0, from.length] == from
|
104
|
+
end && nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def escape_default_separator(key) #:nodoc:
|
108
|
+
I18n::Backend::Flatten.escape_default_separator(key)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|