i18n 0.5.0beta1 → 0.5.0beta2

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

Potentially problematic release.


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

Files changed (62) hide show
  1. data/README.textile +4 -17
  2. data/ci/Gemfile.no-rails +5 -0
  3. data/ci/Gemfile.no-rails.lock +17 -0
  4. data/ci/Gemfile.rails-2.3.x +9 -0
  5. data/ci/Gemfile.rails-2.3.x.lock +26 -0
  6. data/ci/Gemfile.rails-3.x +9 -0
  7. data/ci/Gemfile.rails-3.x.lock +26 -0
  8. data/lib/i18n.rb +4 -8
  9. data/lib/i18n/backend.rb +0 -1
  10. data/lib/i18n/backend/base.rb +4 -32
  11. data/lib/i18n/backend/gettext.rb +3 -3
  12. data/lib/i18n/backend/interpolation_compiler.rb +1 -1
  13. data/lib/i18n/backend/metadata.rb +1 -1
  14. data/lib/i18n/config.rb +1 -1
  15. data/lib/i18n/core_ext/kernel/surpress_warnings.rb +9 -0
  16. data/lib/i18n/core_ext/string/interpolate.rb +0 -96
  17. data/lib/i18n/exceptions.rb +0 -6
  18. data/lib/i18n/interpolate/ruby.rb +31 -0
  19. data/lib/i18n/locale/fallbacks.rb +3 -3
  20. data/lib/i18n/tests/localization/procs.rb +32 -19
  21. data/lib/i18n/tests/localization/time.rb +2 -2
  22. data/lib/i18n/version.rb +1 -1
  23. data/test/all.rb +8 -0
  24. data/test/api/all_features_test.rb +58 -0
  25. data/test/api/cascade_test.rb +28 -0
  26. data/test/api/chain_test.rb +24 -0
  27. data/test/api/fallbacks_test.rb +30 -0
  28. data/test/api/key_value_test.rb +28 -0
  29. data/test/api/memoize_test.rb +60 -0
  30. data/test/api/pluralization_test.rb +30 -0
  31. data/test/api/simple_test.rb +28 -0
  32. data/test/backend/cache_test.rb +83 -0
  33. data/test/backend/cascade_test.rb +85 -0
  34. data/test/backend/chain_test.rb +67 -0
  35. data/test/backend/exceptions_test.rb +23 -0
  36. data/test/backend/fallbacks_test.rb +116 -0
  37. data/test/backend/interpolation_compiler_test.rb +102 -0
  38. data/test/backend/key_value_test.rb +46 -0
  39. data/test/backend/memoize_test.rb +47 -0
  40. data/test/backend/metadata_test.rb +67 -0
  41. data/test/backend/pluralization_test.rb +44 -0
  42. data/test/backend/simple_test.rb +79 -0
  43. data/test/backend/transliterator_test.rb +81 -0
  44. data/test/core_ext/hash_test.rb +30 -0
  45. data/test/gettext/api_test.rb +206 -0
  46. data/test/gettext/backend_test.rb +93 -0
  47. data/test/i18n/exceptions_test.rb +116 -0
  48. data/test/i18n/interpolate_test.rb +60 -0
  49. data/test/i18n/load_path_test.rb +26 -0
  50. data/test/i18n_test.rb +236 -0
  51. data/test/locale/fallbacks_test.rb +124 -0
  52. data/test/locale/tag/rfc4646_test.rb +142 -0
  53. data/test/locale/tag/simple_test.rb +32 -0
  54. data/test/run_all.rb +21 -0
  55. data/test/test_data/locales/de.po +72 -0
  56. data/test/test_data/locales/en.rb +3 -0
  57. data/test/test_data/locales/en.yml +3 -0
  58. data/test/test_data/locales/invalid/empty.yml +1 -0
  59. data/test/test_data/locales/plurals.rb +113 -0
  60. data/test/test_helper.rb +56 -0
  61. metadata +116 -14
  62. data/lib/i18n/backend/cldr.rb +0 -99
