i18n-tasks 0.9.6 → 0.9.7
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/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
|
|