tater 2.0.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/tater.rb +29 -93
  3. data/test/tater_test.rb +25 -12
  4. metadata +7 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51644f41d80e87d20ed43b9e8c6b4797fb7aeb4258c94d5d9f9d7a50eb5ee5c6
4
- data.tar.gz: 1fe43b99fbc2f24cdc342ec4278ff7140ee6b9579dd51d236fcc713907f1455d
3
+ metadata.gz: c34d7058c3566313243c4ccb7b99d967c60bf2e00e091d1fbb66dfbd257e853f
4
+ data.tar.gz: 0a5c1d4df6a34b9953086af0459af4c72cb8d9faf674d3216e1eb9e00aa0e82f
5
5
  SHA512:
6
- metadata.gz: d4c059fdc696d39c489e61d3e53954fe921feaba78055bd5e62c944d45daf10dfa178b76e4e836d326ba61be0dbf7bbec13b63f52b95e13f23da9ca5be4d3b8c
7
- data.tar.gz: 6b12ffa8f2a1186f2de92c9c16bb5c2e1027f93ab5ee2c877dbad297777274b9f4f38882255490db3c555a0dafb129ed876bd784d3a872e07a4e7e9f6e0e24ec
6
+ metadata.gz: ac657b28f3e3421def12e3d0b50bcd895c5d1a1b23de7c97da6bf0e20bc5e0a51e20abf7394ec9e99b2137e9b2261392213f0dc85d2d3b0c598c4e73184d8857
7
+ data.tar.gz: 4b5b32cf7b23a66afcde0a73f129a76d791f62a8efa45a7223204d9e017328796cf528ad8884a2c25a568ea47d3047fff57c4973741aaae20e1e7574350a9068
data/lib/tater.rb CHANGED
@@ -3,91 +3,14 @@ require 'bigdecimal'
3
3
  require 'date'
4
4
  require 'time'
5
5
  require 'yaml'
6
+ require 'tater/utils'
6
7
 
7
8
  # Tater is a internationalization (i18n) and localization (l10n) library
8
9
  # designed for speed and simplicity.
9
10
  class Tater
10
11
  class MissingLocalizationFormat < ArgumentError; end
11
-
12
12
  class UnLocalizableObject < ArgumentError; end
13
13
 
14
- module Utils # :nodoc:
15
- # Merge all the way down.
16
- #
17
- # @param to [Hash]
18
- # The target Hash to merge into.
19
- # @param from [Hash]
20
- # The Hash to copy values from.
21
- # @return [Hash]
22
- def self.deep_merge(to, from)
23
- to.merge(from) do |_key, left, right|
24
- if left.is_a?(Hash) && right.is_a?(Hash)
25
- Utils.deep_merge(left, right)
26
- else
27
- right
28
- end
29
- end
30
- end
31
-
32
- # Transform keys all the way down.
33
- #
34
- # @param hash [Hash]
35
- # The Hash to stringify keys for.
36
- # @return [Hash]
37
- def self.deep_stringify_keys(hash)
38
- hash.transform_keys(&:to_s).transform_values do |value|
39
- if value.is_a?(Hash)
40
- Utils.deep_stringify_keys(value)
41
- else
42
- value
43
- end
44
- end
45
- end
46
-
47
- # Freeze all the way down.
48
- #
49
- # @param hash [Hash]
50
- # @return [Hash]
51
- def self.deep_freeze(hash)
52
- hash.transform_keys(&:freeze).transform_values do |value|
53
- if value.is_a?(Hash)
54
- Utils.deep_freeze(value)
55
- else
56
- value.freeze
57
- end
58
- end.freeze
59
- end
60
-
61
- # Try to interpolate these things, if one of them is a string.
62
- #
63
- # @param string [String]
64
- # The target string to interpolate into.
65
- # @param options [Hash]
66
- # The values to interpolate into the target string.
67
- #
68
- # @return [String]
69
- def self.interpolate(string, options = HASH)
70
- return string unless string.is_a?(String)
71
- return string if options.empty?
72
-
73
- format(string, options)
74
- end
75
-
76
- # Convert a Numeric to a string, particularly formatting BigDecimals to a
77
- # Float-like string representation.
78
- #
79
- # @param numeric [Numeric]
80
- #
81
- # @return [String]
82
- def self.string_from_numeric(numeric)
83
- if numeric.is_a?(BigDecimal)
84
- numeric.to_s('F')
85
- else
86
- numeric.to_s
87
- end
88
- end
89
- end
90
-
91
14
  DEFAULT = 'default'
