svenfuchs-i18n 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 The Ruby I18n team
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,20 @@
1
+ h1. Ruby I18n gem
2
+
3
+ I18n and localization solution for Ruby.
4
+
5
+ For information please refer to http://rails-i18n.org
6
+
7
+ h2. Authors
8
+
9
+ * "Matt Aimonetti":http://railsontherun.com
10
+ * "Sven Fuchs":http://www.artweb-design.de
11
+ * "Joshua Harvey":http://www.workingwithrails.com/person/759-joshua-harvey
12
+ * "Saimon Moore":http://saimonmoore.net
13
+ * "Stephan Soller":http://www.arkanis-development.de
14
+
15
+ h2. License
16
+
17
+ MIT License. See the included MIT-LICENCE file.
18
+
19
+
20
+
data/i18n.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "i18n"
3
+ s.version = "0.1.0"
4
+ s.date = "2008-10-26"
5
+ s.summary = "Internationalization support for Ruby"
6
+ s.email = "rails-i18n@googlegroups.com"
7
+ s.homepage = "http://rails-i18n.org"
8
+ s.description = "Add Internationalization support to your Ruby application."
9
+ s.has_rdoc = false
10
+ s.authors = ['Sven Fuchs', 'Joshua Harvey', 'Matt Aimonetti', 'Stephan Soller', 'Saimon Moore']
11
+ s.files = [
12
+ 'i18n.gemspec',
13
+ 'lib/i18n/backend/simple.rb',
14
+ 'lib/i18n/exceptions.rb',
15
+ 'lib/i18n.rb',
16
+ 'MIT-LICENSE',
17
+ 'README.textile'
18
+ ]
19
+ s.test_files = [
20
+ 'test/all.rb',
21
+ 'test/i18n_exceptions_test.rb',
22
+ 'test/i18n_test.rb',
23
+ 'test/locale/en-US.rb',
24
+ 'test/locale/en-US.yml',
25
+ 'test/simple_backend_test.rb'
26
+ ]
27
+ end
@@ -0,0 +1,216 @@
1
+ require 'yaml'
2
+
3
+ module I18n
4
+ module Backend
5
+ class Simple
6
+ INTERPOLATION_RESERVED_KEYS = %w(scope default)
7
+ MATCH = /(\\\\)?\{\{([^\}]+)\}\}/
8
+
9
+ # Accepts a list of paths to translation files. Loads translations from
10
+ # plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml
11
+ # for details.
12
+ def load_translations(*filenames)
13
+ filenames.each { |filename| load_file(filename) }
14
+ end
15
+
16
+ # Stores translations for the given locale in memory.
17
+ # This uses a deep merge for the translations hash, so existing
18
+ # translations will be overwritten by new ones only at the deepest
19
+ # level of the hash.
20
+ def store_translations(locale, data)
21
+ merge_translations(locale, data)
22
+ end
23
+
24
+ def translate(locale, key, options = {})
25
+ raise InvalidLocale.new(locale) if locale.nil?
26
+ return key.map { |k| translate(locale, k, options) } if key.is_a? Array
27
+
28
+ reserved = :scope, :default
29
+ count, scope, default = options.values_at(:count, *reserved)
30
+ options.delete(:default)
31
+ values = options.reject { |name, value| reserved.include?(name) }
32
+
33
+ entry = lookup(locale, key, scope)
34
+ if entry.nil?
35
+ entry = default(locale, default, options)
36
+ if entry.nil?
37
+ raise(I18n::MissingTranslationData.new(locale, key, options))
38
+ end
39
+ end
40
+ entry = pluralize(locale, entry, count)
41
+ entry = interpolate(locale, entry, values)
42
+ entry
43
+ end
44
+
45
+ # Acts the same as +strftime+, but returns a localized version of the
46
+ # formatted date string. Takes a key from the date/time formats
47
+ # translations as a format argument (<em>e.g.</em>, <tt>:short</tt> in <tt>:'date.formats'</tt>).
48
+ def localize(locale, object, format = :default)
49
+ raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime)
50
+
51
+ type = object.respond_to?(:sec) ? 'time' : 'date'
52
+ # TODO only translate these if format is a String?
53
+ formats = translate(locale, :"#{type}.formats")
54
+ format = formats[format.to_sym] if formats && formats[format.to_sym]
55
+ # TODO raise exception unless format found?
56
+ format = format.to_s.dup
57
+
58
+ # TODO only translate these if the format string is actually present
59
+ # TODO check which format strings are present, then bulk translate then, then replace them
60
+ format.gsub!(/%a/, translate(locale, :"date.abbr_day_names")[object.wday])
61
+ format.gsub!(/%A/, translate(locale, :"date.day_names")[object.wday])
62
+ format.gsub!(/%b/, translate(locale, :"date.abbr_month_names")[object.mon])
63
+ format.gsub!(/%B/, translate(locale, :"date.month_names")[object.mon])
64
+ format.gsub!(/%p/, translate(locale, :"time.#{object.hour < 12 ? :am : :pm}")) if object.respond_to? :hour
65
+ object.strftime(format)
66
+ end
67
+
68
+ def initialized?
69
+ @initialized ||= false
70
+ end
71
+
72
+ def reload!
73
+ @initialized = false
74
+ @translations = nil
75
+ end
76
+
77
+ protected
78
+ def init_translations
79
+ load_translations(*I18n.load_path)
80
+ @initialized = true
81
+ end
82
+
83
+ def translations
84
+ @translations ||= {}
85
+ end
86
+
87
+ # Looks up a translation from the translations hash. Returns nil if
88
+ # eiher key is nil, or locale, scope or key do not exist as a key in the
89
+ # nested translations hash. Splits keys or scopes containing dots
90
+ # into multiple keys, i.e. <tt>currency.format</tt> is regarded the same as
91
+ # <tt>%w(currency format)</tt>.
92
+ def lookup(locale, key, scope = [])
93
+ return unless key
94
+ init_translations unless initialized?
95
+ keys = I18n.send(:normalize_translation_keys, locale, key, scope)
96
+ keys.inject(translations) do |result, k|
97
+ if (x = result[k.to_sym]).nil?
98
+ return nil
99
+ else
100
+ x
101
+ end
102
+ end
103
+ end
104
+
105
+ # Evaluates a default translation.
106
+ # If the given default is a String it is used literally. If it is a Symbol
107
+ # it will be translated with the given options. If it is an Array the first
108
+ # translation yielded will be returned.
109
+ #
110
+ # <em>I.e.</em>, <tt>default(locale, [:foo, 'default'])</tt> will return +default+ if
111
+ # <tt>translate(locale, :foo)</tt> does not yield a result.
112
+ def default(locale, default, options = {})
113
+ case default
114
+ when String then default
115
+ when Symbol then translate locale, default, options
116
+ when Array then default.each do |obj|
117
+ result = default(locale, obj, options.dup) and return result
118
+ end and nil
119
+ end
120
+ rescue MissingTranslationData
121
+ nil
122
+ end
123
+
124
+ # Picks a translation from an array according to English pluralization
125
+ # rules. It will pick the first translation if count is not equal to 1
126
+ # and the second translation if it is equal to 1. Other backends can
127
+ # implement more flexible or complex pluralization rules.
128
+ def pluralize(locale, entry, count)
129
+ return entry unless entry.is_a?(Hash) and count
130
+ # raise InvalidPluralizationData.new(entry, count) unless entry.is_a?(Hash)
131
+ key = :zero if count == 0 && entry.has_key?(:zero)
132
+ key ||= count == 1 ? :one : :other
133
+ raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key)
134
+ entry[key]
135
+ end
136
+
137
+ # Interpolates values into a given string.
138
+ #
139
+ # interpolate "file {{file}} opened by \\{{user}}", :file => 'test.txt', :user => 'Mr. X'
140
+ # # => "file test.txt opened by {{user}}"
141
+ #
142
+ # Note that you have to double escape the <tt>\\</tt> when you want to escape
143
+ # the <tt>{{...}}</tt> key in a string (once for the string and once for the
144
+ # interpolation).
145
+ def interpolate(locale, string, values = {})
146
+ return string unless string.is_a?(String)
147
+
148
+ if string.respond_to?(:force_encoding)
149
+ original_encoding = string.encoding
150
+ string.force_encoding(Encoding::BINARY)
151
+ end
152
+
153
+ result = string.gsub(MATCH) do
154
+ escaped, pattern, key = $1, $2, $2.to_sym
155
+
156
+ if escaped
157
+ pattern
158
+ elsif INTERPOLATION_RESERVED_KEYS.include?(pattern)
159
+ raise ReservedInterpolationKey.new(pattern, string)
160
+ elsif !values.include?(key)
161
+ raise MissingInterpolationArgument.new(pattern, string)
162
+ else
163
+ values[key].to_s
164
+ end
165
+ end
166
+
167
+ result.force_encoding(original_encoding) if original_encoding
168
+ result
169
+ end
170
+
171
+ # Loads a single translations file by delegating to #load_rb or
172
+ # #load_yml depending on the file extension and directly merges the
173
+ # data to the existing translations. Raises I18n::UnknownFileType
174
+ # for all other file extensions.
175
+ def load_file(filename)
176
+ type = File.extname(filename).tr('.', '').downcase
177
+ raise UnknownFileType.new(type, filename) unless respond_to?(:"load_#{type}")
178
+ data = send :"load_#{type}", filename # TODO raise a meaningful exception if this does not yield a Hash
179
+ data.each { |locale, d| merge_translations(locale, d) }
180
+ end
181
+
182
+ # Loads a plain Ruby translations file. eval'ing the file must yield
183
+ # a Hash containing translation data with locales as toplevel keys.
184
+ def load_rb(filename)
185
+ eval(IO.read(filename), binding, filename)
186
+ end
187
+
188
+ # Loads a YAML translations file. The data must have locales as
189
+ # toplevel keys.
190
+ def load_yml(filename)
191
+ YAML::load(IO.read(filename))
192
+ end
193
+
194
+ # Deep merges the given translations hash with the existing translations
195
+ # for the given locale
196
+ def merge_translations(locale, data)
197
+ locale = locale.to_sym
198
+ translations[locale] ||= {}
199
+ data = deep_symbolize_keys(data)
200
+
201
+ # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
202
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
203
+ translations[locale].merge!(data, &merger)
204
+ end
205
+
206
+ # Return a new hash with all keys and nested keys converted to symbols.
207
+ def deep_symbolize_keys(hash)
208
+ hash.inject({}) { |result, (key, value)|
209
+ value = deep_symbolize_keys(value) if value.is_a? Hash
210
+ result[(key.to_sym rescue key) || key] = value
211
+ result
212
+ }
213
+ end
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,53 @@
1
+ module I18n
2
+ class ArgumentError < ::ArgumentError; end
3
+
4
+ class InvalidLocale < ArgumentError
5
+ attr_reader :locale
6
+ def initialize(locale)
7
+ @locale = locale
8
+ super "#{locale.inspect} is not a valid locale"
9
+ end
10
+ end
11
+
12
+ class MissingTranslationData < ArgumentError
13
+ attr_reader :locale, :key, :options
14
+ def initialize(locale, key, options)
15
+ @key, @locale, @options = key, locale, options
16
+ keys = I18n.send(:normalize_translation_keys, locale, key, options[:scope])
17
+ keys << 'no key' if keys.size < 2
18
+ super "translation missing: #{keys.join(', ')}"
19
+ end
20
+ end
21
+
22
+ class InvalidPluralizationData < ArgumentError
23
+ attr_reader :entry, :count
24
+ def initialize(entry, count)
25
+ @entry, @count = entry, count
26
+ super "translation data #{entry.inspect} can not be used with :count => #{count}"
27
+ end
28
+ end
29
+
30
+ class MissingInterpolationArgument < ArgumentError
31
+ attr_reader :key, :string
32
+ def initialize(key, string)
33
+ @key, @string = key, string
34
+ super "interpolation argument #{key} missing in #{string.inspect}"
35
+ end
36
+ end
37
+
38
+ class ReservedInterpolationKey < ArgumentError
39
+ attr_reader :key, :string
40
+ def initialize(key, string)
41
+ @key, @string = key, string
42
+ super "reserved key #{key.inspect} used in #{string.inspect}"
43
+ end
44
+ end
45
+
46
+ class UnknownFileType < ArgumentError
47
+ attr_reader :type, :filename
48
+ def initialize(type, filename)
49
+ @type, @filename = type, filename
50
+ super "can not load translations from #{filename}, the file type #{type} is not known"
51
+ end
52
+ end
53
+ end
data/lib/i18n.rb CHANGED
@@ -2,39 +2,39 @@
2
2
  # Sven Fuchs (http://www.artweb-design.de),
3
3
  # Joshua Harvey (http://www.workingwithrails.com/person/759-joshua-harvey),
4
4
  # Saimon Moore (http://saimonmoore.net),
5
- # Stephan Soller (http://www.arkanis-development.de/)
5
+ # Stephan Soller (http://www.arkanis-development.de/)
6
6
  # Copyright:: Copyright (c) 2008 The Ruby i18n Team
7
7
  # License:: MIT
8
8
  require 'i18n/backend/simple'
9
9
  require 'i18n/exceptions'
10
10
 
11
- module I18n
11
+ module I18n
12
12
  @@backend = nil
13
- @@load_paths = []
13
+ @@load_path = nil
14
14
  @@default_locale = :'en-US'
15
15
  @@exception_handler = :default_exception_handler
16
-
16
+
17
17
  class << self
18
18
  # Returns the current backend. Defaults to +Backend::Simple+.
19
19
  def backend
20
20
  @@backend ||= Backend::Simple.new
21
21
  end
22
-
22
+
23
23
  # Sets the current backend. Used to set a custom backend.
24
- def backend=(backend)
24
+ def backend=(backend)
25
25
  @@backend = backend
26
26
  end
27
-
27
+
28
28
  # Returns the current default locale. Defaults to 'en-US'
29
29
  def default_locale
30
- @@default_locale
30
+ @@default_locale
31
31
  end
32
-
32
+
33
33
  # Sets the current default locale. Used to set a custom default locale.
34
- def default_locale=(locale)
35
- @@default_locale = locale
34
+ def default_locale=(locale)
35
+ @@default_locale = locale
36
36
  end
37
-
37
+
38
38
  # Returns the current locale. Defaults to I18n.default_locale.
