i18n-tasks 0.9.3 → 0.9.4

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: b5b15ad428fdc29cc404d033f363c08708f5b815
4
- data.tar.gz: c5aaaecace6c6024d544ff552c06097b9ec2f252
3
+ metadata.gz: 4807ae41e4ea2c7274b08bc55c2a2286a6e601d5
4
+ data.tar.gz: bdc921c3485e004c0e395a79afde8a5cfcfa888c
5
5
  SHA512:
6
- metadata.gz: 54586d8f4fb14861a755a75325ccf73230b9e180bc590f2f7fd383dc6c10c3529943179709d1d8045873148530684625c92a53d9b997281b9078acac51c40699
7
- data.tar.gz: 693ff45562b53f09a0c5baf81b0d5418227e35d182f81e51cdff99c740b2a4666c39bbf3ea84f9d64daafb5ce34b454a59410b3c73a03fadf35c3b9ee98244bb
6
+ metadata.gz: 3b58817464f4c4878f822606dda7ae226b33f53b6542b938a272864d1d4a92806a72d81f4d16571e8176e04687784861a7c541f1ac0e92b6ce055ed46a93b8da
7
+ data.tar.gz: 276c9a94d0575d383ea163a8e20d56b26248cf0c16da4caa2efd53f7530ed4632f3f264e9dcf747013db063cd19c984cd218cb60829ace938f79b6c97db7130f
data/README.md CHANGED
@@ -24,7 +24,7 @@ i18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (def
24
24
  Add i18n-tasks to the Gemfile:
25
25
 
26
26
  ```ruby
27
- gem 'i18n-tasks', '~> 0.9.3'
27
+ gem 'i18n-tasks', '~> 0.9.4'
28
28
  ```
29
29
 
30
30
  Copy the default [configuration file](#configuration):
@@ -13,7 +13,7 @@ en:
13
13
  data_format: 'Data format: %{valid_text}.'
14
14
  key_pattern: Filter by key pattern (e.g. 'common.*')
15
15
  key_pattern_to_rename: Full key (pattern) to rename. Required
16
- locale: Locale
16
+ locale: :i18n_tasks.common.locale
17
17
  locale_to_translate_from: Locale to translate from
18
18
  locales_filter: 'Locale(s) to process. Special: base'
19
19
  missing_types: 'Filter by types: %{valid}'
@@ -159,12 +159,20 @@ module I18n::Tasks::Data::Tree
159
159
  Term::ANSIColor.dark '∅'
160
160
  else
161
161
  [Term::ANSIColor.color(1 + level % 15, key),
162
- (": #{Term::ANSIColor.cyan(value.to_s)}" if leaf?),
162
+ (": #{format_value_for_inspect(value)}" if leaf?),
163
163
  (" #{data}" if data?)].compact.join
164
164
  end
165
165
  [' ' * level, label, ("\n" + children.map { |c| c.inspect(level + 1) }.join("\n") if children?)].compact.join
166
166
  end
167
167
 
168
+ def format_value_for_inspect(value)
169
+ if value.is_a?(Symbol)
170
+ "#{Term::ANSIColor.bold(Term::ANSIColor.yellow '⮕ ')}#{Term::ANSIColor.yellow value.to_s}"
171
+ else
172
+ Term::ANSIColor.cyan(value.to_s)
173
+ end
174
+ end
175
+
168
176
  protected
169
177
 
170
178
  def dirty!
@@ -123,21 +123,11 @@ module I18n::Tasks::Data::Tree
123
123
  end
124
124
 
125
125
  def subtract_keys(keys)
126
- to_remove = Set.new
127
- keys.each do |full_key|
128
- node = get full_key
129
- to_remove << node if node
130
- end
131
- remove_nodes_collapsing_emptied_ancestors to_remove
126
+ remove_nodes_and_emptied_ancestors(keys.inject(Set.new) { |set, key| (node = get(key)) ? set << node : set })
132
127
  end
133
128
 
134
129
  def subtract_keys!(keys)
135
- to_remove = Set.new
136
- keys.each do |full_key|
137
- node = get full_key
138
- to_remove << node if node
139
- end
140
- remove_nodes_collapsing_emptied_ancestors! to_remove
130
+ remove_nodes_and_emptied_ancestors!(keys.inject(Set.new) { |set, key| (node = get(key)) ? set << node : set })
141
131
  end
142
132
 
143
133
  def subtract_by_key(other)
@@ -179,19 +169,20 @@ module I18n::Tasks::Data::Tree
179
169
  end
180
170
 
181
171
  # @param nodes [Enumerable] Modified in-place.
182
- def remove_nodes_collapsing_emptied_ancestors(nodes)
172
+ def remove_nodes_and_emptied_ancestors(nodes)
183
173
  add_ancestors_that_only_contain_nodes! nodes
184
174
  select_nodes { |node| !nodes.include?(node) }
185
175
  end
186
176
 
187
177
  # @param nodes [Enumerable] Modified in-place.
188
- def remove_nodes_collapsing_emptied_ancestors!(nodes)
178
+ def remove_nodes_and_emptied_ancestors!(nodes)
189
179
  add_ancestors_that_only_contain_nodes! nodes
190
180
  select_nodes! { |node| !nodes.include?(node) }
191
181
  end
192
182
 
193
183
  private
194
184
 
185
+ # Adds all the ancestors that only contain the given nodes as descendants to the given nodes.
195
186
  # @param nodes [Set] Modified in-place.
196
187
  def add_ancestors_that_only_contain_nodes!(nodes)
197
188
  levels.reverse_each do |level_nodes|
@@ -75,6 +75,12 @@ module I18n::Tasks
75
75
  result
76
76
  end
77
77
 
78
+ def root_key_value_data(sort = false)
79
+ result = keys(root: false).map { |key, node| [node.root.key, key, node.value, node.data] }
80
+ result.sort! { |a, b| a[0] != b[0] ? a[0] <=> b[0] : a[1] <=> b[1] } if sort
81
+ result
82
+ end
83
+
78
84
  #-- modify / derive
79
85
 
80
86
  # Select the nodes for which the block returns true. Pre-order traversal.
@@ -89,25 +89,28 @@ module I18n::Tasks
89
89
  end
90
90
 
91
91
  # @param [::I18n::Tasks::Data::Tree::Siblings] forest
92
- def collapse_missing_used_locales!(forest)
93
- locales_and_nodes_by_key = {}
94
- to_remove = []
92
+ # @yield [::I18n::Tasks::Data::Tree::Node]
93
+ # @yieldreturn [Boolean] whether to collapse the node
94
+ def collapse_same_key_in_locales!(forest)
95
+ locales_and_node_by_key = {}
96
+ to_remove = []
95
97
  forest.each do |root|
96
98
  locale = root.key
97
- root.leaves { |node|
98
- if node.data[:type] == :missing_used
99
- (locales_and_nodes_by_key[node.full_key(root: false)] ||= []) << [locale, node]
100
- to_remove << node
99
+ root.keys { |key, node|
100
+ next unless yield node
101
+ if locales_and_node_by_key.key?(key)
102
+ locales_and_node_by_key[key][0] << locale
103
+ else
104
+ locales_and_node_by_key[key] = [[locale], node]
101
105
  end
106
+ to_remove << node
102
107
  }
103
108
  end
104
- forest.remove_nodes_collapsing_emptied_ancestors! to_remove
105
- keys_and_nodes_by_locale = {}
106
- locales_and_nodes_by_key.each { |key, locales_and_nodes|
107
- locales = locales_and_nodes.map(&:first).sort.join('+')
108
- (keys_and_nodes_by_locale[locales] ||= []) << [key, locales_and_nodes[0][1]]
109
- }
110
- keys_and_nodes_by_locale.map { |locales, keys_nodes|
109
+ forest.remove_nodes_and_emptied_ancestors! to_remove
110
+ locales_and_node_by_key.inject({}) { |inv, (key, (locales, node))|
111
+ (inv[locales.sort.join('+')] ||= []) << [key, node]
112
+ inv
113
+ }.map { |locales, keys_nodes|
111
114
  keys_nodes.each { |(key, node)|
112
115
  forest["#{locales}.#{key}"] = node
113
116
  }
@@ -26,6 +26,7 @@ module I18n::Tasks
26
26
  else
27
27
  resolved_node.children = usage_node.children
28
28
  end
29
+ resolved_node.leaves { |node| node.data[:ref_info] = [ref_node.full_key, ref_node.value.to_s] }
29
30
  }.tap { |new_resolved_refs|
30
31
  refs.key_to_node[ref_node.key].data.tap { |ref_data|
31
32
  ref_data[:occurrences] ||= []
@@ -58,5 +58,11 @@ module I18n::Tasks::Reports
58
58
  locale.tr '+', ' '
59
59
  end
60
60
  end
61
+
62
+ def collapse_missing_tree!(forest)
63
+ forest = task.collapse_plural_nodes!(forest)
64
+ forest = task.collapse_same_key_in_locales!(forest) { |node| node.data[:type] == :missing_used }
65
+ forest
66
+ end
61
67
  end
62
68
  end
@@ -20,9 +20,7 @@ module I18n::Tasks::Reports
20
20
  private
21
21
 
22
22
  def add_missing_sheet(wb)
23
- forest = task.missing_keys
24
- forest = task.collapse_plural_nodes!(forest)
25
- forest = task.collapse_missing_used_locales!(forest)
23
+ forest = collapse_missing_tree! task.missing_keys
26
24
  wb.styles do |s|
27
25
  type_cell = s.add_style :alignment => {:horizontal => :center}
28
26
  locale_cell = s.add_style :alignment => {:horizontal => :center}
@@ -8,15 +8,16 @@ module I18n
8
8
  include Term::ANSIColor
9
9
 
10
10
  def missing_keys(forest = task.missing_keys)
11
- forest = task.collapse_plural_nodes!(forest)
12
- forest = task.collapse_missing_used_locales!(forest)
11
+ forest = collapse_missing_tree! forest
13
12
  if forest.present?
14
13
  print_title missing_title(forest)
15
14
  print_table headings: [cyan(bold(I18n.t('i18n_tasks.common.locale'))),
16
15
  cyan(bold I18n.t('i18n_tasks.common.key')),
17
16
  I18n.t('i18n_tasks.missing.details_title')] do |t|
18
17
  t.rows = sort_by_attr!(forest_to_attr(forest)).map do |a|
19
- [{value: cyan(format_locale(a[:locale])), alignment: :center}, cyan(a[:key]), missing_key_info(a)]
18
+ [{value: cyan(format_locale(a[:locale])), alignment: :center},
19
+ format_key(a[:key], a[:data]),
20
+ missing_key_info(a)]
20
21
  end
21
22
  end
22
23
  else
@@ -46,27 +47,27 @@ module I18n
46
47
  end
47
48
 
48
49
  def unused_keys(tree = task.unused_keys)
49
- keys = tree.root_key_values(true)
50
+ keys = tree.root_key_value_data(true)
50
51
  if keys.present?
51
52
  print_title unused_title(keys)
52
- print_locale_key_value_table keys
53
+ print_locale_key_value_data_table keys
53
54
  else
54
55
  print_success I18n.t('i18n_tasks.unused.none')
55
56
  end
56
57
  end
57
58
 
58
59
  def eq_base_keys(tree = task.eq_base_keys)
59
- keys = tree.root_key_values(true)
60
+ keys = tree.root_key_value_data(true)
60
61
  if keys.present?
61
62
  print_title eq_base_title(keys)
62
- print_locale_key_value_table keys
63
+ print_locale_key_value_data_table keys
63
64
  else
64
65
  print_info cyan('No translations are the same as base value')
65
66
  end
66
67
  end
67
68
 
68
69
  def show_tree(tree)
69
- print_locale_key_value_table tree.root_key_values(true)
70
+ print_locale_key_value_data_table tree.root_key_value_data(true)
70
71
  end
71
72
 
72
73
  def forest_stats(forest, stats = task.forest_stats(forest))
@@ -89,25 +90,37 @@ module I18n
89
90
  end
90
91
  end
91
92
 
93
+ def format_key(key, data)
94
+ if data[:ref_info]
95
+ from, to = data[:ref_info]
96
+ resolved = key[0...to.length]
97
+ after = key[to.length..-1]
98
+ " #{yellow from}#{cyan after}\n#{bold(yellow('⮕'))} #{bold yellow resolved}"
99
+ else
100
+ cyan(key)
101
+ end
102
+ end
103
+
92
104
  def format_value(val)
93
105
  val.is_a?(Symbol) ? "#{bold(yellow('⮕ '))}#{yellow(val.to_s)}" : val.to_s.strip
94
106
  end
95
107
 
96
- def format_reference_desc(node)
97
- case node.data[:type]
108
+ def format_reference_desc(node_data)
109
+ return nil unless node_data
110
+ case node_data[:ref_type]
98
111
  when :reference_usage
99
- bold(yellow('(reference)'))
112
+ bold(yellow('(ref)'))
100
113
  when :reference_usage_resolved
101
- bold(yellow('(resolved reference)'))
114
+ bold(yellow('(resolved ref)'))
102
115
  when :reference_usage_key
103
- bold(yellow('(reference key)'))
116
+ bold(yellow('(ref key)'))
104
117
  end
105
118
  end
106
119
 
107
120
  def print_occurrences(node, full_key = node.full_key)
108
121
  occurrences = node.data[:occurrences]
109
122
  puts [bold("#{full_key}"),
110
- format_reference_desc(node),
123
+ format_reference_desc(node.data),
111
124
  (green(occurrences.size.to_s) if occurrences.size > 1)
112
125
  ].compact.join ' '
113
126
  occurrences.each do |occurrence|
@@ -115,13 +128,13 @@ module I18n
115
128
  end
116
129
  end
117
130
 
118
- def print_locale_key_value_table(locale_key_values)
119
- if locale_key_values.present?
131
+ def print_locale_key_value_data_table(locale_key_value_datas)
132
+ if locale_key_value_datas.present?
120
133
  print_table headings: [bold(cyan(I18n.t('i18n_tasks.common.locale'))),
121
134
  bold(cyan(I18n.t('i18n_tasks.common.key'))),
122
135
  I18n.t('i18n_tasks.common.value')] do |t|
123
- t.rows = locale_key_values.map { |(locale, k, v)|
124
- [{value: cyan(locale), alignment: :center}, cyan(k), format_value(v)]
136
+ t.rows = locale_key_value_datas.map { |(locale, k, v, data)|
137
+ [{value: cyan(locale), alignment: :center}, format_key(k, data), format_value(v)]
125
138
  }
126
139
  end
127
140
  else
@@ -12,9 +12,7 @@ module I18n
12
12
  # @param [String] locale
13
13
  # @param [Boolean] strict if true, do not match dynamic keys
14
14
  def unused_tree(locale: base_locale, strict: nil)
15
- used_key_names = used_tree(strict: true).keys.reject {|_key, node|
16
- node.data[:type] == :used_reference_key_raw
17
- }.map(&:first)
15
+ used_key_names = used_tree(strict: true).key_names
18
16
  collapse_plural_nodes! data[locale].select_keys { |key, _node|
19
17
  !ignore_key?(key, :unused) &&
20
18
  (strict || !used_in_expr?(key)) &&
@@ -30,14 +30,14 @@ module I18n::Tasks
30
30
  #
31
31
  # @param key_filter [String] only return keys matching this pattern.
32
32
  # @param strict [Boolean] if true, dynamic keys are excluded (e.g. `t("category.#{ category.key }")`)
33
+ # @param include_raw_references [Boolean] if true, includes reference usages as they appear in the source
33
34
  # @return [Data::Tree::Siblings]
34
35
  def used_tree(key_filter: nil, strict: nil, include_raw_references: false)
35
36
  src_tree = used_in_source_tree(key_filter: key_filter, strict: strict)
36
-
37
37
  raw_refs, resolved_refs, used_refs = process_references(src_tree['used'].children)
38
- raw_refs.leaves { |node| node.data[:type] = :reference_usage }
39
- resolved_refs.leaves { |node| node.data[:type] = :reference_usage_resolved }
40
- used_refs.leaves { |node| node.data[:type] = :reference_usage_key }
38
+ raw_refs.leaves { |node| node.data[:ref_type] = :reference_usage }
39
+ resolved_refs.leaves { |node| node.data[:ref_type] = :reference_usage_resolved }
40
+ used_refs.leaves { |node| node.data[:ref_type] = :reference_usage_key }
41
41
  src_tree.tap do |result|
42
42
  tree = result['used'].children
43
43
  tree.subtract_by_key!(raw_refs)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module I18n
3
3
  module Tasks
4
- VERSION = '0.9.3'
4
+ VERSION = '0.9.4'
5
5
  end
6
6
  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.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-04 00:00:00.000000000 Z
11
+ date: 2016-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport