diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000..9711239b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,21 @@
+## What I tried to do
+
+* Fill this out!
+
+## What I expected to happen
+
+* Fill this out!
+
+## What actually happened
+
+* Fill this out!
+
+## Versions of i18n, rails, and anything else you think is neccessary
+
+* Fill this out!
+
+----
+
+Bonus points for providing an application or a small code example which reproduces the issue.
+
+Thanks! :heart:
diff --git a/.travis.yml b/.travis.yml
index 5b2a84e8..77aa4460 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,48 @@
+before_install:
+ - gem install bundler
+
rvm:
- - 1.8.7
- - 1.9.2
- 1.9.3
- 2.0.0
- - ree
+ - 2.1.8
+ - 2.2.4
+ - 2.3.1
+ - ruby-head
- rbx
- jruby
gemfile:
- - ci/Gemfile.no-rails
- - ci/Gemfile.rails-2.3.x
- - ci/Gemfile.rails-3.x
+ - Gemfile
+ - gemfiles/Gemfile.rails-3.2.x
+ - gemfiles/Gemfile.rails-4.0.x
+ - gemfiles/Gemfile.rails-4.1.x
+ - gemfiles/Gemfile.rails-4.2.x
+ - gemfiles/Gemfile.rails-5.0.x
+ - gemfiles/Gemfile.rails-master
+
+matrix:
+ exclude:
+ # Rails 5+ requires Ruby >= 2.2.2
+ - rvm: 1.9.3
+ gemfile: gemfiles/Gemfile.rails-master
+ - rvm: 2.0.0
+ gemfile: gemfiles/Gemfile.rails-master
+ - rvm: 2.1.8
+ gemfile: gemfiles/Gemfile.rails-master
+ - rvm: 1.9.3
+ gemfile: gemfiles/Gemfile.rails-5.0.x
+ - rvm: 2.0.0
+ gemfile: gemfiles/Gemfile.rails-5.0.x
+ - rvm: 2.1.8
+ gemfile: gemfiles/Gemfile.rails-5.0.x
+ # activesupport has a dependency on json, which does not build on this version
+ - rvm: ruby-head
+ gemfile: gemfiles/Gemfile.rails-4.1.x
+ # activesupport has a dependency on json, which does not build on this version
+ - rvm: ruby-head
+ gemfile: gemfiles/Gemfile.rails-4.2.x
+ allow_failures:
+ - rvm: 2.2
+ - rvm: rbx
+ - rvm: jruby
+ fast_finish: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..7608c5f9
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,13 @@
+# master
+
+* `Hash#slice` ignores non existing keys.
+
+# 0.7.0
+
+* Drop support to Ruby 1.8.7 / REE
+* Drop support to Rails 2.3 / 3.0 / 3.1
+* Remove deprecated stuff:
+ - Setting `:default_exception_hander` Symbol to `I18n.exception_handler`.
+ - `normalize_translation_keys` in favor of `normalize_keys`.
+ - `:rescue_format` option on the exception handler.
+ - `enforce_available_locales` now defaults to true with no deprecation message.
diff --git a/Gemfile b/Gemfile
deleted file mode 120000
index bcfd9a12..00000000
--- a/Gemfile
+++ /dev/null
@@ -1 +0,0 @@
-ci/Gemfile.no-rails
\ No newline at end of file
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 00000000..92f28620
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,8 @@
+source 'https://rubygems.org'
+
+gemspec
+
+gem 'mocha'
+gem 'test_declarative'
+gem 'rake'
+gem 'minitest'
diff --git a/Gemfile.lock b/Gemfile.lock
index 6dde73ae..2ede6301 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,15 +1,28 @@
+PATH
+ remote: .
+ specs:
+ i18n (0.8.0.beta1)
+
GEM
remote: https://rubygems.org/
specs:
- mocha (0.9.9)
- rake
- rake (0.8.7)
- test_declarative (0.0.4)
+ metaclass (0.0.4)
+ minitest (5.10.1)
+ mocha (1.2.1)
+ metaclass (~> 0.0.1)
+ rake (11.3.0)
+ test_declarative (0.0.5)
PLATFORMS
java
ruby
DEPENDENCIES
+ i18n!
+ minitest
mocha
+ rake
test_declarative
+
+BUNDLED WITH
+ 1.13.6
diff --git a/README.textile b/README.md
similarity index 50%
rename from README.textile
rename to README.md
index 57b79c10..ae9faf7d 100644
--- a/README.textile
+++ b/README.md
@@ -1,6 +1,6 @@
-h1. Ruby I18n
+# Ruby I18n
-!https://secure.travis-ci.org/svenfuchs/i18n.png?branch=master(Build Status)!:http://travis-ci.org/svenfuchs/i18n
+[![Build Status](https://api.travis-ci.org/svenfuchs/i18n.svg?branch=master)](https://travis-ci.org/svenfuchs/i18n)
Ruby Internationalization and localization solution.
@@ -22,7 +22,7 @@ Pluggable features:
* Cache
* Pluralization: lambda pluralizers stored as translation data
* Locale fallbacks, RFC4647 compliant (optionally: RFC4646 locale validation)
-* Gettext support
+* [Gettext support](https://github.com/svenfuchs/i18n/wiki/Gettext)
* Translation metadata
Alternative backends:
@@ -31,43 +31,20 @@ Alternative backends:
* ActiveRecord (optionally: ActiveRecord::Missing and ActiveRecord::StoreProcs)
* KeyValue (uses active_support/json and cannot store procs)
-For more information and lots of resources see: "http://ruby-i18n.org/wiki":http://ruby-i18n.org/wiki
+For more information and lots of resources see [the 'Resources' page on the wiki](https://github.com/svenfuchs/i18n/wiki/Resources).
-h2. Installation
+## Installation
+```
gem install i18n
+```
-h4. Rails version warning
-
-On Rails < 2.3.6 the method I18n.localize will fail with MissingInterpolationArgument (issue "20":http://github.com/svenfuchs/i18n/issues/issue/20). Upgrade to Rails 2.3.6 or higher (2.3.8 preferably) is recommended.
-
-h3. Installation on Rails < 2.3.5 (deprecated)
-
-Up to version 2.3.4 Rails will not accept i18n gems > 0.1.3. There is an unpacked
-gem inside of active_support/lib/vendor which gets loaded unless gem 'i18n', '~> 0.1.3'.
-This requirement is relaxed in "6da03653":http://github.com/rails/rails/commit/6da03653
-
-The new i18n gem can be loaded from vendor/plugins like this:
-
-
- def reload_i18n!
- raise "Move to i18n version 0.2.0 or greater" if Rails.version > "2.3.4"
-
- $:.grep(/i18n/).each { |path| $:.delete(path) }
- I18n::Backend.send :remove_const, "Simple"
- $: << Rails.root.join('vendor', 'plugins', 'i18n', 'lib').to_s
- end
-
-
-Then you can `reload_i18n!` inside an i18n initializer.
-
-h2. Tests
+## Tests
You can run tests both with
* `rake test` or just `rake`
-* run any test file directly, e.g. `ruby -Ilib -Itest test/api/simple_test.rb`
-* run all tests with `ruby -Ilib -Itest test/all.rb`
+* run any test file directly, e.g. `ruby -Ilib:test test/api/simple_test.rb`
You can run all tests against all Gemfiles with
@@ -85,21 +62,21 @@ as test methods) in test cases with different setups.
You can find the test cases that enforce the API in test/api. And you can find
the API definition test methods in test/api/tests.
-All other test cases (e.g. as defined in test/backend, test/core\_ext) etc.
+All other test cases (e.g. as defined in test/backend, test/core_ext) etc.
follow the usual test setup and should be easy to grok.
-h2. Authors
+## Authors
-* "Sven Fuchs":http://www.artweb-design.de
-* "Joshua Harvey":http://www.workingwithrails.com/person/759-joshua-harvey
-* "Stephan Soller":http://www.arkanis-development.de
-* "Saimon Moore":http://saimonmoore.net
-* "Matt Aimonetti":http://railsontherun.com
+* [Sven Fuchs](http://www.artweb-design.de)
+* [Joshua Harvey](http://www.workingwithrails.com/person/759-joshua-harvey)
+* [Stephan Soller](http://www.arkanis-development.de)
+* [Saimon Moore](http://saimonmoore.net)
+* [Matt Aimonetti](https://matt.aimonetti.net/)
-h2. Contributors
+## Contributors
-http://github.com/svenfuchs/i18n/contributors
+https://github.com/svenfuchs/i18n/graphs/contributors
-h2. License
+## License
MIT License. See the included MIT-LICENSE file.
diff --git a/Rakefile b/Rakefile
index 94036070..bdc6683c 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,3 +1,4 @@
+require 'bundler/gem_tasks'
require 'rake/testtask'
task :default => [:test]
@@ -5,23 +6,8 @@ task :default => [:test]
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
- t.pattern = "#{File.dirname(__FILE__)}/test/all.rb"
+ t.pattern = "test/**/*_test.rb"
t.verbose = true
t.warning = true
end
Rake::Task['test'].comment = "Run all i18n tests"
-
-# require "rake/gempackagetask"
-# require "rake/clean"
-# CLEAN << "pkg" << "doc" << "coverage" << ".yardoc"
-#
-# Rake::GemPackageTask.new(eval(File.read("i18n.gemspec"))) { |pkg| }
-#
-# begin
-# require "yard"
-# YARD::Rake::YardocTask.new do |t|
-# t.options = ["--output-dir=doc"]
-# t.options << "--files" << ["CHANGELOG.textile", "contributors.txt", "MIT-LICENSE"].join(",")
-# end
-# rescue LoadError
-# end
diff --git a/benchmark/example.yml b/benchmark/example.yml
index da5f9fe7..650c3905 100644
--- a/benchmark/example.yml
+++ b/benchmark/example.yml
@@ -60,7 +60,10 @@ en:
month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
# Used in date_select and datime_select.
- order: [ :year, :month, :day ]
+ order:
+ - :year,
+ - :month,
+ - :day
time:
formats:
@@ -131,7 +134,10 @@ en:
month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
# Used in date_select and datime_select.
- order: [ :year, :month, :day ]
+ order:
+ - :year
+ - :month
+ - :day
time:
formats:
@@ -145,4 +151,4 @@ en:
array:
words_connector: ", "
two_words_connector: " and "
- last_word_connector: ", and "
\ No newline at end of file
+ last_word_connector: ", and "
diff --git a/benchmark/run.rb b/benchmark/run.rb
index 0a59eeb1..b37c3b7f 100644
--- a/benchmark/run.rb
+++ b/benchmark/run.rb
@@ -1,11 +1,11 @@
-#! /usr/bin/ruby
+#!/usr/bin/ruby
$:.unshift File.expand_path('../../lib', __FILE__)
+require 'bundler/setup'
require 'i18n'
require 'benchmark'
require 'yaml'
-DATA_STORES = ARGV.delete("-ds")
N = (ARGV.shift || 1000).to_i
YAML_HASH = YAML.load_file(File.expand_path("example.yml", File.dirname(__FILE__)))
@@ -16,20 +16,16 @@ module Backends
include I18n::Backend::InterpolationCompiler
end.new
- if DATA_STORES
- require 'rubygems'
- require File.expand_path('../../test/test_setup/active_record', __FILE__)
- require File.expand_path('../../test/test_setup/rufus_tokyo', __FILE__)
-
- Test.setup_active_record
- ActiveRecord = I18n::Backend::ActiveRecord.new if defined?(::ActiveRecord)
-
- Test.setup_rufus_tokyo
- TokyoCabinet = I18n::Backend::KeyValue.new(Rufus::Tokyo::Cabinet.new("*"), true) if defined?(::Rufus::Tokyo)
+ begin
+ require 'active_support'
+ KeyValue = I18n::Backend::KeyValue.new({}, true)
+ puts "Running KeyValue with ActiveSupport #{ActiveSupport::VERSION::STRING}"
+ rescue LoadError
+ puts 'Skipping KeyValue since ActiveSupport could not be loaded.'
end
end
-ORDER = %w(Simple Interpolation ActiveRecord TokyoCabinet)
+ORDER = %w(Simple Interpolation KeyValue)
ORDER.map!(&:to_sym) if RUBY_VERSION > '1.9'
module Benchmark
@@ -62,7 +58,7 @@ def self.measure_objects(n, &blk)
puts "=> #{backend_name}\n\n"
Benchmark.rt "store", 1 do
- I18n.backend.store_translations *(YAML_HASH.to_a.first)
+ I18n.backend.store_translations(*YAML_HASH.to_a.first)
end
I18n.backend.translate :en, :first
@@ -114,4 +110,4 @@ def self.measure_objects(n, &blk)
end
puts "Running memoized benchmarks with N = #{N}\n\n"
-(ORDER & Backends.constants).each(&benchmarker)
\ No newline at end of file
+(ORDER & Backends.constants).each(&benchmarker)
diff --git a/ci/Gemfile.no-rails b/ci/Gemfile.no-rails
deleted file mode 100644
index 449613e8..00000000
--- a/ci/Gemfile.no-rails
+++ /dev/null
@@ -1,5 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'mocha'
-gem 'test_declarative'
-
diff --git a/ci/Gemfile.no-rails.lock b/ci/Gemfile.no-rails.lock
deleted file mode 100644
index 569b32a7..00000000
--- a/ci/Gemfile.no-rails.lock
+++ /dev/null
@@ -1,14 +0,0 @@
-GEM
- remote: http://rubygems.org/
- specs:
- mocha (0.9.9)
- rake
- rake (0.8.7)
- test_declarative (0.0.4)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- mocha
- test_declarative
diff --git a/ci/Gemfile.rails-2.3.x b/ci/Gemfile.rails-2.3.x
deleted file mode 100644
index 3227b3ae..00000000
--- a/ci/Gemfile.rails-2.3.x
+++ /dev/null
@@ -1,9 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'activesupport', '~> 2.3'
-gem 'sqlite3-ruby'
-gem 'mocha'
-gem 'test_declarative'
-gem 'rufus-tokyo'
-gem 'ffi'
-
diff --git a/ci/Gemfile.rails-2.3.x.lock b/ci/Gemfile.rails-2.3.x.lock
deleted file mode 100644
index 60106158..00000000
--- a/ci/Gemfile.rails-2.3.x.lock
+++ /dev/null
@@ -1,23 +0,0 @@
-GEM
- remote: http://rubygems.org/
- specs:
- activesupport (2.3.10)
- ffi (0.6.3)
- rake (>= 0.8.7)
- mocha (0.9.9)
- rake
- rake (0.8.7)
- rufus-tokyo (1.0.7)
- sqlite3-ruby (1.3.2)
- test_declarative (0.0.4)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- activesupport (~> 2.3)
- ffi
- mocha
- rufus-tokyo
- sqlite3-ruby
- test_declarative
diff --git a/ci/Gemfile.rails-3.x b/ci/Gemfile.rails-3.x
deleted file mode 100644
index d0947e55..00000000
--- a/ci/Gemfile.rails-3.x
+++ /dev/null
@@ -1,9 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'activesupport', '~> 3.0.0'
-gem 'sqlite3-ruby'
-gem 'mocha'
-gem 'test_declarative'
-gem 'rufus-tokyo'
-gem 'ffi'
-
diff --git a/ci/Gemfile.rails-3.x.lock b/ci/Gemfile.rails-3.x.lock
deleted file mode 100644
index de7aad6a..00000000
--- a/ci/Gemfile.rails-3.x.lock
+++ /dev/null
@@ -1,23 +0,0 @@
-GEM
- remote: http://rubygems.org/
- specs:
- activesupport (3.0.3)
- ffi (0.6.3)
- rake (>= 0.8.7)
- mocha (0.9.9)
- rake
- rake (0.8.7)
- rufus-tokyo (1.0.7)
- sqlite3-ruby (1.3.2)
- test_declarative (0.0.4)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- activesupport (~> 3.0.0)
- ffi
- mocha
- rufus-tokyo
- sqlite3-ruby
- test_declarative
diff --git a/gemfiles/Gemfile.rails-3.2.x b/gemfiles/Gemfile.rails-3.2.x
new file mode 100644
index 00000000..50bd10ee
--- /dev/null
+++ b/gemfiles/Gemfile.rails-3.2.x
@@ -0,0 +1,9 @@
+source 'https://rubygems.org'
+
+gemspec :path => '..'
+
+gem 'activesupport', '~> 3.2.0'
+gem 'mocha'
+gem 'test_declarative'
+gem 'rake'
+gem 'minitest'
diff --git a/gemfiles/Gemfile.rails-3.2.x.lock b/gemfiles/Gemfile.rails-3.2.x.lock
new file mode 100644
index 00000000..1aa3d4f4
--- /dev/null
+++ b/gemfiles/Gemfile.rails-3.2.x.lock
@@ -0,0 +1,32 @@
+PATH
+ remote: ..
+ specs:
+ i18n (0.7.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activesupport (3.2.21)
+ i18n (~> 0.6, >= 0.6.4)
+ multi_json (~> 1.0)
+ metaclass (0.0.4)
+ minitest (5.9.1)
+ mocha (1.1.0)
+ metaclass (~> 0.0.1)
+ multi_json (1.11.0)
+ rake (10.4.2)
+ test_declarative (0.0.5)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activesupport (~> 3.2.0)
+ i18n!
+ minitest
+ mocha
+ rake
+ test_declarative
+
+BUNDLED WITH
+ 1.13.5
diff --git a/gemfiles/Gemfile.rails-4.0.x b/gemfiles/Gemfile.rails-4.0.x
new file mode 100644
index 00000000..33e634b5
--- /dev/null
+++ b/gemfiles/Gemfile.rails-4.0.x
@@ -0,0 +1,9 @@
+source 'https://rubygems.org'
+
+gemspec :path => '..'
+
+gem 'activesupport', '~> 4.0.0'
+gem 'mocha'
+gem 'test_declarative'
+gem 'rake'
+gem 'minitest'
diff --git a/gemfiles/Gemfile.rails-4.0.x.lock b/gemfiles/Gemfile.rails-4.0.x.lock
new file mode 100644
index 00000000..d14c35f1
--- /dev/null
+++ b/gemfiles/Gemfile.rails-4.0.x.lock
@@ -0,0 +1,37 @@
+PATH
+ remote: ..
+ specs:
+ i18n (0.7.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activesupport (4.0.13)
+ i18n (~> 0.6, >= 0.6.9)
+ minitest (~> 4.2)
+ multi_json (~> 1.3)
+ thread_safe (~> 0.1)
+ tzinfo (~> 0.3.37)
+ metaclass (0.0.4)
+ minitest (4.7.5)
+ mocha (1.1.0)
+ metaclass (~> 0.0.1)
+ multi_json (1.11.0)
+ rake (10.4.2)
+ test_declarative (0.0.5)
+ thread_safe (0.3.5)
+ tzinfo (0.3.43)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activesupport (~> 4.0.0)
+ i18n!
+ minitest
+ mocha
+ rake
+ test_declarative
+
+BUNDLED WITH
+ 1.13.5
diff --git a/gemfiles/Gemfile.rails-4.1.x b/gemfiles/Gemfile.rails-4.1.x
new file mode 100644
index 00000000..49093b07
--- /dev/null
+++ b/gemfiles/Gemfile.rails-4.1.x
@@ -0,0 +1,9 @@
+source 'https://rubygems.org'
+
+gemspec :path => '..'
+
+gem 'activesupport', '~> 4.1.0'
+gem 'mocha'
+gem 'test_declarative'
+gem 'rake'
+gem 'minitest'
diff --git a/gemfiles/Gemfile.rails-4.1.x.lock b/gemfiles/Gemfile.rails-4.1.x.lock
new file mode 100644
index 00000000..93dc7ae0
--- /dev/null
+++ b/gemfiles/Gemfile.rails-4.1.x.lock
@@ -0,0 +1,38 @@
+PATH
+ remote: ..
+ specs:
+ i18n (0.7.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activesupport (4.1.10)
+ i18n (~> 0.6, >= 0.6.9)
+ json (~> 1.7, >= 1.7.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.1)
+ tzinfo (~> 1.1)
+ json (1.8.2)
+ metaclass (0.0.4)
+ minitest (5.5.1)
+ mocha (1.1.0)
+ metaclass (~> 0.0.1)
+ rake (10.4.2)
+ test_declarative (0.0.5)
+ thread_safe (0.3.5)
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activesupport (~> 4.1.0)
+ i18n!
+ minitest
+ mocha
+ rake
+ test_declarative
+
+BUNDLED WITH
+ 1.13.5
diff --git a/gemfiles/Gemfile.rails-4.2.x b/gemfiles/Gemfile.rails-4.2.x
new file mode 100644
index 00000000..8d0dc309
--- /dev/null
+++ b/gemfiles/Gemfile.rails-4.2.x
@@ -0,0 +1,9 @@
+source 'https://rubygems.org'
+
+gemspec :path => '..'
+
+gem 'activesupport', '~> 4.2.0'
+gem 'mocha'
+gem 'test_declarative'
+gem 'rake'
+gem 'minitest'
diff --git a/gemfiles/Gemfile.rails-4.2.x.lock b/gemfiles/Gemfile.rails-4.2.x.lock
new file mode 100644
index 00000000..6459e822
--- /dev/null
+++ b/gemfiles/Gemfile.rails-4.2.x.lock
@@ -0,0 +1,38 @@
+PATH
+ remote: ..
+ specs:
+ i18n (0.7.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activesupport (4.2.1)
+ i18n (~> 0.7)
+ json (~> 1.7, >= 1.7.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ json (1.8.2)
+ metaclass (0.0.4)
+ minitest (5.5.1)
+ mocha (1.1.0)
+ metaclass (~> 0.0.1)
+ rake (10.4.2)
+ test_declarative (0.0.5)
+ thread_safe (0.3.5)
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activesupport (~> 4.2.0)
+ i18n!
+ minitest
+ mocha
+ rake
+ test_declarative
+
+BUNDLED WITH
+ 1.13.5
diff --git a/gemfiles/Gemfile.rails-5.0.x b/gemfiles/Gemfile.rails-5.0.x
new file mode 100644
index 00000000..bddfa474
--- /dev/null
+++ b/gemfiles/Gemfile.rails-5.0.x
@@ -0,0 +1,9 @@
+source 'https://rubygems.org'
+
+gemspec :path => '..'
+
+gem 'activesupport', '~> 5.0.0'
+gem 'mocha'
+gem 'test_declarative'
+gem 'rake'
+gem 'minitest'
diff --git a/gemfiles/Gemfile.rails-5.0.x.lock b/gemfiles/Gemfile.rails-5.0.x.lock
new file mode 100644
index 00000000..74442adf
--- /dev/null
+++ b/gemfiles/Gemfile.rails-5.0.x.lock
@@ -0,0 +1,37 @@
+PATH
+ remote: ..
+ specs:
+ i18n (0.7.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activesupport (5.0.0.1)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ concurrent-ruby (1.0.2)
+ metaclass (0.0.4)
+ minitest (5.9.1)
+ mocha (1.2.1)
+ metaclass (~> 0.0.1)
+ rake (11.3.0)
+ test_declarative (0.0.5)
+ thread_safe (0.3.5)
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activesupport (~> 5.0.0)
+ i18n!
+ minitest
+ mocha
+ rake
+ test_declarative
+
+BUNDLED WITH
+ 1.13.6
diff --git a/gemfiles/Gemfile.rails-master b/gemfiles/Gemfile.rails-master
new file mode 100644
index 00000000..0fef9099
--- /dev/null
+++ b/gemfiles/Gemfile.rails-master
@@ -0,0 +1,9 @@
+source 'https://rubygems.org'
+
+gemspec :path => '..'
+
+gem 'activesupport', github: 'rails/rails', branch: 'master'
+gem 'mocha'
+gem 'test_declarative'
+gem 'rake'
+gem 'minitest'
diff --git a/gemfiles/Gemfile.rails-master.lock b/gemfiles/Gemfile.rails-master.lock
new file mode 100644
index 00000000..f5b9f7bb
--- /dev/null
+++ b/gemfiles/Gemfile.rails-master.lock
@@ -0,0 +1,43 @@
+GIT
+ remote: git://github.com/rails/rails.git
+ revision: da23e125f8d755917b08f5cca1f7fe1ff38c8b7e
+ branch: master
+ specs:
+ activesupport (5.1.0.alpha)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+
+PATH
+ remote: ..
+ specs:
+ i18n (0.7.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ concurrent-ruby (1.0.2)
+ metaclass (0.0.4)
+ minitest (5.5.1)
+ mocha (1.1.0)
+ metaclass (~> 0.0.1)
+ rake (10.4.2)
+ test_declarative (0.0.5)
+ thread_safe (0.3.5)
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activesupport!
+ i18n!
+ minitest
+ mocha
+ rake
+ test_declarative
+
+BUNDLED WITH
+ 1.13.6
diff --git a/i18n.gemspec b/i18n.gemspec
index 4c22bb77..5f20c15d 100644
--- a/i18n.gemspec
+++ b/i18n.gemspec
@@ -13,14 +13,10 @@ Gem::Specification.new do |s|
s.description = "New wave Internationalization support for Ruby."
s.license = "MIT"
- s.files = Dir.glob("{ci,lib,test}/**/**") + %w(README.textile MIT-LICENSE)
+ s.files = Dir.glob("{gemfiles,lib,test}/**/**") + %w(README.md MIT-LICENSE)
s.platform = Gem::Platform::RUBY
s.require_path = 'lib'
s.rubyforge_project = '[none]'
s.required_rubygems_version = '>= 1.3.5'
-
- s.add_development_dependency 'activesupport', '>= 3.0.0'
- s.add_development_dependency 'sqlite3'
- s.add_development_dependency 'mocha'
- s.add_development_dependency 'test_declarative'
+ s.required_ruby_version = '>= 1.9.3'
end
diff --git a/lib/i18n.rb b/lib/i18n.rb
old mode 100755
new mode 100644
index a97f7b85..f696d913
--- a/lib/i18n.rb
+++ b/lib/i18n.rb
@@ -9,10 +9,10 @@ module I18n
autoload :Locale, 'i18n/locale'
autoload :Tests, 'i18n/tests'
- RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :throw, :raise, :rescue_format]
+ RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :throw, :raise, :deep_interpolation]
RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/
- extend(Module.new {
+ module Base
# Gets I18n configuration object.
def config
Thread.current[:i18n_config] ||= I18n::Config.new
@@ -41,6 +41,7 @@ def #{method}=(value)
# Rails development environment. Backends can implement whatever strategy
# is useful.
def reload!
+ config.clear_available_locales_set
config.backend.reload!
end
@@ -271,26 +272,19 @@ def normalize_keys(locale, key, scope, separator = nil)
keys
end
- # Returns true when the passed locale is in I18.available_locales.
- # Returns false otherwise.
- # Compare with Strings as `locale` may be coming from user input
+ # Returns true when the passed locale, which can be either a String or a
+ # Symbol, is in the list of available locales. Returns false otherwise.
def locale_available?(locale)
- I18n.available_locales.map(&:to_s).include?(locale.to_s)
+ I18n.config.available_locales_set.include?(locale)
end
- # Raises an InvalidLocale exception when the passed locale is not
- # included in I18n.available_locales.
- # Returns false otherwise
+ # Raises an InvalidLocale exception when the passed locale is not available.
def enforce_available_locales!(locale)
- handle_enforce_available_locales_deprecation
-
if config.enforce_available_locales
raise I18n::InvalidLocale.new(locale) if !locale_available?(locale)
end
end
- # making these private until Ruby 1.9.2 can send to protected methods again
- # see http://redmine.ruby-lang.org/repositories/revision/ruby-19?rev=24280
private
# Any exceptions thrown in translate will be sent to the @@exception_handler
@@ -303,18 +297,18 @@ def enforce_available_locales!(locale)
#
# Examples:
#
- # I18n.exception_handler = :default_exception_handler # this is the default
- # I18n.default_exception_handler(exception, locale, key, options) # will be called like this
+ # I18n.exception_handler = :custom_exception_handler # this is the default
+ # I18n.custom_exception_handler(exception, locale, key, options) # will be called like this
#
# I18n.exception_handler = lambda { |*args| ... } # a lambda
# I18n.exception_handler.call(exception, locale, key, options) # will be called like this
#
- # I18n.exception_handler = I18nExceptionHandler.new # an object
- # I18n.exception_handler.call(exception, locale, key, options) # will be called like this
+ # I18n.exception_handler = I18nExceptionHandler.new # an object
+ # I18n.exception_handler.call(exception, locale, key, options) # will be called like this
def handle_exception(handling, exception, locale, key, options)
case handling
when :raise
- raise(exception.respond_to?(:to_exception) ? exception.to_exception : exception)
+ raise exception.respond_to?(:to_exception) ? exception.to_exception : exception
when :throw
throw :exception, exception
else
@@ -343,25 +337,7 @@ def normalize_key(key, separator)
def normalized_key_cache
@normalized_key_cache ||= Hash.new { |h,k| h[k] = {} }
end
+ end
- # DEPRECATED. Use I18n.normalize_keys instead.
- def normalize_translation_keys(locale, key, scope, separator = nil)
- puts "I18n.normalize_translation_keys is deprecated. Please use the class I18n.normalize_keys instead."
- normalize_keys(locale, key, scope, separator)
- end
-
- # DEPRECATED. Please use the I18n::ExceptionHandler class instead.
- def default_exception_handler(exception, locale, key, options)
- puts "I18n.default_exception_handler is deprecated. Please use the class I18n::ExceptionHandler instead " +
- "(an instance of which is set to I18n.exception_handler by default)."
- exception.is_a?(MissingTranslation) ? exception.message : raise(exception)
- end
-
- def handle_enforce_available_locales_deprecation
- if config.enforce_available_locales.nil? && !@unenforced_available_locales_deprecation
- $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."
- @unenforced_available_locales_deprecation = true
- end
- end
- })
+ extend Base
end
diff --git a/lib/i18n/backend/base.rb b/lib/i18n/backend/base.rb
index dddb145a..668a4221 100644
--- a/lib/i18n/backend/base.rb
+++ b/lib/i18n/backend/base.rb
@@ -1,6 +1,6 @@
require 'yaml'
require 'i18n/core_ext/hash'
-require 'i18n/core_ext/kernel/surpress_warnings'
+require 'i18n/core_ext/kernel/suppress_warnings'
module I18n
module Backend
@@ -25,20 +25,32 @@ def translate(locale, key, options = {})
raise InvalidLocale.new(locale) unless locale
entry = key && lookup(locale, key, options[:scope], options)
- if options.empty?
- entry = resolve(locale, key, entry, options)
+ if entry.nil? && options.key?(:default)
+ entry = default(locale, key, options[:default], options)
else
- count, default = options.values_at(:count, :default)
- values = options.except(*RESERVED_KEYS)
- entry = entry.nil? && default ?
- default(locale, key, default, options) : resolve(locale, key, entry, options)
+ entry = resolve(locale, key, entry, options)
+ end
+
+ if entry.nil?
+ if (options.key?(:default) && !options[:default].nil?) || !options.key?(:default)
+ throw(:exception, I18n::MissingTranslation.new(locale, key, options))
+ end
end
- throw(:exception, I18n::MissingTranslation.new(locale, key, options)) if entry.nil?
entry = entry.dup if entry.is_a?(String)
+ count = options[:count]
entry = pluralize(locale, entry, count) if count
- entry = interpolate(locale, entry, values) if values
+
+ deep_interpolation = options[:deep_interpolation]
+ values = options.except(*RESERVED_KEYS)
+ if values
+ entry = if deep_interpolation
+ deep_interpolate(locale, entry, values)
+ else
+ interpolate(locale, entry, values)
+ end
+ end
entry
end
@@ -50,6 +62,9 @@ def exists?(locale, key)
# format string. Takes a key from the date/time formats translations as
# a format argument (e.g., :short in :'date.formats').
def localize(locale, object, format = :default, options = {})
+ if object.nil? && options.include?(:default)
+ return options[:default]
+ end
raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime)
if Symbol === format
@@ -59,18 +74,7 @@ def localize(locale, object, format = :default, options = {})
format = I18n.t(:"#{type}.formats.#{key}", options)
end
- # format = resolve(locale, object, format, options)
- format = format.to_s.gsub(/%[aAbBpP]/) do |match|
- case match
- when '%a' then I18n.t(:"date.abbr_day_names", :locale => locale, :format => format)[object.wday]
- when '%A' then I18n.t(:"date.day_names", :locale => locale, :format => format)[object.wday]
- when '%b' then I18n.t(:"date.abbr_month_names", :locale => locale, :format => format)[object.mon]
- when '%B' then I18n.t(:"date.month_names", :locale => locale, :format => format)[object.mon]
- when '%p' then I18n.t(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format).upcase if object.respond_to? :hour
- when '%P' then I18n.t(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format).downcase if object.respond_to? :hour
- end
- end
-
+ format = translate_localization_format(locale, object, format, options)
object.strftime(format)
end
@@ -81,7 +85,6 @@ def available_locales
end
def reload!
- @skip_syntax_deprecation = false
end
protected
@@ -156,6 +159,30 @@ def interpolate(locale, string, values = {})
end
end
+ # Deep interpolation
+ #
+ # deep_interpolate { people: { ann: "Ann is %{ann}", john: "John is %{john}" } },
+ # ann: 'good', john: 'big'
+ # #=> { people: { ann: "Ann is good", john: "John is big" } }
+ def deep_interpolate(locale, data, values = {})
+ return data if values.empty?
+
+ case data
+ when ::String
+ I18n.interpolate(data, values)
+ when ::Hash
+ data.each_with_object({}) do |(k, v), result|
+ result[k] = deep_interpolate(locale, v, values)
+ end
+ when ::Array
+ data.map do |v|
+ deep_interpolate(locale, v, values)
+ end
+ else
+ data
+ end
+ end
+
# Loads a single translations file by delegating to #load_rb or
# #load_yml depending on the file extension and directly merges the
# data to the existing translations. Raises I18n::UnknownFileType
@@ -185,6 +212,19 @@ def load_yml(filename)
raise InvalidLocaleData.new(filename, e.inspect)
end
end
+
+ def translate_localization_format(locale, object, format, options)
+ format.to_s.gsub(/%[aAbBpP]/) do |match|
+ case match
+ when '%a' then I18n.t(:"date.abbr_day_names", :locale => locale, :format => format)[object.wday]
+ when '%A' then I18n.t(:"date.day_names", :locale => locale, :format => format)[object.wday]
+ when '%b' then I18n.t(:"date.abbr_month_names", :locale => locale, :format => format)[object.mon]
+ when '%B' then I18n.t(:"date.month_names", :locale => locale, :format => format)[object.mon]
+ when '%p' then I18n.t(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format).upcase if object.respond_to? :hour
+ when '%P' then I18n.t(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format).downcase if object.respond_to? :hour
+ end
+ end
+ end
end
end
end
diff --git a/lib/i18n/backend/cache.rb b/lib/i18n/backend/cache.rb
index 3c456ff9..1aa64348 100644
--- a/lib/i18n/backend/cache.rb
+++ b/lib/i18n/backend/cache.rb
@@ -13,9 +13,13 @@
# You can use any cache implementation you want that provides the same API as
# ActiveSupport::Cache (only the methods #fetch and #write are being used).
#
-# The cache_key implementation assumes that you only pass values to
-# I18n.translate that return a valid key from #hash (see
-# http://www.ruby-doc.org/core/classes/Object.html#M000337).
+# The cache_key implementation by default assumes you pass values that return
+# a valid key from #hash (see
+# http://www.ruby-doc.org/core/classes/Object.html#M000337). However, you can
+# configure your own digest method via which responds to #hexdigest (see
+# http://ruby-doc.org/stdlib/libdoc/digest/rdoc/index.html):
+#
+# I18n.cache_key_digest = Digest::MD5.new
#
# If you use a lambda as a default value in your translation like this:
#
@@ -37,6 +41,7 @@ module I18n
class << self
@@cache_store = nil
@@cache_namespace = nil
+ @@cache_key_digest = nil
def cache_store
@@cache_store
@@ -54,6 +59,14 @@ def cache_namespace=(namespace)
@@cache_namespace = namespace
end
+ def cache_key_digest
+ @@cache_key_digest
+ end
+
+ def cache_key_digest=(key_digest)
+ @@cache_key_digest = key_digest
+ end
+
def perform_caching?
!cache_store.nil?
end
@@ -76,7 +89,8 @@ def fetch(cache_key, &block)
end
def _fetch(cache_key, &block)
- result = I18n.cache_store.read(cache_key) and return result
+ result = I18n.cache_store.read(cache_key)
+ return result unless result.nil?
result = catch(:exception, &block)
I18n.cache_store.write(cache_key, result) unless result.is_a?(Proc)
result
@@ -84,13 +98,17 @@ def _fetch(cache_key, &block)
def cache_key(locale, key, options)
# This assumes that only simple, native Ruby values are passed to I18n.translate.
- "i18n/#{I18n.cache_namespace}/#{locale}/#{key.hash}/#{USE_INSPECT_HASH ? options.inspect.hash : options.hash}"
+ "i18n/#{I18n.cache_namespace}/#{locale}/#{digest_item(key)}/#{USE_INSPECT_HASH ? digest_item(options.inspect) : digest_item(options)}"
end
private
# In Ruby < 1.9 the following is true: { :foo => 1, :bar => 2 }.hash == { :foo => 2, :bar => 1 }.hash
# Therefore we must use the hash of the inspect string instead to avoid cache key colisions.
USE_INSPECT_HASH = RUBY_VERSION <= "1.9"
+
+ def digest_item(key)
+ I18n.cache_key_digest ? I18n.cache_key_digest.hexdigest(key.to_s) : key.hash
+ end
end
end
end
diff --git a/lib/i18n/backend/chain.rb b/lib/i18n/backend/chain.rb
index cb6ad43b..2a45cad3 100644
--- a/lib/i18n/backend/chain.rb
+++ b/lib/i18n/backend/chain.rb
@@ -45,8 +45,8 @@ def translate(locale, key, default_options = {})
options = default_options if backend == backends.last
translation = backend.translate(locale, key, options)
if namespace_lookup?(translation, options)
- namespace = translation.merge(namespace || {})
- elsif !translation.nil?
+ namespace = _deep_merge(translation, namespace || {})
+ elsif !translation.nil? || (options.key?(:default) && options[:default].nil?)
return translation
end
end
@@ -75,6 +75,20 @@ def localize(locale, object, format = :default, options = {})
def namespace_lookup?(result, options)
result.is_a?(Hash) && !options.has_key?(:count)
end
+
+ private
+ # This is approximately what gets used in ActiveSupport.
+ # However since we are not guaranteed to run in an ActiveSupport context
+ # it is wise to have our own copy. We underscore it
+ # to not pollute the namespace of the including class.
+ def _deep_merge(hash, other_hash)
+ copy = hash.dup
+ other_hash.each_pair do |k,v|
+ value_from_other = hash[k]
+ copy[k] = value_from_other.is_a?(Hash) && v.is_a?(Hash) ? _deep_merge(value_from_other, v) : v
+ end
+ copy
+ end
end
include Implementation
diff --git a/lib/i18n/backend/fallbacks.rb b/lib/i18n/backend/fallbacks.rb
index 6b41a752..7683b5e6 100644
--- a/lib/i18n/backend/fallbacks.rb
+++ b/lib/i18n/backend/fallbacks.rb
@@ -36,18 +36,27 @@ module Fallbacks
# it is evaluated last after all the fallback locales have been tried.
def translate(locale, key, options = {})
- return super if options[:fallback]
+ return super unless options.fetch(:fallback, true)
+ return super if (@fallback_locked ||= false)
default = extract_non_symbol_default!(options) if options[:default]
- options[:fallback] = true
- I18n.fallbacks[locale].each do |fallback|
- catch(:exception) do
- result = super(fallback, key, options)
- return result unless result.nil?
+ begin
+ options[:fallback] = true
+ I18n.fallbacks[locale].each do |fallback|
+ begin
+ catch(:exception) do
+ result = super(fallback, key, options)
+ return result if (result.nil? && options.key?(:default) && options[:default].nil?) || !result.nil?
+ end
+ rescue I18n::InvalidLocale
+ # we do nothing when the locale is invalid, as this is a fallback anyways.
+ end
end
+ ensure
+ options.delete(:fallback)
end
- options.delete(:fallback)
- return super(locale, key, options.merge(:default => default))
+
+ return super(locale, key, options.merge(:default => default)) if default
throw(:exception, I18n::MissingTranslation.new(locale, key, options))
end
@@ -60,6 +69,17 @@ def extract_non_symbol_default!(options)
return first_non_symbol_default
end
+ def exists?(locale, key)
+ I18n.fallbacks[locale].each do |fallback|
+ begin
+ return true if super(fallback, key)
+ rescue I18n::InvalidLocale
+ # we do nothing when the locale is invalid, as this is a fallback anyways.
+ end
+ end
+
+ false
+ end
end
end
end
diff --git a/lib/i18n/backend/gettext.rb b/lib/i18n/backend/gettext.rb
index c357a6d4..f41df685 100644
--- a/lib/i18n/backend/gettext.rb
+++ b/lib/i18n/backend/gettext.rb
@@ -1,24 +1,33 @@
require 'i18n/gettext'
require 'i18n/gettext/po_parser'
-# Experimental support for using Gettext po files to store translations.
-#
-# To use this you can simply include the module to the Simple backend - or
-# whatever other backend you are using.
-#
-# I18n::Backend::Simple.include(I18n::Backend::Gettext)
-#
-# Now you should be able to include your Gettext translation (*.po) files to
-# the I18n.load_path so they're loaded to the backend and you can use them as
-# usual:
-#
-# I18n.load_path += Dir["path/to/locales/*.po"]
-#
-# Following the Gettext convention this implementation expects that your
-# translation files are named by their locales. E.g. the file en.po would
-# contain the translations for the English locale.
module I18n
module Backend
+ # Experimental support for using Gettext po files to store translations.
+ #
+ # To use this you can simply include the module to the Simple backend - or
+ # whatever other backend you are using.
+ #
+ # I18n::Backend::Simple.include(I18n::Backend::Gettext)
+ #
+ # Now you should be able to include your Gettext translation (*.po) files to
+ # the +I18n.load_path+ so they're loaded to the backend and you can use them as
+ # usual:
+ #
+ # I18n.load_path += Dir["path/to/locales/*.po"]
+ #
+ # Following the Gettext convention this implementation expects that your
+ # translation files are named by their locales. E.g. the file en.po would
+ # contain the translations for the English locale.
+ #
+ # To translate text you must use one of the translate methods provided by
+ # I18n::Gettext::Helpers.
+ #
+ # include I18n::Gettext::Helpers
+ # puts _("some string")
+ #
+ # Without it strings containing periods (".") will not be translated.
+
module Gettext
class PoData < Hash
def set_comment(msgid_or_sym, comment)
diff --git a/lib/i18n/backend/interpolation_compiler.rb b/lib/i18n/backend/interpolation_compiler.rb
index c5440704..0e3a603a 100644
--- a/lib/i18n/backend/interpolation_compiler.rb
+++ b/lib/i18n/backend/interpolation_compiler.rb
@@ -12,7 +12,7 @@
#
# Note that InterpolationCompiler does not yield meaningful results and consequently
# should not be used with Ruby 1.9 (YARV) but improves performance everywhere else
-# (jRuby, Rubinius and 1.8.7).
+# (jRuby, Rubinius).
module I18n
module Backend
module InterpolationCompiler
diff --git a/lib/i18n/backend/key_value.rb b/lib/i18n/backend/key_value.rb
index df80718b..a79fc1aa 100644
--- a/lib/i18n/backend/key_value.rb
+++ b/lib/i18n/backend/key_value.rb
@@ -1,6 +1,5 @@
require 'i18n/backend/base'
require 'active_support/json'
-require 'active_support/ordered_hash' # active_support/json/encoding uses ActiveSupport::OrderedHash but does not require it
module I18n
module Backend
diff --git a/lib/i18n/backend/metadata.rb b/lib/i18n/backend/metadata.rb
index 52c0a295..a8d922a0 100644
--- a/lib/i18n/backend/metadata.rb
+++ b/lib/i18n/backend/metadata.rb
@@ -21,11 +21,15 @@ class << self
def included(base)
Object.class_eval do
def translation_metadata
- @translation_metadata ||= {}
+ unless self.frozen?
+ @translation_metadata ||= {}
+ else
+ {}
+ end
end
def translation_metadata=(translation_metadata)
- @translation_metadata = translation_metadata
+ @translation_metadata = translation_metadata unless self.frozen?
end
end unless Object.method_defined?(:translation_metadata)
end
diff --git a/lib/i18n/backend/simple.rb b/lib/i18n/backend/simple.rb
index 95ffb6ab..00a887b4 100644
--- a/lib/i18n/backend/simple.rb
+++ b/lib/i18n/backend/simple.rb
@@ -63,7 +63,7 @@ def translations
end
# Looks up a translation from the translations hash. Returns nil if
- # eiher key is nil, or locale, scope or key do not exist as a key in the
+ # either key is nil, or locale, scope or key do not exist as a key in the
# nested translations hash. Splits keys or scopes containing dots
# into multiple keys, i.e. currency.format is regarded the same as
# %w(currency format).
diff --git a/lib/i18n/backend/transliterator.rb b/lib/i18n/backend/transliterator.rb
index 2ee983de..538dd600 100644
--- a/lib/i18n/backend/transliterator.rb
+++ b/lib/i18n/backend/transliterator.rb
@@ -71,13 +71,13 @@ class HashTransliterator
def initialize(rule = nil)
@rule = rule
- add DEFAULT_APPROXIMATIONS.dup
+ add_default_approximations
add rule if rule
end
- def transliterate(string, replacement = nil)
+ def transliterate(string, replacement = DEFAULT_REPLACEMENT_CHAR)
string.gsub(/[^\x00-\x7f]/u) do |char|
- approximations[char] || replacement || DEFAULT_REPLACEMENT_CHAR
+ approximations[char] || replacement
end
end
@@ -87,6 +87,12 @@ def approximations
@approximations ||= {}
end
+ def add_default_approximations
+ DEFAULT_APPROXIMATIONS.each do |key, value|
+ approximations[key] = value
+ end
+ end
+
# Add transliteration rules to the approximations hash.
def add(hash)
hash.each do |key, value|
@@ -96,4 +102,4 @@ def add(hash)
end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/i18n/config.rb b/lib/i18n/config.rb
index 76293a1a..fa16667f 100644
--- a/lib/i18n/config.rb
+++ b/lib/i18n/config.rb
@@ -1,15 +1,17 @@
+require 'set'
+
module I18n
class Config
# The only configuration value that is not global and scoped to thread is :locale.
# It defaults to the default_locale.
def locale
- @locale ||= default_locale
+ defined?(@locale) && @locale ? @locale : default_locale
end
# Sets the current locale pseudo-globally, i.e. in the Thread.current hash.
def locale=(locale)
I18n.enforce_available_locales!(locale)
- @locale = locale.to_sym rescue nil
+ @locale = locale && locale.to_sym
end
# Returns the current backend. Defaults to +Backend::Simple+.
@@ -30,7 +32,7 @@ def default_locale
# Sets the current default locale. Used to set a custom default locale.
def default_locale=(locale)
I18n.enforce_available_locales!(locale)
- @@default_locale = locale.to_sym rescue nil
+ @@default_locale = locale && locale.to_sym
end
# Returns an array of locales for which translations are available.
@@ -41,10 +43,25 @@ def available_locales
@@available_locales || backend.available_locales
end
+ # Caches the available locales list as both strings and symbols in a Set, so
+ # that we can have faster lookups to do the available locales enforce check.
+ def available_locales_set #:nodoc:
+ @@available_locales_set ||= available_locales.inject(Set.new) do |set, locale|
+ set << locale.to_s << locale.to_sym
+ end
+ end
+
# Sets the available locales.
def available_locales=(locales)
@@available_locales = Array(locales).map { |locale| locale.to_sym }
@@available_locales = nil if @@available_locales.empty?
+ @@available_locales_set = nil
+ end
+
+ # Clears the available locales set so it can be recomputed again after I18n
+ # gets reloaded.
+ def clear_available_locales_set #:nodoc:
+ @@available_locales_set = nil
end
# Returns the current default scope separator. Defaults to '.'
@@ -57,7 +74,8 @@ def default_separator=(separator)
@@default_separator = separator
end
- # Return the current exception handler. Defaults to :default_exception_handler.
+ # Returns the current exception handler. Defaults to an instance of
+ # I18n::ExceptionHandler.
def exception_handler
@@exception_handler ||= ExceptionHandler.new
end
@@ -106,12 +124,15 @@ def load_path
# behave like a Ruby Array.
def load_path=(load_path)
@@load_path = load_path
+ @@available_locales_set = nil
+ backend.reload!
end
- # [Deprecated] this will default to true in the future
- # Defaults to nil so that it triggers the deprecation warning
+ # Whether or not to verify if locales are in the list of available locales.
+ # Defaults to true.
+ @@enforce_available_locales = true
def enforce_available_locales
- defined?(@@enforce_available_locales) ? @@enforce_available_locales : nil
+ @@enforce_available_locales
end
def enforce_available_locales=(enforce_available_locales)
diff --git a/lib/i18n/core_ext/hash.rb b/lib/i18n/core_ext/hash.rb
index f2a2422b..0c254ecc 100644
--- a/lib/i18n/core_ext/hash.rb
+++ b/lib/i18n/core_ext/hash.rb
@@ -1,7 +1,7 @@
class Hash
def slice(*keep_keys)
- h = {}
- keep_keys.each { |key| h[key] = fetch(key) }
+ h = self.class.new
+ keep_keys.each { |key| h[key] = fetch(key) if has_key?(key) }
h
end unless Hash.method_defined?(:slice)
@@ -21,7 +21,7 @@ def deep_symbolize_keys
MERGER = proc do |key, v1, v2|
Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2
end
-
+
def deep_merge!(data)
merge!(data, &MERGER)
end unless Hash.method_defined?(:deep_merge!)
diff --git a/lib/i18n/core_ext/kernel/suppress_warnings.rb b/lib/i18n/core_ext/kernel/suppress_warnings.rb
new file mode 100644
index 00000000..eec1435a
--- /dev/null
+++ b/lib/i18n/core_ext/kernel/suppress_warnings.rb
@@ -0,0 +1,8 @@
+module Kernel
+ def suppress_warnings
+ original_verbosity, $VERBOSE = $VERBOSE, nil
+ yield
+ ensure
+ $VERBOSE = original_verbosity
+ end
+end
diff --git a/lib/i18n/core_ext/kernel/surpress_warnings.rb b/lib/i18n/core_ext/kernel/surpress_warnings.rb
deleted file mode 100644
index cc03b1c1..00000000
--- a/lib/i18n/core_ext/kernel/surpress_warnings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module Kernel
- def suppress_warnings
- original_verbosity = $VERBOSE
- $VERBOSE = nil
- result = yield
- $VERBOSE = original_verbosity
- result
- end
-end
diff --git a/lib/i18n/core_ext/string/interpolate.rb b/lib/i18n/core_ext/string/interpolate.rb
index 56de8c00..a353310b 100644
--- a/lib/i18n/core_ext/string/interpolate.rb
+++ b/lib/i18n/core_ext/string/interpolate.rb
@@ -1,105 +1,9 @@
-# This backports the Ruby 1.9 String interpolation syntax to Ruby 1.8.
+# This file used to backport the Ruby 1.9 String interpolation syntax to Ruby 1.8.
#
-# This backport has been shipped with I18n for a number of versions. Meanwhile
-# Rails has started to rely on it and we are going to move it to ActiveSupport.
-# See https://rails.lighthouseapp.com/projects/8994/tickets/6013-move-19-string-interpolation-syntax-backport-from-i18n-to-activesupport
+# Since I18n has dropped support to Ruby 1.8, this file is not required anymore,
+# however, Rails 3.2 still requires it directly:
#
-# Once the above patch has been applied to Rails the following code will be
-# removed from I18n.
-
-=begin
- heavily based on Masao Mutoh's gettext String interpolation extension
- http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
- Copyright (C) 2005-2009 Masao Mutoh
- You may redistribute it and/or modify it under the same license terms as Ruby.
-=end
-
-begin
- raise ArgumentError if ("a %{x}" % {:x=>'b'}) != 'a b'
-rescue ArgumentError
- # KeyError is raised by String#% when the string contains a named placeholder
- # that is not contained in the given arguments hash. Ruby 1.9 includes and
- # raises this exception natively. We define it to mimic Ruby 1.9's behaviour
- # in Ruby 1.8.x
- class KeyError < IndexError
- def initialize(message = nil)
- super(message || "key not found")
- end
- end unless defined?(KeyError)
-
- # Extension for String class. This feature is included in Ruby 1.9 or later but not occur TypeError.
- #
- # String#% method which accept "named argument". The translator can know
- # the meaning of the msgids using "named argument" instead of %s/%d style.
- class String
- # For older ruby versions, such as ruby-1.8.5
- alias :bytesize :size unless instance_methods.find {|m| m.to_s == 'bytesize'}
- alias :interpolate_without_ruby_19_syntax :% # :nodoc:
-
- INTERPOLATION_PATTERN = Regexp.union(
- /%\{(\w+)\}/, # matches placeholders like "%{foo}"
- /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%.d"
- )
-
- INTERPOLATION_PATTERN_WITH_ESCAPE = Regexp.union(
- /%%/,
- INTERPOLATION_PATTERN
- )
-
- # % uses self (i.e. the String) as a format specification and returns the
- # result of applying it to the given arguments. In other words it interpolates
- # the given arguments to the string according to the formats the string
- # defines.
- #
- # There are three ways to use it:
- #
- # * Using a single argument or Array of arguments.
- #
- # This is the default behaviour of the String class. See Kernel#sprintf for
- # more details about the format string.
- #
- # Example:
- #
- # "%d %s" % [1, "message"]
- # # => "1 message"
- #
- # * Using a Hash as an argument and unformatted, named placeholders.
- #
- # When you pass a Hash as an argument and specify placeholders with %{foo}
- # it will interpret the hash values as named arguments.
- #
- # Example:
- #
- # "%{firstname}, %{lastname}" % {:firstname => "Masao", :lastname => "Mutoh"}
- # # => "Masao Mutoh"
- #
- # * Using a Hash as an argument and formatted, named placeholders.
- #
- # When you pass a Hash as an argument and specify placeholders with %d
- # it will interpret the hash values as named arguments and format the value
- # according to the formatting instruction appended to the closing >.
- #
- # Example:
- #
- # "%d, %.1f" % { :integer => 10, :float => 43.4 }
- # # => "10, 43.3"
- def %(args)
- if args.kind_of?(Hash)
- dup.gsub(INTERPOLATION_PATTERN_WITH_ESCAPE) do |match|
- if match == '%%'
- '%'
- else
- key = ($1 || $2).to_sym
- raise KeyError unless args.has_key?(key)
- $3 ? sprintf("%#{$3}", args[key]) : args[key]
- end
- end
- elsif self =~ INTERPOLATION_PATTERN
- raise ArgumentError.new('one hash required')
- else
- result = gsub(/%([{<])/, '%%\1')
- result.send :'interpolate_without_ruby_19_syntax', args
- end
- end
- end
-end
+# https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/string/interpolation.rb#L2
+#
+# So we can't just drop the file entirely, which would then break Rails users
+# under Ruby 1.9. This file can be removed once Rails 3.2 support is dropped.
diff --git a/lib/i18n/exceptions.rb b/lib/i18n/exceptions.rb
index 48d50b85..c0d7477c 100644
--- a/lib/i18n/exceptions.rb
+++ b/lib/i18n/exceptions.rb
@@ -8,21 +8,10 @@ module I18n
class ExceptionHandler
include Module.new {
def call(exception, locale, key, options)
- if exception.is_a?(MissingTranslation)
- #
- # TODO: this block is to be replaced by `exception.message` when
- # rescue_format is removed
- if options[:rescue_format] == :html
- if @rescue_format_deprecation
- $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."
- @rescue_format_deprecation = true
- end
- exception.html_message
- else
- exception.message
- end
-
- elsif exception.is_a?(Exception)
+ case exception
+ when MissingTranslation
+ exception.message
+ when Exception
raise exception
else
throw :exception, exception
@@ -49,21 +38,15 @@ def initialize(filename, exception_message)
end
end
- class MissingTranslation
+ class MissingTranslation < ArgumentError
module Base
attr_reader :locale, :key, :options
- def initialize(locale, key, options = nil)
- @key, @locale, @options = key, locale, options.dup || {}
+ def initialize(locale, key, options = {})
+ @key, @locale, @options = key, locale, options.dup
options.each { |k, v| self.options[k] = v.inspect if v.is_a?(Proc) }
end
- def html_message
- key = CGI.escapeHTML titleize(keys.last)
- path = CGI.escapeHTML keys.join('.')
- %(#{key})
- end
-
def keys
@keys ||= I18n.normalize_keys(locale, key, options[:scope]).tap do |keys|
keys << 'no key' if keys.size < 2
@@ -78,13 +61,6 @@ def message
def to_exception
MissingTranslationData.new(locale, key, options)
end
-
- protected
-
- # TODO : remove when #html_message is removed
- def titleize(key)
- key.to_s.gsub('_', ' ').gsub(/\b('?[a-z])/) { $1.capitalize }
- end
end
include Base
diff --git a/lib/i18n/gettext/helpers.rb b/lib/i18n/gettext/helpers.rb
index ea07d052..c97fd349 100644
--- a/lib/i18n/gettext/helpers.rb
+++ b/lib/i18n/gettext/helpers.rb
@@ -7,6 +7,15 @@ module Gettext
#
# include I18n::Gettext::Helpers
module Helpers
+ # Makes dynamic translation messages readable for the gettext parser.
+ # _(fruit) cannot be understood by the gettext parser. To help the parser find all your translations,
+ # you can add fruit = N_("Apple") which does not translate, but tells the parser: "Apple" needs translation.
+ # * msgid: the message id.
+ # * Returns: msgid.
+ def N_(msgsid)
+ msgsid
+ end
+
def gettext(msgid, options = {})
I18n.t(msgid, { :default => msgid, :separator => '|' }.merge(options))
end
diff --git a/lib/i18n/interpolate/ruby.rb b/lib/i18n/interpolate/ruby.rb
index 442677f2..d2fdda75 100644
--- a/lib/i18n/interpolate/ruby.rb
+++ b/lib/i18n/interpolate/ruby.rb
@@ -22,7 +22,7 @@ def interpolate_hash(string, values)
if match == '%%'
'%'
else
- key = ($1 || $2).to_sym
+ key = ($1 || $2 || match.tr("%{}", "")).to_sym
value = if values.key?(key)
values[key]
else
diff --git a/lib/i18n/tests/defaults.rb b/lib/i18n/tests/defaults.rb
index c89200b9..2ba590e9 100644
--- a/lib/i18n/tests/defaults.rb
+++ b/lib/i18n/tests/defaults.rb
@@ -24,6 +24,14 @@ def setup
assert_equal 'bar', I18n.t(:does_not_exist, :default => [:does_not_exist_2, :'foo.bar'])
end
+ test "defaults: given false it returns false" do
+ assert_equal false, I18n.t(:does_not_exist, :default => false)
+ end
+
+ test "defaults: given nil it returns nil" do
+ assert_equal nil, I18n.t(:does_not_exist, :default => nil)
+ end
+
test "defaults: given an array of missing keys it raises a MissingTranslationData exception" do
assert_raise I18n::MissingTranslationData do
I18n.t(:does_not_exist, :default => [:does_not_exist_2, :does_not_exist_3], :raise => true)
diff --git a/lib/i18n/tests/interpolation.rb b/lib/i18n/tests/interpolation.rb
index add8b90e..c457b3d7 100644
--- a/lib/i18n/tests/interpolation.rb
+++ b/lib/i18n/tests/interpolation.rb
@@ -104,6 +104,26 @@ module Interpolation
assert_raise(I18n::ReservedInterpolationKey) { interpolate(:default => '%{separator}', :foo => :bar) }
end
+ test "interpolation: deep interpolation for default string" do
+ assert_equal 'Hi %{name}!', interpolate(:default => 'Hi %{name}!', :deep_interpolation => true)
+ end
+
+ test "interpolation: deep interpolation for interpolated string" do
+ assert_equal 'Hi Ann!', interpolate(:default => 'Hi %{name}!', :name => 'Ann', :deep_interpolation => true)
+ end
+
+ test "interpolation: deep interpolation for Hash" do
+ people = { :people => { :ann => 'Ann is %{ann}', :john => 'John is %{john}' } }
+ interpolated_people = { :people => { :ann => 'Ann is good', :john => 'John is big' } }
+ assert_equal interpolated_people, interpolate(:default => people, :ann => 'good', :john => 'big', :deep_interpolation => true)
+ end
+
+ test "interpolation: deep interpolation for Array" do
+ people = { :people => ['Ann is %{ann}', 'John is %{john}'] }
+ interpolated_people = { :people => ['Ann is good', 'John is big'] }
+ assert_equal interpolated_people, interpolate(:default => people, :ann => 'good', :john => 'big', :deep_interpolation => true)
+ end
+
protected
def capture(stream)
diff --git a/lib/i18n/tests/localization/date.rb b/lib/i18n/tests/localization/date.rb
index a7234752..fba5fe5c 100644
--- a/lib/i18n/tests/localization/date.rb
+++ b/lib/i18n/tests/localization/date.rb
@@ -51,6 +51,10 @@ def setup
assert_nothing_raised { I18n.l(@date, options.freeze) }
end
+ test "localize Date: given nil with default value it returns default" do
+ assert_equal 'default', I18n.l(nil, :default => 'default')
+ end
+
test "localize Date: given nil it raises I18n::ArgumentError" do
assert_raise(I18n::ArgumentError) { I18n.l(nil) }
end
diff --git a/lib/i18n/tests/localization/procs.rb b/lib/i18n/tests/localization/procs.rb
index 7b7813e2..bdfa9480 100644
--- a/lib/i18n/tests/localization/procs.rb
+++ b/lib/i18n/tests/localization/procs.rb
@@ -52,19 +52,19 @@ module Procs
test "localize Time: given a format that resolves to a Proc it calls the Proc with the object" do
setup_time_proc_translations
time = ::Time.utc(2008, 3, 1, 6, 0)
- assert_equal inspect_args([time, {}]), I18n.l(time, :format => :proc, :locale => :ru)
+ assert_equal I18n::Tests::Localization::Procs.inspect_args([time, {}]), I18n.l(time, :format => :proc, :locale => :ru)
end
test "localize Time: given a format that resolves to a Proc it calls the Proc with the object and extra options" do
setup_time_proc_translations
time = ::Time.utc(2008, 3, 1, 6, 0)
options = { :foo => 'foo' }
- assert_equal inspect_args([time, options]), I18n.l(time, options.merge(:format => :proc, :locale => :ru))
+ assert_equal I18n::Tests::Localization::Procs.inspect_args([time, options]), I18n.l(time, options.merge(:format => :proc, :locale => :ru))
end
protected
- def inspect_args(args)
+ def self.inspect_args(args)
args = args.map do |arg|
case arg
when ::Time, ::DateTime
@@ -85,12 +85,12 @@ def setup_time_proc_translations
I18n.backend.store_translations :ru, {
:time => {
:formats => {
- :proc => lambda { |*args| inspect_args(args) }
+ :proc => lambda { |*args| I18n::Tests::Localization::Procs.inspect_args(args) }
}
},
:date => {
:formats => {
- :proc => lambda { |*args| inspect_args(args) }
+ :proc => lambda { |*args| I18n::Tests::Localization::Procs.inspect_args(args) }
},
:'day_names' => lambda { |key, options|
(options[:format] =~ /^%A/) ?
diff --git a/lib/i18n/tests/lookup.rb b/lib/i18n/tests/lookup.rb
index 62c069d1..3b4c8434 100644
--- a/lib/i18n/tests/lookup.rb
+++ b/lib/i18n/tests/lookup.rb
@@ -17,7 +17,7 @@ def setup
assert_equal({ :a => "b" }, I18n.t(:hash))
end
- test "lookup: it returns a array" do
+ test "lookup: it returns an array" do
assert_equal(%w(a b c), I18n.t(:array))
end
diff --git a/lib/i18n/tests/procs.rb b/lib/i18n/tests/procs.rb
index 345d8995..9ad2793f 100644
--- a/lib/i18n/tests/procs.rb
+++ b/lib/i18n/tests/procs.rb
@@ -4,29 +4,30 @@ module I18n
module Tests
module Procs
test "lookup: given a translation is a Proc it calls the Proc with the key and interpolation values" do
- I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| filter_args(*args) })
+ I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| I18n::Tests::Procs.filter_args(*args) })
assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:a_lambda, :foo => 'foo')
end
test "defaults: given a default is a Proc it calls it with the key and interpolation values" do
- proc = lambda { |*args| filter_args(*args) }
+ proc = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
assert_equal '[:does_not_exist, {:foo=>"foo"}]', I18n.t(:does_not_exist, :default => proc, :foo => 'foo')
end
test "defaults: given a default is a key that resolves to a Proc it calls it with the key and interpolation values" do
- I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| filter_args(*args) })
+ the_lambda = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
+ I18n.backend.store_translations(:en, :a_lambda => the_lambda)
assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:does_not_exist, :default => :a_lambda, :foo => 'foo')
assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:does_not_exist, :default => [nil, :a_lambda], :foo => 'foo')
end
- test "interpolation: given an interpolation value is a Proc it calls it with key and values before interpolating it" do
- proc = lambda { |*args| filter_args(*args) }
+ test "interpolation: given an interpolation value is a lambda it calls it with key and values before interpolating it" do
+ proc = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
assert_match %r(\[\{:foo=>#\}\]), I18n.t(:does_not_exist, :default => '%{foo}', :foo => proc)
end
test "interpolation: given a key resolves to a Proc that returns a string then interpolation still works" do
- proc = lambda { |*args| "%{foo}: " + filter_args(*args) }
- assert_equal "foo: [:does_not_exist, {:foo=>\"foo\"}]", I18n.t(:does_not_exist, :default => proc, :foo => 'foo')
+ proc = lambda { |*args| "%{foo}: " + I18n::Tests::Procs.filter_args(*args) }
+ assert_equal 'foo: [:does_not_exist, {:foo=>"foo"}]', I18n.t(:does_not_exist, :default => proc, :foo => 'foo')
end
test "pluralization: given a key resolves to a Proc that returns valid data then pluralization still works" do
@@ -37,17 +38,16 @@ module Procs
end
test "lookup: given the option :resolve => false was passed it does not resolve Proc translations" do
- I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| filter_args(*args) })
+ I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| I18n::Tests::Procs.filter_args(*args) })
assert_equal Proc, I18n.t(:a_lambda, :resolve => false).class
end
test "lookup: given the option :resolve => false was passed it does not resolve Proc default" do
- assert_equal Proc, I18n.t(:does_not_exist, :default => lambda { |*args| filter_args(*args) }, :resolve => false).class
+ assert_equal Proc, I18n.t(:does_not_exist, :default => lambda { |*args| I18n::Tests::Procs.filter_args(*args) }, :resolve => false).class
end
- protected
- def filter_args(*args)
+ def self.filter_args(*args)
args.map {|arg| arg.delete(:fallback) if arg.is_a?(Hash) ; arg }.inspect
end
end
diff --git a/lib/i18n/version.rb b/lib/i18n/version.rb
index 01f274a3..31178899 100644
--- a/lib/i18n/version.rb
+++ b/lib/i18n/version.rb
@@ -1,3 +1,3 @@
module I18n
- VERSION = "0.6.9"
+ VERSION = "0.8.0.beta1"
end
diff --git a/test/all.rb b/test/all.rb
deleted file mode 100644
index e846143a..00000000
--- a/test/all.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# encoding: utf-8
-
-dir = File.dirname(__FILE__)
-$LOAD_PATH.unshift(dir)
-
-Dir["#{dir}/**/*_test.rb"].sort.each do |file|
- require file.sub(/^#{dir}\/(.*)\.rb$/, '\1')
-end
diff --git a/test/api/all_features_test.rb b/test/api/all_features_test.rb
index 74589b7f..a1799bd6 100644
--- a/test/api/all_features_test.rb
+++ b/test/api/all_features_test.rb
@@ -7,7 +7,7 @@
puts "not testing with Cache enabled because active_support can not be found"
end
-class I18nAllFeaturesApiTest < Test::Unit::TestCase
+class I18nAllFeaturesApiTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Metadata
include I18n::Backend::Cache
diff --git a/test/api/cascade_test.rb b/test/api/cascade_test.rb
index a40587b3..4d9516c4 100644
--- a/test/api/cascade_test.rb
+++ b/test/api/cascade_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class I18nCascadeApiTest < Test::Unit::TestCase
+class I18nCascadeApiTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Cascade
end
diff --git a/test/api/chain_test.rb b/test/api/chain_test.rb
index 0a61cb0a..f3dff1b5 100644
--- a/test/api/chain_test.rb
+++ b/test/api/chain_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class I18nApiChainTest < Test::Unit::TestCase
+class I18nApiChainTest < I18n::TestCase
def setup
super
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n.backend)
diff --git a/test/api/fallbacks_test.rb b/test/api/fallbacks_test.rb
index 31ebb003..e5ca5f20 100644
--- a/test/api/fallbacks_test.rb
+++ b/test/api/fallbacks_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class I18nFallbacksApiTest < Test::Unit::TestCase
+class I18nFallbacksApiTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Fallbacks
end
diff --git a/test/api/key_value_test.rb b/test/api/key_value_test.rb
index 976ca6ba..4d6cdd8a 100644
--- a/test/api/key_value_test.rb
+++ b/test/api/key_value_test.rb
@@ -1,8 +1,6 @@
require 'test_helper'
-I18n::Tests.setup_rufus_tokyo
-
-class I18nKeyValueApiTest < Test::Unit::TestCase
+class I18nKeyValueApiTest < I18n::TestCase
include I18n::Tests::Basics
include I18n::Tests::Defaults
include I18n::Tests::Interpolation
@@ -15,14 +13,12 @@ class I18nKeyValueApiTest < Test::Unit::TestCase
include I18n::Tests::Localization::Time
# include Tests::Api::Localization::Procs
- STORE = Rufus::Tokyo::Cabinet.new('*')
-
def setup
- I18n.backend = I18n::Backend::KeyValue.new(STORE)
+ I18n.backend = I18n::Backend::KeyValue.new({})
super
end
test "make sure we use the KeyValue backend" do
assert_equal I18n::Backend::KeyValue, I18n.backend.class
end
-end if defined?(Rufus::Tokyo::Cabinet)
+end if I18n::TestCase.key_value?
diff --git a/test/api/memoize_test.rb b/test/api/memoize_test.rb
index 8839ec8c..ed938665 100644
--- a/test/api/memoize_test.rb
+++ b/test/api/memoize_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class I18nMemoizeBackendWithSimpleApiTest < Test::Unit::TestCase
+class I18nMemoizeBackendWithSimpleApiTest < I18n::TestCase
include I18n::Tests::Basics
include I18n::Tests::Defaults
include I18n::Tests::Interpolation
@@ -27,9 +27,7 @@ def setup
end
end
-I18n::Tests.setup_rufus_tokyo
-
-class I18nMemoizeBackendWithKeyValueApiTest < Test::Unit::TestCase
+class I18nMemoizeBackendWithKeyValueApiTest < I18n::TestCase
include I18n::Tests::Basics
include I18n::Tests::Defaults
include I18n::Tests::Interpolation
@@ -47,14 +45,12 @@ class MemoizeBackend < I18n::Backend::KeyValue
include I18n::Backend::Memoize
end
- STORE = Rufus::Tokyo::Cabinet.new('*')
-
def setup
- I18n.backend = MemoizeBackend.new(STORE)
+ I18n.backend = MemoizeBackend.new({})
super
end
test "make sure we use the MemoizeBackend backend" do
assert_equal MemoizeBackend, I18n.backend.class
end
-end if defined?(Rufus::Tokyo::Cabinet)
+end if I18n::TestCase.key_value?
diff --git a/test/api/override_test.rb b/test/api/override_test.rb
index 1f4e564e..6e1248ad 100644
--- a/test/api/override_test.rb
+++ b/test/api/override_test.rb
@@ -1,28 +1,24 @@
require 'test_helper'
-class I18nOverrideTest < Test::Unit::TestCase
+class I18nOverrideTest < I18n::TestCase
module OverrideInverse
-
def translate(*args)
super(*args).reverse
end
alias :t :translate
-
end
module OverrideSignature
-
def translate(*args)
args.first + args[1]
end
alias :t :translate
-
end
def setup
+ super
@I18n = I18n.dup
@I18n.backend = I18n::Backend::Simple.new
- super
end
test "make sure modules can overwrite I18n methods" do
@@ -30,8 +26,7 @@ def setup
@I18n.backend.store_translations('en', :foo => 'bar')
assert_equal 'rab', @I18n.translate(:foo, :locale => 'en')
- # FIXME: this fails under 1.8.7
- # assert_equal 'rab', @I18n.t(:foo, :locale => 'en')
+ assert_equal 'rab', @I18n.t(:foo, :locale => 'en')
assert_equal 'rab', @I18n.translate!(:foo, :locale => 'en')
assert_equal 'rab', @I18n.t!(:foo, :locale => 'en')
end
@@ -44,5 +39,4 @@ def setup
@I18n.extend OverrideSignature
assert_equal 'HelloWelcome message on home page', @I18n.translate('Hello', 'Welcome message on home page', :tokenize => true) # tr8n example
end
-
end
diff --git a/test/api/pluralization_test.rb b/test/api/pluralization_test.rb
index 5da3a5ef..53004beb 100644
--- a/test/api/pluralization_test.rb
+++ b/test/api/pluralization_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class I18nPluralizationApiTest < Test::Unit::TestCase
+class I18nPluralizationApiTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Pluralization
end
diff --git a/test/api/simple_test.rb b/test/api/simple_test.rb
index 02d62058..3fd3a424 100644
--- a/test/api/simple_test.rb
+++ b/test/api/simple_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class I18nSimpleBackendApiTest < Test::Unit::TestCase
+class I18nSimpleBackendApiTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Pluralization
end
diff --git a/test/backend/cache_test.rb b/test/backend/cache_test.rb
index 39df10d4..bda05860 100644
--- a/test/backend/cache_test.rb
+++ b/test/backend/cache_test.rb
@@ -6,7 +6,7 @@
$stderr.puts "Skipping cache tests using ActiveSupport"
else
-class I18nBackendCacheTest < Test::Unit::TestCase
+class I18nBackendCacheTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Cache
end
@@ -15,9 +15,11 @@ def setup
I18n.backend = Backend.new
super
I18n.cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
+ I18n.cache_key_digest = nil
end
def teardown
+ super
I18n.cache_store = nil
end
@@ -36,6 +38,12 @@ def teardown
assert_equal 'Bar', I18n.t(:bar)
end
+ test "translate returns a cached false response" do
+ I18n.backend.expects(:lookup).never
+ I18n.cache_store.expects(:read).returns(false)
+ assert_equal false, I18n.t(:foo)
+ end
+
test "still raises MissingTranslationData but also caches it" do
assert_raise(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) }
assert_raise(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) }
@@ -59,10 +67,19 @@ def teardown
test "adds locale and hash of key and hash of options" do
options = { :bar=>1 }
- options_hash = I18n::Backend::Cache::USE_INSPECT_HASH ? options.inspect.hash : options.hash
+ options_hash = RUBY_VERSION <= "1.9" ? options.inspect.hash : options.hash
assert_equal "i18n//en/#{:foo.hash}/#{options_hash}", I18n.backend.send(:cache_key, :en, :foo, options)
end
+ test "cache_key uses configured digest method" do
+ md5 = Digest::MD5.new
+ options = { :bar=>1 }
+ options_hash = options.inspect
+ with_cache_key_digest(md5) do
+ assert_equal "i18n//en/#{md5.hexdigest(:foo.to_s)}/#{md5.hexdigest(options_hash)}", I18n.backend.send(:cache_key, :en, :foo, options)
+ end
+ end
+
test "keys should not be equal" do
interpolation_values1 = { :foo => 1, :bar => 2 }
interpolation_values2 = { :foo => 2, :bar => 1 }
@@ -80,6 +97,12 @@ def with_cache_namespace(namespace)
yield
I18n.cache_namespace = nil
end
+
+ def with_cache_key_digest(digest)
+ I18n.cache_key_digest = digest
+ yield
+ I18n.cache_key_digest = nil
+ end
end
end # AS cache check
diff --git a/test/backend/cascade_test.rb b/test/backend/cascade_test.rb
index 71fae50c..d1d0c4aa 100644
--- a/test/backend/cascade_test.rb
+++ b/test/backend/cascade_test.rb
@@ -1,11 +1,12 @@
require 'test_helper'
-class I18nBackendCascadeTest < Test::Unit::TestCase
+class I18nBackendCascadeTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Cascade
end
def setup
+ super
I18n.backend = Backend.new
store_translations(:en, :foo => 'foo', :bar => { :baz => 'baz' })
@cascade_options = { :step => 1, :offset => 1, :skip_root => false }
diff --git a/test/backend/chain_test.rb b/test/backend/chain_test.rb
index 67147be5..61f8ca36 100644
--- a/test/backend/chain_test.rb
+++ b/test/backend/chain_test.rb
@@ -1,12 +1,23 @@
require 'test_helper'
-class I18nBackendChainTest < Test::Unit::TestCase
+class I18nBackendChainTest < I18n::TestCase
def setup
+ super
@first = backend(:en => {
- :foo => 'Foo', :formats => { :short => 'short' }, :plural_1 => { :one => '%{count}' }, :dates => {:a => "A"}
+ :foo => 'Foo', :formats => {
+ :short => 'short',
+ :subformats => {:short => 'short'},
+ },
+ :plural_1 => { :one => '%{count}' },
+ :dates => {:a => "A"}
})
@second = backend(:en => {
- :bar => 'Bar', :formats => { :long => 'long' }, :plural_2 => { :one => 'one' }, :dates => {:a => "B", :b => "B"}
+ :bar => 'Bar', :formats => {
+ :long => 'long',
+ :subformats => {:long => 'long'},
+ },
+ :plural_2 => { :one => 'one' },
+ :dates => {:a => "B", :b => "B"}
})
@chain = I18n.backend = I18n::Backend::Chain.new(@first, @second)
end
@@ -38,11 +49,11 @@ def setup
assert_equal({}, I18n.t(:'i18n.transliterate.rule', :locale => 'en', :default => {}))
end
- test "namespace lookup collects results from all backends" do
- assert_equal({ :short => 'short', :long => 'long' }, I18n.t(:formats))
+ test "namespace lookup collects results from all backends and merges deep hashes" do
+ assert_equal({:long=>"long", :subformats=>{:long=>"long", :short=>"short"}, :short=>"short"}, I18n.t(:formats))
end
- test "namespace lookup collects results from all backends and does not overwrite" do
+ test "namespace lookup collects results from all backends and lets leftmost backend take priority" do
assert_equal({ :a => "A", :b => "B" }, I18n.t(:dates))
end
@@ -58,7 +69,11 @@ def setup
test "bulk lookup collects results from all backends" do
assert_equal ['Foo', 'Bar'], I18n.t([:foo, :bar])
assert_equal ['Foo', 'Bar', 'Bah'], I18n.t([:foo, :bar, :bah], :default => 'Bah')
- assert_equal [{ :short => 'short', :long => 'long' }, { :one => 'one' }, 'Bah'], I18n.t([:formats, :plural_2, :bah], :default => 'Bah')
+ assert_equal [{
+ :long=>"long",
+ :subformats=>{:long=>"long", :short=>"short"},
+ :short=>"short"}, {:one=>"one"},
+ "Bah"], I18n.t([:formats, :plural_2, :bah], :default => 'Bah')
end
test "store_translations options are not dropped while transfering to backend" do
diff --git a/test/backend/exceptions_test.rb b/test/backend/exceptions_test.rb
index fc0f557c..cc221669 100644
--- a/test/backend/exceptions_test.rb
+++ b/test/backend/exceptions_test.rb
@@ -1,7 +1,8 @@
require 'test_helper'
-class I18nBackendExceptionsTest < Test::Unit::TestCase
+class I18nBackendExceptionsTest < I18n::TestCase
def setup
+ super
I18n.backend = I18n::Backend::Simple.new
end
diff --git a/test/backend/fallbacks_test.rb b/test/backend/fallbacks_test.rb
index 2b17da94..a1d5a74a 100644
--- a/test/backend/fallbacks_test.rb
+++ b/test/backend/fallbacks_test.rb
@@ -1,15 +1,17 @@
require 'test_helper'
-class I18nBackendFallbacksTranslateTest < Test::Unit::TestCase
+class I18nBackendFallbacksTranslateTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Fallbacks
end
def setup
+ super
I18n.backend = Backend.new
store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en', :buz => 'Buz in :en')
store_translations(:de, :bar => 'Bar in :de', :baz => 'Baz in :de')
store_translations(:'de-DE', :baz => 'Baz in :de-DE')
+ store_translations(:'pt-BR', :baz => 'Baz in :pt-BR')
end
test "still returns an existing translation as usual" do
@@ -74,14 +76,24 @@ def setup
test "should ensure that default is not splitted on new line char" do
assert_equal "Default \n Bar", I18n.t(:missing_bar, :default => "Default \n Bar")
end
+
+ test "should not raise error when enforce_available_locales is true, :'pt' is missing and default is a Symbol" do
+ I18n.enforce_available_locales = true
+ begin
+ assert_equal 'Foo', I18n.t(:'model.attrs.foo', :locale => :'pt-BR', :default => [:'attrs.foo', "Foo"])
+ ensure
+ I18n.enforce_available_locales = false
+ end
+ end
end
-class I18nBackendFallbacksLocalizeTest < Test::Unit::TestCase
+class I18nBackendFallbacksLocalizeTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Fallbacks
end
def setup
+ super
I18n.backend = Backend.new
store_translations(:en, :date => { :formats => { :en => 'en' }, :day_names => %w(Sunday) })
store_translations(:de, :date => { :formats => { :de => 'de' } })
@@ -108,18 +120,79 @@ def setup
end
end
-class I18nBackendFallbacksWithChainTest < Test::Unit::TestCase
+class I18nBackendFallbacksWithChainTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Fallbacks
end
+ class Chain < I18n::Backend::Chain
+ include I18n::Backend::Fallbacks
+ end
+
def setup
+ super
backend = Backend.new
backend.store_translations(:de, :foo => 'FOO')
- I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, backend)
+ backend.store_translations(:'pt-BR', :foo => 'Baz in :pt-BR')
+ I18n.backend = Chain.new(I18n::Backend::Simple.new, backend)
end
test "falls back from de-DE to de when there is no translation for de-DE available" do
assert_equal 'FOO', I18n.t(:foo, :locale => :'de-DE')
end
+
+ test "falls back from de-DE to de when there is no translation for de-DE available when using arrays, too" do
+ assert_equal ['FOO', 'FOO'], I18n.t([:foo, :foo], :locale => :'de-DE')
+ end
+
+ test "should not raise error when enforce_available_locales is true, :'pt' is missing and default is a Symbol" do
+ I18n.enforce_available_locales = true
+ begin
+ assert_equal 'Foo', I18n.t(:'model.attrs.foo', :locale => :'pt-BR', :default => [:'attrs.foo', "Foo"])
+ ensure
+ I18n.enforce_available_locales = false
+ end
+ end
end
+
+class I18nBackendFallbacksExistsTest < I18n::TestCase
+ class Backend < I18n::Backend::Simple
+ include I18n::Backend::Fallbacks
+ end
+
+ def setup
+ super
+ I18n.backend = Backend.new
+ store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en')
+ store_translations(:de, :bar => 'Bar in :de')
+ store_translations(:'de-DE', :baz => 'Baz in :de-DE')
+ end
+
+ test "exists? given an existing key will return true" do
+ assert_equal true, I18n.exists?(:foo)
+ end
+
+ test "exists? given a non-existing key will return false" do
+ assert_equal false, I18n.exists?(:bogus)
+ end
+
+ test "exists? given an existing key and an existing locale will return true" do
+ assert_equal true, I18n.exists?(:foo, :en)
+ assert_equal true, I18n.exists?(:bar, :de)
+ end
+
+ test "exists? given a non-existing key and an existing locale will return false" do
+ assert_equal false, I18n.exists?(:bogus, :en)
+ assert_equal false, I18n.exists?(:bogus, :de)
+ end
+
+ test "exists? should return true given a key which is missing from the given locale and exists in a fallback locale" do
+ assert_equal true, I18n.exists?(:foo, :de)
+ assert_equal true, I18n.exists?(:foo, :'de-DE')
+ end
+
+ test "exists? should return false given a key which is missing from the given locale and all its fallback locales" do
+ assert_equal false, I18n.exists?(:baz, :de)
+ assert_equal false, I18n.exists?(:bogus, :'de-DE')
+ end
+end
\ No newline at end of file
diff --git a/test/backend/interpolation_compiler_test.rb b/test/backend/interpolation_compiler_test.rb
index f4d287a9..cffe28f9 100644
--- a/test/backend/interpolation_compiler_test.rb
+++ b/test/backend/interpolation_compiler_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class InterpolationCompilerTest < Test::Unit::TestCase
+class InterpolationCompilerTest < I18n::TestCase
Compiler = I18n::Backend::InterpolationCompiler::Compiler
def compile_and_interpolate(str, values = {})
@@ -95,18 +95,18 @@ def test_custom_missing_interpolation_argument_handler
end
end
-class I18nBackendInterpolationCompilerTest < Test::Unit::TestCase
+class I18nBackendInterpolationCompilerTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::InterpolationCompiler
end
-
+
include I18n::Tests::Interpolation
def setup
I18n.backend = Backend.new
super
end
-
+
# pre-compile default strings to make sure we are testing I18n::Backend::InterpolationCompiler
def interpolate(*args)
options = args.last.kind_of?(Hash) ? args.last : {}
@@ -115,5 +115,4 @@ def interpolate(*args)
end
super
end
-
end
diff --git a/test/backend/key_value_test.rb b/test/backend/key_value_test.rb
index 74c6b7d1..097780df 100644
--- a/test/backend/key_value_test.rb
+++ b/test/backend/key_value_test.rb
@@ -1,10 +1,8 @@
require 'test_helper'
-I18n::Tests.setup_rufus_tokyo
-
-class I18nBackendKeyValueTest < Test::Unit::TestCase
+class I18nBackendKeyValueTest < I18n::TestCase
def setup_backend!(subtree=true)
- I18n.backend = I18n::Backend::KeyValue.new(Rufus::Tokyo::Cabinet.new('*'), subtree)
+ I18n.backend = I18n::Backend::KeyValue.new({}, subtree)
store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' })
end
@@ -42,5 +40,4 @@ def assert_flattens(expected, nested, escape=true, subtree=true)
I18n.t("foo", :raise => true)
end
end
-
-end if defined?(Rufus::Tokyo::Cabinet)
+end if I18n::TestCase.key_value?
diff --git a/test/backend/memoize_test.rb b/test/backend/memoize_test.rb
index a8a2e11e..0fb9f904 100644
--- a/test/backend/memoize_test.rb
+++ b/test/backend/memoize_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-
-require 'backend/simple_test'
+# TODO: change back to "require 'backend/simple'" when dropping support to Ruby 1.8.7.
+require File.expand_path('../simple_test', __FILE__)
class I18nBackendMemoizeTest < I18nBackendSimpleTest
module MemoizeSpy
diff --git a/test/backend/metadata_test.rb b/test/backend/metadata_test.rb
index 584c7f65..44612cf0 100644
--- a/test/backend/metadata_test.rb
+++ b/test/backend/metadata_test.rb
@@ -1,11 +1,12 @@
require 'test_helper'
-class I18nBackendMetadataTest < Test::Unit::TestCase
+class I18nBackendMetadataTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Metadata
end
def setup
+ super
I18n.backend = Backend.new
store_translations(:en, :foo => 'Hi %{name}')
end
diff --git a/test/backend/pluralization_test.rb b/test/backend/pluralization_test.rb
index 9d883db7..12c5cbad 100644
--- a/test/backend/pluralization_test.rb
+++ b/test/backend/pluralization_test.rb
@@ -1,12 +1,13 @@
require 'test_helper'
-class I18nBackendPluralizationTest < Test::Unit::TestCase
+class I18nBackendPluralizationTest < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Pluralization
include I18n::Backend::Fallbacks
end
def setup
+ super
I18n.backend = Backend.new
@rule = lambda { |n| n == 1 ? :one : n == 0 || (2..10).include?(n % 100) ? :few : (11..19).include?(n % 100) ? :many : :other }
store_translations(:xx, :i18n => { :plural => { :rule => @rule } })
diff --git a/test/backend/simple_test.rb b/test/backend/simple_test.rb
index 515a1b98..f6f7886f 100644
--- a/test/backend/simple_test.rb
+++ b/test/backend/simple_test.rb
@@ -1,7 +1,8 @@
require 'test_helper'
-class I18nBackendSimpleTest < Test::Unit::TestCase
+class I18nBackendSimpleTest < I18n::TestCase
def setup
+ super
I18n.backend = I18n::Backend::Simple.new
I18n.load_path = [locales_dir + '/en.yml']
end
@@ -49,23 +50,23 @@ def setup
# storing translations
test "simple store_translations: stores translations, ... no, really :-)" do
- I18n.backend.store_translations :'en', :foo => 'bar'
+ store_translations :'en', :foo => 'bar'
assert_equal Hash[:'en', {:foo => 'bar'}], translations
end
test "simple store_translations: deep_merges with existing translations" do
- I18n.backend.store_translations :'en', :foo => {:bar => 'bar'}
- I18n.backend.store_translations :'en', :foo => {:baz => 'baz'}
+ store_translations :'en', :foo => {:bar => 'bar'}
+ store_translations :'en', :foo => {:baz => 'baz'}
assert_equal Hash[:'en', {:foo => {:bar => 'bar', :baz => 'baz'}}], translations
end
test "simple store_translations: converts the given locale to a Symbol" do
- I18n.backend.store_translations 'en', :foo => 'bar'
+ store_translations 'en', :foo => 'bar'
assert_equal Hash[:'en', {:foo => 'bar'}], translations
end
test "simple store_translations: converts keys to Symbols" do
- I18n.backend.store_translations 'en', 'foo' => {'bar' => 'bar', 'baz' => 'baz'}
+ store_translations 'en', 'foo' => {'bar' => 'bar', 'baz' => 'baz'}
assert_equal Hash[:'en', {:foo => {:bar => 'bar', :baz => 'baz'}}], translations
end
@@ -78,6 +79,6 @@ def setup
test "simple reload_translations: uninitializes the backend" do
I18n.backend.reload!
- assert_equal I18n.backend.initialized?, false
+ assert_equal false, I18n.backend.initialized?
end
end
diff --git a/test/backend/transliterator_test.rb b/test/backend/transliterator_test.rb
index a7f914e0..c40e2bbf 100644
--- a/test/backend/transliterator_test.rb
+++ b/test/backend/transliterator_test.rb
@@ -1,8 +1,9 @@
# encoding: utf-8
require 'test_helper'
-class I18nBackendTransliterator < Test::Unit::TestCase
+class I18nBackendTransliterator < I18n::TestCase
def setup
+ super
I18n.backend = I18n::Backend::Simple.new
@proc = lambda { |n| n.upcase }
@hash = { "ü" => "ue", "ö" => "oe", "a" => "a" }
@@ -55,11 +56,9 @@ def setup
assert_equal "abc#", @transliterator.transliterate("abcſ", "#")
end
- if RUBY_VERSION >= "1.9"
- test "default transliterator raises errors for invalid UTF-8" do
- assert_raise ArgumentError do
- @transliterator.transliterate("a\x92b")
- end
+ test "default transliterator raises errors for invalid UTF-8" do
+ assert_raise ArgumentError do
+ @transliterator.transliterate("a\x92b")
end
end
diff --git a/test/core_ext/hash_test.rb b/test/core_ext/hash_test.rb
index 25c57488..7325c50a 100644
--- a/test/core_ext/hash_test.rb
+++ b/test/core_ext/hash_test.rb
@@ -1,7 +1,7 @@
require 'test_helper'
require 'i18n/core_ext/hash'
-class I18nCoreExtHashInterpolationTest < Test::Unit::TestCase
+class I18nCoreExtHashInterpolationTest < I18n::TestCase
test "#deep_symbolize_keys" do
hash = { 'foo' => { 'bar' => { 'baz' => 'bar' } } }
expected = { :foo => { :bar => { :baz => 'bar' } } }
@@ -14,6 +14,18 @@ class I18nCoreExtHashInterpolationTest < Test::Unit::TestCase
assert_equal expected, hash.slice(:foo)
end
+ test "#slice non-existent key" do
+ hash = { :foo => 'bar', :baz => 'bar' }
+ expected = { :foo => 'bar' }
+ assert_equal expected, hash.slice(:foo, :not_here)
+ end
+
+ test "#slice maintains subclasses of Hash" do
+ klass = Class.new(Hash)
+ hash = klass[:foo, 'bar', :baz, 'bar']
+ assert_instance_of klass, hash.slice(:foo)
+ end
+
test "#except" do
hash = { :foo => 'bar', :baz => 'bar' }
expected = { :foo => 'bar' }
diff --git a/test/core_ext/string/interpolate_test.rb b/test/core_ext/string/interpolate_test.rb
deleted file mode 100644
index 993d454d..00000000
--- a/test/core_ext/string/interpolate_test.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-require 'test_helper'
-
-# thanks to Masao's String extensions these should work the same in
-# Ruby 1.8 (patched) and Ruby 1.9 (native)
-# some tests taken from Masao's tests
-# http://github.com/mutoh/gettext/blob/edbbe1fa8238fa12c7f26f2418403015f0270e47/test/test_string.rb
-
-class I18nCoreExtStringInterpolationTest < Test::Unit::TestCase
- test "String interpolates a single argument" do
- assert_equal "Masao", "%s" % "Masao"
- end
-
- test "String interpolates an array argument" do
- assert_equal "1 message", "%d %s" % [1, 'message']
- end
-
- test "String interpolates a hash argument w/ named placeholders" do
- assert_equal "Masao Mutoh", "%{first} %{last}" % { :first => 'Masao', :last => 'Mutoh' }
- end
-
- test "String interpolates a hash argument w/ named placeholders (reverse order)" do
- assert_equal "Mutoh, Masao", "%{last}, %{first}" % { :first => 'Masao', :last => 'Mutoh' }
- end
-
- test "String interpolates named placeholders with sprintf syntax" do
- assert_equal "10, 43.4", "%d, %.1f" % {:integer => 10, :float => 43.4}
- end
-
- test "String interpolates named placeholders with sprintf syntax, does not recurse" do
- assert_equal "%s", "%{msg}" % { :msg => '%s', :not_translated => 'should not happen' }
- end
-
- test "String interpolation does not replace anything when no placeholders are given" do
- assert_equal("aaa", "aaa" % {:num => 1})
- assert_equal("bbb", "bbb" % [1])
- end
-
- test "String interpolation sprintf behaviour equals Ruby 1.9 behaviour" do
- assert_equal("1", "%d" % {:num => 1})
- assert_equal("0b1", "%#b" % {:num => 1})
- assert_equal("foo", "%s" % {:msg => "foo"})
- assert_equal("1.000000", "%f" % {:num => 1.0})
- assert_equal(" 1", "%3.0f" % {:num => 1.0})
- assert_equal("100.00", "%2.2f" % {:num => 100.0})
- assert_equal("0x64", "%#x" % {:num => 100.0})
- assert_raise(ArgumentError) { "%,d" % {:num => 100} }
- assert_raise(ArgumentError) { "%/d" % {:num => 100} }
- end
-
- test "String interpolation old-style sprintf still works" do
- assert_equal("foo 1.000000", "%s %f" % ["foo", 1.0])
- end
-
- test "String interpolation raises an ArgumentError when the string has extra placeholders (Array)" do
- assert_raise(ArgumentError) do # Ruby 1.9 msg: "too few arguments"
- "%s %s" % %w(Masao)
- end
- end
-
- test "String interpolation raises a KeyError when the string has extra placeholders (Hash)" do
- assert_raise(KeyError) do # Ruby 1.9 msg: "key not found"
- "%{first} %{last}" % { :first => 'Masao' }
- end
- end
-
- test "String interpolation does not raise when passed extra values (Array)" do
- assert_nothing_raised do
- assert_equal "Masao", "%s" % %w(Masao Mutoh)
- end
- end
-
- test "String interpolation does not raise when passed extra values (Hash)" do
- assert_nothing_raised do
- assert_equal "Masao Mutoh", "%{first} %{last}" % { :first => 'Masao', :last => 'Mutoh', :salutation => 'Mr.' }
- end
- end
-
- test "% acts as escape character in String interpolation" do
- assert_equal "%{first}", "%%{first}" % { :first => 'Masao' }
- assert_equal("% 1", "%% %d" % {:num => 1.0})
- assert_equal("%{num} %d", "%%{num} %%d" % {:num => 1})
- end
-
- test "% can be used in Ruby's own sprintf behavior" do
- assert_equal "70%", "%d%%" % 70
- assert_equal "70-100%", "%d-%d%%" % [70, 100]
- assert_equal "+2.30%", "%+.2f%%" % 2.3
- end
-
- def test_sprintf_mix_unformatted_and_formatted_named_placeholders
- assert_equal("foo 1.000000", "%{name} %f" % {:name => "foo", :num => 1.0})
- end
-
- def test_string_interpolation_raises_an_argument_error_when_mixing_named_and_unnamed_placeholders
- assert_raise(ArgumentError) { "%{name} %f" % [1.0] }
- assert_raise(ArgumentError) { "%{name} %f" % [1.0, 2.0] }
- end
-end
-
diff --git a/test/gettext/api_test.rb b/test/gettext/api_test.rb
index 947b5a23..2cd157c0 100644
--- a/test/gettext/api_test.rb
+++ b/test/gettext/api_test.rb
@@ -4,8 +4,9 @@
include I18n::Gettext::Helpers
-class I18nGettextApiTest < Test::Unit::TestCase
+class I18nGettextApiTest < I18n::TestCase
def setup
+ super
I18n.locale = :en
I18n.backend.store_translations :de, {
'Hi Gettext!' => 'Hallo Gettext!',
@@ -17,6 +18,13 @@ def setup
}, :separator => '|'
end
+ # N_
+ def test_N_returns_original_msg
+ assert_equal 'foo|bar', N_('foo|bar')
+ I18n.locale = :de
+ assert_equal 'Hi Gettext!', N_('Hi Gettext!')
+ end
+
# gettext
def test_gettext_uses_msg_as_default
assert_equal 'Hi Gettext!', _('Hi Gettext!')
diff --git a/test/gettext/backend_test.rb b/test/gettext/backend_test.rb
index 39c64b35..30254e6b 100644
--- a/test/gettext/backend_test.rb
+++ b/test/gettext/backend_test.rb
@@ -2,100 +2,91 @@
require 'test_helper'
-# apparently Ruby 1.9.1p129 has encoding problems with the gettext po parser
-unless RUBY_VERSION == '1.9.1' && RUBY_PATCHLEVEL <= 129
+class I18nGettextBackendTest < I18n::TestCase
+ include I18n::Gettext::Helpers
- class I18nGettextBackendTest < Test::Unit::TestCase
- include I18n::Gettext::Helpers
-
- class Backend < I18n::Backend::Simple
- include I18n::Backend::Gettext
- end
-
- def setup
- I18n.backend = Backend.new
- I18n.locale = :en
- I18n.load_path = ["#{locales_dir}/de.po"]
- @old_separator, I18n.default_separator = I18n.default_separator, '|'
- end
+ class Backend < I18n::Backend::Simple
+ include I18n::Backend::Gettext
+ end
- def teardown
- I18n.load_path = nil
- I18n.backend = nil
- I18n.default_separator = @old_separator
- end
+ def setup
+ super
+ I18n.backend = Backend.new
+ I18n.locale = :en
+ I18n.load_path = ["#{locales_dir}/de.po"]
+ I18n.default_separator = '|'
+ end
- def test_backend_loads_po_file
- I18n.backend.send(:init_translations)
- assert I18n.backend.send(:translations)[:de][:"Axis"]
- end
+ def test_backend_loads_po_file
+ I18n.backend.send(:init_translations)
+ assert I18n.backend.send(:translations)[:de][:"Axis"]
+ end
- def test_looks_up_a_translation
- I18n.locale = :de
- assert_equal 'Auto', gettext('car')
- end
+ def test_looks_up_a_translation
+ I18n.locale = :de
+ assert_equal 'Auto', gettext('car')
+ end
- def test_uses_default_translation
- assert_equal 'car', gettext('car')
- end
+ def test_uses_default_translation
+ assert_equal 'car', gettext('car')
+ end
- def test_looks_up_a_namespaced_translation
- I18n.locale = :de
- assert_equal 'Räderzahl', sgettext('Car|Wheels count')
- assert_equal 'Räderzahl', pgettext('Car', 'Wheels count')
- assert_equal 'Räderzahl!', pgettext('New car', 'Wheels count')
- end
+ def test_looks_up_a_namespaced_translation
+ I18n.locale = :de
+ assert_equal 'Räderzahl', sgettext('Car|Wheels count')
+ assert_equal 'Räderzahl', pgettext('Car', 'Wheels count')
+ assert_equal 'Räderzahl!', pgettext('New car', 'Wheels count')
+ end
- def test_uses_namespaced_default_translation
- assert_equal 'Wheels count', sgettext('Car|Wheels count')
- assert_equal 'Wheels count', pgettext('Car', 'Wheels count')
- assert_equal 'Wheels count', pgettext('New car', 'Wheels count')
- end
+ def test_uses_namespaced_default_translation
+ assert_equal 'Wheels count', sgettext('Car|Wheels count')
+ assert_equal 'Wheels count', pgettext('Car', 'Wheels count')
+ assert_equal 'Wheels count', pgettext('New car', 'Wheels count')
+ end
- def test_pluralizes_entry
- I18n.locale = :de
- assert_equal 'Achse', ngettext('Axis', 'Axis', 1)
- assert_equal 'Achsen', ngettext('Axis', 'Axis', 2)
- end
+ def test_pluralizes_entry
+ I18n.locale = :de
+ assert_equal 'Achse', ngettext('Axis', 'Axis', 1)
+ assert_equal 'Achsen', ngettext('Axis', 'Axis', 2)
+ end
- def test_pluralizes_default_entry
- assert_equal 'Axis', ngettext('Axis', 'Axis', 1)
- assert_equal 'Axis', ngettext('Axis', 'Axis', 2)
- end
+ def test_pluralizes_default_entry
+ assert_equal 'Axis', ngettext('Axis', 'Axis', 1)
+ assert_equal 'Axis', ngettext('Axis', 'Axis', 2)
+ end
- def test_pluralizes_namespaced_entry
- I18n.locale = :de
- assert_equal 'Rad', nsgettext('Car|wheel', 'wheels', 1)
- assert_equal 'Räder', nsgettext('Car|wheel', 'wheels', 2)
- assert_equal 'Rad', npgettext('Car', 'wheel', 'wheels', 1)
- assert_equal 'Räder', npgettext('Car', 'wheel', 'wheels', 2)
- assert_equal 'Rad!', npgettext('New car', 'wheel', 'wheels', 1)
- assert_equal 'Räder!', npgettext('New car', 'wheel', 'wheels', 2)
- end
+ def test_pluralizes_namespaced_entry
+ I18n.locale = :de
+ assert_equal 'Rad', nsgettext('Car|wheel', 'wheels', 1)
+ assert_equal 'Räder', nsgettext('Car|wheel', 'wheels', 2)
+ assert_equal 'Rad', npgettext('Car', 'wheel', 'wheels', 1)
+ assert_equal 'Räder', npgettext('Car', 'wheel', 'wheels', 2)
+ assert_equal 'Rad!', npgettext('New car', 'wheel', 'wheels', 1)
+ assert_equal 'Räder!', npgettext('New car', 'wheel', 'wheels', 2)
+ end
- def test_pluralizes_namespaced_default_entry
- assert_equal 'wheel', nsgettext('Car|wheel', 'wheels', 1)
- assert_equal 'wheels', nsgettext('Car|wheel', 'wheels', 2)
- assert_equal 'wheel', npgettext('Car', 'wheel', 'wheels', 1)
- assert_equal 'wheels', npgettext('Car', 'wheel', 'wheels', 2)
- assert_equal 'wheel', npgettext('New car', 'wheel', 'wheels', 1)
- assert_equal 'wheels', npgettext('New car', 'wheel', 'wheels', 2)
- end
+ def test_pluralizes_namespaced_default_entry
+ assert_equal 'wheel', nsgettext('Car|wheel', 'wheels', 1)
+ assert_equal 'wheels', nsgettext('Car|wheel', 'wheels', 2)
+ assert_equal 'wheel', npgettext('Car', 'wheel', 'wheels', 1)
+ assert_equal 'wheels', npgettext('Car', 'wheel', 'wheels', 2)
+ assert_equal 'wheel', npgettext('New car', 'wheel', 'wheels', 1)
+ assert_equal 'wheels', npgettext('New car', 'wheel', 'wheels', 2)
+ end
- def test_pluralizes_namespaced_entry_with_alternative_syntax
- I18n.locale = :de
- assert_equal 'Rad', nsgettext(['Car|wheel', 'wheels'], 1)
- assert_equal 'Räder', nsgettext(['Car|wheel', 'wheels'], 2)
- assert_equal 'Rad', npgettext('Car', ['wheel', 'wheels'], 1)
- assert_equal 'Räder', npgettext('Car', ['wheel', 'wheels'], 2)
- assert_equal 'Rad!', npgettext('New car', ['wheel', 'wheels'], 1)
- assert_equal 'Räder!', npgettext('New car', ['wheel', 'wheels'], 2)
- end
+ def test_pluralizes_namespaced_entry_with_alternative_syntax
+ I18n.locale = :de
+ assert_equal 'Rad', nsgettext(['Car|wheel', 'wheels'], 1)
+ assert_equal 'Räder', nsgettext(['Car|wheel', 'wheels'], 2)
+ assert_equal 'Rad', npgettext('Car', ['wheel', 'wheels'], 1)
+ assert_equal 'Räder', npgettext('Car', ['wheel', 'wheels'], 2)
+ assert_equal 'Rad!', npgettext('New car', ['wheel', 'wheels'], 1)
+ assert_equal 'Räder!', npgettext('New car', ['wheel', 'wheels'], 2)
+ end
- def test_ngettextpluralizes_entry_with_dots
- I18n.locale = :de
- assert_equal 'Auf 1 Achse.', n_("On %{count} wheel.", "On %{count} wheels.", 1)
- assert_equal 'Auf 2 Achsen.', n_("On %{count} wheel.", "On %{count} wheels.", 2)
- end
+ def test_ngettextpluralizes_entry_with_dots
+ I18n.locale = :de
+ assert_equal 'Auf 1 Achse.', n_("On %{count} wheel.", "On %{count} wheels.", 1)
+ assert_equal 'Auf 2 Achsen.', n_("On %{count} wheel.", "On %{count} wheels.", 2)
end
end
diff --git a/test/i18n/exceptions_test.rb b/test/i18n/exceptions_test.rb
index 098eefe6..3e528c64 100644
--- a/test/i18n/exceptions_test.rb
+++ b/test/i18n/exceptions_test.rb
@@ -1,9 +1,9 @@
require 'test_helper'
-class I18nExceptionsTest < Test::Unit::TestCase
+class I18nExceptionsTest < I18n::TestCase
def test_invalid_locale_stores_locale
force_invalid_locale
- rescue I18n::ArgumentError => e
+ rescue I18n::ArgumentError => exception
assert_nil exception.locale
end
@@ -13,6 +13,11 @@ def test_invalid_locale_stores_locale
end
end
+ test "MissingTranslation can be initialized without options" do
+ exception = I18n::MissingTranslation.new(:en, 'foo')
+ assert_equal({}, exception.options)
+ end
+
test "MissingTranslationData exception stores locale, key and options" do
force_missing_translation_data do |exception|
assert_equal 'de', exception.locale
@@ -27,21 +32,6 @@ def test_invalid_locale_stores_locale
end
end
- test "MissingTranslationData html_message is a span with the titlelized last key token" do
- exception = I18n::MissingTranslationData.new(:de, :foo, :scope => :bar)
- assert_equal 'Foo', exception.html_message
- end
-
- test "MissingTranslationData html_message html escapes key names" do
- exception = I18n::MissingTranslationData.new(:de, '', :scope => '')
- assert_equal '<Script>Evil</Script>', exception.html_message
- end
-
- test "ExceptionHandler returns the html_message if :rescue_format => :html was given" do
- message = force_missing_translation_data(:rescue_format => :html)
- assert_equal 'Foo', message
- end
-
test "InvalidPluralizationData stores entry and count" do
force_invalid_pluralization_data do |exception|
assert_equal [:bar], exception.entry
@@ -81,6 +71,10 @@ def test_invalid_locale_stores_locale
assert_equal 'reserved key :scope used in "%{scope}"', exception.message
end
end
+
+ test "MissingTranslationData#new can be initialized with just two arguments" do
+ assert I18n::MissingTranslationData.new('en', 'key')
+ end
private
@@ -91,28 +85,28 @@ def force_invalid_locale
end
def force_missing_translation_data(options = {})
- I18n.backend.store_translations('de', :bar => nil)
+ store_translations('de', :bar => nil)
I18n.translate(:foo, options.merge(:scope => :bar, :locale => :de))
rescue I18n::ArgumentError => e
block_given? ? yield(e) : raise(e)
end
def force_invalid_pluralization_data
- I18n.backend.store_translations('de', :foo => [:bar])
+ store_translations('de', :foo => [:bar])
I18n.translate(:foo, :count => 1, :locale => :de)
rescue I18n::ArgumentError => e
block_given? ? yield(e) : raise(e)
end
def force_missing_interpolation_argument
- I18n.backend.store_translations('de', :foo => "%{bar}")
+ store_translations('de', :foo => "%{bar}")
I18n.translate(:foo, :baz => 'baz', :locale => :de)
rescue I18n::ArgumentError => e
block_given? ? yield(e) : raise(e)
end
def force_reserved_interpolation_key
- I18n.backend.store_translations('de', :foo => "%{scope}")
+ store_translations('de', :foo => "%{scope}")
I18n.translate(:foo, :baz => 'baz', :locale => :de)
rescue I18n::ArgumentError => e
block_given? ? yield(e) : raise(e)
diff --git a/test/i18n/interpolate_test.rb b/test/i18n/interpolate_test.rb
index 7041b322..78e54d3b 100644
--- a/test/i18n/interpolate_test.rb
+++ b/test/i18n/interpolate_test.rb
@@ -1,10 +1,9 @@
require 'test_helper'
-require 'i18n/core_ext/string/interpolate'
# thanks to Masao's String extensions, some tests taken from Masao's tests
# http://github.com/mutoh/gettext/blob/edbbe1fa8238fa12c7f26f2418403015f0270e47/test/test_string.rb
-class I18nInterpolateTest < Test::Unit::TestCase
+class I18nInterpolateTest < I18n::TestCase
test "String interpolates a hash argument w/ named placeholders" do
assert_equal "Masao Mutoh", I18n.interpolate("%{first} %{last}", :first => 'Masao', :last => 'Mutoh' )
end
@@ -58,10 +57,22 @@ class I18nInterpolateTest < Test::Unit::TestCase
def test_sprintf_mix_unformatted_and_formatted_named_placeholders
assert_equal "foo 1.000000", I18n.interpolate("%{name} %f", :name => "foo", :num => 1.0)
end
+
+ class RailsSafeBuffer < String
+
+ def gsub(*args, &block)
+ to_str.gsub(*args, &block)
+ end
+
+ end
+ test "with String subclass that redefined gsub method" do
+ assert_equal "Hello mars world", I18n.interpolate(RailsSafeBuffer.new("Hello %{planet} world"), :planet => 'mars')
+ end
end
-class I18nMissingInterpolationCustomHandlerTest < Test::Unit::TestCase
+class I18nMissingInterpolationCustomHandlerTest < I18n::TestCase
def setup
+ super
@old_handler = I18n.config.missing_interpolation_argument_handler
I18n.config.missing_interpolation_argument_handler = lambda do |key, values, string|
"missing key is #{key}, values are #{values.inspect}, given string is '#{string}'"
@@ -70,6 +81,7 @@ def setup
def teardown
I18n.config.missing_interpolation_argument_handler = @old_handler
+ super
end
test "String interpolation can use custom missing interpolation handler" do
diff --git a/test/i18n/load_path_test.rb b/test/i18n/load_path_test.rb
index 26d086ab..804aa88f 100644
--- a/test/i18n/load_path_test.rb
+++ b/test/i18n/load_path_test.rb
@@ -1,7 +1,8 @@
require 'test_helper'
-class I18nLoadPathTest < Test::Unit::TestCase
+class I18nLoadPathTest < I18n::TestCase
def setup
+ super
I18n.locale = :en
I18n.backend = I18n::Backend::Simple.new
store_translations(:en, :foo => {:bar => 'bar', :baz => 'baz'})
diff --git a/test/i18n_test.rb b/test/i18n_test.rb
index cffa5df9..4288d8f1 100644
--- a/test/i18n_test.rb
+++ b/test/i18n_test.rb
@@ -1,10 +1,11 @@
# encoding: utf-8
require 'test_helper'
-class I18nTest < Test::Unit::TestCase
+class I18nTest < I18n::TestCase
def setup
- I18n.backend.store_translations(:'en', :currency => { :format => { :separator => '.', :delimiter => ',', } })
- I18n.backend.store_translations(:'nl', :currency => { :format => { :separator => ',', :delimiter => '.', } })
+ super
+ store_translations(:en, :currency => { :format => { :separator => '.', :delimiter => ',', } })
+ store_translations(:nl, :currency => { :format => { :separator => ',', :delimiter => '.', } })
end
test "exposes its VERSION constant" do
@@ -37,6 +38,10 @@ def setup
end
end
+ test "default_locale= doesn't ignore junk" do
+ assert_raise(NoMethodError) { I18n.default_locale = Class }
+ end
+
test "raises an I18n::InvalidLocale exception when setting an unavailable default locale" do
begin
I18n.config.enforce_available_locales = true
@@ -57,6 +62,10 @@ def setup
I18n.locale = :en
end
+ test "locale= doesn't ignore junk" do
+ assert_raise(NoMethodError) { I18n.locale = Class }
+ end
+
test "raises an I18n::InvalidLocale exception when setting an unavailable locale" do
begin
I18n.config.enforce_available_locales = true
@@ -219,6 +228,23 @@ def setup
end
end
+ test "available_locales can be replaced at runtime" do
+ begin
+ I18n.config.enforce_available_locales = true
+ assert_raise(I18n::InvalidLocale) { I18n.t(:foo, :locale => 'klingon') }
+ old_locales, I18n.config.available_locales = I18n.config.available_locales, [:klingon]
+ I18n.t(:foo, :locale => 'klingon')
+ ensure
+ I18n.config.enforce_available_locales = false
+ I18n.config.available_locales = old_locales
+ end
+ end
+
+ test "available_locales_set should return a set" do
+ assert_equal Set, I18n.config.available_locales_set.class
+ assert_equal I18n.config.available_locales.size * 2, I18n.config.available_locales_set.size
+ end
+
test "exists? given an existing key will return true" do
assert_equal true, I18n.exists?(:currency)
end
@@ -255,6 +281,10 @@ def setup
assert_raise(I18n::ArgumentError) { I18n.l nil }
end
+ test "localize given nil and default returns default" do
+ assert_equal nil, I18n.l(nil, :default => nil)
+ end
+
test "localize given an Object raises an I18n::ArgumentError" do
assert_raise(I18n::ArgumentError) { I18n.l Object.new }
end
@@ -374,4 +404,42 @@ def call(exception, locale, key, options); key; end
I18n.config.enforce_available_locales = false
end
end
+
+ test 'I18n.reload! reloads the set of locales that are enforced' do
+ begin
+ # Clear the backend that affects the available locales and somehow can remain
+ # set from the last running test.
+ # For instance, it contains enough translations to cause a false positive with
+ # this test when ran with --seed=50992
+ I18n.backend = I18n::Backend::Simple.new
+
+ assert !I18n.available_locales.include?(:de), "Available locales should not include :de at this point"
+
+ I18n.enforce_available_locales = true
+
+ assert_raise(I18n::InvalidLocale) { I18n.default_locale = :de }
+ assert_raise(I18n::InvalidLocale) { I18n.locale = :de }
+
+ store_translations(:de, :foo => 'Foo in :de')
+
+ assert_raise(I18n::InvalidLocale) { I18n.default_locale = :de }
+ assert_raise(I18n::InvalidLocale) { I18n.locale = :de }
+
+ I18n.reload!
+
+ store_translations(:en, :foo => 'Foo in :en')
+ store_translations(:de, :foo => 'Foo in :de')
+ store_translations(:pl, :foo => 'Foo in :pl')
+
+ assert I18n.available_locales.include?(:de), ":de should now be allowed"
+ assert I18n.available_locales.include?(:en), ":en should now be allowed"
+ assert I18n.available_locales.include?(:pl), ":pl should now be allowed"
+
+ assert_nothing_raised { I18n.default_locale = I18n.locale = :en }
+ assert_nothing_raised { I18n.default_locale = I18n.locale = :de }
+ assert_nothing_raised { I18n.default_locale = I18n.locale = :pl }
+ ensure
+ I18n.enforce_available_locales = false
+ end
+ end
end
diff --git a/test/locale/fallbacks_test.rb b/test/locale/fallbacks_test.rb
index ca5e9427..7a438523 100644
--- a/test/locale/fallbacks_test.rb
+++ b/test/locale/fallbacks_test.rb
@@ -2,11 +2,7 @@
include I18n::Locale
-class I18nFallbacksDefaultsTest < Test::Unit::TestCase
- def teardown
- I18n.default_locale = :en
- end
-
+class I18nFallbacksDefaultsTest < I18n::TestCase
test "defaults reflect the I18n.default_locale if no default has been set manually" do
I18n.default_locale = :'en-US'
fallbacks = Fallbacks.new
@@ -26,8 +22,9 @@ def teardown
end
end
-class I18nFallbacksComputationTest < Test::Unit::TestCase
+class I18nFallbacksComputationTest < I18n::TestCase
def setup
+ super
@fallbacks = Fallbacks.new(:'en-US')
end
diff --git a/test/locale/tag/rfc4646_test.rb b/test/locale/tag/rfc4646_test.rb
index 11180493..a0f42864 100644
--- a/test/locale/tag/rfc4646_test.rb
+++ b/test/locale/tag/rfc4646_test.rb
@@ -1,7 +1,7 @@
# encoding: utf-8
require 'test_helper'
-class I18nLocaleTagRfc4646ParserTest < Test::Unit::TestCase
+class I18nLocaleTagRfc4646ParserTest < I18n::TestCase
include I18n::Locale
test "Rfc4646::Parser given a valid tag 'de' returns an array of subtags" do
@@ -31,10 +31,11 @@ class I18nLocaleTagRfc4646ParserTest < Test::Unit::TestCase
# Tag for the locale 'de-Latn-DE-Variant-a-ext-x-phonebk-i-klingon'
-class I18nLocaleTagSubtagsTest < Test::Unit::TestCase
+class I18nLocaleTagSubtagsTest < I18n::TestCase
include I18n::Locale
def setup
+ super
subtags = %w(de Latn DE variant a-ext x-phonebk i-klingon)
@tag = Tag::Rfc4646.new(*subtags)
end
@@ -78,7 +79,7 @@ def setup
# Tag inheritance
-class I18nLocaleTagSubtagsTest < Test::Unit::TestCase
+class I18nLocaleTagSubtagsTest < I18n::TestCase
test "#parent returns 'de-Latn-DE-variant-a-ext-x-phonebk' as the parent of 'de-Latn-DE-variant-a-ext-x-phonebk-i-klingon'" do
tag = Tag::Rfc4646.new(*%w(de Latn DE variant a-ext x-phonebk i-klingon))
assert_equal 'de-Latn-DE-variant-a-ext-x-phonebk', tag.parent.to_s
diff --git a/test/locale/tag/simple_test.rb b/test/locale/tag/simple_test.rb
index ed2f76b4..002c63d2 100644
--- a/test/locale/tag/simple_test.rb
+++ b/test/locale/tag/simple_test.rb
@@ -1,7 +1,7 @@
# encoding: utf-8
require 'test_helper'
-class I18nLocaleTagSimpleTest < Test::Unit::TestCase
+class I18nLocaleTagSimpleTest < I18n::TestCase
include I18n::Locale
test "returns 'de' as the language subtag in lowercase" do
diff --git a/test/run_all.rb b/test/run_all.rb
index 0c31db7c..64ff743d 100644
--- a/test/run_all.rb
+++ b/test/run_all.rb
@@ -1,21 +1,20 @@
def bundle_check
- `bundle check` == "The Gemfile's dependencies are satisfied\n"
+ `bundle check` == "Resolving dependencies...\nThe Gemfile's dependencies are satisfied\n"
end
-command = 'ruby -w -Ilib -Itest test/all.rb'
-gemfiles = %w(ci/Gemfile.rails-3.x ci/Gemfile.rails-2.3.x ci/Gemfile.no-rails)
+def execute(command)
+ puts command
+ system command
+end
-results = gemfiles.map do |gemfile|
- puts "BUNDLE_GEMFILE=#{gemfile}"
- ENV['BUNDLE_GEMFILE'] = gemfile
+gemfiles = %w(Gemfile) + Dir['gemfiles/Gemfile*'].reject { |f| f.end_with?('.lock') }
- unless bundle_check
- puts "bundle install"
- system('bundle install')
- end
+results = gemfiles.map do |gemfile|
+ puts "\nBUNDLE_GEMFILE=#{gemfile}"
+ ENV['BUNDLE_GEMFILE'] = File.expand_path("../../#{gemfile}", __FILE__)
- puts command
- system('ruby -w -Ilib -Itest test/all.rb')
+ execute 'bundle install' unless bundle_check
+ execute 'bundle exec rake test'
end
-exit(results.inject(true) { |a, b| a && b })
+exit results.all?
diff --git a/test/test_data/locales/plurals.rb b/test/test_data/locales/plurals.rb
index 835e28f5..f4002851 100644
--- a/test/test_data/locales/plurals.rb
+++ b/test/test_data/locales/plurals.rb
@@ -74,7 +74,7 @@
:or => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } },
:pa => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } },
:pap => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } },
- :pl => { :i18n => { :plural => { :keys => [:one, :few, :other], :rule => lambda { |n| n == 1 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : :other } } } },
+ :pl => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n == 1 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : (n != 1 && [0, 1].include?(n % 10)) || [5, 6, 7, 8, 9].include?(n % 10) || [12, 13, 14].include?(n % 100) ? :many : :other } } } },
:ps => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } },
:pt => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } },
:"pt-PT" => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } },
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 982dd2d6..dabb6a7b 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -1,38 +1,51 @@
$KCODE = 'u' if RUBY_VERSION <= '1.9'
-require 'rubygems'
-require 'test/unit'
-
-# Do not load the i18n gem from libraries like active_support.
-#
-# This is required for testing against Rails 2.3 because active_support/vendor.rb#24 tries
-# to load I18n using the gem method. Instead, we want to test the local library of course.
-alias :gem_for_ruby_19 :gem # for 1.9. gives a super ugly seg fault otherwise
-def gem(gem_name, *version_requirements)
- gem_name =='i18n' ? puts("skipping loading the i18n gem ...") : super
+require 'minitest/autorun'
+TEST_CASE = defined?(Minitest::Test) ? Minitest::Test : MiniTest::Unit::TestCase
+
+# TODO: Remove these aliases and update tests accordingly.
+class TEST_CASE
+ alias :assert_raise :assert_raises
+ alias :assert_not_equal :refute_equal
+
+ def assert_nothing_raised(*args)
+ yield
+ end
end
require 'bundler/setup'
require 'i18n'
-require 'mocha'
+require 'mocha/setup'
require 'test_declarative'
-class Test::Unit::TestCase
+class I18n::TestCase < TEST_CASE
+ def self.key_value?
+ defined?(ActiveSupport)
+ end
+
+ def setup
+ super
+ I18n.enforce_available_locales = false
+ end
+
def teardown
I18n.locale = nil
- I18n.default_locale = :en
- I18n.load_path = []
+ I18n.default_locale = nil
+ I18n.load_path = nil
I18n.available_locales = nil
I18n.backend = nil
+ I18n.default_separator = nil
+ I18n.enforce_available_locales = true
+ super
end
+ protected
+
def translations
I18n.backend.instance_variable_get(:@translations)
end
- def store_translations(*args)
- data = args.pop
- locale = args.pop || :en
+ def store_translations(locale, data)
I18n.backend.store_translations(locale, data)
end
@@ -40,17 +53,3 @@ def locales_dir
File.dirname(__FILE__) + '/test_data/locales'
end
end
-
-module Kernel
- def setup_rufus_tokyo
- require 'rufus/tokyo'
- rescue LoadError => e
- puts "can't use KeyValue backend because: #{e.message}"
- end
-end
-
-Object.class_eval do
- def meta_class
- class << self; self; end
- end
-end unless Object.method_defined?(:meta_class)