92
15
  DELIMITING_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/.freeze
93
16
  HASH = {}.freeze
@@ -154,7 +77,7 @@ class Tater
154
77
  end
155
78
 
156
79
  Dir.glob(File.join(path, '**', '*.rb')).each do |file|
157
- @messages = Utils.deep_merge(@messages, Utils.deep_stringify_keys(eval(IO.read(file), binding, file))) # rubocop:disable Security/Eval
80
+ @messages = Utils.deep_merge(@messages, Utils.deep_stringify_keys(eval(File.read(file), binding, file))) # rubocop:disable Security/Eval
158
81
  end
159
82
  end
160
83
 
@@ -220,7 +143,6 @@ class Tater
220
143
  raise(UnLocalizableObject, "The object class #{ object.class } cannot be localized by Tater.")
221
144
  end
222
145
  end
223
- alias l localize
224
146
 
225
147
  # Lookup a key in the messages hash, using the current locale or an override.
226
148
  #
@@ -325,25 +247,39 @@ class Tater
325
247
  # The translated and interpreted string, if found, or any data at the
326
248
  # defined key.
327
249
  def translate(key, options = HASH)
328
- message =
329
- if options.key?(:locales)
330
- options[:locales].append(@locale) if @locale && !options[:locales].include?(@locale)
250
+ if options.empty?
251
+ message = lookup(key)
331
252
 
332
- options[:locales].find do |accept|
333
- found = lookup(key, locale: accept, cascade: options[:cascade])
334
-
335
- break found unless found.nil?
336
- end
253
+ if message.is_a?(Proc) # rubocop:disable Style/CaseLikeIf
254
+ message.call(key)
255
+ elsif message.is_a?(String)
256
+ message
337
257
  else
338
- lookup(key, locale: options[:locale], cascade: options[:cascade])
258
+ "Tater lookup failed: #{ locale }.#{ key }"
339
259
  end
260
+ else
261
+ message =
262
+ if options.key?(:locales)
263
+ options[:locales].append(@locale) if @locale && !options[:locales].include?(@locale)
340
264
 
341
- # Call procs that should return a string.
342
- message = message.call(key, options) if message.is_a?(Proc)
265
+ options[:locales].find do |accept|
266
+ found = lookup(key, locale: accept, cascade: options[:cascade])
343
267
 
344
- Utils.interpolate(message, options) || options[:default] || "Tater lookup failed: #{ options[:locale] || options[:locales] || locale }.#{ key }"
268
+ break found unless found.nil?
269
+ end
270
+ else
271
+ lookup(key, locale: options[:locale], cascade: options[:cascade])
272
+ end
273
+
274
+ if message.is_a?(Proc) # rubocop:disable Style/CaseLikeIf
275
+ message.call(key, options.except(:cascade, :default, :locale, :locales))
276
+ elsif message.is_a?(String)
277
+ Utils.interpolate(message, options.except(:cascade, :default, :locale, :locales))
278
+ else
279
+ options[:default] || "Tater lookup failed: #{ options[:locale] || options[:locales] || locale }.#{ key }"
280
+ end
281
+ end
345
282
  end
346
- alias t translate
347
283
 
348
284
  private
349
285
 
data/test/tater_test.rb CHANGED
@@ -61,6 +61,20 @@ describe Tater do
61
61
  assert_equal '1.0', Tater::Utils.string_from_numeric(BigDecimal('1'))
62
62
  end
63
63
  end
64
+
65
+ describe '#interpolation_string?' do
66
+ def is?(arg)
67
+ Tater::Utils.interpolation_string?(arg)
68
+ end
69
+
70
+ it 'checks whether a string contains interpolation placeholders' do
71
+ assert is?('Hey %{there}!')
72
+ assert is?('Hey %<there>s!')
73
+ refute is?('Nah, this is fine')
74
+ refute is?("<b>HTML shouldn't count")
75
+ refute is?("A single % shouldn't count")
76
+ end
77
+ end
64
78
  end
