tater 3.0.2 → 3.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b543d8ed6a28b2f4059b2c1fc63593bc2f7ced7b2cc9d62e786c78263b97ec35
4
- data.tar.gz: 0042276af4078a436e7f34e1f50500e5dd92649ae060b24921a98f5dfc859789
3
+ metadata.gz: '08a174e27ecb08955ba15997b8b71995aff8a77cbf82bb08514ba5dcd6e404dd'
4
+ data.tar.gz: c9f78478bc5f1b7a48b038add4f3c05230dc6083ccada5d1de00974b1dbd08f8
5
5
  SHA512:
6
- metadata.gz: cd927d5425f5a8b7356fafb72db449d57494042369eb9ba0018a2ba7d68893fe24c0d633d75a93ab8ff1d3e8f2367d148e87c5bc068ec1717afa27d1168cec8c
7
- data.tar.gz: 4f0a917429aef2c443288f9c338a0471f86fb608585e29e5fdc8b3f04b8ecfe654ecdc7e09daed29e99b19ddb3bf1a4175057d6db77c64b495b25a232f2c6eb7
6
+ metadata.gz: 27b9c2ad757cb5a51bf0ce3a792a92912bc3d8a2f9e82c761621396417480b6c82088222cd9e2c552d2309381d8feb0399466cade27b75fd2fb29d6eab2552b0
7
+ data.tar.gz: baf324c10b838927b0aedc2ac5babafed538acbdaeb7a4f7a5e6aebf8731d53037ec2dad4870d459a90056c9b9c2442d59ed6efaf5d94dbb74341f6a6ae3c14d
data/README.org CHANGED
@@ -1,6 +1,7 @@
1
1
  * Tater
2
2
 
3
3
  [[https://badge.fury.io/rb/tater][https://badge.fury.io/rb/tater.svg]]
4
+ [[https://github.com/evanleck/tater/actions/workflows/main.yml][https://github.com/evanleck/tater/actions/workflows/main.yml/badge.svg]]
4
5
 
5
6
  Tater is an internationalization (i18n) and localization (l10n) library designed
6
7
  for simplicity. It doesn't do everything that other libraries do, but that's by
@@ -238,7 +239,7 @@ Tater.new.translate('nope', default: 'Yep!') # => 'Yep!'
238
239
  ** Procs and messages in Ruby
239
240
 
240
241
  Ruby files can be used to store messages in addition to YAML, so long as the
241
- Ruby file returns a =Hash= when evalled.
242
+ Ruby file returns a =Hash= when evaluated.
242
243
 
243
244
  #+begin_src ruby
244
245
  {
@@ -281,7 +282,7 @@ Locales will be tried in order and whichever one matches first will be returned.
281
282
 
282
283
  ** Limitations
283
284
 
284
- - It is not pluggable, it does what it does and that's it.
285
+ - It is not plug-able, it does what it does and that's it.
285
286
  - It doesn't handle pluralization yet, though it may in the future.
286
287
 
287
288
  ** Why?
@@ -292,6 +293,6 @@ file that handles the basics of lookup and interpolation.
292
293
 
293
294
  ** Trivia
294
295
 
295
- I was orininally going to call this library "Translator" but with a [[https://en.wikipedia.org/wiki/Numeronym][numeronym]]
296
+ I was originally going to call this library "Translator" but with a [[https://en.wikipedia.org/wiki/Numeronym][numeronym]]
296
297
  like I18n: "t8r". I looked at it for a while but I read it as "tater" instead
297
298
  of "tee-eight-arr" so I figured I'd just name it Tater. Tater the translator.
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ require 'tater'
3
+
4
+ class Tater # :nodoc:
5
+ # Alias to Tater#localize
6
+ alias l localize
7
+
8
+ # Alias to Tater#translate
9
+ alias t translate
10
+ end
data/lib/tater/hash.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ class Tater
3
+ # Refine Hash and add the #except method from Ruby 3.
4
+ module HashExcept
5
+ refine Hash do
6
+ # Taken from the excellent backports gem written by Marc-André Lafortune.
7
+ # https://github.com/marcandre/backports/blob/master/lib/backports/3.0.0/hash/except.rb
8
+ def except(*keys)
9
+ if keys.size > 4 && size > 4 # index if O(m*n) is big
10
+ h = {}
11
+ keys.each { |key| h[key] = true }
12
+ keys = h
13
+ end
14
+
15
+ reject { |key, _value| keys.include?(key) }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+ class Tater
3
+ # Utility methods that require no state.
4
+ module Utils
5
+ HASH = {}.freeze
6
+ FORMAT_CURLY = '%{'
7
+ FORMAT_NAMED = '%<'
8
+
9
+ # Merge all the way down.
10
+ #
11
+ # @param to [Hash]
12
+ # The target Hash to merge into.
13
+ # @param from [Hash]
14
+ # The Hash to copy values from.
15
+ # @return [Hash]
16
+ def self.deep_merge(to, from)
17
+ to.merge(from) do |_key, left, right|
18
+ if left.is_a?(Hash) && right.is_a?(Hash)
19
+ Utils.deep_merge(left, right)
20
+ else
21
+ right
22
+ end
23
+ end
24
+ end
25
+
26
+ # Transform keys all the way down.
27
+ #
28
+ # @param hash [Hash]
29
+ # The Hash to stringify keys for.
30
+ # @return [Hash]
31
+ def self.deep_stringify_keys(hash)
32
+ hash.transform_keys(&:to_s).transform_values do |value|
33
+ if value.is_a?(Hash)
34
+ Utils.deep_stringify_keys(value)
35
+ else
36
+ value
37
+ end
38
+ end
39
+ end
40
+
41
+ # Freeze all the way down.
42
+ #
43
+ # @param hash [Hash]
44
+ # @return [Hash]
45
+ def self.deep_freeze(hash)
46
+ hash.transform_keys(&:freeze).transform_values do |value|
47
+ if value.is_a?(Hash)
48
+ Utils.deep_freeze(value)
49
+ else
50
+ value.freeze
51
+ end
52
+ end.freeze
53
+ end
54
+
55
+ # Format values into a string if appropriate.
56
+ #
57
+ # @param string [String]
58
+ # The target string to interpolate into.
59
+ # @param options [Hash]
60
+ # The values to interpolate into the target string.
61
+ #
62
+ # @return [String]
63
+ def self.interpolate(string, options = HASH)
64
+ return string if options.empty?
65
+ return string unless interpolation_string?(string)
66
+
67
+ format(string, options)
68
+ end
69
+
70
+ # Determine whether a string includes any interpolation placeholders e.g.
71
+ # "%{" or "%<"
72
+ #
73
+ # @param string [String]
74
+ # @return [Boolean]
75
+ def self.interpolation_string?(string)
76
+ string.include?(FORMAT_CURLY) || string.include?(FORMAT_NAMED)
77
+ end
78
+
79
+ # Convert a Numeric to a string, particularly formatting BigDecimals to a
80
+ # Float-like string representation.
81
+ #
82
+ # @param numeric [Numeric]
83
+ #
84
+ # @return [String]
85
+ def self.string_from_numeric(numeric)
86
+ if numeric.is_a?(BigDecimal)
87
+ numeric.to_s('F')
88
+ else
89
+ numeric.to_s
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ class Tater
3
+ VERSION = '3.0.5'
4
+ end
data/lib/tater.rb CHANGED
@@ -3,8 +3,10 @@ require 'bigdecimal'
3
3
  require 'date'
4
4
  require 'time'
5
5
  require 'yaml'
6
- require_relative 'tater/utils'
7
- require_relative 'tater/hash' unless Hash.method_defined?(:except)
6
+
7
+ require 'tater/hash' unless Hash.method_defined?(:except)
8
+ require 'tater/utils'
9
+ require 'tater/version'
8
10
 
9
11
  # Tater is a internationalization (i18n) and localization (l10n) library
10
12
  # designed for speed and simplicity.
@@ -21,6 +23,11 @@ class Tater
21
23
  # Needed for Ruby < 3.
22
24
  using HashExcept unless Hash.method_defined?(:except)
23
25
 
26
+ # An array of the available locale codes found in loaded messages.
27
+ #
28
+ # @return [Array<String>]
29
+ attr_reader :available
30
+
24
31
  # @return [String]
25
32
  attr_reader :locale
26
33
 
@@ -36,6 +43,8 @@ class Tater
36
43
  # @param path [String]
37
44
  # A path to search for YAML or Ruby files to load messages from.
38
45
  def initialize(cascade: false, locale: nil, messages: nil, path: nil)
46
+ @available = []
47
+ @cache = {}
39
48
  @cascade = cascade
40
49
  @locale = locale
41
50
  @messages = {}
@@ -44,6 +53,11 @@ class Tater
44
53
  load(messages: messages) if messages
45
54
  end
46
55
 
56
+ # @return [String]
57
+ def inspect
58
+ %(#<Tater:#{ object_id } @cascade=#{ @cascade } @locale="#{ @locale }" @available=#{ @available }>)
59
+ end
60
+
47
61
  # Do lookups cascade by default?
48
62
  #
49
63
  # @return [Boolean]
@@ -51,13 +65,6 @@ class Tater
51
65
  @cascade
52
66
  end
53
67
 
54
- # An array of the available locale codes found in loaded messages.
55
- #
56
- # @return [Array]
57
- def available
58
- @available ||= messages.keys
59
- end
60
-
61
68
  # Is this locale available in our current set of messages?
62
69
  #
63
70
  # @return [Boolean]
@@ -88,12 +95,12 @@ class Tater
88
95
  @messages = Utils.deep_merge(@messages, Utils.deep_stringify_keys(messages)) if messages
89
96
  @messages = Utils.deep_freeze(@messages)
90
97
 
91
- # Gotta recalculate available locales after updating.
92
- remove_instance_variable(:@available) if instance_variable_defined?(:@available)
98
+ # Update our available locales.
99
+ @available.replace(@messages.keys.map(&:to_s).sort)
93
100
 
94
101
  # Not only does this clear our cache but it establishes the basic structure
95
102
  # that we rely on in other methods.
96
- @cache = {}
103
+ @cache.clear
97
104
 
98
105
  @messages.each_key do |key|
99
106
  @cache[key] = { false => {}, true => {} }
@@ -105,7 +112,8 @@ class Tater
105
112
  # @param locale [String]
106
113
  # The locale code to set as our default.
107
114
  def locale=(locale)
108
- @locale = locale.to_s if available?(locale)
115
+ str = locale.to_s
116
+ @locale = str if available?(str)
109
117
  end
110
118
 
111
119
  # Localize an Array, Date, Time, DateTime, or Numeric object.
@@ -209,20 +217,24 @@ class Tater
209
217
  #
210
218
  # @return [Boolean]
211
219
  def includes?(key, options = HASH)
212
- message =
213
- if options.key?(:locales)
214
- options[:locales].append(@locale) if @locale && !options[:locales].include?(@locale)
220
+ if options.empty?
221
+ !lookup(key).nil?
222
+ else
223
+ message =
224
+ if options.key?(:locales)
225
+ options[:locales].append(@locale) if @locale && !options[:locales].include?(@locale)
215
226
 
216
- options[:locales].find do |accept|
217
- found = lookup(key, locale: accept, cascade: options[:cascade])
227
+ options[:locales].find do |accept|
228
+ found = lookup(key, locale: accept, cascade: options[:cascade])
218
229
 
219
- break found unless found.nil?
230
+ break found unless found.nil?
231
+ end
232
+ else
233
+ lookup(key, locale: options[:locale], cascade: options[:cascade])
220
234
  end
221
- else
222
- lookup(key, locale: options[:locale], cascade: options[:cascade])
223
- end
224
235
 
225
- !message.nil?
236
+ !message.nil?
237
+ end
226
238
  end
227
239
 
228
240
  # Translate a key path and optional interpolation arguments into a string.
data/test/tater_test.rb CHANGED
@@ -455,4 +455,32 @@ describe Tater do
455
455
  refute i18n.includes?('cascade.nope.tacos', cascade: false)
456
456
  end
457
457
  end
458
+
459
+ describe '#inspect' do
460
+ it 'returns a stringified version of the object' do
461
+ obj = Tater.new(path: File.expand_path('test/fixtures'), locale: 'en')
462
+ assert_equal %(#<Tater:#{ obj.object_id } @cascade=#{ obj.cascades? } @locale="#{ obj.locale }" @available=#{ obj.available }>), obj.inspect
463
+ end
464
+ end
465
+
466
+ describe '#freeze' do
467
+ it 'can be frozen' do
468
+ obj = Tater.new(path: File.expand_path('test/fixtures'), locale: 'en')
469
+ obj.freeze
470
+
471
+ assert obj.includes?('deep')
472
+ assert_equal 'This key is deeper', obj.translate('deep.key')
473
+ assert_equal %w[delimiter_only en fr separator_only], obj.available
474
+
475
+ assert obj.frozen?
476
+ end
477
+
478
+ it 'throws an error if modified after being frozen' do
479
+ obj = Tater.new(path: File.expand_path('test/fixtures'), locale: 'en')
480
+ obj.freeze
481
+
482
+ assert_raises(FrozenError) { obj.locale = 'en' }
483
+ assert_raises(FrozenError) { obj.load(messages: { more: 'Messages' }) }
484
+ end
485
+ end
458
486
  end
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: 3.0.2
4
+ version: 3.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Lecklider
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-19 00:00:00.000000000 Z
11
+ date: 2022-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -132,6 +132,10 @@ files:
132
132
  - LICENSE.txt
133
133
  - README.org
134
134
  - lib/tater.rb
135
+ - lib/tater/aliases.rb
136
+ - lib/tater/hash.rb
137
+ - lib/tater/utils.rb
138
+ - lib/tater/version.rb
135
139
  - test/fixtures/another.yml
136
140
  - test/fixtures/fixtures.yml
137
141
  - test/fixtures/messages/more.yml
@@ -159,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
163
  - !ruby/object:Gem::Version
160
164
  version: '2.0'
161
165
  requirements: []
162
- rubygems_version: 3.2.32
166
+ rubygems_version: 3.3.7
163
167
  signing_key:
164
168
  specification_version: 4
165
169
  summary: Minimal internationalization and localization library.