i18n-tasks 0.7.4 → 0.7.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
  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