i18n-tasks 0.7.4 → 0.7.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0d5a6d44abbe13489dbf413f1fe2934f96ac3ec
4
- data.tar.gz: b73c633dbb50493e77f248a4d019473d38920c6e
3
+ metadata.gz: 850032b9cd081295834563c079f301118c4adc93
4
+ data.tar.gz: bb430460401ab69f396b53e29337b7d12894c49a
5
5
  SHA512:
6
- metadata.gz: 33f1b9a719ad5a1127be44b0513aa9e0f2cd46598c2d855c46be9fbb9e488164c4eacddbd0d7ef0da28e4db7ffd922162770d8dbe883acdb45cf5d8d44dfb28b
7
- data.tar.gz: 625b026add3aa686380a485df1f1db04ab450092eac690d793eb0293f237752c823702164ec13e662a3d7e4d5717a0dd840bfebe41d65f796f97abacd58bef12
6
+ metadata.gz: 2f28025277307b4c42facd0f94691100f73680a27eaf135945484e5711e66db865a094269f895c3f6e7cdb767c021a50df51fb50d77377eccbfa7e8955359e18
7
+ data.tar.gz: 6abfa104439e6592d7a40934fa8e7c70707094be19faad49ce5ca4fbb9a04774613662f0076ff2fa436cd62001a242ad0dea35dcddbcdab7b3e0c49b11f17304
data/CHANGES.md CHANGED
@@ -1,7 +1,15 @@
1
+ ## 0.7.5
2
+
3
+ Dynamic key usage inference fixes by [Mikko Koski](https://github.com/rap1ds):
4
+
5
+ * Append `:` to keys ending with dot '.' (to scan `t('category.' + cat)` as `t('category.:')`)
6
+ * Consider keys ending with `:` as match expressions
7
+ * Make `@` a valid character for keys (to allow `t("category.#{@cat}"`)
8
+
1
9
  ## 0.7.4
2
10
 
3
11
  * Fix `add-missing --help`
4
- * Fix a minor issue with `health` #88(https://github.com/glebm/i18n-tasks/issues/88)
12
+ * Fix a minor issue with `health` [#88](https://github.com/glebm/i18n-tasks/issues/88)
5
13
 
6
14
  ## 0.7.3
7
15
 
@@ -196,29 +204,29 @@ With these trees, information can be associated with each node, which allows for
196
204
 
197
205
  * config/i18n-tasks.yml now processed with ERB
198
206
  * can now be used with any ruby apps, not just Rails
199
- * more locale formats are considered valid
207
+ * more locale formats are considered valid
200
208
  * `i18n:missing` accepts locales
201
209
  * `i18n:missing` supports plural keys
202
210
 
203
211
  ## v0.2.4
204
212
 
205
- * more powerful key pattern matching with sets and backtracking
213
+ * more powerful key pattern matching with sets and backtracking
206
214
 
207
215
  ## v0.2.3
208
216
 
209
- * spreadsheet report, tests run on rbx
217
+ * spreadsheet report, tests run on rbx
210
218
 
211
219
  ## v0.2.2
212
220
 
213
- * improved output with terminal-table
221
+ * improved output with terminal-table
214
222
 
215
223
  ## v0.2.1
216
224
 
217
- * fill tasks renamed, fix symbol key search
225
+ * fill tasks renamed, fix symbol key search
218
226
 
219
227
  ## v0.2.0
220
228
 
221
- * 3 more prefill tasks, including Google Translate
229
+ * 3 more prefill tasks, including Google Translate
222
230
  * tasks renamed
223
231
 
224
232
  ## v0.1.8
@@ -227,16 +235,16 @@ With these trees, information can be associated with each node, which allows for
227
235
 
228
236
  ## v0.1.7
229
237
 
230
- * ability to route prefill output via data.write config
231
- * multiple configuration variables renamed (still understands old syntax with deprecation warnings)
238
+ * ability to route prefill output via data.write config
239
+ * multiple configuration variables renamed (still understands old syntax with deprecation warnings)
232
240
 
233
241
  ## v0.1.6
234
242
 
235
- * New key pattern syntax for i18n-tasks.yml a la globbing
243
+ * New key pattern syntax for i18n-tasks.yml a la globbing
236
244
 
237
245
  ## v0.1.5
238
246
 
239
- * Removed get_locale_data, added data configuration options
247
+ * Removed get_locale_data, added data configuration options
240
248
 
241
249
  ## v0.1.4
242
250
 
@@ -245,10 +253,10 @@ With these trees, information can be associated with each node, which allows for
245
253
 
246
254
  ## v0.1.3
247
255
 
248
- * detect countable keys as used for unused task
256
+ * detect countable keys as used for unused task
249
257
  * account for non-string keys coming from yaml (thanks @lichtamberg)
250
258
 
251
259
  ## v0.1.2
252
260
 
253
261
  * added grep config options (thanks @dmke)
254
- * improved terminal output
262
+ * improved terminal output
data/README.md CHANGED
@@ -25,7 +25,7 @@ i18n-tasks can be used with any project using [i18n][i18n-gem] (default in Rails
25
25
  Add to Gemfile:
26
26
 
27
27
  ```ruby
28
- gem 'i18n-tasks', '~> 0.7.4'
28
+ gem 'i18n-tasks', '~> 0.7.5'
29
29
  ```
30
30
 
31
31
  Copy default [configuration file](#configuration) (optional):
@@ -35,7 +35,7 @@ begin
35
35
  exit
36
36
  }
37
37
  commander.cmds.each do |name, attr|
38
- slop_dsl = slop_adapter.slop_command(name, attr) { |name, opts|
38
+ slop_dsl = slop_adapter.slop_command(name, attr) { |_name, opts|
39
39
  begin
40
40
  ran = true
41
41
  instance.safe_run name, opts
@@ -45,7 +45,7 @@ begin
45
45
  exit 1
46
46
  end
47
47
  }
48
- instance_exec &slop_dsl
48
+ instance_exec(&slop_dsl)
49
49
  end
50
50
  end
51
51
  rescue Slop::Error => e
@@ -9,7 +9,7 @@ module I18n::Tasks
9
9
  include Options::EnumOpt
10
10
  include Options::ListOpt
11
11
 
12
- VALID_LOCALE_RE = /\A\w[\w\-_\.]*\z/i
12
+ VALID_LOCALE_RE = /\A\w[\w\-\.]*\z/i
13
13
 
14
14
  cmd_opt :nostdin, {
15
15
  short: :S,
@@ -43,7 +43,7 @@ module I18n::Tasks
43
43
  opt[key]
44
44
  end
45
45
 
46
- VALID_LOCALE_RE = /\A\w[\w\-_\.]*\z/i
46
+ VALID_LOCALE_RE = /\A\w[\w\-\.]*\z/i
47
47
 
48
48
  def validate_locale!(locale)
49
49
  raise CommandError.new(I18n.t('i18n_tasks.cmd.errors.invalid_locale', invalid: locale)) if VALID_LOCALE_RE !~ locale
@@ -12,7 +12,7 @@ module I18n::Tasks::Configuration
12
12
  )
13
13
 
14
14
  def file_config
15
- file = CONFIG_FILES.detect { |f| File.exists?(f) }
15
+ file = CONFIG_FILES.detect { |f| File.exist?(f) }
16
16
  config = file && YAML.load(Erubis::Eruby.new(File.read(file)).result)
17
17
  if config.present?
18
18
  config.with_indifferent_access.tap do |c|
@@ -12,7 +12,7 @@ module I18n::Tasks
12
12
  include ::I18n::Tasks::Logging
13
13
 
14
14
  attr_reader :config, :base_locale, :locales
15
- attr_accessor :locales
15
+ attr_writer :locales
16
16
 
17
17
  DEFAULTS = {
18
18
  read: ['config/locales/%{locale}.yml'],
@@ -8,11 +8,12 @@ module I18n::Tasks::Data::Tree
8
8
  attr_reader :key, :children, :parent
9
9
 
10
10
  def initialize(opts = {})
11
- @key = opts[:key].try(:to_s)
11
+ @key = opts[:key]
12
+ @key = @key.to_s.freeze if @key
12
13
  @value = opts[:value]
13
14
  @data = opts[:data]
14
15
  @parent = opts[:parent]
15
- self.children = opts[:children] if opts[:children]
16
+ self.children = (opts[:children] if opts[:children])
16
17
  end
17
18
 
18
19
  def attributes
@@ -102,7 +103,7 @@ module I18n::Tasks::Data::Tree
102
103
  def walk_to_root(&visitor)
103
104
  return to_enum(:walk_to_root) unless visitor
104
105
  visitor.yield self
105
- parent.walk_to_root &visitor if parent?
106
+ parent.walk_to_root(&visitor) if parent?
106
107
  end
107
108
 
108
109
  def root
@@ -123,7 +124,7 @@ module I18n::Tasks::Data::Tree
123
124
  end
124
125
 
125
126
  def to_siblings
126
- parent.try(:children) || Siblings.new(nodes: [self])
127
+ parent && parent.children || Siblings.new(nodes: [self])
127
128
  end
128
129
 
129
130
  def to_hash
@@ -49,7 +49,7 @@ module I18n::Tasks::Data::Tree
49
49
 
50
50
  # @return [Node] by full key
51
51
  def get(full_key)
52
- first_key, rest = split_key(full_key, 2)
52
+ first_key, rest = split_key(full_key.to_s, 2)
53
53
  node = key_to_node[first_key]
54
54
  if rest && node
55
55
  node = node.children.try(:get, rest)
@@ -15,13 +15,13 @@ module I18n::Tasks::IgnoreKeys
15
15
  @ignore_patterns[type] ||= {}
16
16
  @ignore_patterns[type][locale] ||= begin
17
17
  global, type_ignore = ignore_config.presence || [], ignore_config(type).presence || []
18
- if type_ignore.is_a?(Array)
19
- patterns = global + type_ignore
20
- elsif type_ignore.is_a?(Hash)
21
- # ignore per locale
22
- patterns = global + (type_ignore['all'] || []) +
23
- type_ignore.select { |k, v| k.to_s =~ /\b#{locale}\b/ }.values.flatten(1).compact
24
- end
18
+ patterns = if type_ignore.is_a?(Array)
19
+ global + type_ignore
20
+ elsif type_ignore.is_a?(Hash)
21
+ # ignore per locale
22
+ global + (type_ignore['all'] || []) +
23
+ type_ignore.select { |k, v| k.to_s =~ /\b#{locale}\b/ }.values.flatten(1).compact
24
+ end
25
25
  compile_patterns_re patterns
26
26
  end
27
27
  end
@@ -39,7 +39,7 @@ module I18n::Tasks::KeyPatternMatching
39
39
  end
40
40
 
41
41
  # @return true if the key looks like an expression
42
- KEY_INTERPOLATION_RE = /(?:\#{.*?}|\*+)/.freeze
42
+ KEY_INTERPOLATION_RE = /(?:\#{.*?}|\*+|\:+)/.freeze
43
43
  def key_expression?(k)
44
44
  @key_is_expr ||= {}
45
45
  if @key_is_expr[k].nil?
@@ -3,7 +3,13 @@ module I18n::Tasks
3
3
  extend self
4
4
 
5
5
  def replace_locale(path, from, to)
6
- path.try :sub, /(?<=^|[\/.])#{from}(?=\.)/, "#{to}"
6
+ path && path.sub(path_locale_re(from), to)
7
+ end
8
+
9
+ private
10
+
11
+ def path_locale_re(locale)
12
+ (@path_locale_res ||= {})[locale] ||= /(?<=^|[\/.])#{locale}(?=\.)/.freeze
7
13
  end
8
14
  end
9
15
  end
@@ -21,6 +21,6 @@ module I18n::Tasks::Logging
21
21
  end
22
22
 
23
23
  def log_stderr(*args)
24
- STDERR.puts *args
24
+ STDERR.puts(*args)
25
25
  end
26
26
  end
@@ -67,7 +67,7 @@ module I18n::Tasks
67
67
  # keys present in compared_to, but not in locale
68
68
  def missing_diff_tree(locale, compared_to = base_locale)
69
69
  data[compared_to].select_keys { |key, _node|
70
- locale_key_missing? locale, depluralize_key(key, locale)
70
+ locale_key_missing? locale, depluralize_key(key, compared_to)
71
71
  }.set_root_key!(locale, type: :missing_diff).keys { |_key, node|
72
72
  if node.data.key?(:path)
73
73
  # change path and locale to base
@@ -21,7 +21,8 @@ module I18n::Tasks::PluralKeys
21
21
  # @return the base form if the key is a specific plural form (e.g. apple for apple.many), and the key as passed otherwise
22
22
  def depluralize_key(key, locale = base_locale)
23
23
  return key if key !~ PLURAL_KEY_RE
24
- parent_key = split_key(key)[0..-2] * '.'
24
+ key_name = last_key_part(key)
25
+ parent_key = key[0 .. - (key_name.length + 2)]
25
26
  nodes = tree("#{locale}.#{parent_key}").presence || (locale != base_locale && tree("#{base_locale}.#{parent_key}"))
26
27
  if nodes && plural_forms?(nodes)
27
28
  parent_key
@@ -40,7 +40,7 @@ module I18n::Tasks::Reports
40
40
  def sort_by_attr!(objects, order = {locale: :asc, key: :asc})
41
41
  order_keys = order.keys
42
42
  objects.sort! { |a, b|
43
- by = order_keys.detect { |by| a[by] != b[by] }
43
+ by = order_keys.detect { |k| a[k] != b[k] }
44
44
  order[by] == :desc ? b[by] <=> a[by] : a[by] <=> b[by]
45
45
  }
46
46
  objects
@@ -42,7 +42,7 @@ module I18n::Tasks::Scanners
42
42
  scan_file(path, opts)
43
43
  }.reduce(:+) || []
44
44
  keys.group_by(&:first).map { |key, key_loc|
45
- [key, data: {source_occurrences: key_loc.map { |(k, attr)| attr[:data] }}]
45
+ [key, data: {source_occurrences: key_loc.map { |(_k, attr)| attr[:data] }}]
46
46
  }
47
47
  end
48
48
 
@@ -61,7 +61,7 @@ module I18n::Tasks::Scanners
61
61
  # @return [Array] Results of block calls
62
62
  def traverse_files
63
63
  result = []
64
- paths = config[:paths].select { |p| File.exists?(p) }
64
+ paths = config[:paths].select { |p| File.exist?(p) }
65
65
  if paths.empty?
66
66
  log_warn "search.paths #{config[:paths].inspect} do not exist"
67
67
  return result
@@ -117,7 +117,7 @@ module I18n::Tasks::Scanners
117
117
 
118
118
  VALID_KEY_CHARS = /[-\w.?!;:]/
119
119
  VALID_KEY_RE_STRICT = /^#{VALID_KEY_CHARS}+$/
120
- VALID_KEY_RE = /^(#{VALID_KEY_CHARS}|[\#{}])+$/
120
+ VALID_KEY_RE = /^(#{VALID_KEY_CHARS}|[\#{@}])+$/
121
121
 
122
122
  def valid_key?(key, strict = false)
123
123
  return false if @key_filter && @key_filter_pattern !~ key
@@ -15,6 +15,7 @@ module I18n::Tasks::Scanners
15
15
  src_pos = Regexp.last_match.offset(0).first
16
16
  key = match_to_key(match, path)
17
17
  next unless valid_key?(key, strict)
18
+ key = key + ':' if key.end_with?('.')
18
19
  location = src_location(path, text, src_pos)
19
20
  unless exclude_line?(location[:line])
20
21
  keys << [key, data: location]
@@ -39,7 +40,6 @@ module I18n::Tasks::Scanners
39
40
  # @return [String] full absolute key name
40
41
  def match_to_key(match, path)
41
42
  key = strip_literal(match[0])
42
- key = key + '*' if key.end_with?('.')
43
43
  key = absolutize_key(key, path) if path && key.start_with?('.')
44
44
  key
45
45
  end
@@ -1,39 +1,65 @@
1
1
  module SplitKey
2
2
  extend self
3
3
 
4
- # split a key taking parenthesis into account
4
+ # split a key by dots (.)
5
+ # dots inside braces or parenthesis are not split on
6
+ #
5
7
  # split_key 'a.b' # => ['a', 'b']
6
8
  # split_key 'a.#{b.c}' # => ['a', '#{b.c}']
7
9
  # split_key 'a.b.c', 2 # => ['a', 'b.c']
8
10
  def split_key(key, max = Float::INFINITY)
9
11
  parts = []
10
- nesting = NESTING_CHARS
11
- counts = Array.new(NESTING_CHARS.size, 0)
12
+ pos = 0
13
+ return [key] if max == 1
14
+ key_parts(key) do |part|
15
+ parts << part
16
+ pos += part.length + 1
17
+ if parts.length + 1 >= max
18
+ parts << key.from(pos) unless pos == key.length
19
+ break
20
+ end
21
+ end
22
+ parts
23
+ end
24
+
25
+ def last_key_part(key)
26
+ last = nil
27
+ key_parts(key) { |part| last = part }
28
+ last
29
+ end
30
+
31
+ # yield each key part
32
+ # dots inside braces or parenthesis are not split on
33
+ def key_parts(key, &block)
34
+ return enum_for(:key_parts, key) unless block
35
+ nesting = PARENS
36
+ counts = PARENS_ZEROS # dup'd later if key contains parenthesis
12
37
  delim = '.'.freeze
13
- buf = []
14
- key.to_s.chars.each do |char|
15
- nest_i, nest_inc = nesting[char]
16
- if nest_i
17
- counts[nest_i] += nest_inc
18
- buf << char
19
- elsif char == delim && parts.length + 1 < max && counts.all?(&:zero?)
20
- part = buf.join
21
- buf.clear
22
- parts << part
23
- yield part if block_given?
38
+ from = to = 0
39
+ key.each_char do |char|
40
+ if char == delim && PARENS_ZEROS == counts
41
+ block.yield key[from...to]
42
+ from = to = (to + 1)
24
43
  else
25
- buf << char
44
+ nest_i, nest_inc = nesting[char]
45
+ if nest_i
46
+ counts = counts.dup if counts.frozen?
47
+ counts[nest_i] += nest_inc
48
+ end
49
+ to += 1
26
50
  end
27
51
  end
28
- parts << buf.join unless buf.empty?
29
- parts
52
+ block.yield(key[from...to]) if from < to && to <= key.length
53
+ true
30
54
  end
31
55
 
32
- NESTING_CHARS = %w({} [] ()).inject({}) { |h, s|
33
- i = h.size / 2
56
+ PARENS = %w({} [] ()).inject({}) { |h, s|
57
+ i = h.size / 2
34
58
  h[s[0].freeze] = [i, 1].freeze
35
59
  h[s[1].freeze] = [i, -1].freeze
36
60
  h
37
61
  }.freeze
38
- private_constant :NESTING_CHARS
62
+ PARENS_ZEROS = Array.new(PARENS.size, 0).freeze
63
+ private_constant :PARENS
64
+ private_constant :PARENS_ZEROS
39
65
  end
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
  module I18n
3
3
  module Tasks
4
- VERSION = '0.7.4'
4
+ VERSION = '0.7.5'
5
5
  end
6
6
  end
@@ -22,6 +22,12 @@ describe 'SplitKey' do
22
22
  expect(split_key 'a.b.c', 1).to eq(['a.b.c'])
23
23
  expect(split_key 'a.b.c', 2).to eq(['a', 'b.c'])
24
24
  expect(split_key 'a.b.c.', 2).to eq(['a', 'b.c.'])
25
+ expect(split_key 'a.b.c.d.e.f', 4).to eq(['a', 'b', 'c', 'd.e.f'])
25
26
  end
26
27
 
28
+ it 'last part' do
29
+ expect(last_key_part 'a.b.c').to eq('c')
30
+ expect(last_key_part 'a').to eq('a')
31
+ expect(last_key_part 'a.b.c.d').to eq('d')
32
+ end
27
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 0.7.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-18 00:00:00.000000000 Z
11
+ date: 2014-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubis