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 +4 -4
- data/README.md +1 -1
- data/config/locales/en.yml +1 -1
- data/lib/i18n/tasks/data/tree/node.rb +9 -1
- data/lib/i18n/tasks/data/tree/siblings.rb +5 -14
- data/lib/i18n/tasks/data/tree/traversal.rb +6 -0
- data/lib/i18n/tasks/missing_keys.rb +17 -14
- data/lib/i18n/tasks/references.rb +1 -0
- data/lib/i18n/tasks/reports/base.rb +6 -0
- data/lib/i18n/tasks/reports/spreadsheet.rb +1 -3
- data/lib/i18n/tasks/reports/terminal.rb +31 -18
- data/lib/i18n/tasks/unused_keys.rb +1 -3
- data/lib/i18n/tasks/used_keys.rb +4 -4
- data/lib/i18n/tasks/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4807ae41e4ea2c7274b08bc55c2a2286a6e601d5
|
4
|
+
data.tar.gz: bdc921c3485e004c0e395a79afde8a5cfcfa888c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
27
|
+
gem 'i18n-tasks', '~> 0.9.4'
|
28
28
|
```
|
29
29
|
|
30
30
|
Copy the default [configuration file](#configuration):
|
data/config/locales/en.yml
CHANGED
@@ -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:
|
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
|
-
(": #{
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
93
|
-
|
94
|
-
|
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.
|
98
|
-
|
99
|
-
|
100
|
-
|
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.
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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 =
|
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},
|
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.
|
50
|
+
keys = tree.root_key_value_data(true)
|
50
51
|
if keys.present?
|
51
52
|
print_title unused_title(keys)
|
52
|
-
|
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.
|
60
|
+
keys = tree.root_key_value_data(true)
|
60
61
|
if keys.present?
|
61
62
|
print_title eq_base_title(keys)
|
62
|
-
|
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
|
-
|
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(
|
97
|
-
|
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('(
|
112
|
+
bold(yellow('(ref)'))
|
100
113
|
when :reference_usage_resolved
|
101
|
-
bold(yellow('(resolved
|
114
|
+
bold(yellow('(resolved ref)'))
|
102
115
|
when :reference_usage_key
|
103
|
-
bold(yellow('(
|
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
|
119
|
-
if
|
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 =
|
124
|
-
[{value: cyan(locale), alignment: :center},
|
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).
|
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)) &&
|
data/lib/i18n/tasks/used_keys.rb
CHANGED
@@ -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[:
|
39
|
-
resolved_refs.leaves { |node| node.data[:
|
40
|
-
used_refs.leaves { |node| node.data[:
|
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)
|
data/lib/i18n/tasks/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2016-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|