i18n-tasks 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/Rakefile +2 -1
- data/bin/i18n-tasks +1 -0
- data/config/locales/en.yml +15 -9
- data/config/locales/ru.yml +80 -74
- data/i18n-tasks.gemspec +9 -8
- data/lib/i18n/tasks.rb +2 -5
- data/lib/i18n/tasks/cli.rb +14 -18
- data/lib/i18n/tasks/command/commander.rb +2 -3
- data/lib/i18n/tasks/command/commands/health.rb +1 -1
- data/lib/i18n/tasks/command/commands/meta.rb +2 -2
- data/lib/i18n/tasks/command/commands/missing.rb +17 -19
- data/lib/i18n/tasks/command/commands/tree.rb +3 -3
- data/lib/i18n/tasks/command/commands/usages.rb +6 -5
- data/lib/i18n/tasks/command/commands/xlsx.rb +1 -1
- data/lib/i18n/tasks/command/dsl.rb +1 -2
- data/lib/i18n/tasks/command/option_parsers/enum.rb +6 -6
- data/lib/i18n/tasks/command/option_parsers/locale.rb +3 -1
- data/lib/i18n/tasks/command/options/data.rb +22 -21
- data/lib/i18n/tasks/command_error.rb +1 -3
- data/lib/i18n/tasks/configuration.rb +37 -27
- data/lib/i18n/tasks/console_context.rb +3 -2
- data/lib/i18n/tasks/data.rb +5 -4
- data/lib/i18n/tasks/data/adapter/json_adapter.rb +13 -12
- data/lib/i18n/tasks/data/adapter/yaml_adapter.rb +13 -14
- data/lib/i18n/tasks/data/file_formats.rb +15 -10
- data/lib/i18n/tasks/data/file_system_base.rb +18 -22
- data/lib/i18n/tasks/data/router/conservative_router.rb +3 -6
- data/lib/i18n/tasks/data/router/pattern_router.rb +4 -5
- data/lib/i18n/tasks/data/tree/node.rb +20 -19
- data/lib/i18n/tasks/data/tree/nodes.rb +4 -3
- data/lib/i18n/tasks/data/tree/siblings.rb +36 -29
- data/lib/i18n/tasks/data/tree/traversal.rb +32 -35
- data/lib/i18n/tasks/google_translation.rb +22 -25
- data/lib/i18n/tasks/html_keys.rb +2 -0
- data/lib/i18n/tasks/ignore_keys.rb +3 -2
- data/lib/i18n/tasks/key_pattern_matching.rb +9 -8
- data/lib/i18n/tasks/locale_list.rb +4 -6
- data/lib/i18n/tasks/locale_pathname.rb +8 -8
- data/lib/i18n/tasks/logging.rb +3 -3
- data/lib/i18n/tasks/missing_keys.rb +29 -31
- data/lib/i18n/tasks/plural_keys.rb +6 -7
- data/lib/i18n/tasks/references.rb +72 -41
- data/lib/i18n/tasks/reports/base.rb +8 -7
- data/lib/i18n/tasks/reports/spreadsheet.rb +15 -16
- data/lib/i18n/tasks/reports/terminal.rb +32 -32
- data/lib/i18n/tasks/scanners/file_scanner.rb +6 -5
- data/lib/i18n/tasks/scanners/files/caching_file_finder_provider.rb +1 -2
- data/lib/i18n/tasks/scanners/files/caching_file_reader.rb +0 -1
- data/lib/i18n/tasks/scanners/files/file_finder.rb +12 -15
- data/lib/i18n/tasks/scanners/files/file_reader.rb +0 -1
- data/lib/i18n/tasks/scanners/occurrence_from_position.rb +8 -7
- data/lib/i18n/tasks/scanners/pattern_mapper.rb +2 -2
- data/lib/i18n/tasks/scanners/pattern_scanner.rb +9 -7
- data/lib/i18n/tasks/scanners/pattern_with_scope_scanner.rb +1 -2
- data/lib/i18n/tasks/scanners/relative_keys.rb +11 -11
- data/lib/i18n/tasks/scanners/results/key_occurrences.rb +3 -4
- data/lib/i18n/tasks/scanners/results/occurrence.rb +8 -7
- data/lib/i18n/tasks/scanners/ruby_ast_call_finder.rb +2 -2
- data/lib/i18n/tasks/scanners/ruby_ast_scanner.rb +39 -31
- data/lib/i18n/tasks/scanners/scanner_multiplexer.rb +9 -3
- data/lib/i18n/tasks/split_key.rb +5 -6
- data/lib/i18n/tasks/stats.rb +10 -8
- data/lib/i18n/tasks/string_interpolation.rb +1 -1
- data/lib/i18n/tasks/unused_keys.rb +2 -2
- data/lib/i18n/tasks/used_keys.rb +47 -43
- data/lib/i18n/tasks/version.rb +1 -1
- data/templates/rspec/i18n_spec.rb +2 -2
- metadata +30 -3
@@ -7,22 +7,21 @@ module I18n::Tasks::PluralKeys
|
|
7
7
|
def collapse_plural_nodes!(tree)
|
8
8
|
tree.leaves.map(&:parent).compact.uniq.each do |node|
|
9
9
|
children = node.children
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
10
|
+
next unless plural_forms?(children)
|
11
|
+
node.value = children.to_hash
|
12
|
+
node.children = nil
|
13
|
+
node.data.merge! children.first.data
|
15
14
|
end
|
16
15
|
tree
|
17
16
|
end
|
18
17
|
|
19
18
|
# @param [String] key i18n key
|
20
19
|
# @param [String] locale to pull key data from
|
21
|
-
# @return the base form if the key is a specific plural form (e.g. apple for apple.many),
|
20
|
+
# @return [String] the base form if the key is a specific plural form (e.g. apple for apple.many), the key otherwise.
|
22
21
|
def depluralize_key(key, locale = base_locale)
|
23
22
|
return key if key !~ PLURAL_KEY_RE
|
24
23
|
key_name = last_key_part(key)
|
25
|
-
parent_key = key[0
|
24
|
+
parent_key = key[0..- (key_name.length + 2)]
|
26
25
|
nodes = tree("#{locale}.#{parent_key}").presence || (locale != base_locale && tree("#{base_locale}.#{parent_key}"))
|
27
26
|
if nodes && plural_forms?(nodes)
|
28
27
|
parent_key
|
@@ -5,64 +5,95 @@ module I18n::Tasks
|
|
5
5
|
# 1. Raw references -- a subset of the usages tree with keys that are reference key usages.
|
6
6
|
# 2. Resolved references -- all the used references in their fully resolved form.
|
7
7
|
# 3. Reference keys -- all the used reference keys.
|
8
|
-
def process_references(usages,
|
9
|
-
|
10
|
-
fail ArgumentError
|
11
|
-
|
8
|
+
def process_references(usages,
|
9
|
+
data_refs = merge_reference_trees(data_forest.select_keys { |_, node| node.reference? }))
|
10
|
+
fail ArgumentError, 'usages must be a Data::Tree::Instance' unless usages.is_a?(Data::Tree::Siblings)
|
11
|
+
fail ArgumentError, 'all_references must be a Data::Tree::Instance' unless data_refs.is_a?(Data::Tree::Siblings)
|
12
|
+
raw_refs = empty_forest
|
12
13
|
resolved_refs = empty_forest
|
13
|
-
refs
|
14
|
-
|
14
|
+
refs = empty_forest
|
15
|
+
data_refs.key_to_node.each do |ref_key_part, ref_node|
|
15
16
|
usages.each do |usage_node|
|
16
17
|
next unless usage_node.key == ref_key_part
|
17
18
|
if ref_node.leaf?
|
18
|
-
|
19
|
-
refs.merge_node!(Data::Tree::Node.new(key: ref_node.key, data: usage_node.data))
|
20
|
-
end
|
21
|
-
resolved_refs.merge!(
|
22
|
-
Data::Tree::Siblings.from_key_names([ref_node.value.to_s]) { |_, resolved_node|
|
23
|
-
raw_refs.merge_node!(usage_node)
|
24
|
-
if usage_node.leaf?
|
25
|
-
resolved_node.data.merge!(usage_node.data)
|
26
|
-
else
|
27
|
-
resolved_node.children = usage_node.children
|
28
|
-
end
|
29
|
-
resolved_node.leaves { |node| node.data[:ref_info] = [ref_node.full_key, ref_node.value.to_s] }
|
30
|
-
}.tap { |new_resolved_refs|
|
31
|
-
refs.key_to_node[ref_node.key].data.tap { |ref_data|
|
32
|
-
ref_data[:occurrences] ||= []
|
33
|
-
new_resolved_refs.leaves { |leaf| ref_data[:occurrences].concat(leaf.data[:occurrences] || []) }
|
34
|
-
ref_data[:occurrences].sort_by!(&:path)
|
35
|
-
ref_data[:occurrences].uniq!
|
36
|
-
}
|
37
|
-
})
|
19
|
+
process_leaf!(ref_node, usage_node, raw_refs, resolved_refs, refs)
|
38
20
|
else
|
39
|
-
|
40
|
-
raw_refs.merge_node! Data::Tree::Node.new(key: ref_node.key, children: child_raw_refs) unless child_raw_refs.empty?
|
41
|
-
resolved_refs.merge! child_resolved_refs
|
42
|
-
refs.merge_node! Data::Tree::Node.new(key: ref_node.key, children: child_refs) unless child_refs.empty?
|
21
|
+
process_non_leaf!(ref_node, usage_node, raw_refs, resolved_refs, refs)
|
43
22
|
end
|
44
23
|
end
|
45
24
|
end
|
46
25
|
[raw_refs, resolved_refs, refs]
|
47
26
|
end
|
48
27
|
|
28
|
+
private
|
29
|
+
|
30
|
+
# @param [I18n::Tasks::Data::Tree::Node] ref
|
31
|
+
# @param [I18n::Tasks::Data::Tree::Node] usage
|
32
|
+
# @param [I18n::Tasks::Data::Tree::Siblings] raw_refs
|
33
|
+
# @param [I18n::Tasks::Data::Tree::Siblings] resolved_refs
|
34
|
+
# @param [I18n::Tasks::Data::Tree::Siblings] refs
|
35
|
+
def process_leaf!(ref, usage, raw_refs, resolved_refs, refs)
|
36
|
+
refs.merge_node!(Data::Tree::Node.new(key: ref.key, data: usage.data)) unless refs.key_to_node.key?(ref.key)
|
37
|
+
new_resolved_refs = Data::Tree::Siblings.from_key_names([ref.value.to_s]) do |_, resolved_node|
|
38
|
+
raw_refs.merge_node!(usage)
|
39
|
+
if usage.leaf?
|
40
|
+
resolved_node.data.merge!(usage.data)
|
41
|
+
else
|
42
|
+
resolved_node.children = usage.children
|
43
|
+
end
|
44
|
+
resolved_node.leaves { |node| node.data[:ref_info] = [ref.full_key, ref.value.to_s] }
|
45
|
+
end
|
46
|
+
add_occurences! refs.key_to_node[ref.key].data, new_resolved_refs
|
47
|
+
resolved_refs.merge! new_resolved_refs
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param [Hash] ref_data
|
51
|
+
# @param [I18n::Tasks::Data::Tree::Siblings] new_resolved_refs
|
52
|
+
def add_occurences!(ref_data, new_resolved_refs)
|
53
|
+
ref_data[:occurrences] ||= []
|
54
|
+
new_resolved_refs.leaves do |leaf|
|
55
|
+
ref_data[:occurrences].concat(leaf.data[:occurrences] || [])
|
56
|
+
end
|
57
|
+
ref_data[:occurrences].sort_by!(&:path)
|
58
|
+
ref_data[:occurrences].uniq!
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param [I18n::Tasks::Data::Tree::Node] ref
|
62
|
+
# @param [I18n::Tasks::Data::Tree::Node] usage
|
63
|
+
# @param [I18n::Tasks::Data::Tree::Siblings] raw_refs
|
64
|
+
# @param [I18n::Tasks::Data::Tree::Siblings] resolved_refs
|
65
|
+
# @param [I18n::Tasks::Data::Tree::Siblings] refs
|
66
|
+
def process_non_leaf!(ref, usage, raw_refs, resolved_refs, refs)
|
67
|
+
child_raw_refs, child_resolved_refs, child_refs = process_references(usage.children, ref.children)
|
68
|
+
raw_refs.merge_node! Data::Tree::Node.new(key: ref.key, children: child_raw_refs) unless child_raw_refs.empty?
|
69
|
+
resolved_refs.merge! child_resolved_refs
|
70
|
+
refs.merge_node! Data::Tree::Node.new(key: ref.key, children: child_refs) unless child_refs.empty?
|
71
|
+
end
|
72
|
+
|
49
73
|
# Given a forest of references, merge trees into one tree, ensuring there are no conflicting references.
|
50
|
-
# @param roots [Data::Tree::Siblings]
|
51
|
-
# @return [Data::Tree::Siblings]
|
74
|
+
# @param roots [I18n::Tasks::Data::Tree::Siblings]
|
75
|
+
# @return [I18n::Tasks::Data::Tree::Siblings]
|
52
76
|
def merge_reference_trees(roots)
|
53
77
|
roots.inject(empty_forest) do |forest, root|
|
54
|
-
root.keys
|
55
|
-
|
78
|
+
root.keys do |full_key, node|
|
79
|
+
if full_key == node.value.to_s
|
80
|
+
log_warn(
|
56
81
|
"Self-referencing key #{node.full_key(root: false).inspect} in #{node.data[:locale].inspect}"
|
57
|
-
|
58
|
-
|
82
|
+
)
|
83
|
+
end
|
84
|
+
end
|
59
85
|
forest.merge!(
|
60
|
-
|
61
|
-
|
86
|
+
root.children,
|
87
|
+
on_leaves_merge: lambda do |node, other|
|
88
|
+
if node.value != other.value
|
62
89
|
log_warn(
|
63
|
-
|
64
|
-
|
65
|
-
}
|
90
|
+
'Conflicting references: '\
|
91
|
+
"#{node.full_key(root: false)} ⮕ #{node.value} in #{node.data[:locale]},"\
|
92
|
+
" but ⮕ #{other.value} in #{other.data[:locale]}"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
)
|
66
97
|
end
|
67
98
|
end
|
68
99
|
end
|
@@ -30,24 +30,25 @@ module I18n::Tasks::Reports
|
|
30
30
|
|
31
31
|
def used_title(keys_nodes, filter)
|
32
32
|
used_n = keys_nodes.map { |_k, node| node.data[:occurrences].size }.reduce(:+).to_i
|
33
|
-
"#{keys_nodes.size} key#{'s' if keys_nodes.size != 1}#{" matching '#{filter}'" if filter}
|
33
|
+
"#{keys_nodes.size} key#{'s' if keys_nodes.size != 1}#{" matching '#{filter}'" if filter}"\
|
34
|
+
"#{" (#{used_n} usage#{'s' if used_n != 1})" if used_n > 0}"
|
34
35
|
end
|
35
36
|
|
36
37
|
# Sort keys by their attributes in order
|
37
38
|
# @param [Hash] order e.g. {locale: :asc, type: :desc, key: :asc}
|
38
|
-
def sort_by_attr!(objects, order = {locale: :asc, key: :asc})
|
39
|
+
def sort_by_attr!(objects, order = { locale: :asc, key: :asc })
|
39
40
|
order_keys = order.keys
|
40
|
-
objects.sort!
|
41
|
+
objects.sort! do |a, b|
|
41
42
|
by = order_keys.detect { |k| a[k] != b[k] }
|
42
43
|
order[by] == :desc ? b[by] <=> a[by] : a[by] <=> b[by]
|
43
|
-
|
44
|
+
end
|
44
45
|
objects
|
45
46
|
end
|
46
47
|
|
47
48
|
def forest_to_attr(forest)
|
48
|
-
forest.keys(root: false).map
|
49
|
-
{key: key, value: node.value, type: node.data[:type], locale: node.root.key, data: node.data}
|
50
|
-
|
49
|
+
forest.keys(root: false).map do |key, node|
|
50
|
+
{ key: key, value: node.value, type: node.data[:type], locale: node.root.key, data: node.data }
|
51
|
+
end
|
51
52
|
end
|
52
53
|
|
53
54
|
def format_locale(locale)
|
@@ -4,8 +4,7 @@ require 'fileutils'
|
|
4
4
|
|
5
5
|
module I18n::Tasks::Reports
|
6
6
|
class Spreadsheet < Base
|
7
|
-
|
8
|
-
def save_report(path, opts)
|
7
|
+
def save_report(path, _opts)
|
9
8
|
path = path.presence || 'tmp/i18n-report.xlsx'
|
10
9
|
p = Axlsx::Package.new
|
11
10
|
p.use_shared_strings = true # see #159
|
@@ -19,22 +18,24 @@ module I18n::Tasks::Reports
|
|
19
18
|
|
20
19
|
private
|
21
20
|
|
22
|
-
def add_missing_sheet(wb)
|
21
|
+
def add_missing_sheet(wb) # rubocop:disable Metrics/AbcSize
|
23
22
|
forest = collapse_missing_tree! task.missing_keys
|
24
23
|
wb.styles do |s|
|
25
|
-
type_cell = s.add_style :
|
26
|
-
locale_cell
|
24
|
+
type_cell = s.add_style alignment: { horizontal: :center }
|
25
|
+
locale_cell = s.add_style alignment: { horizontal: :center }
|
27
26
|
regular_style = s.add_style
|
28
|
-
wb.add_worksheet(name: missing_title(forest))
|
29
|
-
sheet.page_setup.fit_to :
|
30
|
-
sheet.add_row [I18n.t('i18n_tasks.common.type'), I18n.t('i18n_tasks.common.locale'),
|
27
|
+
wb.add_worksheet(name: missing_title(forest)) do |sheet|
|
28
|
+
sheet.page_setup.fit_to width: 1
|
29
|
+
sheet.add_row [I18n.t('i18n_tasks.common.type'), I18n.t('i18n_tasks.common.locale'),
|
30
|
+
I18n.t('i18n_tasks.common.key'), I18n.t('i18n_tasks.common.base_value')]
|
31
31
|
style_header sheet
|
32
32
|
forest.keys do |key, node|
|
33
|
-
locale
|
33
|
+
locale = format_locale(node.root.data[:locale])
|
34
|
+
type = node.data[:type]
|
34
35
|
sheet.add_row [missing_type_info(type)[:summary], locale, key, task.t(key)],
|
35
|
-
|
36
|
+
styles: [type_cell, locale_cell, regular_style, regular_style]
|
36
37
|
end
|
37
|
-
|
38
|
+
end
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
@@ -48,11 +49,10 @@ module I18n::Tasks::Reports
|
|
48
49
|
add_locale_key_value_table wb, keys, name: unused_title(keys)
|
49
50
|
end
|
50
51
|
|
51
|
-
private
|
52
|
-
|
53
52
|
def add_locale_key_value_table(wb, keys, worksheet_opts = {})
|
54
53
|
wb.add_worksheet worksheet_opts do |sheet|
|
55
|
-
sheet.add_row [I18n.t('i18n_tasks.common.locale'), I18n.t('i18n_tasks.common.key'),
|
54
|
+
sheet.add_row [I18n.t('i18n_tasks.common.locale'), I18n.t('i18n_tasks.common.key'),
|
55
|
+
I18n.t('i18n_tasks.common.value')]
|
56
56
|
style_header sheet
|
57
57
|
keys.each do |locale_k_v|
|
58
58
|
sheet.add_row locale_k_v
|
@@ -60,9 +60,8 @@ module I18n::Tasks::Reports
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
|
64
63
|
def style_header(sheet)
|
65
|
-
border_bottom = sheet.workbook.styles.add_style(border: {style: :thin, color: '000000', edges: [:bottom]})
|
64
|
+
border_bottom = sheet.workbook.styles.add_style(border: { style: :thin, color: '000000', edges: [:bottom] })
|
66
65
|
sheet.rows.first.style = border_bottom
|
67
66
|
end
|
68
67
|
end
|
@@ -4,7 +4,7 @@ require 'terminal-table'
|
|
4
4
|
module I18n
|
5
5
|
module Tasks
|
6
6
|
module Reports
|
7
|
-
class Terminal < Base
|
7
|
+
class Terminal < Base # rubocop:disable Metrics/ClassLength
|
8
8
|
include Term::ANSIColor
|
9
9
|
|
10
10
|
def missing_keys(forest = task.missing_keys)
|
@@ -12,10 +12,10 @@ module I18n
|
|
12
12
|
if forest.present?
|
13
13
|
print_title missing_title(forest)
|
14
14
|
print_table headings: [cyan(bold(I18n.t('i18n_tasks.common.locale'))),
|
15
|
-
cyan(bold
|
15
|
+
cyan(bold(I18n.t('i18n_tasks.common.key'))),
|
16
16
|
I18n.t('i18n_tasks.missing.details_title')] do |t|
|
17
17
|
t.rows = sort_by_attr!(forest_to_attr(forest)).map do |a|
|
18
|
-
[{value: cyan(format_locale(a[:locale])), alignment: :center},
|
18
|
+
[{ value: cyan(format_locale(a[:locale])), alignment: :center },
|
19
19
|
format_key(a[:key], a[:data]),
|
20
20
|
missing_key_info(a)]
|
21
21
|
end
|
@@ -27,14 +27,14 @@ module I18n
|
|
27
27
|
|
28
28
|
def icon(type)
|
29
29
|
glyph = missing_type_info(type)[:glyph]
|
30
|
-
{missing_used: red(glyph), missing_diff: yellow(glyph)}[type]
|
30
|
+
{ missing_used: red(glyph), missing_diff: yellow(glyph) }[type]
|
31
31
|
end
|
32
32
|
|
33
33
|
def used_keys(used_tree = task.used_tree)
|
34
34
|
# For the used tree we may have usage nodes that are not leaves as references.
|
35
|
-
keys_nodes = used_tree.nodes.select { |node|
|
35
|
+
keys_nodes = used_tree.nodes.select { |node| node.data[:occurrences].present? }.map do |node|
|
36
36
|
[node.full_key(root: false), node]
|
37
|
-
|
37
|
+
end
|
38
38
|
print_title used_title(keys_nodes, used_tree.first.root.data[:key_filter])
|
39
39
|
# Group multiple nodes
|
40
40
|
if keys_nodes.present?
|
@@ -86,7 +86,8 @@ module I18n
|
|
86
86
|
if leaf[:type] == :missing_used
|
87
87
|
first_occurrence leaf
|
88
88
|
else
|
89
|
-
"#{cyan leaf[:data][:missing_diff_locale]}
|
89
|
+
"#{cyan leaf[:data][:missing_diff_locale]} "\
|
90
|
+
"#{format_value(leaf[:value].is_a?(String) ? leaf[:value].strip : leaf[:value])}"
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
@@ -106,23 +107,22 @@ module I18n
|
|
106
107
|
end
|
107
108
|
|
108
109
|
def format_reference_desc(node_data)
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
110
|
+
return nil unless node_data
|
111
|
+
case node_data[:ref_type]
|
112
|
+
when :reference_usage
|
113
|
+
bold(yellow('(ref)'))
|
114
|
+
when :reference_usage_resolved
|
115
|
+
bold(yellow('(resolved ref)'))
|
116
|
+
when :reference_usage_key
|
117
|
+
bold(yellow('(ref key)'))
|
118
|
+
end
|
118
119
|
end
|
119
120
|
|
120
121
|
def print_occurrences(node, full_key = node.full_key)
|
121
122
|
occurrences = node.data[:occurrences]
|
122
|
-
puts [bold(
|
123
|
+
puts [bold(full_key.to_s),
|
123
124
|
format_reference_desc(node.data),
|
124
|
-
(green(occurrences.size.to_s) if occurrences.size > 1)
|
125
|
-
].compact.join ' '
|
125
|
+
(green(occurrences.size.to_s) if occurrences.size > 1)].compact.join ' '
|
126
126
|
occurrences.each do |occurrence|
|
127
127
|
puts " #{key_occurrence full_key, occurrence}"
|
128
128
|
end
|
@@ -134,7 +134,7 @@ module I18n
|
|
134
134
|
bold(cyan(I18n.t('i18n_tasks.common.key'))),
|
135
135
|
I18n.t('i18n_tasks.common.value')] do |t|
|
136
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)]
|
137
|
+
[{ value: cyan(locale), alignment: :center }, format_key(k, data), format_value(v)]
|
138
138
|
}
|
139
139
|
end
|
140
140
|
else
|
@@ -143,15 +143,15 @@ module I18n
|
|
143
143
|
end
|
144
144
|
|
145
145
|
def print_title(title)
|
146
|
-
log_stderr "#{bold title.strip} #{dark
|
146
|
+
log_stderr "#{bold title.strip} #{dark '|'} #{"i18n-tasks v#{I18n::Tasks::VERSION}"}"
|
147
147
|
end
|
148
148
|
|
149
149
|
def print_success(message)
|
150
|
-
log_stderr bold(green
|
150
|
+
log_stderr bold(green("✓ #{I18n.t('i18n_tasks.cmd.encourage').sample} #{message}"))
|
151
151
|
end
|
152
152
|
|
153
153
|
def print_error(message)
|
154
|
-
log_stderr(bold
|
154
|
+
log_stderr(bold(red(message)))
|
155
155
|
end
|
156
156
|
|
157
157
|
def print_info(message)
|
@@ -159,8 +159,7 @@ module I18n
|
|
159
159
|
end
|
160
160
|
|
161
161
|
def indent(txt, n = 2)
|
162
|
-
|
163
|
-
txt.gsub /^/, spaces
|
162
|
+
txt.gsub(/^/, ' ' * n)
|
164
163
|
end
|
165
164
|
|
166
165
|
def print_table(opts, &block)
|
@@ -177,18 +176,19 @@ module I18n
|
|
177
176
|
# @type [I18n::Tasks::Scanners::KeyOccurrences]
|
178
177
|
occurrences = leaf[:data][:occurrences]
|
179
178
|
# @type [I18n::Tasks::Scanners::Occurrence]
|
180
|
-
first
|
181
|
-
[
|
182
|
-
|
179
|
+
first = occurrences.first
|
180
|
+
[
|
181
|
+
green("#{first.path}:#{first.line_num}"),
|
182
|
+
("(#{I18n.t 'i18n_tasks.common.n_more', count: occurrences.length - 1})" if occurrences.length > 1)
|
183
183
|
].compact.join(' ')
|
184
184
|
end
|
185
185
|
|
186
186
|
def highlight_key(full_key, line, range = (0..-1))
|
187
|
-
line.dup.tap
|
188
|
-
s[range] = s[range].sub(full_key)
|
187
|
+
line.dup.tap do |s|
|
188
|
+
s[range] = s[range].sub(full_key) do |m|
|
189
189
|
highlight_string m
|
190
|
-
|
191
|
-
|
190
|
+
end
|
191
|
+
end
|
192
192
|
end
|
193
193
|
|
194
194
|
module HighlightUnderline
|
@@ -12,7 +12,8 @@ module I18n::Tasks::Scanners
|
|
12
12
|
def initialize(
|
13
13
|
config: {},
|
14
14
|
file_finder_provider: Files::CachingFileFinderProvider.new,
|
15
|
-
file_reader: Files::CachingFileReader.new
|
15
|
+
file_reader: Files::CachingFileReader.new
|
16
|
+
)
|
16
17
|
@config = config
|
17
18
|
@file_reader = file_reader
|
18
19
|
@file_finder = file_finder_provider.get(**config.slice(:paths, :only, :exclude))
|
@@ -20,11 +21,11 @@ module I18n::Tasks::Scanners
|
|
20
21
|
|
21
22
|
# @return (see Scanner#keys)
|
22
23
|
def keys
|
23
|
-
(traverse_files
|
24
|
+
(traverse_files do |path|
|
24
25
|
scan_file(path)
|
25
|
-
|
26
|
+
end.reduce(:+) || []).group_by(&:first).map do |key, keys_occurrences|
|
26
27
|
Results::KeyOccurrences.new(key: key, occurrences: keys_occurrences.map(&:second))
|
27
|
-
|
28
|
+
end
|
28
29
|
end
|
29
30
|
|
30
31
|
protected
|
@@ -32,7 +33,7 @@ module I18n::Tasks::Scanners
|
|
32
33
|
# Extract all occurrences of translate calls from the file at the given path.
|
33
34
|
#
|
34
35
|
# @return [Array<[key, Results::KeyOccurrence]>] each occurrence found in the file
|
35
|
-
def scan_file(
|
36
|
+
def scan_file(_path)
|
36
37
|
fail 'Unimplemented'
|
37
38
|
end
|
38
39
|
|