i18n 0.4.0 → 1.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +0 -0
  3. data/README.md +127 -0
  4. data/lib/i18n/backend/base.rb +189 -111
  5. data/lib/i18n/backend/cache.rb +58 -22
  6. data/lib/i18n/backend/cache_file.rb +36 -0
  7. data/lib/i18n/backend/cascade.rb +9 -10
  8. data/lib/i18n/backend/chain.rb +95 -42
  9. data/lib/i18n/backend/fallbacks.rb +68 -22
  10. data/lib/i18n/backend/flatten.rb +13 -8
  11. data/lib/i18n/backend/gettext.rb +33 -25
  12. data/lib/i18n/backend/interpolation_compiler.rb +12 -14
  13. data/lib/i18n/backend/key_value.rb +112 -10
  14. data/lib/i18n/backend/lazy_loadable.rb +184 -0
  15. data/lib/i18n/backend/memoize.rb +13 -7
  16. data/lib/i18n/backend/metadata.rb +12 -6
  17. data/lib/i18n/backend/pluralization.rb +64 -25
  18. data/lib/i18n/backend/simple.rb +44 -18
  19. data/lib/i18n/backend/transliterator.rb +43 -33
  20. data/lib/i18n/backend.rb +5 -3
  21. data/lib/i18n/config.rb +91 -10
  22. data/lib/i18n/exceptions.rb +118 -22
  23. data/lib/i18n/gettext/helpers.rb +14 -4
  24. data/lib/i18n/gettext/po_parser.rb +7 -7
  25. data/lib/i18n/gettext.rb +6 -5
  26. data/lib/i18n/interpolate/ruby.rb +53 -0
  27. data/lib/i18n/locale/fallbacks.rb +33 -26
  28. data/lib/i18n/locale/tag/parents.rb +8 -8
  29. data/lib/i18n/locale/tag/rfc4646.rb +0 -2
  30. data/lib/i18n/locale/tag/simple.rb +2 -4
  31. data/lib/i18n/locale.rb +2 -0
  32. data/lib/i18n/middleware.rb +17 -0
  33. data/lib/i18n/tests/basics.rb +58 -0
  34. data/lib/i18n/tests/defaults.rb +52 -0
  35. data/lib/i18n/tests/interpolation.rb +167 -0
  36. data/lib/i18n/tests/link.rb +66 -0
  37. data/lib/i18n/tests/localization/date.rb +122 -0
  38. data/lib/i18n/tests/localization/date_time.rb +103 -0
  39. data/lib/i18n/tests/localization/procs.rb +118 -0
  40. data/lib/i18n/tests/localization/time.rb +103 -0
  41. data/lib/i18n/tests/localization.rb +19 -0
  42. data/lib/i18n/tests/lookup.rb +81 -0
  43. data/lib/i18n/tests/pluralization.rb +35 -0
  44. data/lib/i18n/tests/procs.rb +66 -0
  45. data/lib/i18n/tests.rb +14 -0
  46. data/lib/i18n/utils.rb +55 -0
  47. data/lib/i18n/version.rb +3 -1
  48. data/lib/i18n.rb +200 -87
  49. metadata +64 -56
  50. data/CHANGELOG.textile +0 -135
  51. data/README.textile +0 -93
  52. data/lib/i18n/backend/active_record/missing.rb +0 -65
  53. data/lib/i18n/backend/active_record/store_procs.rb +0 -38
  54. data/lib/i18n/backend/active_record/translation.rb +0 -93
  55. data/lib/i18n/backend/active_record.rb +0 -61
  56. data/lib/i18n/backend/cldr.rb +0 -100
  57. data/lib/i18n/core_ext/hash.rb +0 -29
  58. data/lib/i18n/core_ext/string/interpolate.rb +0 -98
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+
3
+ module I18n
4
+ module Tests
5
+ module Localization
6
+ module DateTime
7
+ def setup
8
+ super
9
+ setup_datetime_translations
10
+ @datetime = ::DateTime.new(2008, 3, 1, 6)
11
+ @other_datetime = ::DateTime.new(2008, 3, 1, 18)
12
+ end
13
+
14
+ test "localize DateTime: given the short format it uses it" do
15
+ assert_equal '01. Mär 06:00', I18n.l(@datetime, :format => :short, :locale => :de)
16
+ end
17
+
18
+ test "localize DateTime: given the long format it uses it" do
19
+ assert_equal '01. März 2008 06:00', I18n.l(@datetime, :format => :long, :locale => :de)
20
+ end
21
+
22
+ test "localize DateTime: given the default format it uses it" do
23
+ assert_equal 'Sa, 01. Mär 2008 06:00:00 +0000', I18n.l(@datetime, :format => :default, :locale => :de)
24
+ end
25
+
26
+ test "localize DateTime: given a day name format it returns the correct day name" do
27
+ assert_equal 'Samstag', I18n.l(@datetime, :format => '%A', :locale => :de)
28
+ end
29
+
30
+ test "localize DateTime: given a uppercased day name format it returns the correct day name in upcase" do
31
+ assert_equal 'samstag'.upcase, I18n.l(@datetime, :format => '%^A', :locale => :de)
32
+ end
33
+
34
+ test "localize DateTime: given an abbreviated day name format it returns the correct abbreviated day name" do
35
+ assert_equal 'Sa', I18n.l(@datetime, :format => '%a', :locale => :de)
36
+ end
37
+
38
+ test "localize DateTime: given an abbreviated and uppercased day name format it returns the correct abbreviated day name in upcase" do
39
+ assert_equal 'sa'.upcase, I18n.l(@datetime, :format => '%^a', :locale => :de)
40
+ end
41
+
42
+ test "localize DateTime: given a month name format it returns the correct month name" do
43
+ assert_equal 'März', I18n.l(@datetime, :format => '%B', :locale => :de)
44
+ end
45
+
46
+ test "localize DateTime: given a uppercased month name format it returns the correct month name in upcase" do
47
+ assert_equal 'märz'.upcase, I18n.l(@datetime, :format => '%^B', :locale => :de)
48
+ end
49
+
50
+ test "localize DateTime: given an abbreviated month name format it returns the correct abbreviated month name" do
51
+ assert_equal 'Mär', I18n.l(@datetime, :format => '%b', :locale => :de)
52
+ end
53
+
54
+ test "localize DateTime: given an abbreviated and uppercased month name format it returns the correct abbreviated month name in upcase" do
55
+ assert_equal 'mär'.upcase, I18n.l(@datetime, :format => '%^b', :locale => :de)
56
+ end
57
+
58
+ test "localize DateTime: given a date format with the month name upcased it returns the correct value" do
59
+ assert_equal '1. FEBRUAR 2008', I18n.l(::DateTime.new(2008, 2, 1, 6), :format => "%-d. %^B %Y", :locale => :de)
60
+ end
61
+
62
+ test "localize DateTime: given missing translations it returns the correct error message" do
63
+ assert_equal 'Translation missing: fr.date.abbr_month_names', I18n.l(@datetime, :format => '%b', :locale => :fr)
64
+ end
65
+
66
+ test "localize DateTime: given a meridian indicator format it returns the correct meridian indicator" do
67
+ assert_equal 'AM', I18n.l(@datetime, :format => '%p', :locale => :de)
68
+ assert_equal 'PM', I18n.l(@other_datetime, :format => '%p', :locale => :de)
69
+ end
70
+
71
+ test "localize DateTime: given a meridian indicator format it returns the correct meridian indicator in downcase" do
72
+ assert_equal 'am', I18n.l(@datetime, :format => '%P', :locale => :de)
73
+ assert_equal 'pm', I18n.l(@other_datetime, :format => '%P', :locale => :de)
74
+ end
75
+
76
+ test "localize DateTime: given an unknown format it does not fail" do
77
+ assert_nothing_raised { I18n.l(@datetime, :format => '%x') }
78
+ end
79
+
80
+ test "localize DateTime: given a format is missing it raises I18n::MissingTranslationData" do
81
+ assert_raises(I18n::MissingTranslationData) { I18n.l(@datetime, :format => :missing) }
82
+ end
83
+
84
+ protected
85
+
86
+ def setup_datetime_translations
87
+ # time translations might have been set up in Tests::Api::Localization::Time
88
+ I18n.backend.store_translations :de, {
89
+ :time => {
90
+ :formats => {
91
+ :default => "%a, %d. %b %Y %H:%M:%S %z",
92
+ :short => "%d. %b %H:%M",
93
+ :long => "%d. %B %Y %H:%M"
94
+ },
95
+ :am => 'am',
96
+ :pm => 'pm'
97
+ }
98
+ }
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,118 @@
1
+ # encoding: utf-8
2
+
3
+ module I18n
4
+ module Tests
5
+ module Localization
6
+ module Procs
7
+ test "localize: using day names from lambdas" do
8
+ setup_time_proc_translations
9
+ time = ::Time.utc(2008, 3, 1, 6, 0)
10
+ assert_match(/Суббота/, I18n.l(time, :format => "%A, %d %B", :locale => :ru))
11
+ assert_match(/суббота/, I18n.l(time, :format => "%d %B (%A)", :locale => :ru))
12
+ end
13
+
14
+ test "localize: using month names from lambdas" do
15
+ setup_time_proc_translations
16
+ time = ::Time.utc(2008, 3, 1, 6, 0)
17
+ assert_match(/марта/, I18n.l(time, :format => "%d %B %Y", :locale => :ru))
18
+ assert_match(/Март /, I18n.l(time, :format => "%B %Y", :locale => :ru))
19
+ end
20
+
21
+ test "localize: using abbreviated day names from lambdas" do
22
+ setup_time_proc_translations
23
+ time = ::Time.utc(2008, 3, 1, 6, 0)
24
+ assert_match(/марта/, I18n.l(time, :format => "%d %b %Y", :locale => :ru))
25
+ assert_match(/март /, I18n.l(time, :format => "%b %Y", :locale => :ru))
26
+ end
27
+
28
+ test "localize Date: given a format that resolves to a Proc it calls the Proc with the object" do
29
+ setup_time_proc_translations
30
+ date = ::Date.new(2008, 3, 1)
31
+ assert_equal '[Sat, 01 Mar 2008, {}]', I18n.l(date, :format => :proc, :locale => :ru)
32
+ end
33
+
34
+ test "localize Date: given a format that resolves to a Proc it calls the Proc with the object and extra options" do
35
+ setup_time_proc_translations
36
+ date = ::Date.new(2008, 3, 1)
37
+ assert_equal '[Sat, 01 Mar 2008, {:foo=>"foo"}]', I18n.l(date, :format => :proc, :foo => 'foo', :locale => :ru)
38
+ end
39
+
40
+ test "localize DateTime: given a format that resolves to a Proc it calls the Proc with the object" do
41
+ setup_time_proc_translations
42
+ datetime = ::DateTime.new(2008, 3, 1, 6)
43
+ assert_equal '[Sat, 01 Mar 2008 06:00:00 +00:00, {}]', I18n.l(datetime, :format => :proc, :locale => :ru)
44
+ end
45
+
46
+ test "localize DateTime: given a format that resolves to a Proc it calls the Proc with the object and extra options" do
47
+ setup_time_proc_translations
48
+ datetime = ::DateTime.new(2008, 3, 1, 6)
49
+ assert_equal '[Sat, 01 Mar 2008 06:00:00 +00:00, {:foo=>"foo"}]', I18n.l(datetime, :format => :proc, :foo => 'foo', :locale => :ru)
50
+ end
51
+
52
+ test "localize Time: given a format that resolves to a Proc it calls the Proc with the object" do
53
+ setup_time_proc_translations
54
+ time = ::Time.utc(2008, 3, 1, 6, 0)
55
+ assert_equal I18n::Tests::Localization::Procs.inspect_args([time], {}), I18n.l(time, :format => :proc, :locale => :ru)
56
+ end
57
+
58
+ test "localize Time: given a format that resolves to a Proc it calls the Proc with the object and extra options" do
59
+ setup_time_proc_translations
60
+ time = ::Time.utc(2008, 3, 1, 6, 0)
61
+ options = { :foo => 'foo' }
62
+ assert_equal I18n::Tests::Localization::Procs.inspect_args([time], options), I18n.l(time, **options.merge(:format => :proc, :locale => :ru))
63
+ end
64
+
65
+ protected
66
+
67
+ def self.inspect_args(args, kwargs)
68
+ args << kwargs
69
+ args = args.map do |arg|
70
+ case arg
71
+ when ::Time, ::DateTime
72
+ arg.strftime('%a, %d %b %Y %H:%M:%S %Z').sub('+0000', '+00:00')
73
+ when ::Date
74
+ arg.strftime('%a, %d %b %Y')
75
+ when Hash
76
+ arg.delete(:fallback_in_progress)
77
+ arg.delete(:fallback_original_locale)
78
+ arg.inspect
79
+ else
80
+ arg.inspect
81
+ end
82
+ end
83
+ "[#{args.join(', ')}]"
84
+ end
85
+
86
+ def setup_time_proc_translations
87
+ I18n.backend.store_translations :ru, {
88
+ :time => {
89
+ :formats => {
90
+ :proc => lambda { |*args, **kwargs| I18n::Tests::Localization::Procs.inspect_args(args, kwargs) }
91
+ }
92
+ },
93
+ :date => {
94
+ :formats => {
95
+ :proc => lambda { |*args, **kwargs| I18n::Tests::Localization::Procs.inspect_args(args, kwargs) }
96
+ },
97
+ :'day_names' => lambda { |key, options|
98
+ (options[:format] =~ /^%A/) ?
99
+ %w(Воскресенье Понедельник Вторник Среда Четверг Пятница Суббота) :
100
+ %w(воскресенье понедельник вторник среда четверг пятница суббота)
101
+ },
102
+ :'month_names' => lambda { |key, options|
103
+ (options[:format] =~ /(%d|%e)(\s*)?(%B)/) ?
104
+ %w(января февраля марта апреля мая июня июля августа сентября октября ноября декабря).unshift(nil) :
105
+ %w(Январь Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь).unshift(nil)
106
+ },
107
+ :'abbr_month_names' => lambda { |key, options|
108
+ (options[:format] =~ /(%d|%e)(\s*)(%b)/) ?
109
+ %w(янв. февр. марта апр. мая июня июля авг. сент. окт. нояб. дек.).unshift(nil) :
110
+ %w(янв. февр. март апр. май июнь июль авг. сент. окт. нояб. дек.).unshift(nil)
111
+ },
112
+ }
113
+ }
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+
3
+ module I18n
4
+ module Tests
5
+ module Localization
6
+ module Time
7
+ def setup
8
+ super
9
+ setup_time_translations
10
+ @time = ::Time.utc(2008, 3, 1, 6, 0)
11
+ @other_time = ::Time.utc(2008, 3, 1, 18, 0)
12
+ end
13
+
14
+ test "localize Time: given the short format it uses it" do
15
+ assert_equal '01. Mär 06:00', I18n.l(@time, :format => :short, :locale => :de)
16
+ end
17
+
18
+ test "localize Time: given the long format it uses it" do
19
+ assert_equal '01. März 2008 06:00', I18n.l(@time, :format => :long, :locale => :de)
20
+ end
21
+
22
+ # TODO Seems to break on Windows because ENV['TZ'] is ignored. What's a better way to do this?
23
+ # def test_localize_given_the_default_format_it_uses_it
24
+ # assert_equal 'Sa, 01. Mar 2008 06:00:00 +0000', I18n.l(@time, :format => :default, :locale => :de)
25
+ # end
26
+
27
+ test "localize Time: given a day name format it returns the correct day name" do
28
+ assert_equal 'Samstag', I18n.l(@time, :format => '%A', :locale => :de)
29
+ end
30
+
31
+ test "localize Time: given a uppercased day name format it returns the correct day name in upcase" do
32
+ assert_equal 'samstag'.upcase, I18n.l(@time, :format => '%^A', :locale => :de)
33
+ end
34
+
35
+ test "localize Time: given an abbreviated day name format it returns the correct abbreviated day name" do
36
+ assert_equal 'Sa', I18n.l(@time, :format => '%a', :locale => :de)
37
+ end
38
+
39
+ test "localize Time: given an abbreviated and uppercased day name format it returns the correct abbreviated day name in upcase" do
40
+ assert_equal 'sa'.upcase, I18n.l(@time, :format => '%^a', :locale => :de)
41
+ end
42
+
43
+ test "localize Time: given a month name format it returns the correct month name" do
44
+ assert_equal 'März', I18n.l(@time, :format => '%B', :locale => :de)
45
+ end
46
+
47
+ test "localize Time: given a uppercased month name format it returns the correct month name in upcase" do
48
+ assert_equal 'märz'.upcase, I18n.l(@time, :format => '%^B', :locale => :de)
49
+ end
50
+
51
+ test "localize Time: given an abbreviated month name format it returns the correct abbreviated month name" do
52
+ assert_equal 'Mär', I18n.l(@time, :format => '%b', :locale => :de)
53
+ end
54
+
55
+ test "localize Time: given an abbreviated and uppercased month name format it returns the correct abbreviated month name in upcase" do
56
+ assert_equal 'mär'.upcase, I18n.l(@time, :format => '%^b', :locale => :de)
57
+ end
58
+
59
+ test "localize Time: given a date format with the month name upcased it returns the correct value" do
60
+ assert_equal '1. FEBRUAR 2008', I18n.l(::Time.utc(2008, 2, 1, 6, 0), :format => "%-d. %^B %Y", :locale => :de)
61
+ end
62
+
63
+ test "localize Time: given missing translations it returns the correct error message" do
64
+ assert_equal 'Translation missing: fr.date.abbr_month_names', I18n.l(@time, :format => '%b', :locale => :fr)
65
+ end
66
+
67
+ test "localize Time: given a meridian indicator format it returns the correct meridian indicator" do
68
+ assert_equal 'AM', I18n.l(@time, :format => '%p', :locale => :de)
69
+ assert_equal 'PM', I18n.l(@other_time, :format => '%p', :locale => :de)
70
+ end
71
+
72
+ test "localize Time: given a meridian indicator format it returns the correct meridian indicator in upcase" do
73
+ assert_equal 'am', I18n.l(@time, :format => '%P', :locale => :de)
74
+ assert_equal 'pm', I18n.l(@other_time, :format => '%P', :locale => :de)
75
+ end
76
+
77
+ test "localize Time: given an unknown format it does not fail" do
78
+ assert_nothing_raised { I18n.l(@time, :format => '%x') }
79
+ end
80
+
81
+ test "localize Time: given a format is missing it raises I18n::MissingTranslationData" do
82
+ assert_raises(I18n::MissingTranslationData) { I18n.l(@time, :format => :missing) }
83
+ end
84
+
85
+ protected
86
+
87
+ def setup_time_translations
88
+ I18n.backend.store_translations :de, {
89
+ :time => {
90
+ :formats => {
91
+ :default => "%a, %d. %b %Y %H:%M:%S %z",
92
+ :short => "%d. %b %H:%M",
93
+ :long => "%d. %B %Y %H:%M",
94
+ },
95
+ :am => 'am',
96
+ :pm => 'pm'
97
+ }
98
+ }
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,19 @@
1
+ module I18n
2
+ module Tests
3
+ module Localization
4
+ autoload :Date, 'i18n/tests/localization/date'
5
+ autoload :DateTime, 'i18n/tests/localization/date_time'
6
+ autoload :Time, 'i18n/tests/localization/time'
7
+ autoload :Procs, 'i18n/tests/localization/procs'
8
+
9
+ def self.included(base)
10
+ base.class_eval do
11
+ include I18n::Tests::Localization::Date
12
+ include I18n::Tests::Localization::DateTime
13
+ include I18n::Tests::Localization::Procs
14
+ include I18n::Tests::Localization::Time
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+
3
+ module I18n
4
+ module Tests
5
+ module Lookup
6
+ def setup
7
+ super
8
+ I18n.backend.store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' }, :falsy => false, :truthy => true,
9
+ :string => "a", :array => %w(a b c), :hash => { "a" => "b" })
10
+ end
11
+
12
+ test "lookup: it returns a string" do
13
+ assert_equal("a", I18n.t(:string))
14
+ end
15
+
16
+ test "lookup: it returns hash" do
17
+ assert_equal({ :a => "b" }, I18n.t(:hash))
18
+ end
19
+
20
+ test "lookup: it returns an array" do
21
+ assert_equal(%w(a b c), I18n.t(:array))
22
+ end
23
+
24
+ test "lookup: it returns a native true" do
25
+ assert I18n.t(:truthy) === true
26
+ end
27
+
28
+ test "lookup: it returns a native false" do
29
+ assert I18n.t(:falsy) === false
30
+ end
31
+
32
+ test "lookup: given a missing key, no default and no raise option it returns an error message" do
33
+ assert_equal "Translation missing: en.missing", I18n.t(:missing)
34
+ end
35
+
36
+ test "lookup: given a missing key, no default and the raise option it raises MissingTranslationData" do
37
+ assert_raises(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) }
38
+ end
39
+
40
+ test "lookup: does not raise an exception if no translation data is present for the given locale" do
41
+ assert_nothing_raised { I18n.t(:foo, :locale => :xx) }
42
+ end
43
+
44
+ test "lookup: does not modify the options hash" do
45
+ options = {}
46
+ assert_equal "a", I18n.t(:string, **options)
47
+ assert_equal({}, options)
48
+ assert_nothing_raised { I18n.t(:string, **options.freeze) }
49
+ end
50
+
51
+ test "lookup: given an array of keys it translates all of them" do
52
+ assert_equal %w(bar baz), I18n.t([:bar, :baz], :scope => [:foo])
53
+ end
54
+
55
+ test "lookup: using a custom scope separator" do
56
+ # data must have been stored using the custom separator when using the ActiveRecord backend
57
+ I18n.backend.store_translations(:en, { :foo => { :bar => 'bar' } }, { :separator => '|' })
58
+ assert_equal 'bar', I18n.t('foo|bar', :separator => '|')
59
+ end
60
+
61
+ # In fact it probably *should* fail but Rails currently relies on using the default locale instead.
62
+ # So we'll stick to this for now until we get it fixed in Rails.
63
+ test "lookup: given nil as a locale it does not raise but use the default locale" do
64
+ # assert_raises(I18n::InvalidLocale) { I18n.t(:bar, :locale => nil) }
65
+ assert_nothing_raised { I18n.t(:bar, :locale => nil) }
66
+ end
67
+
68
+ test "lookup: a resulting String is not frozen" do
69
+ assert !I18n.t(:string).frozen?
70
+ end
71
+
72
+ test "lookup: a resulting Array is not frozen" do
73
+ assert !I18n.t(:array).frozen?
74
+ end
75
+
76
+ test "lookup: a resulting Hash is not frozen" do
77
+ assert !I18n.t(:hash).frozen?
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ module I18n
4
+ module Tests
5
+ module Pluralization
6
+ test "pluralization: given 0 it returns the :zero translation if it is defined" do
7
+ assert_equal 'zero', I18n.t(:default => { :zero => 'zero' }, :count => 0)
8
+ end
9
+
10
+ test "pluralization: given 0 it returns the :other translation if :zero is not defined" do
11
+ assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 0)
12
+ end
13
+
14
+ test "pluralization: given 1 it returns the singular translation" do
15
+ assert_equal 'bar', I18n.t(:default => { :one => 'bar' }, :count => 1)
16
+ end
17
+
18
+ test "pluralization: given 2 it returns the :other translation" do
19
+ assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 2)
20
+ end
21
+
22
+ test "pluralization: given 3 it returns the :other translation" do
23
+ assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 3)
24
+ end
25
+
26
+ test "pluralization: given nil it returns the whole entry" do
27
+ assert_equal({ :one => 'bar' }, I18n.t(:default => { :one => 'bar' }, :count => nil))
28
+ end
29
+
30
+ test "pluralization: given incomplete pluralization data it raises I18n::InvalidPluralizationData" do
31
+ assert_raises(I18n::InvalidPluralizationData) { I18n.t(:default => { :one => 'bar' }, :count => 2) }
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ module I18n
4
+ module Tests
5
+ module Procs
6
+ test "lookup: given a translation is a proc it calls the proc with the key and interpolation values" do
7
+ I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| I18n::Tests::Procs.filter_args(*args) })
8
+ assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:a_lambda, :foo => 'foo')
9
+ end
10
+
11
+ test "lookup: given a translation is a proc it passes the interpolation values as keyword arguments" do
12
+ I18n.backend.store_translations(:en, :a_lambda => lambda { |key, foo:, **| I18n::Tests::Procs.filter_args(key, foo: foo) })
13
+ assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:a_lambda, :foo => 'foo')
14
+ end
15
+
16
+ test "defaults: given a default is a Proc it calls it with the key and interpolation values" do
17
+ proc = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
18
+ assert_equal '[nil, {:foo=>"foo"}]', I18n.t(nil, :default => proc, :foo => 'foo')
19
+ end
20
+
21
+ test "defaults: given a default is a key that resolves to a Proc it calls it with the key and interpolation values" do
22
+ the_lambda = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
23
+ I18n.backend.store_translations(:en, :a_lambda => the_lambda)
24
+ assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(nil, :default => :a_lambda, :foo => 'foo')
25
+ assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(nil, :default => [nil, :a_lambda], :foo => 'foo')
26
+ end
27
+
28
+ test "interpolation: given an interpolation value is a lambda it calls it with key and values before interpolating it" do
29
+ proc = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
30
+ assert_match %r(\[\{:foo=>#<Proc.*>\}\]), I18n.t(nil, :default => '%{foo}', :foo => proc)
31
+ end
32
+
33
+ test "interpolation: given a key resolves to a Proc that returns a string then interpolation still works" do
34
+ proc = lambda { |*args| "%{foo}: " + I18n::Tests::Procs.filter_args(*args) }
35
+ assert_equal 'foo: [nil, {:foo=>"foo"}]', I18n.t(nil, :default => proc, :foo => 'foo')
36
+ end
37
+
38
+ test "pluralization: given a key resolves to a Proc that returns valid data then pluralization still works" do
39
+ proc = lambda { |*args| { :zero => 'zero', :one => 'one', :other => 'other' } }
40
+ assert_equal 'zero', I18n.t(:default => proc, :count => 0)
41
+ assert_equal 'one', I18n.t(:default => proc, :count => 1)
42
+ assert_equal 'other', I18n.t(:default => proc, :count => 2)
43
+ end
44
+
45
+ test "lookup: given the option :resolve => false was passed it does not resolve proc translations" do
46
+ I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| I18n::Tests::Procs.filter_args(*args) })
47
+ assert_equal Proc, I18n.t(:a_lambda, :resolve => false).class
48
+ end
49
+
50
+ test "lookup: given the option :resolve => false was passed it does not resolve proc default" do
51
+ assert_equal Proc, I18n.t(nil, :default => lambda { |*args| I18n::Tests::Procs.filter_args(*args) }, :resolve => false).class
52
+ end
53
+
54
+
55
+ def self.filter_args(*args)
56
+ args.map do |arg|
57
+ if arg.is_a?(Hash)
58
+ arg.delete(:fallback_in_progress)
59
+ arg.delete(:fallback_original_locale)
60
+ end
61
+ arg
62
+ end.inspect
63
+ end
64
+ end
65
+ end
66
+ end
data/lib/i18n/tests.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18n
4
+ module Tests
5
+ autoload :Basics, 'i18n/tests/basics'
6
+ autoload :Defaults, 'i18n/tests/defaults'
7
+ autoload :Interpolation, 'i18n/tests/interpolation'
8
+ autoload :Link, 'i18n/tests/link'
9
+ autoload :Localization, 'i18n/tests/localization'
10
+ autoload :Lookup, 'i18n/tests/lookup'
11
+ autoload :Pluralization, 'i18n/tests/pluralization'
12
+ autoload :Procs, 'i18n/tests/procs'
13
+ end
14
+ end
data/lib/i18n/utils.rb ADDED
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18n
4
+ module Utils
5
+ class << self
6
+ if Hash.method_defined?(:except)
7
+ def except(hash, *keys)
8
+ hash.except(*keys)
9
+ end
10
+ else
11
+ def except(hash, *keys)
12
+ hash = hash.dup
13
+ keys.each { |k| hash.delete(k) }
14
+ hash
15
+ end
16
+ end
17
+
18
+ def deep_merge(hash, other_hash, &block)
19
+ deep_merge!(hash.dup, other_hash, &block)
20
+ end
21
+
22
+ def deep_merge!(hash, other_hash, &block)
23
+ hash.merge!(other_hash) do |key, this_val, other_val|
24
+ if this_val.is_a?(Hash) && other_val.is_a?(Hash)
25
+ deep_merge(this_val, other_val, &block)
26
+ elsif block_given?
27
+ yield key, this_val, other_val
28
+ else
29
+ other_val
30
+ end
31
+ end
32
+ end
33
+
34
+ def deep_symbolize_keys(hash)
35
+ hash.each_with_object({}) do |(key, value), result|
36
+ result[key.respond_to?(:to_sym) ? key.to_sym : key] = deep_symbolize_keys_in_object(value)
37
+ result
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def deep_symbolize_keys_in_object(value)
44
+ case value
45
+ when Hash
46
+ deep_symbolize_keys(value)
47
+ when Array
48
+ value.map { |e| deep_symbolize_keys_in_object(e) }
49
+ else
50
+ value
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
data/lib/i18n/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module I18n
2
- VERSION = "0.4.0"
4
+ VERSION = "1.14.4"
3
5
  end