65
79
 
66
80
  describe '#available?' do
@@ -143,6 +157,10 @@ describe Tater do
143
157
  assert_nil i18n.lookup('nope')
144
158
  end
145
159
 
160
+ it 'returns arbitrary data at keys' do
161
+ assert_equal({ 'key' => 'This key is deeper' }, i18n.lookup('deep'))
162
+ end
163
+
146
164
  it 'cascades' do
147
165
  assert_equal 'Delicious', i18n.lookup('cascade.nope.tacos', cascade: true)
148
166
  assert_equal 'Whoaa', i18n.lookup('cascade.another.nope.crazy', cascade: true)
@@ -164,8 +182,8 @@ describe Tater do
164
182
  assert_equal 'This key is deeper', i18n.translate('deep.key')
165
183
  end
166
184
 
167
- it 'returns a hash for nested keys' do
168
- assert_equal({ 'key' => 'This key is deeper' }, i18n.translate('deep'))
185
+ it 'does not return a hash for nested keys' do
186
+ assert_equal 'Tater lookup failed: en.deep', i18n.translate('deep')
169
187
  end
170
188
 
171
189
  it 'interpolates additional variables' do
@@ -182,10 +200,6 @@ describe Tater do
182
200
  assert_equal 'Tater lookup failed: en.nope', i18n.translate('nope')
183
201
  end
184
202
 
185
- it 'is aliased as t' do
186
- assert_equal 'This is a title', i18n.t('title')
187
- end
188
-
189
203
  it 'cascades lookups' do
190
204
  assert_equal 'Tater lookup failed: en.cascade.another.nope.crazy', i18n.translate('cascade.another.nope.crazy', cascade: false)
191
205
  assert_equal 'Tater lookup failed: en.cascade.nope.tacos', i18n.translate('cascade.nope.tacos')
@@ -203,9 +217,12 @@ describe Tater do
203
217
  assert_equal 'Tater lookup failed: ["fr", "en"].neither', i18n.translate('neither', locales: %w[fr en])
204
218
  end
205
219
 
206
- it 'finds Ruby files as well' do
220
+ it 'finds Ruby files' do
207
221
  assert_equal 'Hey ruby!', i18n.translate('ruby')
208
- assert_equal 'Hey options!', i18n.translate('options', options: 'options')
222
+ end
223
+
224
+ it 'does not interpolate messages returned by procs' do
225
+ assert_equal 'Hey %{options}!', i18n.translate('options', options: 'options')
209
226
  end
210
227
  end
211
228
 
@@ -316,10 +333,6 @@ describe Tater do
316
333
  end
317
334
  end
318
335
 
319
- it 'is aliased l' do
320
- assert_equal '1970/1/1', i18n.l(Date.new(1970, 1, 1))
321
- end
322
-
323
336
  describe 'month, day, and AM/PM names' do
324
337
  let :i18n do
325
338
  Tater.new(path: File.expand_path('test/fixtures'), locale: 'fr')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tater
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Lecklider
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-12 00:00:00.000000000 Z
11
+ date: 2021-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -142,8 +142,9 @@ licenses:
142
142
  - MIT
143
143
  metadata:
144
144
  bug_tracker_uri: https://github.com/evanleck/tater/issues
145
+ rubygems_mfa_required: 'true'
145
146
  source_code_uri: https://github.com/evanleck/tater
146
- post_install_message:
147
+ post_install_message:
147
148
  rdoc_options: []
148
149
  require_paths:
149
150
  - lib
@@ -158,8 +159,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
159
  - !ruby/object:Gem::Version
159
160
  version: '2.0'
160
161
  requirements: []
161
- rubygems_version: 3.2.22
162
- signing_key:
162
+ rubygems_version: 3.2.32
163
+ signing_key:
163
164
  specification_version: 4
164
165
  summary: Minimal internationalization and localization library.
165
166
  test_files: