i18n 0.5.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of i18n might be problematic. Click here for more details.
- data/CHANGELOG.textile +3 -12
- data/README.textile +17 -4
- data/lib/i18n.rb +37 -5
- data/lib/i18n/backend.rb +1 -0
- data/lib/i18n/backend/base.rb +32 -4
- data/lib/i18n/backend/cldr.rb +99 -0
- data/lib/i18n/backend/gettext.rb +3 -3
- data/lib/i18n/backend/interpolation_compiler.rb +1 -1
- data/lib/i18n/backend/metadata.rb +1 -1
- data/lib/i18n/config.rb +13 -1
- data/lib/i18n/core_ext/string/interpolate.rb +0 -9
- data/lib/i18n/exceptions.rb +31 -3
- data/lib/i18n/locale/fallbacks.rb +3 -3
- data/lib/i18n/tests/localization/procs.rb +24 -25
- data/lib/i18n/version.rb +1 -1
- metadata +16 -121
- data/ci/Gemfile.no-rails +0 -5
- data/ci/Gemfile.no-rails.lock +0 -14
- data/ci/Gemfile.rails-2.3.x +0 -9
- data/ci/Gemfile.rails-2.3.x.lock +0 -23
- data/ci/Gemfile.rails-3.x +0 -9
- data/ci/Gemfile.rails-3.x.lock +0 -23
- data/lib/i18n/core_ext/kernel/surpress_warnings.rb +0 -9
- data/lib/i18n/interpolate/ruby.rb +0 -31
- data/test/all.rb +0 -8
- data/test/api/all_features_test.rb +0 -58
- data/test/api/cascade_test.rb +0 -28
- data/test/api/chain_test.rb +0 -24
- data/test/api/fallbacks_test.rb +0 -30
- data/test/api/key_value_test.rb +0 -28
- data/test/api/memoize_test.rb +0 -60
- data/test/api/pluralization_test.rb +0 -30
- data/test/api/simple_test.rb +0 -28
- data/test/backend/cache_test.rb +0 -83
- data/test/backend/cascade_test.rb +0 -85
- data/test/backend/chain_test.rb +0 -67
- data/test/backend/exceptions_test.rb +0 -23
- data/test/backend/fallbacks_test.rb +0 -116
- data/test/backend/interpolation_compiler_test.rb +0 -102
- data/test/backend/key_value_test.rb +0 -46
- data/test/backend/memoize_test.rb +0 -47
- data/test/backend/metadata_test.rb +0 -67
- data/test/backend/pluralization_test.rb +0 -44
- data/test/backend/simple_test.rb +0 -79
- data/test/backend/transliterator_test.rb +0 -81
- data/test/core_ext/hash_test.rb +0 -30
- data/test/core_ext/string/interpolate_test.rb +0 -99
- data/test/gettext/api_test.rb +0 -206
- data/test/gettext/backend_test.rb +0 -93
- data/test/i18n/exceptions_test.rb +0 -116
- data/test/i18n/interpolate_test.rb +0 -61
- data/test/i18n/load_path_test.rb +0 -26
- data/test/i18n_test.rb +0 -236
- data/test/locale/fallbacks_test.rb +0 -124
- data/test/locale/tag/rfc4646_test.rb +0 -142
- data/test/locale/tag/simple_test.rb +0 -32
- data/test/run_all.rb +0 -21
- data/test/test_data/locales/de.po +0 -72
- data/test/test_data/locales/en.rb +0 -3
- data/test/test_data/locales/en.yml +0 -3
- data/test/test_data/locales/invalid/empty.yml +0 -1
- data/test/test_data/locales/plurals.rb +0 -113
- data/test/test_helper.rb +0 -56
data/CHANGELOG.textile
CHANGED
@@ -1,14 +1,5 @@
|
|
1
1
|
h1. Changelog
|
2
2
|
|
3
|
-
h2. 0.5.0
|
4
|
-
|
5
|
-
* "Extract Backend::ActiveRecord to a separate gem":https://github.com/svenfuchs/i18n/commit/197dacebad356b910d69fa69a719c2ad10cf49e6 (see "i18n-active_record":https://github.com/svenfuchs/i18n-active_record)
|
6
|
-
* "Improve exception handling":https://github.com/svenfuchs/i18n/commit/2913ff9a7544f223f60e7d7b32c2a0e1af89812b (deprectates I18n.default_exception_handler)
|
7
|
-
* "Change MissingTranslationData message to 'translation missing: foo.bar'":https://github.com/svenfuchs/i18n/commit/68fdfe47952325411afe5942e971ce10b2bdf900
|
8
|
-
* "Expose MissingTranslationsData#keys method":https://github.com/svenfuchs/i18n/commit/3a37a389ecaac9670355b334e23e775549ee9822
|
9
|
-
* "Improve Cascade#lookup (add default options)":https://github.com/svenfuchs/i18n/commit/0b9a1f2058a2be9543106cc19d08071c359511e1
|
10
|
-
* "Finally remove deprecated interpolation syntax":https://github.com/svenfuchs/i18n/commit/2d43846d2b2a2e596f30fa58ea1c9ddb2243bb64
|
11
|
-
|
12
3
|
h2. 0.4.2 (2010-10-26)
|
13
4
|
|
14
5
|
* "Improve UTF8 handling":http://github.com/svenfuchs/i18n/commit/e8d5820a3b08eeca28de1a2b9c8a6ad2b9e6476c
|
@@ -53,7 +44,7 @@ h2. 0.3.6 (2010-03-23)
|
|
53
44
|
|
54
45
|
h2. 0.3.5 (2010-02-26)
|
55
46
|
|
56
|
-
* "Delegate I18n.normalize_translation_keys to I18n.normalize_keys and deprecate
|
47
|
+
* "Delegate I18n.normalize_translation_keys to I18n.normalize_keys and deprecate
|
57
48
|
the former":http://github.com/svenfuchs/i18n/commit/7284b04d5f5dd9679cb68875515cdd0cdfc96fef
|
58
49
|
|
59
50
|
h2. 0.3.4 (2010-02-25)
|
@@ -102,7 +93,7 @@ h2. 0.3.0 (2009-11-30)
|
|
102
93
|
h2. 0.2.0 (2009-07-12)
|
103
94
|
|
104
95
|
* "Allow using Ruby 1.9 syntax for string interpolation (API addition)":http://github.com/svenfuchs/i18n/commit/c6e0b06d512f2af57199a843a1d8a40241b32861
|
105
|
-
* "Allow configuring the default scope separator, allow to pass a custom scope separator(API addition)":http://github.com/svenfuchs/i18n/commit/5b75bfbc348061adc11e3790187a187275bfd471 (e.g. I18n.t(:'foo|bar', :separator => '|')
|
96
|
+
* "Allow configuring the default scope separator, allow to pass a custom scope separator(API addition)":http://github.com/svenfuchs/i18n/commit/5b75bfbc348061adc11e3790187a187275bfd471 (e.g. I18n.t(:'foo|bar', :separator => '|')
|
106
97
|
* "Pass :format option to #translate for #localize more useful lambda support":http://github.com/svenfuchs/i18n/commit/e277711b3c844fe7589b8d3f9af0f7d1b969a273
|
107
98
|
* "Refactor Simple backend #resolve to #default and #resolve for more consistency. Now allows to pass lambdas as defaults and re-resolve Symbols":http://github.com/svenfuchs/i18n/commit/8c4ce3d923ce5fa73e973fe28217e18165549aba
|
108
99
|
* "Add lambda support to #translate (API addition)":http://github.com/svenfuchs/i18n/commit/c90e62d8f7d3d5b78f34cfe328d871b58884f115
|
@@ -149,4 +140,4 @@ h2. More information
|
|
149
140
|
* "Wiki":http://rails-i18n.org/wiki
|
150
141
|
* "Mailinglist":http://groups.google.com/group/rails-i18n
|
151
142
|
* "About the project/history":http://www.artweb-design.de/2008/7/18/finally-ruby-on-rails-gets-internationalized
|
152
|
-
* "Initial API Intro":http://www.artweb-design.de/2008/7/18/the-ruby-on-rails-i18n-core-api
|
143
|
+
* "Initial API Intro":http://www.artweb-design.de/2008/7/18/the-ruby-on-rails-i18n-core-api
|
data/README.textile
CHANGED
@@ -64,12 +64,25 @@ h2. Tests
|
|
64
64
|
You can run tests both with
|
65
65
|
|
66
66
|
* `rake test` or just `rake`
|
67
|
-
* run any test file directly, e.g. `ruby
|
68
|
-
* run all tests with `ruby
|
67
|
+
* run any test file directly, e.g. `ruby test/api/simple_test.rb`
|
68
|
+
* run all tests with `ruby test/all.rb`
|
69
69
|
|
70
|
-
You can
|
70
|
+
You can parametrize the test suite for using different sets of dependencies by
|
71
|
+
using:
|
71
72
|
|
72
|
-
|
73
|
+
.pre `ruby test/all.rb -w DEPENDENCIES`
|
74
|
+
|
75
|
+
... where DEPENDENCIES is a comma-separated list of:
|
76
|
+
|
77
|
+
* r23 or rails-2.3.x
|
78
|
+
* r3 or rails-3.x
|
79
|
+
* no-rails
|
80
|
+
* sqlite
|
81
|
+
* mysql
|
82
|
+
|
83
|
+
So, e.g. this would run the test suite against Rails 2.3.x using mysql:
|
84
|
+
|
85
|
+
.pre `ruby test/all.rb -w r23,mysql`
|
73
86
|
|
74
87
|
The structure of the test suite is a bit unusual as it uses modules to reuse
|
75
88
|
particular tests in different test cases.
|
data/lib/i18n.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
+
# Authors:: Sven Fuchs (http://www.artweb-design.de),
|
2
|
+
# Joshua Harvey (http://www.workingwithrails.com/person/759-joshua-harvey),
|
3
|
+
# Stephan Soller (http://www.arkanis-development.de/),
|
4
|
+
# Saimon Moore (http://saimonmoore.net),
|
5
|
+
# Matt Aimonetti (http://railsontherun.com/)
|
6
|
+
# Copyright:: Copyright (c) 2008 The Ruby i18n Team
|
7
|
+
# License:: MIT
|
1
8
|
require 'i18n/version'
|
2
9
|
require 'i18n/exceptions'
|
3
|
-
require 'i18n/interpolate
|
10
|
+
require 'i18n/core_ext/string/interpolate'
|
4
11
|
|
5
12
|
module I18n
|
6
13
|
autoload :Backend, 'i18n/backend'
|
@@ -9,9 +16,6 @@ module I18n
|
|
9
16
|
autoload :Locale, 'i18n/locale'
|
10
17
|
autoload :Tests, 'i18n/tests'
|
11
18
|
|
12
|
-
RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :raise, :rescue_format]
|
13
|
-
RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/
|
14
|
-
|
15
19
|
class << self
|
16
20
|
# Gets I18n configuration object.
|
17
21
|
def config
|
@@ -25,7 +29,7 @@ module I18n
|
|
25
29
|
|
26
30
|
# Write methods which delegates to the configuration object
|
27
31
|
%w(locale backend default_locale available_locales default_separator
|
28
|
-
exception_handler load_path).each do |method|
|
32
|
+
exception_handler load_path enforce_available_locales).each do |method|
|
29
33
|
module_eval <<-DELEGATORS, __FILE__, __LINE__ + 1
|
30
34
|
def #{method}
|
31
35
|
config.#{method}
|
@@ -147,6 +151,7 @@ module I18n
|
|
147
151
|
locale = options.delete(:locale) || config.locale
|
148
152
|
raises = options.delete(:raise)
|
149
153
|
|
154
|
+
enforce_available_locales!(locale)
|
150
155
|
raise I18n::ArgumentError if key.is_a?(String) && key.empty?
|
151
156
|
|
152
157
|
if key.is_a?(Array)
|
@@ -222,6 +227,7 @@ module I18n
|
|
222
227
|
locale = options && options.delete(:locale) || config.locale
|
223
228
|
raises = options && options.delete(:raise)
|
224
229
|
replacement = options && options.delete(:replacement)
|
230
|
+
enforce_available_locales!(locale)
|
225
231
|
config.backend.transliterate(locale, key, replacement)
|
226
232
|
rescue I18n::ArgumentError => exception
|
227
233
|
raise exception if raises
|
@@ -232,6 +238,7 @@ module I18n
|
|
232
238
|
def localize(object, options = {})
|
233
239
|
locale = options.delete(:locale) || config.locale
|
234
240
|
format = options.delete(:format) || :default
|
241
|
+
enforce_available_locales!(locale)
|
235
242
|
config.backend.localize(locale, object, format, options)
|
236
243
|
end
|
237
244
|
alias :l :localize
|
@@ -260,6 +267,24 @@ module I18n
|
|
260
267
|
keys
|
261
268
|
end
|
262
269
|
|
270
|
+
# Returns true when the passed locale is in I18.available_locales.
|
271
|
+
# Returns false otherwise.
|
272
|
+
# Compare with Strings as `locale` may be coming from user input
|
273
|
+
def locale_available?(locale)
|
274
|
+
I18n.available_locales.map(&:to_s).include?(locale.to_s)
|
275
|
+
end
|
276
|
+
|
277
|
+
# Raises an InvalidLocale exception when the passed locale is not
|
278
|
+
# included in I18n.available_locales.
|
279
|
+
# Returns false otherwise
|
280
|
+
def enforce_available_locales!(locale)
|
281
|
+
handle_enforce_available_locales_deprecation
|
282
|
+
|
283
|
+
if config.enforce_available_locales
|
284
|
+
raise I18n::InvalidLocale.new(locale) if !locale_available?(locale)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
263
288
|
# making these private until Ruby 1.9.2 can send to protected methods again
|
264
289
|
# see http://redmine.ruby-lang.org/repositories/revision/ruby-19?rev=24280
|
265
290
|
private
|
@@ -290,6 +315,13 @@ module I18n
|
|
290
315
|
end
|
291
316
|
end
|
292
317
|
|
318
|
+
def handle_enforce_available_locales_deprecation
|
319
|
+
if config.enforce_available_locales.nil? && !@unenforced_available_locales_deprecation
|
320
|
+
$stderr.puts "[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message."
|
321
|
+
@unenforced_available_locales_deprecation = true
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
293
325
|
def normalize_key(key, separator)
|
294
326
|
normalized_key_cache[separator][key] ||=
|
295
327
|
case key
|
data/lib/i18n/backend.rb
CHANGED
@@ -5,6 +5,7 @@ module I18n
|
|
5
5
|
autoload :Cache, 'i18n/backend/cache'
|
6
6
|
autoload :Cascade, 'i18n/backend/cascade'
|
7
7
|
autoload :Chain, 'i18n/backend/chain'
|
8
|
+
autoload :Cldr, 'i18n/backend/cldr'
|
8
9
|
autoload :Fallbacks, 'i18n/backend/fallbacks'
|
9
10
|
autoload :Flatten, 'i18n/backend/flatten'
|
10
11
|
autoload :Gettext, 'i18n/backend/gettext'
|
data/lib/i18n/backend/base.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
require 'i18n/core_ext/hash'
|
3
|
-
require 'i18n/core_ext/kernel/surpress_warnings'
|
4
3
|
|
5
4
|
module I18n
|
6
5
|
module Backend
|
7
6
|
module Base
|
8
7
|
include I18n::Backend::Transliterator
|
9
8
|
|
9
|
+
RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback]
|
10
|
+
RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/
|
11
|
+
|
10
12
|
# Accepts a list of paths to translation files. Loads translations from
|
11
13
|
# plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml
|
12
14
|
# for details.
|
@@ -138,14 +140,34 @@ module I18n
|
|
138
140
|
#
|
139
141
|
# interpolate "file %{file} opened by %%{user}", :file => 'test.txt', :user => 'Mr. X'
|
140
142
|
# # => "file test.txt opened by %{user}"
|
143
|
+
#
|
144
|
+
# Note that you have to double escape the <tt>\\</tt> when you want to escape
|
145
|
+
# the <tt>{{...}}</tt> key in a string (once for the string and once for the
|
146
|
+
# interpolation).
|
141
147
|
def interpolate(locale, string, values = {})
|
142
|
-
|
143
|
-
|
148
|
+
return string unless string.is_a?(::String) && !values.empty?
|
149
|
+
|
150
|
+
values.each do |key, value|
|
151
|
+
value = value.call(values) if interpolate_lambda?(value, string, key)
|
152
|
+
value = value.to_s unless value.is_a?(::String)
|
153
|
+
values[key] = value
|
154
|
+
end
|
155
|
+
|
156
|
+
string % values
|
157
|
+
rescue KeyError => e
|
158
|
+
if string =~ RESERVED_KEYS_PATTERN
|
159
|
+
raise ReservedInterpolationKey.new($1.to_sym, string)
|
144
160
|
else
|
145
|
-
string
|
161
|
+
raise MissingInterpolationArgument.new(values, string)
|
146
162
|
end
|
147
163
|
end
|
148
164
|
|
165
|
+
# returns true when the given value responds to :call and the key is
|
166
|
+
# an interpolation placeholder in the given string
|
167
|
+
def interpolate_lambda?(object, string, key)
|
168
|
+
object.respond_to?(:call) && string =~ /%\{#{key}\}|%\<#{key}>.*?\d*\.?\d*[bBdiouxXeEfgGcps]\}/
|
169
|
+
end
|
170
|
+
|
149
171
|
# Loads a single translations file by delegating to #load_rb or
|
150
172
|
# #load_yml depending on the file extension and directly merges the
|
151
173
|
# data to the existing translations. Raises I18n::UnknownFileType
|
@@ -169,6 +191,12 @@ module I18n
|
|
169
191
|
def load_yml(filename)
|
170
192
|
YAML.load_file(filename)
|
171
193
|
end
|
194
|
+
|
195
|
+
def warn_syntax_deprecation!(locale, string) #:nodoc:
|
196
|
+
return if @skip_syntax_deprecation
|
197
|
+
warn "The {{key}} interpolation syntax in I18n messages is deprecated. Please use %{key} instead.\n#{locale} - #{string}\n"
|
198
|
+
@skip_syntax_deprecation = true
|
199
|
+
end
|
172
200
|
end
|
173
201
|
end
|
174
202
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'cldr'
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Backend
|
5
|
+
module Cldr
|
6
|
+
include ::Cldr::Format
|
7
|
+
|
8
|
+
def localize(locale, object, format = :default, options = {})
|
9
|
+
options[:as] ||= detect_type(object, options)
|
10
|
+
send(:"format_#{options[:as]}", locale, object, format, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def format_decimal(locale, object, format = :default, options = {})
|
14
|
+
formatter(locale, :decimal, format).apply(object, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def format_integer(locale, object, format = :default, options = {})
|
18
|
+
format_object(number, options.merge(:precision => 0))
|
19
|
+
end
|
20
|
+
|
21
|
+
def format_currency(locale, object, format = :default, options = {})
|
22
|
+
options.merge!(:currency => lookup_currency(locale, options[:currency], object)) if options[:currency].is_a?(Symbol)
|
23
|
+
formatter(locale, :currency, format).apply(object, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def format_percent(locale, object, format = :default, options = {})
|
27
|
+
formatter(locale, :percent, format).apply(object, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def format_date(locale, object, format = :default, options = {})
|
31
|
+
formatter(locale, :date, format).apply(object, options)
|
32
|
+
end
|
33
|
+
|
34
|
+
def format_time(locale, object, format = :default, options = {})
|
35
|
+
formatter(locale, :time, format).apply(object, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def format_datetime(locale, object, format = :default, options = {})
|
39
|
+
key = :"calendars.gregorian.formats.datetime.#{format}.pattern"
|
40
|
+
date = I18n.l(object, :format => options[:date_format] || format, :locale => locale, :as => :date)
|
41
|
+
time = I18n.l(object, :format => options[:time_format] || format, :locale => locale, :as => :time)
|
42
|
+
I18n.t(key, :date => date, :time => time, :locale => locale, :raise => true)
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def detect_type(object, options)
|
48
|
+
options.has_key?(:currency) ? :currency : case object
|
49
|
+
when ::Numeric
|
50
|
+
:decimal
|
51
|
+
when ::Date, ::DateTime, ::Time
|
52
|
+
object.class.name.downcase.to_sym
|
53
|
+
else
|
54
|
+
raise_unspecified_format_type!
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def formatter(locale, type, format)
|
59
|
+
(@formatters ||= {})[:"#{locale}.#{type}.#{format}"] ||= begin
|
60
|
+
format = lookup_format(locale, type, format)
|
61
|
+
data = lookup_format_data(locale, type)
|
62
|
+
::Cldr::Format.const_get(type.to_s.camelize).new(format, data)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def lookup_format(locale, type, format)
|
67
|
+
key = case type
|
68
|
+
when :date, :time, :datetime
|
69
|
+
:"calendars.gregorian.formats.#{type}.#{format}.pattern"
|
70
|
+
else
|
71
|
+
:"numbers.formats.#{type}.patterns.#{format || :default}"
|
72
|
+
end
|
73
|
+
I18n.t(key, :locale => locale, :raise => true)
|
74
|
+
end
|
75
|
+
|
76
|
+
def lookup_format_data(locale, type)
|
77
|
+
key = case type
|
78
|
+
when :date, :time, :datetime
|
79
|
+
:'calendars.gregorian'
|
80
|
+
else
|
81
|
+
:'numbers.symbols'
|
82
|
+
end
|
83
|
+
I18n.t(key, :locale => locale, :raise => true)
|
84
|
+
end
|
85
|
+
|
86
|
+
def lookup_currency(locale, currency, count)
|
87
|
+
I18n.t(:"currencies.#{currency}", :locale => locale, :count => count)
|
88
|
+
end
|
89
|
+
|
90
|
+
def raise_unspecified_format_type!
|
91
|
+
raise ArgumentError.new("You have to specify a format type, e.g. :as => :number.")
|
92
|
+
end
|
93
|
+
|
94
|
+
def raise_unspecified_currency!
|
95
|
+
raise ArgumentError.new("You have to specify a currency, e.g. :currency => 'EUR'.")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/i18n/backend/gettext.rb
CHANGED
@@ -43,8 +43,8 @@ module I18n
|
|
43
43
|
key, value = normalize_pluralization(locale, key, value) if key.index("\000")
|
44
44
|
|
45
45
|
parts = key.split('|').reverse
|
46
|
-
normalized = parts.inject({}) do |
|
47
|
-
{ part =>
|
46
|
+
normalized = parts.inject({}) do |normalized, part|
|
47
|
+
normalized = { part => normalized.empty? ? value : normalized }
|
48
48
|
end
|
49
49
|
|
50
50
|
result.deep_merge!(normalized)
|
@@ -62,7 +62,7 @@ module I18n
|
|
62
62
|
raise "invalid number of plurals: #{values.size}, keys: #{keys.inspect}" if values.size != keys.size
|
63
63
|
|
64
64
|
result = {}
|
65
|
-
values.each_with_index { |
|
65
|
+
values.each_with_index { |value, ix| result[keys[ix]] = value }
|
66
66
|
[key, result]
|
67
67
|
end
|
68
68
|
|
@@ -61,7 +61,7 @@ module I18n
|
|
61
61
|
|
62
62
|
def interpolate_or_raise_missing(key)
|
63
63
|
escaped_key = escape_key_sym(key)
|
64
|
-
RESERVED_KEYS.include?(key) ? reserved_key(escaped_key) : interpolate_key(escaped_key)
|
64
|
+
Base::RESERVED_KEYS.include?(key) ? reserved_key(escaped_key) : interpolate_key(escaped_key)
|
65
65
|
end
|
66
66
|
|
67
67
|
def interpolate_key(key)
|
@@ -38,7 +38,7 @@ module I18n
|
|
38
38
|
:scope => options[:scope],
|
39
39
|
:default => options[:default],
|
40
40
|
:separator => options[:separator],
|
41
|
-
:values => options.reject { |name, value| RESERVED_KEYS.include?(name) }
|
41
|
+
:values => options.reject { |name, value| Base::RESERVED_KEYS.include?(name) }
|
42
42
|
}
|
43
43
|
with_metadata(metadata) { super }
|
44
44
|
end
|
data/lib/i18n/config.rb
CHANGED
@@ -8,6 +8,7 @@ module I18n
|
|
8
8
|
|
9
9
|
# Sets the current locale pseudo-globally, i.e. in the Thread.current hash.
|
10
10
|
def locale=(locale)
|
11
|
+
I18n.enforce_available_locales!(locale)
|
11
12
|
@locale = locale.to_sym rescue nil
|
12
13
|
end
|
13
14
|
|
@@ -28,6 +29,7 @@ module I18n
|
|
28
29
|
|
29
30
|
# Sets the current default locale. Used to set a custom default locale.
|
30
31
|
def default_locale=(locale)
|
32
|
+
I18n.enforce_available_locales!(locale)
|
31
33
|
@@default_locale = locale.to_sym rescue nil
|
32
34
|
end
|
33
35
|
|
@@ -41,7 +43,7 @@ module I18n
|
|
41
43
|
|
42
44
|
# Sets the available locales.
|
43
45
|
def available_locales=(locales)
|
44
|
-
@@available_locales = Array(locales).map {
|
46
|
+
@@available_locales = Array(locales).map {|locale| locale.to_sym}
|
45
47
|
@@available_locales = nil if @@available_locales.empty?
|
46
48
|
end
|
47
49
|
|
@@ -82,5 +84,15 @@ module I18n
|
|
82
84
|
def load_path=(load_path)
|
83
85
|
@@load_path = load_path
|
84
86
|
end
|
87
|
+
|
88
|
+
# [Deprecated] this will default to true in the future
|
89
|
+
# Defaults to nil so that it triggers the deprecation warning
|
90
|
+
def enforce_available_locales
|
91
|
+
@@enforce_available_locales ||= nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def enforce_available_locales=(enforce_available_locales)
|
95
|
+
@@enforce_available_locales = enforce_available_locales
|
96
|
+
end
|
85
97
|
end
|
86
98
|
end
|
@@ -1,12 +1,3 @@
|
|
1
|
-
# This backports the Ruby 1.9 String interpolation syntax to Ruby 1.8.
|
2
|
-
#
|
3
|
-
# This backport has been shipped with I18n for a number of versions. Meanwhile
|
4
|
-
# Rails has started to rely on it and we are going to move it to ActiveSupport.
|
5
|
-
# See https://rails.lighthouseapp.com/projects/8994/tickets/6013-move-19-string-interpolation-syntax-backport-from-i18n-to-activesupport
|
6
|
-
#
|
7
|
-
# Once the above patch has been applied to Rails the following code will be
|
8
|
-
# removed from I18n.
|
9
|
-
|
10
1
|
=begin
|
11
2
|
heavily based on Masao Mutoh's gettext String interpolation extension
|
12
3
|
http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
|
data/lib/i18n/exceptions.rb
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
require 'cgi'
|
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
|
# Handles exceptions raised in the backend. All exceptions except for
|
3
11
|
# MissingTranslationData exceptions are re-raised. When a MissingTranslationData
|
@@ -7,7 +15,19 @@ module I18n
|
|
7
15
|
include Module.new {
|
8
16
|
def call(exception, locale, key, options)
|
9
17
|
if exception.is_a?(MissingTranslationData)
|
10
|
-
|
18
|
+
#
|
19
|
+
# TODO: this block is to be replaced by `exception.message` when
|
20
|
+
# rescue_format is removed
|
21
|
+
if options[:rescue_format] == :html
|
22
|
+
if @rescue_format_deprecation
|
23
|
+
$stderr.puts "[DEPRECATED] I18n's :recue_format option will be removed from a future release. All exception messages will be plain text. If you need the exception handler to return an html format please set or pass a custom exception handler."
|
24
|
+
@rescue_format_deprecation = true
|
25
|
+
end
|
26
|
+
exception.html_message
|
27
|
+
else
|
28
|
+
exception.message
|
29
|
+
end
|
30
|
+
|
11
31
|
else
|
12
32
|
raise exception
|
13
33
|
end
|
@@ -43,8 +63,9 @@ module I18n
|
|
43
63
|
end
|
44
64
|
|
45
65
|
def html_message
|
46
|
-
key
|
47
|
-
|
66
|
+
key = CGI.escapeHTML titleize(keys.last)
|
67
|
+
path = CGI.escapeHTML keys.join('.')
|
68
|
+
%(<span class="translation_missing" title="translation missing: #{path}">#{key}</span>)
|
48
69
|
end
|
49
70
|
|
50
71
|
def keys
|
@@ -52,6 +73,13 @@ module I18n
|
|
52
73
|
keys << 'no key' if keys.size < 2
|
53
74
|
end
|
54
75
|
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
# TODO : remove when #html_message is removed
|
80
|
+
def titleize(key)
|
81
|
+
key.to_s.gsub('_', ' ').gsub(/\b('?[a-z])/) { $1.capitalize }
|
82
|
+
end
|
55
83
|
end
|
56
84
|
|
57
85
|
class InvalidPluralizationData < ArgumentError
|