39
39
  def locale
40
40
  Thread.current[:locale] ||= default_locale
@@ -44,42 +44,55 @@ module I18n
44
44
  def locale=(locale)
45
45
  Thread.current[:locale] = locale
46
46
  end
47
-
47
+
48
48
  # Sets the exception handler.
49
49
  def exception_handler=(exception_handler)
50
50
  @@exception_handler = exception_handler
51
51
  end
52
-
53
- # Allow clients to register paths providing translation data sources. The
52
+
53
+ # Allow clients to register paths providing translation data sources. The
54
54
  # backend defines acceptable sources.
55
55
  #
56
56
  # E.g. the provided SimpleBackend accepts a list of paths to translation
57
57
  # files which are either named *.rb and contain plain Ruby Hashes or are
58
- # named *.yml and contain YAML data. So for the SimpleBackend clients may
58
+ # named *.yml and contain YAML data. So for the SimpleBackend clients may
59
59
  # register translation files like this:
60
- # I18n.load_paths << 'path/to/locale/en-US.yml'
61
- def load_paths
62
- @@load_paths
60
+ # I18n.load_path << 'path/to/locale/en-US.yml'
61
+ def load_path
62
+ @@load_path ||= []
63
+ end
64
+
65
+ # Sets the load path instance. Custom implementations are expected to
66
+ # behave like a Ruby Array.
67
+ def load_path=(load_path)
68
+ @@load_path = load_path
69
+ end
70
+
71
+ # Tells the backend to reload translations. Used in situations like the
72
+ # Rails development environment. Backends can implement whatever strategy
73
+ # is useful.
74
+ def reload!
75
+ backend.reload!
63
76
  end
64
-
65
- # Translates, pluralizes and interpolates a given key using a given locale,
77
+
78
+ # Translates, pluralizes and interpolates a given key using a given locale,
66
79
  # scope, and default, as well as interpolation values.
67
80
  #
68
81
  # *LOOKUP*
69
82
  #
70
- # Translation data is organized as a nested hash using the upper-level keys
71
- # as namespaces. <em>E.g.</em>, ActionView ships with the translation:
83
+ # Translation data is organized as a nested hash using the upper-level keys
84
+ # as namespaces. <em>E.g.</em>, ActionView ships with the translation:
72
85
  # <tt>:date => {:formats => {:short => "%b %d"}}</tt>.
73
- #
74
- # Translations can be looked up at any level of this hash using the key argument
75
- # and the scope option. <em>E.g.</em>, in this example <tt>I18n.t :date</tt>
86
+ #
87
+ # Translations can be looked up at any level of this hash using the key argument
88
+ # and the scope option. <em>E.g.</em>, in this example <tt>I18n.t :date</tt>
76
89
  # returns the whole translations hash <tt>{:formats => {:short => "%b %d"}}</tt>.
77
- #
78
- # Key can be either a single key or a dot-separated key (both Strings and Symbols
90
+ #
91
+ # Key can be either a single key or a dot-separated key (both Strings and Symbols
79
92
  # work). <em>E.g.</em>, the short format can be looked up using both:
80
93
  # I18n.t 'date.formats.short'
81
94
  # I18n.t :'date.formats.short'
82
- #
95
+ #
83
96
  # Scope can be either a single key, a dot-separated key or an array of keys
84
97
  # or dot-separated keys. Keys and scopes can be combined freely. So these
85
98
  # examples will all look up the same short date format:
@@ -92,9 +105,9 @@ module I18n
92
105
  #
93
106
  # Translations can contain interpolation variables which will be replaced by
94
107
  # values passed to #translate as part of the options hash, with the keys matching
95
- # the interpolation variable names.
108
+ # the interpolation variable names.
96
109
  #
97
- # <em>E.g.</em>, with a translation <tt>:foo => "foo {{bar}}"</tt> the option
110
+ # <em>E.g.</em>, with a translation <tt>:foo => "foo {{bar}}"</tt> the option
98
111
  # value for the key +bar+ will be interpolated into the translation:
99
112
  # I18n.t :foo, :bar => 'baz' # => 'foo baz'
100
113
  #
@@ -103,7 +116,7 @@ module I18n
103
116
  # Translation data can contain pluralized translations. Pluralized translations
104
117
  # are arrays of singluar/plural versions of translations like <tt>['Foo', 'Foos']</tt>.
105
118
  #
106
- # Note that <tt>I18n::Backend::Simple</tt> only supports an algorithm for English
119
+ # Note that <tt>I18n::Backend::Simple</tt> only supports an algorithm for English
107
120
  # pluralization rules. Other algorithms can be supported by custom backends.
108
121
  #
109
122
  # This returns the singular version of a pluralized translation:
@@ -112,9 +125,9 @@ module I18n
112
125
  # These both return the plural version of a pluralized translation:
113
126
  # I18n.t :foo, :count => 0 # => 'Foos'
114
127
  # I18n.t :foo, :count => 2 # => 'Foos'
115
- #
116
- # The <tt>:count</tt> option can be used both for pluralization and interpolation.
117
- # <em>E.g.</em>, with the translation
128
+ #
129
+ # The <tt>:count</tt> option can be used both for pluralization and interpolation.
130
+ # <em>E.g.</em>, with the translation
118
131
  # <tt>:foo => ['{{count}} foo', '{{count}} foos']</tt>, count will
119
132
  # be interpolated to the pluralized translation:
120
133
  # I18n.t :foo, :count => 1 # => '1 foo'
@@ -124,11 +137,11 @@ module I18n
124
137
  # This returns the translation for <tt>:foo</tt> or <tt>default</tt> if no translation was found:
125
138
  # I18n.t :foo, :default => 'default'
126
139
  #
127
- # This returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt> if no
140
+ # This returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt> if no
128
141
  # translation for <tt>:foo</tt> was found:
129
142
  # I18n.t :foo, :default => :bar
130
143
  #
131
- # Returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt>
144
+ # Returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt>
132
145
  # or <tt>default</tt> if no translations for <tt>:foo</tt> and <tt>:bar</tt> were found.
133
146
  # I18n.t :foo, :default => [:bar, 'default']
134
147
  #
@@ -144,13 +157,13 @@ module I18n
144
157
  # I18n.t [:foo, :bar], :scope => :baz
145
158
  def translate(key, options = {})
146
159
  locale = options.delete(:locale) || I18n.locale
147
- backend.translate locale, key, options
160
+ backend.translate(locale, key, options)
148
161
  rescue I18n::ArgumentError => e
149
162
  raise e if options[:raise]
150
- send @@exception_handler, e, locale, key, options
151
- end
163
+ send(@@exception_handler, e, locale, key, options)
164
+ end
152
165
  alias :t :translate
153
-
166
+
154
167
  # Localizes certain objects, such as dates and numbers to local formatting.
155
168
  def localize(object, options = {})
156
169
  locale = options[:locale] || I18n.locale
@@ -158,7 +171,7 @@ module I18n
158
171
  backend.localize(locale, object, format)
159
172
  end
160
173
  alias :l :localize
161
-
174
+
162
175
  protected
163
176
  # Handles exceptions raised in the backend. All exceptions except for
164
177
  # MissingTranslationData exceptions are re-raised. When a MissingTranslationData
@@ -168,14 +181,14 @@ module I18n
168
181
  return exception.message if MissingTranslationData === exception
169
182
  raise exception
170
183
  end
171
-
184
+
172
185
  # Merges the given locale, key and scope into a single array of keys.
173
186
  # Splits keys that contain dots into multiple keys. Makes sure all
174
187
  # keys are Symbols.
175
188
  def normalize_translation_keys(locale, key, scope)
176
189
  keys = [locale] + Array(scope) + [key]
177
- keys = keys.map{|k| k.to_s.split(/\./) }
178
- keys.flatten.map{|k| k.to_sym}
190
+ keys = keys.map { |k| k.to_s.split(/\./) }
191
+ keys.flatten.map { |k| k.to_sym }
179
192
  end
180
193
  end
181
- end
194
+ end
data/test/all.rb ADDED
@@ -0,0 +1,5 @@
1
+ dir = File.dirname(__FILE__)
2
+ require dir + '/i18n_test.rb'
3
+ require dir + '/simple_backend_test.rb'
4
+ require dir + '/i18n_exceptions_test.rb'
5
+ # *require* dir + '/custom_backend_test.rb'
@@ -0,0 +1,100 @@
1
+ $:.unshift "lib"
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'mocha'
6
+ require 'i18n'
7
+ require 'active_support'
8
+
9
+ class I18nExceptionsTest < Test::Unit::TestCase
10
+ def test_invalid_locale_stores_locale
11
+ force_invalid_locale
12
+ rescue I18n::ArgumentError => e
13
+ assert_nil e.locale
14
+ end
15
+
16
+ def test_invalid_locale_message
17
+ force_invalid_locale
18
+ rescue I18n::ArgumentError => e
19
+ assert_equal 'nil is not a valid locale', e.message
20
+ end
21
+
22
+ def test_missing_translation_data_stores_locale_key_and_options
23
+ force_missing_translation_data
24
+ rescue I18n::ArgumentError => e
25
+ options = {:scope => :bar}
26
+ assert_equal 'de-DE', e.locale
27
+ assert_equal :foo, e.key
28
+ assert_equal options, e.options
29
+ end
30
+
31
+ def test_missing_translation_data_message
32
+ force_missing_translation_data
33
+ rescue I18n::ArgumentError => e
34
+ assert_equal 'translation missing: de-DE, bar, foo', e.message
35
+ end
36
+
37
+ def test_invalid_pluralization_data_stores_entry_and_count
38
+ force_invalid_pluralization_data
39
+ rescue I18n::ArgumentError => e
40
+ assert_equal [:bar], e.entry
41
+ assert_equal 1, e.count
42
+ end
43
+
44
+ def test_invalid_pluralization_data_message
45
+ force_invalid_pluralization_data
46
+ rescue I18n::ArgumentError => e
47
+ assert_equal 'translation data [:bar] can not be used with :count => 1', e.message
48
+ end
49
+
50
+ def test_missing_interpolation_argument_stores_key_and_string
51
+ force_missing_interpolation_argument
52
+ rescue I18n::ArgumentError => e
53
+ assert_equal 'bar', e.key
54
+ assert_equal "{{bar}}", e.string
55
+ end
56
+
57
+ def test_missing_interpolation_argument_message
58
+ force_missing_interpolation_argument
59
+ rescue I18n::ArgumentError => e
60
+ assert_equal 'interpolation argument bar missing in "{{bar}}"', e.message
61
+ end
62
+
63
+ def test_reserved_interpolation_key_stores_key_and_string
64
+ force_reserved_interpolation_key
65
+ rescue I18n::ArgumentError => e
66
+ assert_equal 'scope', e.key
67
+ assert_equal "{{scope}}", e.string
68
+ end
69
+
70
+ def test_reserved_interpolation_key_message
71
+ force_reserved_interpolation_key
72
+ rescue I18n::ArgumentError => e
73
+ assert_equal 'reserved key "scope" used in "{{scope}}"', e.message
74
+ end
75
+
76
+ private
77
+ def force_invalid_locale
78
+ I18n.backend.translate nil, :foo
79
+ end
80
+
81
+ def force_missing_translation_data
82
+ I18n.backend.store_translations 'de-DE', :bar => nil
83
+ I18n.backend.translate 'de-DE', :foo, :scope => :bar
84
+ end
85
+
86
+ def force_invalid_pluralization_data
87
+ I18n.backend.store_translations 'de-DE', :foo => [:bar]
88
+ I18n.backend.translate 'de-DE', :foo, :count => 1
89
+ end
90
+
91
+ def force_missing_interpolation_argument
92
+ I18n.backend.store_translations 'de-DE', :foo => "{{bar}}"
93
+ I18n.backend.translate 'de-DE', :foo, :baz => 'baz'
94
+ end
95
+
96
+ def force_reserved_interpolation_key
97
+ I18n.backend.store_translations 'de-DE', :foo => "{{scope}}"
98
+ I18n.backend.translate 'de-DE', :foo, :baz => 'baz'
99
+ end
100
+ end
data/test/i18n_test.rb ADDED
@@ -0,0 +1,125 @@
1
+ $:.unshift "lib"
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'mocha'
6
+ require 'i18n'
7
+ require 'active_support'
8
+
9
+ class I18nTest < Test::Unit::TestCase
10
+ def setup
11
+ I18n.backend.store_translations :'en-US', {
12
+ :currency => {
13
+ :format => {
14
+ :separator => '.',
15
+ :delimiter => ',',
16
+ }
17
+ }
18
+ }
19
+ end
20
+
21
+ def test_uses_simple_backend_set_by_default
22
+ assert I18n.backend.is_a?(I18n::Backend::Simple)
23
+ end
24
+
25
+ def test_can_set_backend
26
+ assert_nothing_raised{ I18n.backend = self }
27
+ assert_equal self, I18n.backend
28
+ I18n.backend = I18n::Backend::Simple.new
29
+ end
30
+
31
+ def test_uses_en_us_as_default_locale_by_default
32
+ assert_equal 'en-US', I18n.default_locale
33
+ end
34
+
35
+ def test_can_set_default_locale
36
+ assert_nothing_raised{ I18n.default_locale = 'de-DE' }
37
+ assert_equal 'de-DE', I18n.default_locale
38
+ I18n.default_locale = 'en-US'
39
+ end
40
+
41
+ def test_uses_default_locale_as_locale_by_default
42
+ assert_equal I18n.default_locale, I18n.locale
43
+ end
44
+
45
+ def test_can_set_locale_to_thread_current
46
+ assert_nothing_raised{ I18n.locale = 'de-DE' }
47
+ assert_equal 'de-DE', I18n.locale
48
+ assert_equal 'de-DE', Thread.current[:locale]
49
+ I18n.locale = 'en-US'
50
+ end
51
+
52
+ def test_can_set_exception_handler
53
+ assert_nothing_raised{ I18n.exception_handler = :custom_exception_handler }
54
+ I18n.exception_handler = :default_exception_handler # revert it
55
+ end
56
+
57
+ def test_uses_custom_exception_handler
58
+ I18n.exception_handler = :custom_exception_handler
59
+ I18n.expects(:custom_exception_handler)
60
+ I18n.translate :bogus
61
+ I18n.exception_handler = :default_exception_handler # revert it
62
+ end
63
+
64
+ def test_delegates_translate_to_backend
65
+ I18n.backend.expects(:translate).with 'de-DE', :foo, {}
66
+ I18n.translate :foo, :locale => 'de-DE'
67
+ end
68
+
69
+ def test_delegates_localize_to_backend
70
+ I18n.backend.expects(:localize).with 'de-DE', :whatever, :default
71
+ I18n.localize :whatever, :locale => 'de-DE'
72
+ end
73
+
74
+ def test_translate_given_no_locale_uses_i18n_locale
75
+ I18n.backend.expects(:translate).with 'en-US', :foo, {}
76
+ I18n.translate :foo
77
+ end
78
+
79
+ def test_translate_on_nested_symbol_keys_works
80
+ assert_equal ".", I18n.t(:'currency.format.separator')
81
+ end
82
+
83
+ def test_translate_with_nested_string_keys_works
84
+ assert_equal ".", I18n.t('currency.format.separator')
85
+ end
86
+
87
+ def test_translate_with_array_as_scope_works
88
+ assert_equal ".", I18n.t(:separator, :scope => ['currency.format'])
89
+ end
90
+
91
+ def test_translate_with_array_containing_dot_separated_strings_as_scope_works
92
+ assert_equal ".", I18n.t(:separator, :scope => ['currency.format'])
93
+ end
94
+
95
+ def test_translate_with_key_array_and_dot_separated_scope_works
96
+ assert_equal [".", ","], I18n.t(%w(separator delimiter), :scope => 'currency.format')
97
+ end
98
+
99
+ def test_translate_with_dot_separated_key_array_and_scope_works
100
+ assert_equal [".", ","], I18n.t(%w(format.separator format.delimiter), :scope => 'currency')
101
+ end
102
+
103
+ def test_translate_with_options_using_scope_works
104
+ I18n.backend.expects(:translate).with('de-DE', :precision, :scope => :"currency.format")
105
+ I18n.with_options :locale => 'de-DE', :scope => :'currency.format' do |locale|
106
+ locale.t :precision
107
+ end
108
+ end
109
+
110
+ # def test_translate_given_no_args_raises_missing_translation_data
111
+ # assert_equal "translation missing: en-US, no key", I18n.t
112
+ # end
113
+
114
+ def test_translate_given_a_bogus_key_raises_missing_translation_data
115
+ assert_equal "translation missing: en-US, bogus", I18n.t(:bogus)
116
+ end
117
+
118
+ def test_localize_nil_raises_argument_error
119
+ assert_raises(I18n::ArgumentError) { I18n.l nil }
120
+ end
121
+
122
+ def test_localize_object_raises_argument_error
123
+ assert_raises(I18n::ArgumentError) { I18n.l Object.new }
124
+ end
125
+ end
@@ -0,0 +1 @@
1
+ {:'en-US-Ruby' => {:foo => {:bar => "baz"}}}
@@ -0,0 +1,3 @@
1
+ en-US-Yaml:
2
+ foo:
3
+ bar: baz
@@ -0,0 +1,502 @@
1
+ # encoding: utf-8
2
+ $:.unshift "lib"
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'mocha'
7
+ require 'i18n'
8
+ require 'time'
9
+ require 'yaml'
10
+
11
+ module I18nSimpleBackendTestSetup
12
+ def setup_backend
13
+ # backend_reset_translations!
14
+ @backend = I18n::Backend::Simple.new
15
+ @backend.store_translations 'en-US', :foo => {:bar => 'bar', :baz => 'baz'}
16
+ @locale_dir = File.dirname(__FILE__) + '/locale'
17
+ end
18
+ alias :setup :setup_backend
19
+
20
+ # def backend_reset_translations!
21
+ # I18n::Backend::Simple::ClassMethods.send :class_variable_set, :@@translations, {}
22
+ # end
23
+
24
+ def backend_get_translations
25
+ # I18n::Backend::Simple::ClassMethods.send :class_variable_get, :@@translations
26
+ @backend.instance_variable_get :@translations
27
+ end
28
+
29
+ def add_datetime_translations
30
+ @backend.store_translations :'de-DE', {
31
+ :date => {
32
+ :formats => {
33
+ :default => "%d.%m.%Y",
34
+ :short => "%d. %b",
35
+ :long => "%d. %B %Y",
36
+ },
37
+ :day_names => %w(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag),
38
+ :abbr_day_names => %w(So Mo Di Mi Do Fr Sa),
39
+ :month_names => %w(Januar Februar März April Mai Juni Juli August September Oktober November Dezember).unshift(nil),
40
+ :abbr_month_names => %w(Jan Feb Mar Apr Mai Jun Jul Aug Sep Okt Nov Dez).unshift(nil),
41
+ :order => [:day, :month, :year]
42
+ },
43
+ :time => {
44
+ :formats => {
45
+ :default => "%a, %d. %b %Y %H:%M:%S %z",
46
+ :short => "%d. %b %H:%M",
47
+ :long => "%d. %B %Y %H:%M",
48
+ },
49
+ :am => 'am',
50
+ :pm => 'pm'
51
+ },
52
+ :datetime => {
53
+ :distance_in_words => {
54
+ :half_a_minute => 'half a minute',
55
+ :less_than_x_seconds => {
56
+ :one => 'less than 1 second',
57
+ :other => 'less than {{count}} seconds'
58
+ },
59
+ :x_seconds => {
60
+ :one => '1 second',
61
+ :other => '{{count}} seconds'
62
+ },
63
+ :less_than_x_minutes => {
64
+ :one => 'less than a minute',
65
+ :other => 'less than {{count}} minutes'
66
+ },
67
+ :x_minutes => {
68
+ :one => '1 minute',
69
+ :other => '{{count}} minutes'
70
+ },
71
+ :about_x_hours => {
72
+ :one => 'about 1 hour',
73
+ :other => 'about {{count}} hours'
74
+ },
75
+ :x_days => {
76
+ :one => '1 day',
77
+ :other => '{{count}} days'
78
+ },
79
+ :about_x_months => {
80
+ :one => 'about 1 month',
81
+ :other => 'about {{count}} months'
82
+ },
83
+ :x_months => {
84
+ :one => '1 month',
85
+ :other => '{{count}} months'
86
+ },
87
+ :about_x_years => {
88
+ :one => 'about 1 year',
89
+ :other => 'about {{count}} year'
90
+ },
91
+ :over_x_years => {
92
+ :one => 'over 1 year',
93
+ :other => 'over {{count}} years'
94
+ }
95
+ }
96
+ }
97
+ }
98
+ end
99
+ end
100
+
101
+ class I18nSimpleBackendTranslationsTest < Test::Unit::TestCase
102
+ include I18nSimpleBackendTestSetup
103
+
104
+ def test_store_translations_adds_translations # no, really :-)
105
+ @backend.store_translations :'en-US', :foo => 'bar'
106
+ assert_equal Hash[:'en-US', {:foo => 'bar'}], backend_get_translations
107
+ end
108
+
109
+ def test_store_translations_deep_merges_translations
110
+ @backend.store_translations :'en-US', :foo => {:bar => 'bar'}
111
+ @backend.store_translations :'en-US', :foo => {:baz => 'baz'}
112
+ assert_equal Hash[:'en-US', {:foo => {:bar => 'bar', :baz => 'baz'}}], backend_get_translations
113
+ end
114
+
115
+ def test_store_translations_forces_locale_to_sym
116
+ @backend.store_translations 'en-US', :foo => 'bar'
117
+ assert_equal Hash[:'en-US', {:foo => 'bar'}], backend_get_translations
118
+ end
119
+
120
+ def test_store_translations_converts_keys_to_symbols
121
+ # backend_reset_translations!
122
+ @backend.store_translations 'en-US', 'foo' => {'bar' => 'bar', 'baz' => 'baz'}
123
+ assert_equal Hash[:'en-US', {:foo => {:bar => 'bar', :baz => 'baz'}}], backend_get_translations
124
+ end
125
+ end
126
+
127
+ class I18nSimpleBackendTranslateTest < Test::Unit::TestCase
128
+ include I18nSimpleBackendTestSetup
129
+
130
+ def test_translate_calls_lookup_with_locale_given
131
+ @backend.expects(:lookup).with('de-DE', :bar, [:foo]).returns 'bar'
132
+ @backend.translate 'de-DE', :bar, :scope => [:foo]
133
+ end
134
+
135
+ def test_given_no_keys_it_returns_the_default
136
+ assert_equal 'default', @backend.translate('en-US', nil, :default => 'default')
137
+ end
138
+
139
+ def test_translate_given_a_symbol_as_a_default_translates_the_symbol
140
+ assert_equal 'bar', @backend.translate('en-US', nil, :scope => [:foo], :default => :bar)
141
+ end
142
+
143
+ def test_translate_given_an_array_as_default_uses_the_first_match
144
+ assert_equal 'bar', @backend.translate('en-US', :does_not_exist, :scope => [:foo], :default => [:does_not_exist_2, :bar])
145
+ end
146
+
147
+ def test_translate_given_an_array_of_inexistent_keys_it_raises_missing_translation_data
148
+ assert_raises I18n::MissingTranslationData do
149
+ @backend.translate('en-US', :does_not_exist, :scope => [:foo], :default => [:does_not_exist_2, :does_not_exist_3])
150
+ end
151
+ end
152
+
153
+ def test_translate_an_array_of_keys_translates_all_of_them
154
+ assert_equal %w(bar baz), @backend.translate('en-US', [:bar, :baz], :scope => [:foo])
155
+ end
156
+
157
+ def test_translate_calls_pluralize
158
+ @backend.expects(:pluralize).with 'en-US', 'bar', 1
159
+ @backend.translate 'en-US', :bar, :scope => [:foo], :count => 1
160
+ end
161
+
162
+ def test_translate_calls_interpolate
163
+ @backend.expects(:interpolate).with 'en-US', 'bar', {}
164
+ @backend.translate 'en-US', :bar, :scope => [:foo]
165
+ end
166
+
167
+ def test_translate_calls_interpolate_including_count_as_a_value
168
+ @backend.expects(:interpolate).with 'en-US', 'bar', {:count => 1}
169
+ @backend.translate 'en-US', :bar, :scope => [:foo], :count => 1
170
+ end
171
+
172
+ def test_translate_given_nil_as_a_locale_raises_an_argument_error
173
+ assert_raises(I18n::InvalidLocale){ @backend.translate nil, :bar }
174
+ end
175
+
176
+ def test_translate_with_a_bogus_key_and_no_default_raises_missing_translation_data
177
+ assert_raises(I18n::MissingTranslationData){ @backend.translate 'de-DE', :bogus }
178
+ end
179
+ end
180
+
181
+ class I18nSimpleBackendLookupTest < Test::Unit::TestCase
182
+ include I18nSimpleBackendTestSetup
183
+
184
+ # useful because this way we can use the backend with no key for interpolation/pluralization
185
+ def test_lookup_given_nil_as_a_key_returns_nil
186
+ assert_nil @backend.send(:lookup, 'en-US', nil)
187
+ end
188
+
189
+ def test_lookup_given_nested_keys_looks_up_a_nested_hash_value
190
+ assert_equal 'bar', @backend.send(:lookup, 'en-US', :bar, [:foo])
191
+ end
192
+ end
193
+
194
+ class I18nSimpleBackendPluralizeTest < Test::Unit::TestCase
195
+ include I18nSimpleBackendTestSetup
196
+
197
+ def test_pluralize_given_nil_returns_the_given_entry
198
+ entry = {:one => 'bar', :other => 'bars'}
199
+ assert_equal entry, @backend.send(:pluralize, nil, entry, nil)
200
+ end
201
+
202
+ def test_pluralize_given_0_returns_zero_string_if_zero_key_given
203
+ assert_equal 'zero', @backend.send(:pluralize, nil, {:zero => 'zero', :one => 'bar', :other => 'bars'}, 0)
204
+ end
205
+
206
+ def test_pluralize_given_0_returns_plural_string_if_no_zero_key_given
207
+ assert_equal 'bars', @backend.send(:pluralize, nil, {:one => 'bar', :other => 'bars'}, 0)
208
+ end
209
+
210
+ def test_pluralize_given_1_returns_singular_string
211
+ assert_equal 'bar', @backend.send(:pluralize, nil, {:one => 'bar', :other => 'bars'}, 1)
212
+ end
213
+
214
+ def test_pluralize_given_2_returns_plural_string
215
+ assert_equal 'bars', @backend.send(:pluralize, nil, {:one => 'bar', :other => 'bars'}, 2)
216
+ end
217
+
218
+ def test_pluralize_given_3_returns_plural_string
219
+ assert_equal 'bars', @backend.send(:pluralize, nil, {:one => 'bar', :other => 'bars'}, 3)
220
+ end
221
+
222
+ def test_interpolate_given_incomplete_pluralization_data_raises_invalid_pluralization_data
223
+ assert_raises(I18n::InvalidPluralizationData){ @backend.send(:pluralize, nil, {:one => 'bar'}, 2) }
224
+ end
225
+
226
+ # def test_interpolate_given_a_string_raises_invalid_pluralization_data
227
+ # assert_raises(I18n::InvalidPluralizationData){ @backend.send(:pluralize, nil, 'bar', 2) }
228
+ # end
229
+ #
230
+ # def test_interpolate_given_an_array_raises_invalid_pluralization_data
231
+ # assert_raises(I18n::InvalidPluralizationData){ @backend.send(:pluralize, nil, ['bar'], 2) }
232
+ # end
233
+ end
234
+
235
+ class I18nSimpleBackendInterpolateTest < Test::Unit::TestCase
236
+ include I18nSimpleBackendTestSetup
237
+
238
+ def test_interpolate_given_a_value_hash_interpolates_the_values_to_the_string
239
+ assert_equal 'Hi David!', @backend.send(:interpolate, nil, 'Hi {{name}}!', :name => 'David')
240
+ end
241
+
242
+ def test_interpolate_given_a_value_hash_interpolates_into_unicode_string
243
+ assert_equal 'Häi David!', @backend.send(:interpolate, nil, 'Häi {{name}}!', :name => 'David')
244
+ end
245
+
246
+ def test_interpolate_given_nil_as_a_string_returns_nil
247
+ assert_nil @backend.send(:interpolate, nil, nil, :name => 'David')
248
+ end
249
+
250
+ def test_interpolate_given_an_non_string_as_a_string_returns_nil
251
+ assert_equal [], @backend.send(:interpolate, nil, [], :name => 'David')
252
+ end
253
+
254
+ def test_interpolate_given_a_values_hash_with_nil_values_interpolates_the_string
255
+ assert_equal 'Hi !', @backend.send(:interpolate, nil, 'Hi {{name}}!', {:name => nil})
256
+ end
257
+
258
+ def test_interpolate_given_an_empty_values_hash_raises_missing_interpolation_argument
259
+ assert_raises(I18n::MissingInterpolationArgument) { @backend.send(:interpolate, nil, 'Hi {{name}}!', {}) }
260
+ end
261
+
262
+ def test_interpolate_given_a_string_containing_a_reserved_key_raises_reserved_interpolation_key
263
+ assert_raises(I18n::ReservedInterpolationKey) { @backend.send(:interpolate, nil, '{{default}}', {:default => nil}) }
264
+ end
265
+ end
266
+
267
+ class I18nSimpleBackendLocalizeDateTest < Test::Unit::TestCase
268
+ include I18nSimpleBackendTestSetup
269
+
270
+ def setup
271
+ @backend = I18n::Backend::Simple.new
272
+ add_datetime_translations
273
+ @date = Date.new 2008, 1, 1
274
+ end
275
+
276
+ def test_translate_given_the_short_format_it_uses_it
277
+ assert_equal '01. Jan', @backend.localize('de-DE', @date, :short)
278
+ end
279
+
280
+ def test_translate_given_the_long_format_it_uses_it
281
+ assert_equal '01. Januar 2008', @backend.localize('de-DE', @date, :long)
282
+ end
283
+
284
+ def test_translate_given_the_default_format_it_uses_it
285
+ assert_equal '01.01.2008', @backend.localize('de-DE', @date, :default)
286
+ end
287
+
288
+ def test_translate_given_a_day_name_format_it_returns_a_day_name
289
+ assert_equal 'Dienstag', @backend.localize('de-DE', @date, '%A')
290
+ end
291
+
292
+ def test_translate_given_an_abbr_day_name_format_it_returns_an_abbrevated_day_name
293
+ assert_equal 'Di', @backend.localize('de-DE', @date, '%a')
294
+ end
295
+
296
+ def test_translate_given_a_month_name_format_it_returns_a_month_name
297
+ assert_equal 'Januar', @backend.localize('de-DE', @date, '%B')
298
+ end
299
+
300
+ def test_translate_given_an_abbr_month_name_format_it_returns_an_abbrevated_month_name
301
+ assert_equal 'Jan', @backend.localize('de-DE', @date, '%b')
302
+ end
303
+
304
+ def test_translate_given_no_format_it_does_not_fail
305
+ assert_nothing_raised{ @backend.localize 'de-DE', @date }
306
+ end
307
+
308
+ def test_translate_given_an_unknown_format_it_does_not_fail
309
+ assert_nothing_raised{ @backend.localize 'de-DE', @date, '%x' }
310
+ end
311
+
312
+ def test_localize_nil_raises_argument_error
313
+ assert_raises(I18n::ArgumentError) { @backend.localize 'de-DE', nil }
314
+ end
315
+
316
+ def test_localize_object_raises_argument_error
317
+ assert_raises(I18n::ArgumentError) { @backend.localize 'de-DE', Object.new }
318
+ end
319
+ end
320
+
321
+ class I18nSimpleBackendLocalizeDateTimeTest < Test::Unit::TestCase
322
+ include I18nSimpleBackendTestSetup
323
+
324
+ def setup
325
+ @backend = I18n::Backend::Simple.new
326
+ add_datetime_translations
327
+ @morning = DateTime.new 2008, 1, 1, 6
328
+ @evening = DateTime.new 2008, 1, 1, 18
329
+ end
330
+
331
+ def test_translate_given_the_short_format_it_uses_it
332
+ assert_equal '01. Jan 06:00', @backend.localize('de-DE', @morning, :short)
333
+ end
334
+
335
+ def test_translate_given_the_long_format_it_uses_it
336
+ assert_equal '01. Januar 2008 06:00', @backend.localize('de-DE', @morning, :long)
337
+ end
338
+
339
+ def test_translate_given_the_default_format_it_uses_it
340
+ assert_equal 'Di, 01. Jan 2008 06:00:00 +0000', @backend.localize('de-DE', @morning, :default)
341
+ end
342
+
343
+ def test_translate_given_a_day_name_format_it_returns_the_correct_day_name
344
+ assert_equal 'Dienstag', @backend.localize('de-DE', @morning, '%A')
345
+ end
346
+
347
+ def test_translate_given_an_abbr_day_name_format_it_returns_the_correct_abbrevated_day_name
348
+ assert_equal 'Di', @backend.localize('de-DE', @morning, '%a')
349
+ end
350
+
351
+ def test_translate_given_a_month_name_format_it_returns_the_correct_month_name
352
+ assert_equal 'Januar', @backend.localize('de-DE', @morning, '%B')
353
+ end
354
+
355
+ def test_translate_given_an_abbr_month_name_format_it_returns_the_correct_abbrevated_month_name
356
+ assert_equal 'Jan', @backend.localize('de-DE', @morning, '%b')
357
+ end
358
+
359
+ def test_translate_given_a_meridian_indicator_format_it_returns_the_correct_meridian_indicator
360
+ assert_equal 'am', @backend.localize('de-DE', @morning, '%p')
361
+ assert_equal 'pm', @backend.localize('de-DE', @evening, '%p')
362
+ end
363
+
364
+ def test_translate_given_no_format_it_does_not_fail
365
+ assert_nothing_raised{ @backend.localize 'de-DE', @morning }
366
+ end
367
+
368
+ def test_translate_given_an_unknown_format_it_does_not_fail
369
+ assert_nothing_raised{ @backend.localize 'de-DE', @morning, '%x' }
370
+ end
371
+ end
372
+
373
+ class I18nSimpleBackendLocalizeTimeTest < Test::Unit::TestCase
374
+ include I18nSimpleBackendTestSetup
375
+
376
+ def setup
377
+ @old_timezone, ENV['TZ'] = ENV['TZ'], 'UTC'
378
+ @backend = I18n::Backend::Simple.new
379
+ add_datetime_translations
380
+ @morning = Time.parse '2008-01-01 6:00 UTC'
381
+ @evening = Time.parse '2008-01-01 18:00 UTC'
382
+ end
383
+
384
+ def teardown
385
+ @old_timezone ? ENV['TZ'] = @old_timezone : ENV.delete('TZ')
386
+ end
387
+
388
+ def test_translate_given_the_short_format_it_uses_it
389
+ assert_equal '01. Jan 06:00', @backend.localize('de-DE', @morning, :short)
390
+ end
391
+
392
+ def test_translate_given_the_long_format_it_uses_it
393
+ assert_equal '01. Januar 2008 06:00', @backend.localize('de-DE', @morning, :long)
394
+ end
395
+
396
+ # TODO Seems to break on Windows because ENV['TZ'] is ignored. What's a better way to do this?
397
+ # def test_translate_given_the_default_format_it_uses_it
398
+ # assert_equal 'Di, 01. Jan 2008 06:00:00 +0000', @backend.localize('de-DE', @morning, :default)
399
+ # end
400
+
401
+ def test_translate_given_a_day_name_format_it_returns_the_correct_day_name
402
+ assert_equal 'Dienstag', @backend.localize('de-DE', @morning, '%A')
403
+ end
404
+
405
+ def test_translate_given_an_abbr_day_name_format_it_returns_the_correct_abbrevated_day_name
406
+ assert_equal 'Di', @backend.localize('de-DE', @morning, '%a')
407
+ end
408
+
409
+ def test_translate_given_a_month_name_format_it_returns_the_correct_month_name
410
+ assert_equal 'Januar', @backend.localize('de-DE', @morning, '%B')
411
+ end
412
+
413
+ def test_translate_given_an_abbr_month_name_format_it_returns_the_correct_abbrevated_month_name
414
+ assert_equal 'Jan', @backend.localize('de-DE', @morning, '%b')
415
+ end
416
+
417
+ def test_translate_given_a_meridian_indicator_format_it_returns_the_correct_meridian_indicator
418
+ assert_equal 'am', @backend.localize('de-DE', @morning, '%p')
419
+ assert_equal 'pm', @backend.localize('de-DE', @evening, '%p')
420
+ end
421
+
422
+ def test_translate_given_no_format_it_does_not_fail
423
+ assert_nothing_raised{ @backend.localize 'de-DE', @morning }
424
+ end
425
+
426
+ def test_translate_given_an_unknown_format_it_does_not_fail
427
+ assert_nothing_raised{ @backend.localize 'de-DE', @morning, '%x' }
428
+ end
429
+ end
430
+
431
+ class I18nSimpleBackendHelperMethodsTest < Test::Unit::TestCase
432
+ def setup
433
+ @backend = I18n::Backend::Simple.new
434
+ end
435
+
436
+ def test_deep_symbolize_keys_works
437
+ result = @backend.send :deep_symbolize_keys, 'foo' => {'bar' => {'baz' => 'bar'}}
438
+ expected = {:foo => {:bar => {:baz => 'bar'}}}
439
+ assert_equal expected, result
440
+ end
441
+ end
442
+
443
+ class I18nSimpleBackendLoadTranslationsTest < Test::Unit::TestCase
444
+ include I18nSimpleBackendTestSetup
445
+
446
+ def test_load_translations_with_unknown_file_type_raises_exception
447
+ assert_raises(I18n::UnknownFileType) { @backend.load_translations "#{@locale_dir}/en-US.xml" }
448
+ end
449
+
450
+ def test_load_translations_with_ruby_file_type_does_not_raise_exception
451
+ assert_nothing_raised { @backend.load_translations "#{@locale_dir}/en-US.rb" }
452
+ end
453
+
454
+ def test_load_rb_loads_data_from_ruby_file
455
+ data = @backend.send :load_rb, "#{@locale_dir}/en-US.rb"
456
+ assert_equal({:'en-US-Ruby' => {:foo => {:bar => "baz"}}}, data)
457
+ end
458
+
459
+ def test_load_rb_loads_data_from_yaml_file
460
+ data = @backend.send :load_yml, "#{@locale_dir}/en-US.yml"
461
+ assert_equal({'en-US-Yaml' => {'foo' => {'bar' => 'baz'}}}, data)
462
+ end
463
+
464
+ def test_load_translations_loads_from_different_file_formats
465
+ @backend = I18n::Backend::Simple.new
466
+ @backend.load_translations "#{@locale_dir}/en-US.rb", "#{@locale_dir}/en-US.yml"
467
+ expected = {
468
+ :'en-US-Ruby' => {:foo => {:bar => "baz"}},
469
+ :'en-US-Yaml' => {:foo => {:bar => "baz"}}
470
+ }
471
+ assert_equal expected, backend_get_translations
472
+ end
473
+ end
474
+
475
+ class I18nSimpleBackendReloadTranslationsTest < Test::Unit::TestCase
476
+ include I18nSimpleBackendTestSetup
477
+
478
+ def setup
479
+ @backend = I18n::Backend::Simple.new
480
+ I18n.load_path = [File.dirname(__FILE__) + '/locale/en-US.yml']
481
+ assert_nil backend_get_translations
482
+ @backend.send :init_translations
483
+ end
484
+
485
+ def teardown
486
+ I18n.load_path = []
487
+ end
488
+
489
+ def test_setup
490
+ assert_not_nil backend_get_translations
491
+ end
492
+
493
+ def test_reload_translations_unloads_translations
494
+ @backend.reload!
495
+ assert_nil backend_get_translations
496
+ end
497
+
498
+ def test_reload_translations_uninitializes_translations
499
+ @backend.reload!
500
+ assert_equal @backend.initialized?, false
501
+ end
502
+ end
metadata CHANGED
@@ -1,10 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svenfuchs-i18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Fuchs
8
+ - Joshua Harvey
8
9
  - Matt Aimonetti
