i18n-tasks 1.0.15 → 1.1.0

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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +85 -13
  3. data/Rakefile +4 -4
  4. data/bin/i18n-tasks +3 -3
  5. data/config/locales/en.yml +6 -0
  6. data/config/locales/ru.yml +7 -0
  7. data/i18n-tasks.gemspec +28 -41
  8. data/lib/i18n/tasks/base_task.rb +19 -19
  9. data/lib/i18n/tasks/cli.rb +37 -30
  10. data/lib/i18n/tasks/command/collection.rb +4 -4
  11. data/lib/i18n/tasks/command/commander.rb +5 -5
  12. data/lib/i18n/tasks/command/commands/check_prism.rb +126 -0
  13. data/lib/i18n/tasks/command/commands/data.rb +33 -33
  14. data/lib/i18n/tasks/command/commands/eq_base.rb +3 -3
  15. data/lib/i18n/tasks/command/commands/health.rb +6 -5
  16. data/lib/i18n/tasks/command/commands/interpolations.rb +14 -3
  17. data/lib/i18n/tasks/command/commands/meta.rb +6 -6
  18. data/lib/i18n/tasks/command/commands/missing.rb +25 -25
  19. data/lib/i18n/tasks/command/commands/tree.rb +33 -33
  20. data/lib/i18n/tasks/command/commands/usages.rb +24 -24
  21. data/lib/i18n/tasks/command/dsl.rb +1 -1
  22. data/lib/i18n/tasks/command/option_parsers/enum.rb +5 -5
  23. data/lib/i18n/tasks/command/option_parsers/locale.rb +4 -4
  24. data/lib/i18n/tasks/command/options/common.rb +16 -16
  25. data/lib/i18n/tasks/command/options/data.rb +18 -18
  26. data/lib/i18n/tasks/command/options/locales.rb +32 -32
  27. data/lib/i18n/tasks/commands.rb +14 -12
  28. data/lib/i18n/tasks/concurrent/cache.rb +1 -1
  29. data/lib/i18n/tasks/concurrent/cached_value.rb +1 -1
  30. data/lib/i18n/tasks/configuration.rb +22 -21
  31. data/lib/i18n/tasks/console_context.rb +11 -11
  32. data/lib/i18n/tasks/data/adapter/json_adapter.rb +1 -1
  33. data/lib/i18n/tasks/data/adapter/yaml_adapter.rb +5 -5
  34. data/lib/i18n/tasks/data/file_formats.rb +3 -3
  35. data/lib/i18n/tasks/data/file_system.rb +5 -5
  36. data/lib/i18n/tasks/data/file_system_base.rb +26 -26
  37. data/lib/i18n/tasks/data/language_names.rb +202 -0
  38. data/lib/i18n/tasks/data/router/conservative_router.rb +3 -3
  39. data/lib/i18n/tasks/data/router/isolating_router.rb +19 -19
  40. data/lib/i18n/tasks/data/router/pattern_router.rb +5 -5
  41. data/lib/i18n/tasks/data/tree/node.rb +27 -27
  42. data/lib/i18n/tasks/data/tree/nodes.rb +10 -10
  43. data/lib/i18n/tasks/data/tree/siblings.rb +20 -20
  44. data/lib/i18n/tasks/data/tree/traversal.rb +5 -5
  45. data/lib/i18n/tasks/data.rb +4 -4
  46. data/lib/i18n/tasks/html_keys.rb +2 -2
  47. data/lib/i18n/tasks/ignore_keys.rb +9 -9
  48. data/lib/i18n/tasks/interpolations.rb +21 -1
  49. data/lib/i18n/tasks/key_pattern_matching.rb +8 -8
  50. data/lib/i18n/tasks/logging.rb +2 -1
  51. data/lib/i18n/tasks/missing_keys.rb +24 -8
  52. data/lib/i18n/tasks/plural_keys.rb +6 -4
  53. data/lib/i18n/tasks/references.rb +4 -4
  54. data/lib/i18n/tasks/reports/base.rb +18 -14
  55. data/lib/i18n/tasks/reports/terminal.rb +64 -47
  56. data/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb +3 -3
  57. data/lib/i18n/tasks/scanners/ast_matchers/default_i18n_subject_matcher.rb +3 -3
  58. data/lib/i18n/tasks/scanners/ast_matchers/message_receivers_matcher.rb +10 -10
  59. data/lib/i18n/tasks/scanners/ast_matchers/rails_model_matcher.rb +1 -1
  60. data/lib/i18n/tasks/scanners/erb_ast_scanner.rb +69 -10
  61. data/lib/i18n/tasks/scanners/file_scanner.rb +5 -5
  62. data/lib/i18n/tasks/scanners/files/caching_file_finder.rb +3 -3
  63. data/lib/i18n/tasks/scanners/files/caching_file_finder_provider.rb +3 -3
  64. data/lib/i18n/tasks/scanners/files/caching_file_reader.rb +2 -2
  65. data/lib/i18n/tasks/scanners/files/file_finder.rb +8 -8
  66. data/lib/i18n/tasks/scanners/files/file_reader.rb +1 -1
  67. data/lib/i18n/tasks/scanners/local_ruby_parser.rb +8 -8
  68. data/lib/i18n/tasks/scanners/occurrence_from_position.rb +1 -1
  69. data/lib/i18n/tasks/scanners/pattern_mapper.rb +7 -7
  70. data/lib/i18n/tasks/scanners/pattern_scanner.rb +20 -20
  71. data/lib/i18n/tasks/scanners/pattern_with_scope_scanner.rb +8 -8
  72. data/lib/i18n/tasks/scanners/prism_scanners/arguments_visitor.rb +8 -1
  73. data/lib/i18n/tasks/scanners/prism_scanners/nodes.rb +101 -61
  74. data/lib/i18n/tasks/scanners/prism_scanners/visitor.rb +169 -105
  75. data/lib/i18n/tasks/scanners/relative_keys.rb +8 -8
  76. data/lib/i18n/tasks/scanners/results/key_occurrences.rb +3 -3
  77. data/lib/i18n/tasks/scanners/results/occurrence.rb +14 -10
  78. data/lib/i18n/tasks/scanners/ruby_ast_call_finder.rb +1 -1
  79. data/lib/i18n/tasks/scanners/ruby_key_literals.rb +6 -6
  80. data/lib/i18n/tasks/scanners/ruby_parser_factory.rb +1 -1
  81. data/lib/i18n/tasks/scanners/ruby_scanner.rb +225 -0
  82. data/lib/i18n/tasks/scanners/scanner.rb +2 -2
  83. data/lib/i18n/tasks/scanners/scanner_multiplexer.rb +1 -1
  84. data/lib/i18n/tasks/split_key.rb +4 -4
  85. data/lib/i18n/tasks/stats.rb +3 -3
  86. data/lib/i18n/tasks/translation.rb +5 -5
  87. data/lib/i18n/tasks/translators/base_translator.rb +40 -14
  88. data/lib/i18n/tasks/translators/deepl_translator.rb +17 -14
  89. data/lib/i18n/tasks/translators/google_translator.rb +169 -25
  90. data/lib/i18n/tasks/translators/openai_translator.rb +34 -23
  91. data/lib/i18n/tasks/translators/watsonx_translator.rb +16 -16
  92. data/lib/i18n/tasks/translators/yandex_translator.rb +8 -8
  93. data/lib/i18n/tasks/unused_keys.rb +1 -1
  94. data/lib/i18n/tasks/used_keys.rb +32 -33
  95. data/lib/i18n/tasks/version.rb +1 -1
  96. data/lib/i18n/tasks.rb +17 -17
  97. data/templates/config/i18n-tasks.yml +12 -0
  98. data/templates/minitest/i18n_test.rb +3 -3
  99. data/templates/rspec/i18n_spec.rb +7 -7
  100. metadata +25 -185
  101. data/lib/i18n/tasks/scanners/prism_scanner.rb +0 -83
  102. data/lib/i18n/tasks/scanners/ruby_ast_scanner.rb +0 -145
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18n::Tasks
4
+ module Command
5
+ module Commands
6
+ module CheckPrism
7
+ include Command::Collection
8
+
9
+ arg :prism_mode,
10
+ "--prism_mode MODE",
11
+ "Prism parser mode: 'rails' or 'ruby'. Defaults to 'rails' if Rails is available in the project, otherwise 'ruby'."
12
+
13
+ cmd :check_prism,
14
+ desc: t("i18n_tasks.cmd.desc.check_prism"),
15
+ args: %i[prism_mode]
16
+
17
+ # Run both the default (Parser-based) and the Prism-enabled scanning
18
+ # and produce a plain-text report in tmp/i18n_tasks_check_prism.md suitable
19
+ # for pasting into an issue.
20
+ def check_prism(opt = {})
21
+ now = Time.now
22
+ report_path = File.join(Dir.pwd, "tmp", "i18n_tasks_check_prism.md")
23
+ FileUtils.mkdir_p(File.dirname(report_path))
24
+
25
+ # keep original search config and clear caches helper
26
+ orig_search = (i18n.config[:search] || {}).dup
27
+
28
+ results = {}
29
+
30
+ # determine prism mode: use provided opt or default to rails when Rails present
31
+ chosen_prism_mode = (opt[:prism_mode].presence || (rails_available? ? "rails" : "ruby")).to_s
32
+ unless %w[rails ruby].include?(chosen_prism_mode)
33
+ fail CommandError, "--prism-mode must be 'rails' or 'ruby'"
34
+ end
35
+
36
+ {default: nil, prism: chosen_prism_mode}.each do |label, prism_mode|
37
+ i18n.config[:search] = orig_search.merge(prism: prism_mode)
38
+ # clear caches used by UsedKeys
39
+ i18n.instance_variable_set(:@scanner, nil)
40
+ i18n.instance_variable_set(:@search_config, nil)
41
+ i18n.instance_variable_set(:@keys_used_in_source_tree, nil)
42
+
43
+ tree = i18n.used_in_source_tree
44
+ keys = tree.nodes.select { |n| n.data[:occurrences].present? }
45
+ results[label] = keys.each_with_object({}) do |node, h|
46
+ full_key = node.full_key(root: false)
47
+ h[full_key] = node.data[:occurrences]
48
+ end
49
+ end
50
+
51
+ # restore original config and caches
52
+ i18n.config[:search] = orig_search
53
+ i18n.instance_variable_set(:@scanner, nil)
54
+ i18n.instance_variable_set(:@search_config, nil)
55
+ i18n.instance_variable_set(:@keys_used_in_source_tree, nil)
56
+
57
+ default_keys = results[:default].keys
58
+ prism_keys = results[:prism].keys
59
+
60
+ only_default = (default_keys - prism_keys).sort
61
+ only_prism = (prism_keys - default_keys).sort
62
+ both = (default_keys & prism_keys).sort
63
+
64
+ File.open(report_path, "w") do |f|
65
+ f.puts "# i18n-tasks check_prism report"
66
+ f.puts "Generated at: #{now.utc}"
67
+ f.puts "Prism mode: #{chosen_prism_mode}"
68
+ f.puts "Gem version: #{I18n::Tasks::VERSION}"
69
+ f.puts ""
70
+ f.puts "Summary"
71
+ f.puts "- total keys (default parser): #{default_keys.size}"
72
+ f.puts "- total keys (prism): #{prism_keys.size}"
73
+ f.puts "- keys in both: #{both.size}"
74
+ f.puts "- keys only in default parser: #{only_default.size}"
75
+ f.puts "- keys only in prism: #{only_prism.size}"
76
+ f.puts ""
77
+
78
+ unless only_default.empty?
79
+ f.puts "## Keys found by the default parser but NOT by Prism (#{only_default.size})"
80
+ only_default.each do |k|
81
+ f.puts "\n### #{k}"
82
+ results[:default][k].first(5).each do |occ|
83
+ src = (occ.raw_key || k).to_s
84
+ line = (occ.line || "").strip
85
+ highlighted = line.gsub(src) { |m| "`#{m}`" }
86
+ f.puts "- #{occ.path}:#{occ.line_num} `#{src}` — #{highlighted}"
87
+ end
88
+ end
89
+ end
90
+
91
+ unless only_prism.empty?
92
+ f.puts "## Keys found by Prism but NOT by the default parser (#{only_prism.size})"
93
+ only_prism.each do |k|
94
+ f.puts "\n### #{k}"
95
+ results[:prism][k].each do |occ|
96
+ src = (occ.raw_key || k).to_s
97
+ line = (occ.line || "").strip
98
+ highlighted = line.gsub(src) { |m| "`#{m}`" }
99
+ f.puts "- #{occ.path}:#{occ.line_num} `#{src}` — #{highlighted}"
100
+ end
101
+ end
102
+ end
103
+
104
+ f.puts "\n## Notes"
105
+ f.puts "- This report compares keys discovered by the project default parser and by Prism (rails mode)."
106
+ end
107
+
108
+ log_stderr "Wrote check_prism report: #{report_path}"
109
+ puts File.read(report_path)
110
+ end
111
+
112
+ private
113
+
114
+ def rails_available?
115
+ return true if defined?(Rails)
116
+ return true if Gem.loaded_specs.key?("rails")
117
+ lock = File.join(Dir.pwd, "Gemfile.lock")
118
+ return false unless File.exist?(lock)
119
+ File.read(lock).lines.any? { |l| l.strip.start_with?("rails ") || l.strip =~ /^rails \(/ }
120
+ rescue
121
+ false
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -7,24 +7,24 @@ module I18n::Tasks
7
7
  include Command::Collection
8
8
 
9
9
  arg :pattern_router,
10
- '-p',
11
- '--pattern_router',
12
- t('i18n_tasks.cmd.args.desc.pattern_router')
10
+ "-p",
11
+ "--pattern_router",
12
+ t("i18n_tasks.cmd.args.desc.pattern_router")
13
13
 
14
14
  cmd :normalize,
15
- pos: '[locale ...]',
16
- desc: t('i18n_tasks.cmd.desc.normalize'),
17
- args: %i[locales pattern_router]
15
+ pos: "[locale ...]",
16
+ desc: t("i18n_tasks.cmd.desc.normalize"),
17
+ args: %i[locales pattern_router]
18
18
 
19
19
  def normalize(opt = {})
20
20
  i18n.normalize_store! locales: opt[:locales],
21
- force_pattern_router: opt[:pattern_router]
21
+ force_pattern_router: opt[:pattern_router]
22
22
  end
23
23
 
24
24
  cmd :check_normalized,
25
- pos: '[locale ...]',
26
- desc: t('i18n_tasks.cmd.desc.check_normalized'),
27
- args: %i[locales]
25
+ pos: "[locale ...]",
26
+ desc: t("i18n_tasks.cmd.desc.check_normalized"),
27
+ args: %i[locales]
28
28
 
29
29
  def check_normalized(opt)
30
30
  non_normalized = i18n.non_normalized_paths locales: opt[:locales]
@@ -33,10 +33,10 @@ module I18n::Tasks
33
33
  end
34
34
 
35
35
  cmd :mv,
36
- pos: 'FROM_KEY_PATTERN TO_KEY_PATTERN',
37
- desc: t('i18n_tasks.cmd.desc.mv')
36
+ pos: "FROM_KEY_PATTERN TO_KEY_PATTERN",
37
+ desc: t("i18n_tasks.cmd.desc.mv")
38
38
  def mv(opt = {})
39
- fail CommandError, 'requires FROM_KEY_PATTERN and TO_KEY_PATTERN' if opt[:arguments].size < 2
39
+ fail CommandError, "requires FROM_KEY_PATTERN and TO_KEY_PATTERN" if opt[:arguments].size < 2
40
40
 
41
41
  from_pattern = opt[:arguments].shift
42
42
  to_pattern = opt[:arguments].shift
@@ -47,10 +47,10 @@ module I18n::Tasks
47
47
  end
48
48
 
49
49
  cmd :cp,
50
- pos: 'FROM_KEY_PATTERN TO_KEY_PATTERN',
51
- desc: t('i18n_tasks.cmd.desc.cp')
50
+ pos: "FROM_KEY_PATTERN TO_KEY_PATTERN",
51
+ desc: t("i18n_tasks.cmd.desc.cp")
52
52
  def cp(opt = {})
53
- fail CommandError, 'requires FROM_KEY_PATTERN and TO_KEY_PATTERN' if opt[:arguments].size < 2
53
+ fail CommandError, "requires FROM_KEY_PATTERN and TO_KEY_PATTERN" if opt[:arguments].size < 2
54
54
 
55
55
  from_pattern = opt[:arguments].shift
56
56
  to_pattern = opt[:arguments].shift
@@ -61,32 +61,32 @@ module I18n::Tasks
61
61
  end
62
62
 
63
63
  cmd :rm,
64
- pos: 'KEY_PATTERN [KEY_PATTERN...]',
65
- desc: t('i18n_tasks.cmd.desc.rm')
64
+ pos: "KEY_PATTERN [KEY_PATTERN...]",
65
+ desc: t("i18n_tasks.cmd.desc.rm")
66
66
  def rm(opt = {})
67
- fail CommandError, 'requires KEY_PATTERN' if opt[:arguments].empty?
67
+ fail CommandError, "requires KEY_PATTERN" if opt[:arguments].empty?
68
68
 
69
69
  forest = i18n.data_forest
70
70
  results = opt[:arguments].each_with_object({}) do |key_pattern, h|
71
- h.merge! forest.mv_key!(compile_key_pattern(key_pattern), '', root: false)
71
+ h.merge! forest.mv_key!(compile_key_pattern(key_pattern), "", root: false)
72
72
  end
73
73
  i18n.data.write forest
74
74
  terminal_report.mv_results results
75
75
  end
76
76
 
77
77
  cmd :data,
78
- pos: '[locale ...]',
79
- desc: t('i18n_tasks.cmd.desc.data'),
80
- args: %i[locales out_format]
78
+ pos: "[locale ...]",
79
+ desc: t("i18n_tasks.cmd.desc.data"),
80
+ args: %i[locales out_format]
81
81
 
82
82
  def data(opt = {})
83
83
  print_forest i18n.data_forest(opt[:locales]), opt
84
84
  end
85
85
 
86
86
  cmd :data_merge,
87
- pos: '[tree ...]',
88
- desc: t('i18n_tasks.cmd.desc.data_merge'),
89
- args: %i[data_format nostdin]
87
+ pos: "[tree ...]",
88
+ desc: t("i18n_tasks.cmd.desc.data_merge"),
89
+ args: %i[data_format nostdin]
90
90
 
91
91
  def data_merge(opt = {})
92
92
  forest = merge_forests_stdin_and_pos!(opt)
@@ -95,9 +95,9 @@ module I18n::Tasks
95
95
  end
96
96
 
97
97
  cmd :data_write,
98
- pos: '[tree]',
99
- desc: t('i18n_tasks.cmd.desc.data_write'),
100
- args: %i[data_format nostdin]
98
+ pos: "[tree]",
99
+ desc: t("i18n_tasks.cmd.desc.data_write"),
100
+ args: %i[data_format nostdin]
101
101
 
102
102
  def data_write(opt = {})
103
103
  forest = forest_pos_or_stdin!(opt)
@@ -106,13 +106,13 @@ module I18n::Tasks
106
106
  end
107
107
 
108
108
  cmd :data_remove,
109
- pos: '[tree]',
110
- desc: t('i18n_tasks.cmd.desc.data_remove'),
111
- args: %i[data_format nostdin]
109
+ pos: "[tree]",
110
+ desc: t("i18n_tasks.cmd.desc.data_remove"),
111
+ args: %i[data_format nostdin]
112
112
 
113
113
  def data_remove(opt = {})
114
114
  removed = i18n.data.remove_by_key!(forest_pos_or_stdin!(opt))
115
- log_stderr 'Removed:'
115
+ log_stderr "Removed:"
116
116
  print_forest removed, opt
117
117
  end
118
118
  end
@@ -7,9 +7,9 @@ module I18n::Tasks
7
7
  include Command::Collection
8
8
 
9
9
  cmd :eq_base,
10
- pos: '[locale ...]',
11
- desc: t('i18n_tasks.cmd.desc.eq_base'),
12
- args: %i[locales out_format]
10
+ pos: "[locale ...]",
11
+ desc: t("i18n_tasks.cmd.desc.eq_base"),
12
+ args: %i[locales out_format]
13
13
 
14
14
  def eq_base(opt = {})
15
15
  forest = i18n.eq_base_keys(opt)
@@ -7,20 +7,21 @@ module I18n::Tasks
7
7
  include Command::Collection
8
8
 
9
9
  cmd :health,
10
- pos: '[locale ...]',
11
- desc: t('i18n_tasks.cmd.desc.health'),
12
- args: %i[locales out_format config]
10
+ pos: "[locale ...]",
11
+ desc: t("i18n_tasks.cmd.desc.health"),
12
+ args: %i[locales out_format config]
13
13
 
14
14
  def health(opt = {})
15
15
  forest = i18n.data_forest(opt[:locales])
16
- stats = i18n.forest_stats(forest)
17
- fail CommandError, t('i18n_tasks.health.no_keys_detected') if stats[:key_count].zero?
16
+ stats = i18n.forest_stats(forest)
17
+ fail CommandError, t("i18n_tasks.health.no_keys_detected") if stats[:key_count].zero?
18
18
 
19
19
  terminal_report.forest_stats forest, stats
20
20
  [
21
21
  missing(**opt),
22
22
  unused(**opt),
23
23
  check_consistent_interpolations(**opt),
24
+ check_reserved_interpolations(**opt),
24
25
  check_normalized(**opt)
25
26
  ].detect { |result| result == :exit1 }
26
27
  end
@@ -7,15 +7,26 @@ module I18n::Tasks
7
7
  include Command::Collection
8
8
 
9
9
  cmd :check_consistent_interpolations,
10
- pos: '[locale ...]',
11
- desc: t('i18n_tasks.cmd.desc.check_consistent_interpolations'),
12
- args: %i[locales out_format]
10
+ pos: "[locale ...]",
11
+ desc: t("i18n_tasks.cmd.desc.check_consistent_interpolations"),
12
+ args: %i[locales out_format]
13
13
 
14
14
  def check_consistent_interpolations(opt = {})
15
15
  forest = i18n.inconsistent_interpolations(**opt.slice(:locales, :base_locale))
16
16
  print_forest forest, opt, :inconsistent_interpolations
17
17
  :exit1 unless forest.empty?
18
18
  end
19
+
20
+ cmd :check_reserved_interpolations,
21
+ pos: "[locale]",
22
+ desc: t("i18n_tasks.cmd.desc.check_reserved_interpolations"),
23
+ args: %i[locales out_format]
24
+
25
+ def check_reserved_interpolations(opt = {})
26
+ forest = i18n.reserved_interpolations(**opt.slice(:locale))
27
+ print_forest forest, opt, :reserved_interpolations
28
+ :exit1 unless forest.empty?
29
+ end
19
30
  end
20
31
  end
21
32
  end
@@ -7,28 +7,28 @@ module I18n::Tasks
7
7
  include Command::Collection
8
8
 
9
9
  cmd :config,
10
- pos: '[section ...]',
11
- desc: t('i18n_tasks.cmd.desc.config')
10
+ pos: "[section ...]",
11
+ desc: t("i18n_tasks.cmd.desc.config")
12
12
 
13
13
  def config(opts = {})
14
14
  cfg = i18n.config_for_inspect
15
15
  cfg = cfg.slice(*opts[:arguments]) if opts[:arguments].present?
16
16
  cfg = cfg.to_yaml
17
- cfg.sub!(/\A---\n/, '')
17
+ cfg.sub!(/\A---\n/, "")
18
18
  cfg.gsub!(/^([^\s-].+?:)/, Rainbow('\1').cyan.bright)
19
19
  puts cfg
20
20
  end
21
21
 
22
- cmd :gem_path, desc: t('i18n_tasks.cmd.desc.gem_path')
22
+ cmd :gem_path, desc: t("i18n_tasks.cmd.desc.gem_path")
23
23
 
24
24
  def gem_path
25
25
  puts I18n::Tasks.gem_path
26
26
  end
27
27
 
28
- cmd :irb, desc: t('i18n_tasks.cmd.desc.irb')
28
+ cmd :irb, desc: t("i18n_tasks.cmd.desc.irb")
29
29
 
30
30
  def irb
31
- require 'i18n/tasks/console_context'
31
+ require "i18n/tasks/console_context"
32
32
  ::I18n::Tasks::ConsoleContext.start
33
33
  end
34
34
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'i18n/tasks/command/collection'
3
+ require "i18n/tasks/command/collection"
4
4
 
5
5
  module I18n::Tasks
6
6
  module Command
@@ -10,22 +10,22 @@ module I18n::Tasks
10
10
 
11
11
  missing_types = I18n::Tasks::MissingKeys.missing_keys_types
12
12
  arg :missing_types,
13
- '-t',
14
- "--types #{missing_types * ','}",
15
- Array,
16
- t('i18n_tasks.cmd.args.desc.missing_types', valid: missing_types * ', '),
17
- parser: OptionParsers::Enum::ListParser.new(
18
- missing_types,
19
- proc do |invalid, valid|
20
- I18n.t('i18n_tasks.cmd.errors.invalid_missing_type',
21
- invalid: invalid * ', ', valid: valid * ', ', count: invalid.length)
22
- end
23
- )
13
+ "-t",
14
+ "--types #{missing_types * ","}",
15
+ Array,
16
+ t("i18n_tasks.cmd.args.desc.missing_types", valid: missing_types * ", "),
17
+ parser: OptionParsers::Enum::ListParser.new(
18
+ missing_types,
19
+ proc do |invalid, valid|
20
+ I18n.t("i18n_tasks.cmd.errors.invalid_missing_type",
21
+ invalid: invalid * ", ", valid: valid * ", ", count: invalid.length)
22
+ end
23
+ )
24
24
 
25
25
  cmd :missing,
26
- pos: '[locale ...]',
27
- desc: t('i18n_tasks.cmd.desc.missing'),
28
- args: %i[locales out_format missing_types pattern]
26
+ pos: "[locale ...]",
27
+ desc: t("i18n_tasks.cmd.desc.missing"),
28
+ args: %i[locales out_format missing_types pattern]
29
29
 
30
30
  def missing(opt = {})
31
31
  forest = i18n.missing_keys(**opt.slice(:locales, :base_locale, :types))
@@ -38,9 +38,9 @@ module I18n::Tasks
38
38
  end
39
39
 
40
40
  cmd :translate_missing,
41
- pos: '[locale ...]',
42
- desc: t('i18n_tasks.cmd.desc.translate_missing'),
43
- args: [:locales, :locale_to_translate_from, arg(:out_format).from(1), :translation_backend, :pattern]
41
+ pos: "[locale ...]",
42
+ desc: t("i18n_tasks.cmd.desc.translate_missing"),
43
+ args: [:locales, :locale_to_translate_from, arg(:out_format).from(1), :translation_backend, :pattern]
44
44
 
45
45
  def translate_missing(opt = {})
46
46
  missing = i18n.missing_diff_forest opt[:locales], opt[:from]
@@ -52,15 +52,15 @@ module I18n::Tasks
52
52
  backend = opt[:backend].presence || i18n.translation_config[:backend]
53
53
  translated = i18n.translate_forest missing, from: opt[:from], backend: backend.to_sym
54
54
  i18n.data.merge! translated
55
- log_stderr t('i18n_tasks.translate_missing.translated', count: translated.leaves.count)
55
+ log_stderr t("i18n_tasks.translate_missing.translated", count: translated.leaves.count)
56
56
  print_forest translated, opt
57
57
  end
58
58
 
59
59
  cmd :add_missing,
60
- pos: '[locale ...]',
61
- desc: t('i18n_tasks.cmd.desc.add_missing'),
62
- args: [:locales, :out_format, :pattern, arg(:value) + [{ default: '%{value_or_default_or_human_key}' }],
63
- ['--nil-value', 'Set value to nil. Takes precedence over the value argument.']]
60
+ pos: "[locale ...]",
61
+ desc: t("i18n_tasks.cmd.desc.add_missing"),
62
+ args: [:locales, :out_format, :pattern, arg(:value) + [{default: "%{value_or_default_or_human_key}"}],
63
+ ["--nil-value", "Set value to nil. Takes precedence over the value argument."]]
64
64
 
65
65
  # Merge base locale first, as this may affect the value for the other locales
66
66
  def add_missing(opt = {}) # rubocop:disable Metrics/AbcSize
@@ -69,7 +69,7 @@ module I18n::Tasks
69
69
  opt[:locales] - [i18n.base_locale]
70
70
  ].reject(&:empty?).each_with_object(i18n.empty_forest) do |locales, added|
71
71
  forest = i18n.missing_keys(locales: locales, **opt.slice(:types, :base_locale))
72
- .set_each_value!(opt[:'nil-value'] ? nil : opt[:value])
72
+ .set_each_value!(opt[:"nil-value"] ? nil : opt[:value])
73
73
  if opt[:pattern]
74
74
  pattern_re = i18n.compile_key_pattern(opt[:pattern])
75
75
  forest.select_keys! { |full_key, _node| full_key =~ pattern_re }
@@ -77,7 +77,7 @@ module I18n::Tasks
77
77
  i18n.data.merge! forest
78
78
  added.merge! forest
79
79
  end.tap do |added|
80
- log_stderr t('i18n_tasks.add_missing.added', count: added.leaves.count)
80
+ log_stderr t("i18n_tasks.add_missing.added", count: added.leaves.count)
81
81
  print_forest added, opt
82
82
  end
83
83
  end
@@ -8,9 +8,9 @@ module I18n::Tasks
8
8
  include I18n::Tasks::KeyPatternMatching
9
9
 
10
10
  cmd :tree_translate,
11
- pos: '[tree (or stdin)]',
12
- desc: t('i18n_tasks.cmd.desc.tree_translate'),
13
- args: [:locale_to_translate_from, arg(:data_format).from(1), :translation_backend]
11
+ pos: "[tree (or stdin)]",
12
+ desc: t("i18n_tasks.cmd.desc.tree_translate"),
13
+ args: [:locale_to_translate_from, arg(:data_format).from(1), :translation_backend]
14
14
 
