i18n 0.5.0beta1 → 0.5.0beta2
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/README.textile +4 -17
- data/ci/Gemfile.no-rails +5 -0
- data/ci/Gemfile.no-rails.lock +17 -0
- data/ci/Gemfile.rails-2.3.x +9 -0
- data/ci/Gemfile.rails-2.3.x.lock +26 -0
- data/ci/Gemfile.rails-3.x +9 -0
- data/ci/Gemfile.rails-3.x.lock +26 -0
- data/lib/i18n.rb +4 -8
- data/lib/i18n/backend.rb +0 -1
- data/lib/i18n/backend/base.rb +4 -32
- 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 +1 -1
- data/lib/i18n/core_ext/kernel/surpress_warnings.rb +9 -0
- data/lib/i18n/core_ext/string/interpolate.rb +0 -96
- data/lib/i18n/exceptions.rb +0 -6
- data/lib/i18n/interpolate/ruby.rb +31 -0
- data/lib/i18n/locale/fallbacks.rb +3 -3
- data/lib/i18n/tests/localization/procs.rb +32 -19
- data/lib/i18n/tests/localization/time.rb +2 -2
- data/lib/i18n/version.rb +1 -1
- data/test/all.rb +8 -0
- data/test/api/all_features_test.rb +58 -0
- data/test/api/cascade_test.rb +28 -0
- data/test/api/chain_test.rb +24 -0
- data/test/api/fallbacks_test.rb +30 -0
- data/test/api/key_value_test.rb +28 -0
- data/test/api/memoize_test.rb +60 -0
- data/test/api/pluralization_test.rb +30 -0
- data/test/api/simple_test.rb +28 -0
- data/test/backend/cache_test.rb +83 -0
- data/test/backend/cascade_test.rb +85 -0
- data/test/backend/chain_test.rb +67 -0
- data/test/backend/exceptions_test.rb +23 -0
- data/test/backend/fallbacks_test.rb +116 -0
- data/test/backend/interpolation_compiler_test.rb +102 -0
- data/test/backend/key_value_test.rb +46 -0
- data/test/backend/memoize_test.rb +47 -0
- data/test/backend/metadata_test.rb +67 -0
- data/test/backend/pluralization_test.rb +44 -0
- data/test/backend/simple_test.rb +79 -0
- data/test/backend/transliterator_test.rb +81 -0
- data/test/core_ext/hash_test.rb +30 -0
- data/test/gettext/api_test.rb +206 -0
- data/test/gettext/backend_test.rb +93 -0
- data/test/i18n/exceptions_test.rb +116 -0
- data/test/i18n/interpolate_test.rb +60 -0
- data/test/i18n/load_path_test.rb +26 -0
- data/test/i18n_test.rb +236 -0
- data/test/locale/fallbacks_test.rb +124 -0
- data/test/locale/tag/rfc4646_test.rb +142 -0
- data/test/locale/tag/simple_test.rb +32 -0
- data/test/run_all.rb +21 -0
- data/test/test_data/locales/de.po +72 -0
- data/test/test_data/locales/en.rb +3 -0
- data/test/test_data/locales/en.yml +3 -0
- data/test/test_data/locales/invalid/empty.yml +1 -0
- data/test/test_data/locales/plurals.rb +113 -0
- data/test/test_helper.rb +56 -0
- metadata +116 -14
- data/lib/i18n/backend/cldr.rb +0 -99
data/README.textile
CHANGED
@@ -64,25 +64,12 @@ 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 test/api/simple_test.rb`
|
68
|
-
* run all tests with `ruby test/all.rb`
|
67
|
+
* run any test file directly, e.g. `ruby -Ilib -Itest test/api/simple_test.rb`
|
68
|
+
* run all tests with `ruby -Ilib -Itest test/all.rb`
|
69
69
|
|
70
|
-
You can
|
71
|
-
using:
|
70
|
+
You can run all tests against all Gemfiles with
|
72
71
|
|
73
|
-
|
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`
|
72
|
+
* `ruby test/run_all.rb`
|
86
73
|
|
87
74
|
The structure of the test suite is a bit unusual as it uses modules to reuse
|
88
75
|
particular tests in different test cases.
|
data/ci/Gemfile.no-rails
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (2.3.10)
|
5
|
+
ffi (0.6.3)
|
6
|
+
rake (>= 0.8.7)
|
7
|
+
mocha (0.9.9)
|
8
|
+
rake
|
9
|
+
rake (0.8.7)
|
10
|
+
rufus-tokyo (1.0.7)
|
11
|
+
sqlite3-ruby (1.3.2)
|
12
|
+
test_declarative (0.0.4)
|
13
|
+
|
14
|
+
PLATFORMS
|
15
|
+
ruby
|
16
|
+
|
17
|
+
DEPENDENCIES
|
18
|
+
activesupport (~> 2.3)
|
19
|
+
ffi
|
20
|
+
mocha
|
21
|
+
rufus-tokyo
|
22
|
+
sqlite3-ruby
|
23
|
+
test_declarative
|
24
|
+
|
25
|
+
METADATA
|
26
|
+
version: 1.0.6
|
@@ -0,0 +1,26 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (3.0.1)
|
5
|
+
ffi (0.6.3)
|
6
|
+
rake (>= 0.8.7)
|
7
|
+
mocha (0.9.9)
|
8
|
+
rake
|
9
|
+
rake (0.8.7)
|
10
|
+
rufus-tokyo (1.0.7)
|
11
|
+
sqlite3-ruby (1.3.2)
|
12
|
+
test_declarative (0.0.4)
|
13
|
+
|
14
|
+
PLATFORMS
|
15
|
+
ruby
|
16
|
+
|
17
|
+
DEPENDENCIES
|
18
|
+
activesupport (~> 3.0.0)
|
19
|
+
ffi
|
20
|
+
mocha
|
21
|
+
rufus-tokyo
|
22
|
+
sqlite3-ruby
|
23
|
+
test_declarative
|
24
|
+
|
25
|
+
METADATA
|
26
|
+
version: 1.0.6
|
data/lib/i18n.rb
CHANGED
@@ -1,13 +1,6 @@
|
|
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
|
8
1
|
require 'i18n/version'
|
9
2
|
require 'i18n/exceptions'
|
10
|
-
require 'i18n/
|
3
|
+
require 'i18n/interpolate/ruby.rb'
|
11
4
|
|
12
5
|
module I18n
|
13
6
|
autoload :Backend, 'i18n/backend'
|
@@ -16,6 +9,9 @@ module I18n
|
|
16
9
|
autoload :Locale, 'i18n/locale'
|
17
10
|
autoload :Tests, 'i18n/tests'
|
18
11
|
|
12
|
+
RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :raise, :rescue_format]
|
13
|
+
RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/
|
14
|
+
|
19
15
|
class << self
|
20
16
|
# Gets I18n configuration object.
|
21
17
|
def config
|
data/lib/i18n/backend.rb
CHANGED
@@ -5,7 +5,6 @@ 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'
|
9
8
|
autoload :Fallbacks, 'i18n/backend/fallbacks'
|
10
9
|
autoload :Flatten, 'i18n/backend/flatten'
|
11
10
|
autoload :Gettext, 'i18n/backend/gettext'
|
data/lib/i18n/backend/base.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
require 'i18n/core_ext/hash'
|
3
|
+
require 'i18n/core_ext/kernel/surpress_warnings'
|
3
4
|
|
4
5
|
module I18n
|
5
6
|
module Backend
|
6
7
|
module Base
|
7
8
|
include I18n::Backend::Transliterator
|
8
9
|
|
9
|
-
RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback]
|
10
|
-
RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/
|
11
|
-
|
12
10
|
# Accepts a list of paths to translation files. Loads translations from
|
13
11
|
# plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml
|
14
12
|
# for details.
|
@@ -140,34 +138,14 @@ module I18n
|
|
140
138
|
#
|
141
139
|
# interpolate "file %{file} opened by %%{user}", :file => 'test.txt', :user => 'Mr. X'
|
142
140
|
# # => "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).
|
147
141
|
def interpolate(locale, string, values = {})
|
148
|
-
|
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)
|
142
|
+
if string.is_a?(::String) && !values.empty?
|
143
|
+
I18n.interpolate(string, values)
|
160
144
|
else
|
161
|
-
|
145
|
+
string
|
162
146
|
end
|
163
147
|
end
|
164
148
|
|
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
|
-
|
171
149
|
# Loads a single translations file by delegating to #load_rb or
|
172
150
|
# #load_yml depending on the file extension and directly merges the
|
173
151
|
# data to the existing translations. Raises I18n::UnknownFileType
|
@@ -191,12 +169,6 @@ module I18n
|
|
191
169
|
def load_yml(filename)
|
192
170
|
YAML.load_file(filename)
|
193
171
|
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
|
200
172
|
end
|
201
173
|
end
|
202
174
|
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
|
-
|
46
|
+
normalized = parts.inject({}) do |_normalized, part|
|
47
|
+
{ 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
|
-
|
64
|
+
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|
|
41
|
+
:values => options.reject { |name, value| RESERVED_KEYS.include?(name) }
|
42
42
|
}
|
43
43
|
with_metadata(metadata) { super }
|
44
44
|
end
|
data/lib/i18n/config.rb
CHANGED
@@ -41,7 +41,7 @@ module I18n
|
|
41
41
|
|
42
42
|
# Sets the available locales.
|
43
43
|
def available_locales=(locales)
|
44
|
-
@@available_locales = Array(locales).map {|locale| locale.to_sym}
|
44
|
+
@@available_locales = Array(locales).map { |locale| locale.to_sym }
|
45
45
|
@@available_locales = nil if @@available_locales.empty?
|
46
46
|
end
|
47
47
|
|
@@ -1,96 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
heavily based on Masao Mutoh's gettext String interpolation extension
|
3
|
-
http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
|
4
|
-
Copyright (C) 2005-2009 Masao Mutoh
|
5
|
-
You may redistribute it and/or modify it under the same license terms as Ruby.
|
6
|
-
=end
|
7
|
-
|
8
|
-
begin
|
9
|
-
raise ArgumentError if ("a %{x}" % {:x=>'b'}) != 'a b'
|
10
|
-
rescue ArgumentError
|
11
|
-
# KeyError is raised by String#% when the string contains a named placeholder
|
12
|
-
# that is not contained in the given arguments hash. Ruby 1.9 includes and
|
13
|
-
# raises this exception natively. We define it to mimic Ruby 1.9's behaviour
|
14
|
-
# in Ruby 1.8.x
|
15
|
-
class KeyError < IndexError
|
16
|
-
def initialize(message = nil)
|
17
|
-
super(message || "key not found")
|
18
|
-
end
|
19
|
-
end unless defined?(KeyError)
|
20
|
-
|
21
|
-
# Extension for String class. This feature is included in Ruby 1.9 or later but not occur TypeError.
|
22
|
-
#
|
23
|
-
# String#% method which accept "named argument". The translator can know
|
24
|
-
# the meaning of the msgids using "named argument" instead of %s/%d style.
|
25
|
-
class String
|
26
|
-
# For older ruby versions, such as ruby-1.8.5
|
27
|
-
alias :bytesize :size unless instance_methods.find {|m| m.to_s == 'bytesize'}
|
28
|
-
alias :interpolate_without_ruby_19_syntax :% # :nodoc:
|
29
|
-
|
30
|
-
INTERPOLATION_PATTERN = Regexp.union(
|
31
|
-
/%\{(\w+)\}/, # matches placeholders like "%{foo}"
|
32
|
-
/%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%<foo>.d"
|
33
|
-
)
|
34
|
-
|
35
|
-
INTERPOLATION_PATTERN_WITH_ESCAPE = Regexp.union(
|
36
|
-
/%%/,
|
37
|
-
INTERPOLATION_PATTERN
|
38
|
-
)
|
39
|
-
|
40
|
-
# % uses self (i.e. the String) as a format specification and returns the
|
41
|
-
# result of applying it to the given arguments. In other words it interpolates
|
42
|
-
# the given arguments to the string according to the formats the string
|
43
|
-
# defines.
|
44
|
-
#
|
45
|
-
# There are three ways to use it:
|
46
|
-
#
|
47
|
-
# * Using a single argument or Array of arguments.
|
48
|
-
#
|
49
|
-
# This is the default behaviour of the String class. See Kernel#sprintf for
|
50
|
-
# more details about the format string.
|
51
|
-
#
|
52
|
-
# Example:
|
53
|
-
#
|
54
|
-
# "%d %s" % [1, "message"]
|
55
|
-
# # => "1 message"
|
56
|
-
#
|
57
|
-
# * Using a Hash as an argument and unformatted, named placeholders.
|
58
|
-
#
|
59
|
-
# When you pass a Hash as an argument and specify placeholders with %{foo}
|
60
|
-
# it will interpret the hash values as named arguments.
|
61
|
-
#
|
62
|
-
# Example:
|
63
|
-
#
|
64
|
-
# "%{firstname}, %{lastname}" % {:firstname => "Masao", :lastname => "Mutoh"}
|
65
|
-
# # => "Masao Mutoh"
|
66
|
-
#
|
67
|
-
# * Using a Hash as an argument and formatted, named placeholders.
|
68
|
-
#
|
69
|
-
# When you pass a Hash as an argument and specify placeholders with %<foo>d
|
70
|
-
# it will interpret the hash values as named arguments and format the value
|
71
|
-
# according to the formatting instruction appended to the closing >.
|
72
|
-
#
|
73
|
-
# Example:
|
74
|
-
#
|
75
|
-
# "%<integer>d, %<float>.1f" % { :integer => 10, :float => 43.4 }
|
76
|
-
# # => "10, 43.3"
|
77
|
-
def %(args)
|
78
|
-
if args.kind_of?(Hash)
|
79
|
-
dup.gsub(INTERPOLATION_PATTERN_WITH_ESCAPE) do |match|
|
80
|
-
if match == '%%'
|
81
|
-
'%'
|
82
|
-
else
|
83
|
-
key = ($1 || $2).to_sym
|
84
|
-
raise KeyError unless args.has_key?(key)
|
85
|
-
$3 ? sprintf("%#{$3}", args[key]) : args[key]
|
86
|
-
end
|
87
|
-
end
|
88
|
-
elsif self =~ INTERPOLATION_PATTERN
|
89
|
-
raise ArgumentError.new('one hash required')
|
90
|
-
else
|
91
|
-
result = gsub(/%([{<])/, '%%\1')
|
92
|
-
result.send :'interpolate_without_ruby_19_syntax', args
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
data/lib/i18n/exceptions.rb
CHANGED
@@ -1,9 +1,3 @@
|
|
1
|
-
class KeyError < IndexError
|
2
|
-
def initialize(message = nil)
|
3
|
-
super(message || "key not found")
|
4
|
-
end
|
5
|
-
end unless defined?(KeyError)
|
6
|
-
|
7
1
|
module I18n
|
8
2
|
# Handles exceptions raised in the backend. All exceptions except for
|
9
3
|
# MissingTranslationData exceptions are re-raised. When a MissingTranslationData
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# heavily based on Masao Mutoh's gettext String interpolation extension
|
2
|
+
# http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
|
3
|
+
|
4
|
+
module I18n
|
5
|
+
INTERPOLATION_PATTERN = Regexp.union(
|
6
|
+
/%%/,
|
7
|
+
/%\{(\w+)\}/, # matches placeholders like "%{foo}"
|
8
|
+
/%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%<foo>.d"
|
9
|
+
)
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def interpolate(string, values)
|
13
|
+
raise ReservedInterpolationKey.new($1.to_sym, string) if string =~ RESERVED_KEYS_PATTERN
|
14
|
+
raise ArgumentError.new('Interpolation values must be a Hash.') unless values.kind_of?(Hash)
|
15
|
+
interpolate_hash(string, values)
|
16
|
+
end
|
17
|
+
|
18
|
+
def interpolate_hash(string, values)
|
19
|
+
string.gsub(INTERPOLATION_PATTERN) do |match|
|
20
|
+
if match == '%%'
|
21
|
+
'%'
|
22
|
+
else
|
23
|
+
key = ($1 || $2).to_sym
|
24
|
+
value = values.key?(key) ? values[key] : raise(MissingInterpolationArgument.new(values, string))
|
25
|
+
value = value.call(values) if value.respond_to?(:call)
|
26
|
+
$3 ? sprintf("%#{$3}", value) : value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -73,9 +73,9 @@ module I18n
|
|
73
73
|
def map(mappings)
|
74
74
|
mappings.each do |from, to|
|
75
75
|
from, to = from.to_sym, Array(to)
|
76
|
-
to.each do |
|
76
|
+
to.each do |_to|
|
77
77
|
@map[from] ||= []
|
78
|
-
@map[from] <<
|
78
|
+
@map[from] << _to.to_sym
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
@@ -85,7 +85,7 @@ module I18n
|
|
85
85
|
def compute(tags, include_defaults = true)
|
86
86
|
result = Array(tags).collect do |tag|
|
87
87
|
tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym }
|
88
|
-
tags.each { |
|
88
|
+
tags.each { |_tag| tags += compute(@map[_tag]) if @map[_tag] }
|
89
89
|
tags
|
90
90
|
end.flatten
|
91
91
|
result.push(*defaults) if include_defaults
|