9
10
  - Stephan Soller
10
11
  - Saimon Moore
@@ -12,12 +13,12 @@ autorequire:
12
13
  bindir: bin
13
14
  cert_chain: []
14
15
 
15
- date: 2008-06-13 00:00:00 -07:00
16
+ date: 2008-10-26 00:00:00 -07:00
16
17
  default_executable:
17
18
  dependencies: []
18
19
 
19
- description: Add Internationalization to your Ruby application.
20
- email: rails-patch-i18n@googlegroups.com
20
+ description: Add Internationalization support to your Ruby application.
21
+ email: rails-i18n@googlegroups.com
21
22
  executables: []
22
23
 
23
24
  extensions: []
@@ -25,19 +26,14 @@ extensions: []
25
26
  extra_rdoc_files: []
26
27
 
27
28
  files:
28
- - lib/i18n/backend/minimal.rb
29
- - lib/i18n/core_ext.rb
30
- - lib/i18n/localization.rb
31
- - lib/i18n/translation.rb
29
+ - i18n.gemspec
30
+ - lib/i18n/backend/simple.rb
31
+ - lib/i18n/exceptions.rb
32
32
  - lib/i18n.rb
33
- - LICENSE
34
- - README
35
- - spec/core_ext_spec.rb
36
- - spec/i18n_spec.rb
37
- - spec/spec.opts
38
- - spec/spec/helper.rb
33
+ - MIT-LICENSE
34
+ - README.textile
39
35
  has_rdoc: false
40
- homepage: http://groups.google.com/group/rails-patch-i18n
36
+ homepage: http://rails-i18n.org
41
37
  post_install_message:
42
38
  rdoc_options: []
43
39
 
@@ -61,6 +57,11 @@ rubyforge_project:
61
57
  rubygems_version: 1.2.0
62
58
  signing_key:
63
59
  specification_version: 2
64
- summary: Internationalization for Ruby
65
- test_files: []
66
-
60
+ summary: Internationalization support for Ruby
61
+ test_files:
62
+ - test/all.rb
63
+ - test/i18n_exceptions_test.rb
64
+ - test/i18n_test.rb
65
+ - test/locale/en-US.rb
66
+ - test/locale/en-US.yml
67
+ - test/simple_backend_test.rb