15
15
  def tree_translate(opts = {})
16
16
  forest = forest_pos_or_stdin!(opts)
@@ -18,79 +18,79 @@ module I18n::Tasks
18
18
  end
19
19
 
20
20
  cmd :tree_merge,
21
- pos: '[[tree] [tree] ... (or stdin)]',
22
- desc: t('i18n_tasks.cmd.desc.tree_merge'),
23
- args: %i[data_format nostdin]
21
+ pos: "[[tree] [tree] ... (or stdin)]",
22
+ desc: t("i18n_tasks.cmd.desc.tree_merge"),
23
+ args: %i[data_format nostdin]
24
24
 
25
25
  def tree_merge(opts = {})
26
26
  print_forest merge_forests_stdin_and_pos!(opts), opts
27
27
  end
28
28
 
29
29
  cmd :tree_filter,
30
- pos: '[pattern] [tree (or stdin)]',
31
- desc: t('i18n_tasks.cmd.desc.tree_filter'),
32
- args: %i[data_format pattern]
30
+ pos: "[pattern] [tree (or stdin)]",
31
+ desc: t("i18n_tasks.cmd.desc.tree_filter"),
32
+ args: %i[data_format pattern]
33
33
 
34
34
  def tree_filter(opts = {})
35
35
  pattern = arg_or_pos! :pattern, opts