@@ -0,0 +1,85 @@
1
+ require 'test_helper'
2
+
3
+ class I18nBackendCascadeTest < Test::Unit::TestCase
4
+ class Backend < I18n::Backend::Simple
5
+ include I18n::Backend::Cascade
6
+ end
7
+
8
+ def setup
9
+ I18n.backend = Backend.new
10
+ store_translations(:en, :foo => 'foo', :bar => { :baz => 'baz' })
11
+ @cascade_options = { :step => 1, :offset => 1, :skip_root => false }
12
+ end
13
+
14
+ def lookup(key, options = {})
15
+ I18n.t(key, options.merge(:cascade => @cascade_options))
16
+ end
17
+
18
+ test "still returns an existing translation as usual" do
19
+ assert_equal 'foo', lookup(:foo)
20
+ assert_equal 'baz', lookup(:'bar.baz')
21
+ end
22
+
23
+ test "falls back by cutting keys off the end of the scope" do
24
+ assert_equal 'foo', lookup(:foo, :scope => :'missing')
25
+ assert_equal 'foo', lookup(:foo, :scope => :'missing.missing')
26
+ assert_equal 'baz', lookup(:baz, :scope => :'bar.missing')
27
+ assert_equal 'baz', lookup(:baz, :scope => :'bar.missing.missing')
28
+ end
29
+
30
+ test "raises I18n::MissingTranslationData exception when no translation was found" do
31
+ assert_raise(I18n::MissingTranslationData) { lookup(:'foo.missing', :raise => true) }
32
+ assert_raise(I18n::MissingTranslationData) { lookup(:'bar.baz.missing', :raise => true) }
33
+ assert_raise(I18n::MissingTranslationData) { lookup(:'missing.bar.baz', :raise => true) }
34
+ end
35
+
36
+ test "cascades before evaluating the default" do
37
+ assert_equal 'foo', lookup(:foo, :scope => :missing, :default => 'default')
38
+ end
39
+
40
+ test "cascades defaults, too" do
41
+ assert_equal 'foo', lookup(nil, :default => [:'missing.missing', :'missing.foo'])
42
+ end
43
+
44
+ test "works with :offset => 2 and a single key" do
45
+ @cascade_options[:offset] = 2
46
+ lookup(:foo)
47
+ end
48
+
49
+ test "assemble required fallbacks for ActiveRecord validation messages" do
50
+ store_translations(:en,
51
+ :errors => {
52
+ :odd => 'errors.odd',
53
+ :reply => { :title => { :blank => 'errors.reply.title.blank' }, :taken => 'errors.reply.taken' },
54
+ :topic => { :title => { :format => 'errors.topic.title.format' }, :length => 'errors.topic.length' }
55
+ }
56
+ )
57
+ assert_equal 'errors.reply.title.blank', lookup(:'errors.reply.title.blank', :default => :'errors.topic.title.blank')
58
+ assert_equal 'errors.reply.taken', lookup(:'errors.reply.title.taken', :default => :'errors.topic.title.taken')
59
+ assert_equal 'errors.topic.title.format', lookup(:'errors.reply.title.format', :default => :'errors.topic.title.format')
60
+ assert_equal 'errors.topic.length', lookup(:'errors.reply.title.length', :default => :'errors.topic.title.length')
61
+ assert_equal 'errors.odd', lookup(:'errors.reply.title.odd', :default => :'errors.topic.title.odd')
62
+ end
63
+
64
+ test "assemble action view translation helper lookup cascade" do
65
+ @cascade_options[:offset] = 2
66
+
67
+ store_translations(:en,
68
+ :menu => { :show => 'menu.show' },
69
+ :namespace => {
70
+ :menu => { :new => 'namespace.menu.new' },
71
+ :controller => {
72
+ :menu => { :edit => 'namespace.controller.menu.edit' },
73
+ :action => {
74
+ :menu => { :destroy => 'namespace.controller.action.menu.destroy' }
75
+ }
76
+ }
77
+ }
78
+ )
79
+
80
+ assert_equal 'menu.show', lookup(:'namespace.controller.action.menu.show')
81
+ assert_equal 'namespace.menu.new', lookup(:'namespace.controller.action.menu.new')
82
+ assert_equal 'namespace.controller.menu.edit', lookup(:'namespace.controller.action.menu.edit')
83
+ assert_equal 'namespace.controller.action.menu.destroy', lookup(:'namespace.controller.action.menu.destroy')
84
+ end
85
+ end
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+
3
+ class I18nBackendChainTest < Test::Unit::TestCase
4
+ def setup
5
+ @first = backend(:en => {
6
+ :foo => 'Foo', :formats => { :short => 'short' }, :plural_1 => { :one => '%{count}' }
7
+ })
8
+ @second = backend(:en => {
9
+ :bar => 'Bar', :formats => { :long => 'long' }, :plural_2 => { :one => 'one' }
10
+ })
11
+ @chain = I18n.backend = I18n::Backend::Chain.new(@first, @second)
12
+ end
13
+
14
+ test "looks up translations from the first chained backend" do
15
+ assert_equal 'Foo', @first.send(:translations)[:en][:foo]
16
+ assert_equal 'Foo', I18n.t(:foo)
17
+ end
18
+
19
+ test "looks up translations from the second chained backend" do
20
+ assert_equal 'Bar', @second.send(:translations)[:en][:bar]
21
+ assert_equal 'Bar', I18n.t(:bar)
22
+ end
23
+
24
+ test "defaults only apply to lookups on the last backend in the chain" do
25
+ assert_equal 'Foo', I18n.t(:foo, :default => 'Bah')
26
+ assert_equal 'Bar', I18n.t(:bar, :default => 'Bah')
27
+ assert_equal 'Bah', I18n.t(:bah, :default => 'Bah') # default kicks in only here
28
+ end
29
+
30
+ test "default" do
31
+ assert_equal 'Fuh', I18n.t(:default => 'Fuh')
32
+ assert_equal 'Zero', I18n.t(:default => { :zero => 'Zero' }, :count => 0)
33
+ assert_equal({ :zero => 'Zero' }, I18n.t(:default => { :zero => 'Zero' }))
34
+ assert_equal 'Foo', I18n.t(:default => :foo)
35
+ end
36
+
37
+ test 'default is returned if translation is missing' do
38
+ assert_equal({}, I18n.t(:'i18n.transliterate.rule', :locale => 'en', :default => {}))
39
+ end
40
+
41
+ test "namespace lookup collects results from all backends" do
42
+ assert_equal({ :short => 'short', :long => 'long' }, I18n.t(:formats))
43
+ end
44
+
45
+ test "namespace lookup with only the first backend returning a result" do
46
+ assert_equal({ :one => '%{count}' }, I18n.t(:plural_1))
47
+ end
48
+
49
+ test "pluralization still works" do
50
+ assert_equal '1', I18n.t(:plural_1, :count => 1)
51
+ assert_equal 'one', I18n.t(:plural_2, :count => 1)
52
+ end
53
+
54
+ test "bulk lookup collects results from all backends" do
55
+ assert_equal ['Foo', 'Bar'], I18n.t([:foo, :bar])
56
+ assert_equal ['Foo', 'Bar', 'Bah'], I18n.t([:foo, :bar, :bah], :default => 'Bah')
57
+ assert_equal [{ :short => 'short', :long => 'long' }, { :one => 'one' }, 'Bah'], I18n.t([:formats, :plural_2, :bah], :default => 'Bah')
58
+ end
59
+
60
+ protected
61
+
62
+ def backend(translations)
63
+ backend = I18n::Backend::Simple.new
64
+ translations.each { |locale, data| backend.store_translations(locale, data) }
65
+ backend
66
+ end
67
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ class I18nBackendExceptionsTest < Test::Unit::TestCase
4
+ def setup
5
+ I18n.backend = I18n::Backend::Simple.new
6
+ end
7
+
8
+ test "exceptions: MissingTranslationData message from #translate includes the given scope and full key" do
9
+ begin
10
+ I18n.t(:'baz.missing', :scope => :'foo.bar', :raise => true)
11
+ rescue I18n::MissingTranslationData => exception
12
+ end
13
+ assert_equal "translation missing: en.foo.bar.baz.missing", exception.message
14
+ end
15
+
16
+ test "exceptions: MissingTranslationData message from #localize includes the given scope and full key" do
17
+ begin
18
+ I18n.l(Time.now, :format => :foo)
19
+ rescue I18n::MissingTranslationData => exception
20
+ end
21
+ assert_equal "translation missing: en.time.formats.foo", exception.message
22
+ end
23
+ end
@@ -0,0 +1,116 @@
1
+ require 'test_helper'
2
+
3
+ class I18nBackendFallbacksTranslateTest < Test::Unit::TestCase
4
+ class Backend < I18n::Backend::Simple
5
+ include I18n::Backend::Fallbacks
6
+ end
7
+
8
+ def setup
9
+ I18n.backend = Backend.new
10
+ store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en', :buz => 'Buz in :en')
11
+ store_translations(:de, :bar => 'Bar in :de', :baz => 'Baz in :de')
12
+ store_translations(:'de-DE', :baz => 'Baz in :de-DE')
13
+ end
14
+
15
+ test "still returns an existing translation as usual" do
16
+ assert_equal 'Foo in :en', I18n.t(:foo, :locale => :en)
17
+ assert_equal 'Bar in :de', I18n.t(:bar, :locale => :de)
18
+ assert_equal 'Baz in :de-DE', I18n.t(:baz, :locale => :'de-DE')
19
+ end
20
+
21
+ test "returns the :en translation for a missing :de translation" do
22
+ assert_equal 'Foo in :en', I18n.t(:foo, :locale => :de)
23
+ end
24
+
25
+ test "returns the :de translation for a missing :'de-DE' translation" do
26
+ assert_equal 'Bar in :de', I18n.t(:bar, :locale => :'de-DE')
27
+ end
28
+
29
+ test "returns the :en translation for translation missing in both :de and :'de-De'" do
30
+ assert_equal 'Buz in :en', I18n.t(:buz, :locale => :'de-DE')
31
+ end
32
+
33
+ test "returns the :de translation for a missing :'de-DE' when :default is a String" do
34
+ assert_equal 'Bar in :de', I18n.t(:bar, :locale => :'de-DE', :default => "Default Bar")
35
+ assert_equal "Default Bar", I18n.t(:missing_bar, :locale => :'de-DE', :default => "Default Bar")
36
+ end
37
+
38
+ test "returns the :de translation for a missing :'de-DE' when defaults is a Symbol (which exists in :en)" do
39
+ assert_equal "Bar in :de", I18n.t(:bar, :locale => :'de-DE', :default => [:buz])
40
+ end
41
+
42
+ test "returns the :'de-DE' default :baz translation for a missing :'de-DE' (which exists in :de)" do
43
+ assert_equal "Baz in :de-DE", I18n.t(:bar, :locale => :'de-DE', :default => [:baz])
44
+ end
45
+
46
+ test "returns the :de translation for a missing :'de-DE' when :default is a Proc" do
47
+ assert_equal 'Bar in :de', I18n.t(:bar, :locale => :'de-DE', :default => Proc.new { "Default Bar" })
48
+ assert_equal "Default Bar", I18n.t(:missing_bar, :locale => :'de-DE', :default => Proc.new { "Default Bar" })
49
+ end
50
+
51
+ test "returns the :'de-DE' default :baz translation for a missing :'de-DE' when defaults contains Symbol" do
52
+ assert_equal 'Baz in :de-DE', I18n.t(:missing_foo, :locale => :'de-DE', :default => [:baz, "Default Bar"])
53
+ end
54
+
55
+ test "returns the defaults translation for a missing :'de-DE' when defaults contains a String or Proc before Symbol" do
56
+ assert_equal "Default Bar", I18n.t(:missing_foo, :locale => :'de-DE', :default => [:missing_bar, "Default Bar", :baz])
57
+ assert_equal "Default Bar", I18n.t(:missing_foo, :locale => :'de-DE', :default => [:missing_bar, Proc.new { "Default Bar" }, :baz])
58
+ end
59
+
60
+ test "returns the default translation for a missing :'de-DE' and existing :de when default is a Hash" do
61
+ assert_equal 'Default 6 Bars', I18n.t(:missing_foo, :locale => :'de-DE', :default => [:missing_bar, {:other => "Default %{count} Bars"}, "Default Bar"], :count => 6)
62
+ end
63
+
64
+ test "raises I18n::MissingTranslationData exception when no translation was found" do
65
+ assert_raise(I18n::MissingTranslationData) { I18n.t(:faa, :locale => :en, :raise => true) }
66
+ assert_raise(I18n::MissingTranslationData) { I18n.t(:faa, :locale => :de, :raise => true) }
67
+ end
68
+ end
69
+
70
+ class I18nBackendFallbacksLocalizeTest < Test::Unit::TestCase
71
+ class Backend < I18n::Backend::Simple
72
+ include I18n::Backend::Fallbacks
73
+ end
74
+
75
+ def setup
76
+ I18n.backend = Backend.new
77
+ store_translations(:en, :date => { :formats => { :en => 'en' }, :day_names => %w(Sunday) })
78
+ store_translations(:de, :date => { :formats => { :de => 'de' } })
79
+ end
80
+
81
+ test "still uses an existing format as usual" do
82
+ assert_equal 'en', I18n.l(Date.today, :format => :en, :locale => :en)
83
+ end
84
+
85
+ test "looks up and uses a fallback locale's format for a key missing in the given locale (1)" do
86
+ assert_equal 'en', I18n.l(Date.today, :format => :en, :locale => :de)
87
+ end
88
+
89
+ test "looks up and uses a fallback locale's format for a key missing in the given locale (2)" do
90
+ assert_equal 'de', I18n.l(Date.today, :format => :de, :locale => :'de-DE')
91
+ end
92
+
93
+ test "still uses an existing day name translation as usual" do
94
+ assert_equal 'Sunday', I18n.l(Date.new(2010, 1, 3), :format => '%A', :locale => :en)
95
+ end
96
+
97
+ test "uses a fallback locale's translation for a key missing in the given locale" do
98
+ assert_equal 'Sunday', I18n.l(Date.new(2010, 1, 3), :format => '%A', :locale => :de)
99
+ end
100
+ end
101
+
102
+ class I18nBackendFallbacksWithChainTest < Test::Unit::TestCase
103
+ class Backend < I18n::Backend::Simple
104
+ include I18n::Backend::Fallbacks
105
+ end
106
+
107
+ def setup
108
+ backend = Backend.new
109
+ backend.store_translations(:de, :foo => 'FOO')
110
+ I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, backend)
111
+ end
112
+
113
+ test "falls back from de-DE to de when there is no translation for de-DE available" do
114
+ assert_equal 'FOO', I18n.t(:foo, :locale => :'de-DE')
115
+ end
116
+ end
@@ -0,0 +1,102 @@
1
+ require 'test_helper'
2
+
3
+ class InterpolationCompilerTest < Test::Unit::TestCase
4
+ Compiler = I18n::Backend::InterpolationCompiler::Compiler
5
+
6
+ def compile_and_interpolate(str, values = {})
7
+ Compiler.compile_if_an_interpolation(str).i18n_interpolate(values)
8
+ end
9
+
10
+ def assert_escapes_interpolation_key(expected, malicious_str)
11
+ assert_equal(expected, Compiler.send(:escape_key_sym, malicious_str))
12
+ end
13
+
14
+ def test_escape_key_properly_escapes
15
+ assert_escapes_interpolation_key ':"\""', '"'
16
+ assert_escapes_interpolation_key ':"\\\\"', '\\'
17
+ assert_escapes_interpolation_key ':"\\\\\""', '\\"'
18
+ assert_escapes_interpolation_key ':"\#{}"', '#{}'
19
+ assert_escapes_interpolation_key ':"\\\\\#{}"', '\#{}'
20
+ end
21
+
22
+ def assert_escapes_plain_string(expected, plain_str)
23
+ assert_equal expected, Compiler.send(:escape_plain_str, plain_str)
24
+ end
25
+
26
+ def test_escape_plain_string_properly_escapes
27
+ assert_escapes_plain_string '\\"', '"'
28
+ assert_escapes_plain_string '\'', '\''
29
+ assert_escapes_plain_string '\\#', '#'
30
+ assert_escapes_plain_string '\\#{}', '#{}'
31
+ assert_escapes_plain_string '\\\\\\"','\\"'
32
+ end
33
+
34
+ def test_non_interpolated_strings_or_arrays_dont_get_compiled
35
+ ['abc', '\\{a}}', '{a}}', []].each do |obj|
36
+ Compiler.compile_if_an_interpolation(obj)
37
+ assert_equal false, obj.respond_to?(:i18n_interpolate)
38
+ end
39
+ end
40
+
41
+ def test_interpolated_string_gets_compiled
42
+ assert_equal '-A-', compile_and_interpolate('-%{a}-', :a => 'A')
43
+ end
44
+
45
+ def assert_handles_key(str, key)
46
+ assert_equal 'A', compile_and_interpolate(str, key => 'A')
47
+ end
48
+
49
+ def test_compiles_fancy_keys
50
+ assert_handles_key('%{\}', :'\\' )
51
+ assert_handles_key('%{#}', :'#' )
52
+ assert_handles_key('%{#{}', :'#{' )
53
+ assert_handles_key('%{#$SAFE}', :'#$SAFE')
54
+ assert_handles_key('%{\000}', :'\000' )
55
+ assert_handles_key('%{\'}', :'\'' )
56
+ assert_handles_key('%{\'\'}', :'\'\'' )
57
+ assert_handles_key('%{a.b}', :'a.b' )
58
+ assert_handles_key('%{ }', :' ' )
59
+ assert_handles_key('%{:}', :':' )
60
+ assert_handles_key("%{:''}", :":''" )
61
+ assert_handles_key('%{:"}', :':"' )
62
+ end
63
+
64
+ def test_str_containing_only_escaped_interpolation_is_handled_correctly
65
+ assert_equal 'abc %{x}', compile_and_interpolate('abc %%{x}')
66
+ end
67
+
68
+ def test_handles_weird_strings
69
+ assert_equal '#{} a', compile_and_interpolate('#{} %{a}', :a => 'a')
70
+ assert_equal '"#{abc}"', compile_and_interpolate('"#{ab%{a}c}"', :a => '' )
71
+ assert_equal 'a}', compile_and_interpolate('%{{a}}', :'{a' => 'a')
72
+ assert_equal '"', compile_and_interpolate('"%{a}', :a => '' )
73
+ assert_equal 'a%{a}', compile_and_interpolate('%{a}%%{a}', :a => 'a')
74
+ assert_equal '%%{a}', compile_and_interpolate('%%%{a}')
75
+ assert_equal '\";eval("a")', compile_and_interpolate('\";eval("%{a}")', :a => 'a')
76
+ assert_equal '\";eval("a")', compile_and_interpolate('\";eval("a")%{a}', :a => '' )
77
+ assert_equal "\na", compile_and_interpolate("\n%{a}", :a => 'a')
78
+ end
79
+ end
80
+
81
+ class I18nBackendInterpolationCompilerTest < Test::Unit::TestCase
82
+ class Backend < I18n::Backend::Simple
83
+ include I18n::Backend::InterpolationCompiler
84
+ end
85
+
86
+ include I18n::Tests::Interpolation
87
+
88
+ def setup
89
+ I18n.backend = Backend.new
90
+ super
91
+ end
92
+
93
+ # pre-compile default strings to make sure we are testing I18n::Backend::InterpolationCompiler
94
+ def interpolate(*args)
95
+ options = args.last.kind_of?(Hash) ? args.last : {}
96
+ if default_str = options[:default]
97
+ I18n::Backend::InterpolationCompiler::Compiler.compile_if_an_interpolation(default_str)
98
+ end
99
+ super
100
+ end
101
+
102
+ end
@@ -0,0 +1,46 @@
1
+ require 'test_helper'
2
+
3
+ I18n::Tests.setup_rufus_tokyo
4
+
5
+ class I18nBackendKeyValueTest < Test::Unit::TestCase
6
+ def setup_backend!(subtree=true)
7
+ I18n.backend = I18n::Backend::KeyValue.new(Rufus::Tokyo::Cabinet.new('*'), subtree)
8
+ store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' })
9
+ end
10
+
11
+ def assert_flattens(expected, nested, escape=true, subtree=true)
12
+ assert_equal expected, I18n.backend.flatten_translations("en", nested, escape, subtree)
13
+ end
14
+
15
+ test "hash flattening works" do
16
+ setup_backend!
17
+ assert_flattens(
18
+ {:a=>'a', :b=>{:c=>'c', :d=>'d', :f=>{:x=>'x'}}, :"b.f" => {:x=>"x"}, :"b.c"=>"c", :"b.f.x"=>"x", :"b.d"=>"d"},
19
+ {:a=>'a', :b=>{:c=>'c', :d=>'d', :f=>{:x=>'x'}}}
20
+ )
21
+ assert_flattens({:a=>{:b =>['a', 'b']}, :"a.b"=>['a', 'b']}, {:a=>{:b =>['a', 'b']}})
22
+ assert_flattens({:"a\001b" => "c"}, {:"a.b" => "c"})
23
+ assert_flattens({:"a.b"=>['a', 'b']}, {:a=>{:b =>['a', 'b']}}, true, false)
24
+ assert_flattens({:"a.b" => "c"}, {:"a.b" => "c"}, false)
25
+ end
26
+
27
+ test "store_translations handle subtrees by default" do
28
+ setup_backend!
29
+ assert_equal({ :bar => 'bar', :baz => 'baz' }, I18n.t("foo"))
30
+ end
31
+
32
+ test "store_translations merge subtrees accordingly" do
33
+ setup_backend!
34
+ store_translations(:en, :foo => { :baz => "BAZ"})
35
+ assert_equal('BAZ', I18n.t("foo.baz"))
36
+ assert_equal({ :bar => 'bar', :baz => 'BAZ' }, I18n.t("foo"))
37
+ end
38
+
39
+ test "store_translations does not handle subtrees if desired" do
40
+ setup_backend!(false)
41
+ assert_raise I18n::MissingTranslationData do
42
+ I18n.t("foo", :raise => true)
43
+ end
44
+ end
45
+
46
+ end if defined?(Rufus::Tokyo::Cabinet)
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ require 'backend/simple_test'
4
+
5
+ class I18nBackendMemoizeTest < I18nBackendSimpleTest
6
+ module MemoizeSpy
7
+ attr_accessor :spy_calls
8
+
9
+ def available_locales
10
+ self.spy_calls = (self.spy_calls || 0) + 1
11
+ super
12
+ end
13
+ end
14
+
15
+ class MemoizeBackend < I18n::Backend::Simple
16
+ include MemoizeSpy
17
+ include I18n::Backend::Memoize
18
+ end
19
+
20
+ def setup
21
+ super
22
+ I18n.backend = MemoizeBackend.new
23
+ end
24
+
25
+ def test_memoizes_available_locales
26
+ I18n.backend.spy_calls = 0
27
+ assert_equal I18n.available_locales, I18n.available_locales
28
+ assert_equal 1, I18n.backend.spy_calls
29
+ end
30
+
31
+ def test_resets_available_locales_on_reload!
32
+ I18n.available_locales
33
+ I18n.backend.spy_calls = 0
34
+ I18n.reload!
35
+ assert_equal I18n.available_locales, I18n.available_locales
36
+ assert_equal 1, I18n.backend.spy_calls
37
+ end
38
+
39
+ def test_resets_available_locales_on_store_translations
40
+ I18n.available_locales
41
+ I18n.backend.spy_calls = 0
42
+ I18n.backend.store_translations(:copa, :ca => :bana)
43
+ assert_equal I18n.available_locales, I18n.available_locales
44
+ assert I18n.available_locales.include?(:copa)
45
+ assert_equal 1, I18n.backend.spy_calls
46
+ end
47
+ end