36
- forest = forest_pos_or_stdin! opts
36
+ forest = forest_pos_or_stdin! opts
37
37
  unless pattern.blank?
38
38
  pattern_re = i18n.compile_key_pattern(pattern)
39
- forest = forest.select_keys { |full_key, _node| full_key =~ pattern_re }
39
+ forest = forest.select_keys { |full_key, _node| full_key =~ pattern_re }
40
40
  end
41
41
  print_forest forest, opts
42
42
  end
43
43
 
44
44
  arg :all_locales,
45
- '-a',
46
- '--all-locales',
47
- t('i18n_tasks.cmd.args.desc.all_locales')
45
+ "-a",
46
+ "--all-locales",
47
+ t("i18n_tasks.cmd.args.desc.all_locales")
48
48
 
49
49
  cmd :tree_mv,
50
- pos: 'FROM_KEY_PATTERN TO_KEY_PATTERN [tree (or stdin)]',
51
- desc: t('i18n_tasks.cmd.desc.tree_mv_key'),
52
- args: %i[data_format all_locales]
50
+ pos: "FROM_KEY_PATTERN TO_KEY_PATTERN [tree (or stdin)]",
51
+ desc: t("i18n_tasks.cmd.desc.tree_mv_key"),
52
+ args: %i[data_format all_locales]
53
53
  def tree_mv(opt = {})
54
- fail CommandError, 'requires FROM_KEY_PATTERN and TO_KEY_PATTERN' if opt[:arguments].size < 2
54
+ fail CommandError, "requires FROM_KEY_PATTERN and TO_KEY_PATTERN" if opt[:arguments].size < 2
55
55
 
56
56
  from_pattern = opt[:arguments].shift
57
57
  to_pattern = opt[:arguments].shift
58
58
  forest = forest_pos_or_stdin!(opt)
59
- forest.mv_key!(compile_key_pattern(from_pattern), to_pattern, root: !opt[:'all-locales'])
59
+ forest.mv_key!(compile_key_pattern(from_pattern), to_pattern, root: !opt[:"all-locales"])
60
60
  print_forest forest, opt
61
61
  end
62
62
 
63
63
  cmd :tree_subtract,
64
- pos: '[[tree] [tree] ... (or stdin)]',
65
- desc: t('i18n_tasks.cmd.desc.tree_subtract'),
66
- args: %i[data_format nostdin]
64
+ pos: "[[tree] [tree] ... (or stdin)]",
65
+ desc: t("i18n_tasks.cmd.desc.tree_subtract"),
66
+ args: %i[data_format nostdin]
67
67
 
68
68
  def tree_subtract(opt = {})
69
69
  forests = forests_stdin_and_pos! opt, 2
70
- forest = forests.reduce(:subtract_by_key) || empty_forest
70
+ forest = forests.reduce(:subtract_by_key) || empty_forest
71
71
  print_forest forest, opt
72
72
  end
73
73
 
74
74
  cmd :tree_set_value,
75
- pos: '[VALUE] [tree (or stdin)]',
76
- desc: t('i18n_tasks.cmd.desc.tree_set_value'),
77
- args: %i[value data_format nostdin pattern]
75
+ pos: "[VALUE] [tree (or stdin)]",
76
+ desc: t("i18n_tasks.cmd.desc.tree_set_value"),
77
+ args: %i[value data_format nostdin pattern]
78
78
 
79
79
  def tree_set_value(opt = {})
80
- value = arg_or_pos! :value, opt
81
- forest = forest_pos_or_stdin!(opt)
80
+ value = arg_or_pos! :value, opt
81
+ forest = forest_pos_or_stdin!(opt)
82
82
  key_pattern = opt[:pattern]
83
- fail CommandError, 'pass value (-v, --value)' if value.blank?
83
+ fail CommandError, "pass value (-v, --value)" if value.blank?
84
84
 
85
85
  forest.set_each_value!(value, key_pattern)
86
86
  print_forest forest, opt
87
87
  end
88
88
 
89
89
  cmd :tree_convert,
90
- pos: '[tree (or stdin)]',
91
- desc: t('i18n_tasks.cmd.desc.tree_convert'),
92
- args: [arg(:data_format).dup.tap { |a| a[0..1] = ['-f', '--from FORMAT'] },
93
- arg(:out_format).dup.tap { |a| a[0..1] = ['-t', '--to FORMAT'] }]
90
+ pos: "[tree (or stdin)]",
91
+ desc: t("i18n_tasks.cmd.desc.tree_convert"),
92
+ args: [arg(:data_format).dup.tap { |a| a[0..1] = ["-f", "--from FORMAT"] },
93
+ arg(:out_format).dup.tap { |a| a[0..1] = ["-t", "--to FORMAT"] }]
94
94
 
95
95
  def tree_convert(opt = {})
96
96
  forest = forest_pos_or_stdin! opt.merge(format: opt[:from])