i18n-tasks 0.9.33 → 1.0.12

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +28 -11
  3. data/config/locales/en.yml +5 -3
  4. data/config/locales/ru.yml +1 -0
  5. data/i18n-tasks.gemspec +12 -6
  6. data/lib/i18n/tasks/base_task.rb +2 -1
  7. data/lib/i18n/tasks/cli.rb +27 -17
  8. data/lib/i18n/tasks/command/commander.rb +1 -0
  9. data/lib/i18n/tasks/command/commands/data.rb +8 -6
  10. data/lib/i18n/tasks/command/commands/eq_base.rb +2 -2
  11. data/lib/i18n/tasks/command/commands/health.rb +4 -3
  12. data/lib/i18n/tasks/command/commands/interpolations.rb +1 -1
  13. data/lib/i18n/tasks/command/commands/meta.rb +1 -1
  14. data/lib/i18n/tasks/command/commands/missing.rb +22 -9
  15. data/lib/i18n/tasks/command/commands/tree.rb +8 -6
  16. data/lib/i18n/tasks/command/commands/usages.rb +5 -4
  17. data/lib/i18n/tasks/command/dsl.rb +4 -4
  18. data/lib/i18n/tasks/command/option_parsers/enum.rb +2 -0
  19. data/lib/i18n/tasks/command/option_parsers/locale.rb +2 -1
  20. data/lib/i18n/tasks/command/options/common.rb +5 -0
  21. data/lib/i18n/tasks/command/options/data.rb +4 -1
  22. data/lib/i18n/tasks/command/options/locales.rb +5 -5
  23. data/lib/i18n/tasks/concurrent/cached_value.rb +2 -2
  24. data/lib/i18n/tasks/configuration.rb +17 -10
  25. data/lib/i18n/tasks/console_context.rb +1 -1
  26. data/lib/i18n/tasks/data/adapter/yaml_adapter.rb +9 -2
  27. data/lib/i18n/tasks/data/file_formats.rb +3 -1
  28. data/lib/i18n/tasks/data/file_system_base.rb +7 -6
  29. data/lib/i18n/tasks/data/router/conservative_router.rb +2 -1
  30. data/lib/i18n/tasks/data/router/pattern_router.rb +3 -1
  31. data/lib/i18n/tasks/data/tree/node.rb +6 -3
  32. data/lib/i18n/tasks/data/tree/nodes.rb +6 -7
  33. data/lib/i18n/tasks/data/tree/siblings.rb +10 -4
  34. data/lib/i18n/tasks/data/tree/traversal.rb +34 -11
  35. data/lib/i18n/tasks/html_keys.rb +4 -6
  36. data/lib/i18n/tasks/ignore_keys.rb +4 -3
  37. data/lib/i18n/tasks/interpolations.rb +10 -4
  38. data/lib/i18n/tasks/key_pattern_matching.rb +3 -2
  39. data/lib/i18n/tasks/locale_pathname.rb +1 -1
  40. data/lib/i18n/tasks/missing_keys.rb +4 -0
  41. data/lib/i18n/tasks/plural_keys.rb +5 -6
  42. data/lib/i18n/tasks/references.rb +4 -2
  43. data/lib/i18n/tasks/reports/base.rb +4 -3
  44. data/lib/i18n/tasks/reports/terminal.rb +8 -6
  45. data/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb +118 -0
  46. data/lib/i18n/tasks/scanners/ast_matchers/message_receivers_matcher.rb +91 -0
  47. data/lib/i18n/tasks/scanners/ast_matchers/rails_model_matcher.rb +69 -0
  48. data/lib/i18n/tasks/scanners/erb_ast_processor.rb +74 -0
  49. data/lib/i18n/tasks/scanners/erb_ast_scanner.rb +48 -0
  50. data/lib/i18n/tasks/scanners/file_scanner.rb +4 -3
  51. data/lib/i18n/tasks/scanners/files/caching_file_finder.rb +0 -3
  52. data/lib/i18n/tasks/scanners/files/file_finder.rb +3 -2
  53. data/lib/i18n/tasks/scanners/local_ruby_parser.rb +85 -0
  54. data/lib/i18n/tasks/scanners/occurrence_from_position.rb +3 -3
  55. data/lib/i18n/tasks/scanners/pattern_mapper.rb +1 -1
  56. data/lib/i18n/tasks/scanners/pattern_scanner.rb +8 -5
  57. data/lib/i18n/tasks/scanners/pattern_with_scope_scanner.rb +4 -2
  58. data/lib/i18n/tasks/scanners/relative_keys.rb +19 -4
  59. data/lib/i18n/tasks/scanners/results/occurrence.rb +17 -1
  60. data/lib/i18n/tasks/scanners/ruby_ast_call_finder.rb +9 -34
  61. data/lib/i18n/tasks/scanners/ruby_ast_scanner.rb +91 -154
  62. data/lib/i18n/tasks/scanners/ruby_key_literals.rb +4 -4
  63. data/lib/i18n/tasks/scanners/scanner_multiplexer.rb +2 -0
  64. data/lib/i18n/tasks/split_key.rb +3 -1
  65. data/lib/i18n/tasks/string_interpolation.rb +1 -0
  66. data/lib/i18n/tasks/translation.rb +3 -3
  67. data/lib/i18n/tasks/translators/base_translator.rb +5 -3
  68. data/lib/i18n/tasks/translators/deepl_translator.rb +10 -2
  69. data/lib/i18n/tasks/translators/google_translator.rb +2 -0
  70. data/lib/i18n/tasks/translators/yandex_translator.rb +2 -0
  71. data/lib/i18n/tasks/used_keys.rb +21 -14
  72. data/lib/i18n/tasks/version.rb +1 -1
  73. data/lib/i18n/tasks.rb +17 -7
  74. data/templates/config/i18n-tasks.yml +21 -1
  75. metadata +44 -15
@@ -9,6 +9,7 @@ module I18n::Tasks::Scanners
9
9
  class ScannerMultiplexer < Scanner
10
10
  # @param scanners [Array<Scanner>]
11
11
  def initialize(scanners:)
12
+ super()
12
13
  @scanners = scanners
13
14
  end
14
15
 
@@ -25,6 +26,7 @@ module I18n::Tasks::Scanners
25
26
  # @return [Array<Array<Results::KeyOccurrences>>]
26
27
  def collect_results
27
28
  return [@scanners[0].keys] if @scanners.length == 1
29
+
28
30
  Array.new(@scanners.length).tap do |results|
29
31
  results_mutex = Mutex.new
30
32
  @scanners.map.with_index do |scanner, i|
@@ -15,11 +15,12 @@ module I18n
15
15
  parts = []
16
16
  pos = 0
17
17
  return [key] if max == 1
18
+
18
19
  key_parts(key) do |part|
19
20
  parts << part
20
21
  pos += part.length + 1
21
22
  if parts.length + 1 >= max
22
- parts << key[pos..-1] unless pos == key.length
23
+ parts << key[pos..] unless pos == key.length
23
24
  break
24
25
  end
25
26
  end
@@ -36,6 +37,7 @@ module I18n
36
37
  # dots inside braces or parenthesis are not split on
37
38
  def key_parts(key, &block)
38
39
  return enum_for(:key_parts, key) unless block
40
+
39
41
  nesting = PARENS
40
42
  counts = PARENS_ZEROS # dup'd later if key contains parenthesis
41
43
  delim = '.'
@@ -6,6 +6,7 @@ module I18n::Tasks
6
6
 
7
7
  def interpolate_soft(s, t = {})
8
8
  return s unless s
9
+
9
10
  t.each do |k, v|
10
11
  pat = "%{#{k}}"
11
12
  s = s.gsub pat, v.to_s if s.include?(pat)
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'i18n/tasks/translators/deepl_translator.rb'
4
- require 'i18n/tasks/translators/google_translator.rb'
5
- require 'i18n/tasks/translators/yandex_translator.rb'
3
+ require 'i18n/tasks/translators/deepl_translator'
4
+ require 'i18n/tasks/translators/google_translator'
5
+ require 'i18n/tasks/translators/yandex_translator'
6
6
 
7
7
  module I18n::Tasks
8
8
  module Translation
@@ -24,6 +24,7 @@ module I18n::Tasks
24
24
  # @return [Array<[String, Object]>] translated list
25
25
  def translate_pairs(list, opts)
26
26
  return [] if list.empty?
27
+
27
28
  opts = opts.dup
28
29
  key_pos = list.each_with_index.inject({}) { |idx, ((k, _v), i)| idx.update(k => i) }
29
30
  # copy reference keys as is, instead of translating
@@ -92,8 +93,8 @@ module I18n::Tasks
92
93
  end
93
94
  end
94
95
 
95
- INTERPOLATION_KEY_RE = /%\{[^}]+}/
96
- UNTRANSLATABLE_STRING = 'zxzxzx'
96
+ INTERPOLATION_KEY_RE = /%\{[^}]+}/.freeze
97
+ UNTRANSLATABLE_STRING = 'X__'
97
98
 
98
99
  # @param [String] value
99
100
  # @return [String] 'hello, %{name}' => 'hello, <round-trippable string>'
@@ -110,9 +111,10 @@ module I18n::Tasks
110
111
  # @return [String] 'hello, <round-trippable string>' => 'hello, %{name}'
111
112
  def restore_interpolations(untranslated, translated)
112
113
  return translated if untranslated !~ INTERPOLATION_KEY_RE
114
+
113
115
  values = untranslated.scan(INTERPOLATION_KEY_RE)
114
116
  translated.gsub(/#{Regexp.escape(UNTRANSLATABLE_STRING)}\d+/i) do |m|
115
- values[m[UNTRANSLATABLE_STRING.length..-1].to_i]
117
+ values[m[UNTRANSLATABLE_STRING.length..].to_i]
116
118
  end
117
119
  rescue StandardError => e
118
120
  raise_interpolation_error(untranslated, translated, e)
@@ -48,7 +48,8 @@ module I18n::Tasks::Translators
48
48
  # @return [String] 'hello, <i18n>%{name}</i18n>' => 'hello, %{name}'
49
49
  def restore_interpolations(untranslated, translated)
50
50
  return translated if untranslated !~ INTERPOLATION_KEY_RE
51
- translated.gsub(%r{<\/?i18n>}, '')
51
+
52
+ translated.gsub(%r{</?i18n>}, '')
52
53
  rescue StandardError => e
53
54
  raise_interpolation_error(untranslated, translated, e)
54
55
  end
@@ -66,8 +67,15 @@ module I18n::Tasks::Translators
66
67
 
67
68
  def configure_api_key!
68
69
  api_key = @i18n_tasks.translation_config[:deepl_api_key]
70
+ host = @i18n_tasks.translation_config[:deepl_host]
71
+ version = @i18n_tasks.translation_config[:deepl_version]
69
72
  fail ::I18n::Tasks::CommandError, I18n.t('i18n_tasks.deepl_translate.errors.no_api_key') if api_key.blank?
70
- DeepL.configure { |config| config.auth_key = api_key }
73
+
74
+ DeepL.configure do |config|
75
+ config.auth_key = api_key
76
+ config.host = host unless host.blank?
77
+ config.version = version unless version.blank?
78
+ end
71
79
  end
72
80
  end
73
81
  end
@@ -46,6 +46,7 @@ module I18n::Tasks::Translators
46
46
  # Convert 'es-ES' to 'es'
47
47
  def to_google_translate_compatible_locale(locale)
48
48
  return locale unless locale.include?('-') && !SUPPORTED_LOCALES_WITH_REGION.include?(locale)
49
+
49
50
  locale.split('-', 2).first
50
51
  end
51
52
 
@@ -60,6 +61,7 @@ module I18n::Tasks::Translators
60
61
  key ||= translation_config[:api_key]
61
62
  end
62
63
  fail ::I18n::Tasks::CommandError, I18n.t('i18n_tasks.google_translate.errors.no_api_key') if key.blank?
64
+
63
65
  key
64
66
  end
65
67
  end
@@ -43,6 +43,7 @@ module I18n::Tasks::Translators
43
43
  # Convert 'es-ES' to 'es'
44
44
  def to_yandex_compatible_locale(locale)
45
45
  return locale unless locale.include?('-')
46
+
46
47
  locale.split('-', 2).first
47
48
  end
48
49
 
@@ -54,6 +55,7 @@ module I18n::Tasks::Translators
54
55
  @api_key ||= begin
55
56
  key = @i18n_tasks.translation_config[:yandex_api_key]
56
57
  fail ::I18n::Tasks::CommandError, I18n.t('i18n_tasks.yandex_translate.errors.no_api_key') if key.blank?
58
+
57
59
  key
58
60
  end
59
61
  end
@@ -3,6 +3,7 @@
3
3
  require 'find'
4
4
  require 'i18n/tasks/scanners/pattern_with_scope_scanner'
5
5
  require 'i18n/tasks/scanners/ruby_ast_scanner'
6
+ require 'i18n/tasks/scanners/erb_ast_scanner'
6
7
  require 'i18n/tasks/scanners/scanner_multiplexer'
7
8
  require 'i18n/tasks/scanners/files/caching_file_finder_provider'
8
9
  require 'i18n/tasks/scanners/files/caching_file_reader'
@@ -16,17 +17,20 @@ module I18n::Tasks
16
17
  module UsedKeys # rubocop:disable Metrics/ModuleLength
17
18
  SEARCH_DEFAULTS = {
18
19
  paths: %w[app/].freeze,
20
+ relative_exclude_method_name_paths: [],
19
21
  relative_roots: %w[app/controllers app/helpers app/mailers app/presenters app/views].freeze,
20
22
  scanners: [
21
- ['::I18n::Tasks::Scanners::RubyAstScanner', only: %w[*.rb]],
22
- ['::I18n::Tasks::Scanners::PatternWithScopeScanner', exclude: %w[*.rb]]
23
+ ['::I18n::Tasks::Scanners::RubyAstScanner', { only: %w[*.rb] }],
24
+ ['::I18n::Tasks::Scanners::ErbAstScanner', { only: %w[*.erb] }],
25
+ ['::I18n::Tasks::Scanners::PatternWithScopeScanner', { exclude: %w[*.erb *.rb] }]
23
26
  ],
27
+ ast_matchers: [],
24
28
  strict: true
25
29
  }.freeze
26
30
 
27
- ALWAYS_EXCLUDE = %w[*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less
31
+ ALWAYS_EXCLUDE = %w[*.jpg *.jpeg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less
28
32
  *.yml *.json *.zip *.tar.gz *.swf *.flv *.mp3 *.wav *.flac *.webm *.mp4 *.ogg *.opus
29
- *.webp].freeze
33
+ *.webp *.map *.xlsx].freeze
30
34
 
31
35
  # Find all keys in the source and return a forest with the keys in absolute form and their occurrences.
32
36
  #
@@ -56,8 +60,8 @@ module I18n::Tasks
56
60
  keys = keys.select { |k| k.key =~ key_filter_re }
57
61
  end
58
62
  Data::Tree::Node.new(
59
- key: 'used',
60
- data: { key_filter: key_filter },
63
+ key: 'used',
64
+ data: { key_filter: key_filter },
61
65
  children: Data::Tree::Siblings.from_key_occurrences(keys)
62
66
  ).to_siblings
63
67
  end
@@ -73,10 +77,11 @@ module I18n::Tasks
73
77
  if args && args[:strict]
74
78
  fail CommandError, 'the strict option is global and cannot be applied on the scanner level'
75
79
  end
80
+
76
81
  ActiveSupport::Inflector.constantize(class_name).new(
77
- config: merge_scanner_configs(shared_options, args || {}),
82
+ config: merge_scanner_configs(shared_options, args || {}),
78
83
  file_finder_provider: caching_file_finder_provider,
79
- file_reader: caching_file_reader
84
+ file_reader: caching_file_reader
80
85
  )
81
86
  end.tap { |scanners| log_verbose { scanners.map { |s| " #{s.class.name} #{s.config.inspect}" } * "\n" } }
82
87
  )
@@ -104,7 +109,7 @@ module I18n::Tasks
104
109
 
105
110
  def merge_scanner_configs(a, b)
106
111
  a.deep_merge(b).tap do |c|
107
- %i[scanners paths relative_roots].each do |key|
112
+ %i[scanners paths relative_exclude_method_name_paths relative_roots].each do |key|
108
113
  c[key] = a[key] if b[key].blank?
109
114
  end
110
115
  %i[exclude].each do |key|
@@ -124,7 +129,7 @@ module I18n::Tasks
124
129
 
125
130
  # @return [Boolean] whether the key is potentially used in a code expression such as `t("category.#{category_key}")`
126
131
  def used_in_expr?(key)
127
- !!(key =~ expr_key_re) # rubocop:disable Style/DoubleNegation
132
+ !!(key =~ expr_key_re)
128
133
  end
129
134
 
130
135
  private
@@ -140,12 +145,13 @@ module I18n::Tasks
140
145
  def expr_key_re(replacement: ':')
141
146
  @expr_key_re ||= begin
142
147
  # disallow patterns with no keys
143
- ignore_pattern_re = /\A[\.#{replacement}]*\z/
148
+ ignore_pattern_re = /\A[.#{replacement}]*\z/
144
149
  patterns = used_in_source_tree(strict: false).key_names.select do |k|
145
150
  k.end_with?('.') || k =~ /\#{/
146
151
  end.map do |k|
147
152
  pattern = "#{replace_key_exp(k, replacement)}#{replacement if k.end_with?('.')}"
148
153
  next if pattern =~ ignore_pattern_re
154
+
149
155
  pattern
150
156
  end.compact
151
157
  compile_key_pattern "{#{patterns * ','}}"
@@ -161,17 +167,18 @@ module I18n::Tasks
161
167
  braces = []
162
168
  result = []
163
169
  while (match_until = scanner.scan_until(/(?:#?\{|})/))
164
- if scanner.matched == '#{'
170
+ case scanner.matched
171
+ when '#{'
165
172
  braces << scanner.matched
166
173
  result << match_until[0..-3] if braces.length == 1
167
- elsif scanner.matched == '}'
174
+ when '}'
168
175
  prev_brace = braces.pop
169
176
  result << replacement if braces.empty? && prev_brace == '#{'
170
177
  else
171
178
  braces << '{'
172
179
  end
173
180
  end
174
- result << key[scanner.pos..-1] unless scanner.eos?
181
+ result << key[scanner.pos..] unless scanner.eos?
175
182
  result.join
176
183
  end
177
184
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module I18n
4
4
  module Tasks
5
- VERSION = '0.9.33'
5
+ VERSION = '1.0.12'
6
6
  end
7
7
  end
data/lib/i18n/tasks.rb CHANGED
@@ -34,6 +34,17 @@ module I18n
34
34
  ::I18n::Tasks::Commands.send :include, commands_module
35
35
  self
36
36
  end
37
+
38
+ # Add AST-matcher to i18n-tasks
39
+ #
40
+ # @param matcher_class_name
41
+ # @return self
42
+ def add_ast_matcher(matcher_class_name)
43
+ matchers = I18n::Tasks::Configuration::DEFAULTS[:search][:ast_matchers]
44
+ matchers << matcher_class_name
45
+ matchers.uniq!
46
+ self
47
+ end
37
48
  end
38
49
 
39
50
  @verbose = !ENV['VERBOSE'].nil?
@@ -43,19 +54,18 @@ module I18n
43
54
  end
44
55
  end
45
56
 
57
+ # Per https://github.com/rails/rails/commit/0181f0edd57a2149278bd59c3519233ca1e0a413#commitcomment-60940992
58
+ # 'active_support' must be required first even if we only use parts of it.
59
+ require 'active_support'
60
+
46
61
  require 'active_support/inflector'
47
62
  require 'active_support/core_ext/hash'
48
63
  require 'active_support/core_ext/array/access'
49
64
  require 'active_support/core_ext/array/extract_options'
50
65
  require 'active_support/core_ext/module/delegation'
51
66
  require 'active_support/core_ext/object/blank'
52
- begin
53
- # activesupport >= 3
54
- require 'active_support/core_ext/object/try'
55
- rescue LoadError => _e
56
- # activesupport ~> 2.3.2
57
- require 'active_support/core_ext/try'
58
- end
67
+ require 'active_support/core_ext/object/try'
68
+
59
69
  require 'rainbow'
60
70
  require 'erubi'
61
71
 
@@ -64,12 +64,21 @@ search:
64
64
  # - app/presenters
65
65
  # - app/views
66
66
 
67
+ ## Directories where method names which should not be part of a relative key resolution.
68
+ # By default, if a relative translation is used inside a method, the name of the method will be considered part of the resolved key.
69
+ # Directories listed here will not consider the name of the method part of the resolved key
70
+ #
71
+ # relative_exclude_method_name_paths:
72
+ # -
73
+
67
74
  ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
68
- ## %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
75
+ ## *.jpg *.jpeg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less
76
+ ## *.yml *.json *.zip *.tar.gz *.swf *.flv *.mp3 *.wav *.flac *.webm *.mp4 *.ogg *.opus *.webp *.map *.xlsx
69
77
  exclude:
70
78
  - app/assets/images
71
79
  - app/assets/fonts
72
80
  - app/assets/videos
81
+ - app/assets/builds
73
82
 
74
83
  ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
75
84
  ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
@@ -78,6 +87,15 @@ search:
78
87
  ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
79
88
  # strict: true
80
89
 
90
+ ## Allows adding ast_matchers for finding translations using the AST-scanners
91
+ ## The available matchers are:
92
+ ## - RailsModelMatcher
93
+ ## Matches ActiveRecord translations like
94
+ ## User.human_attribute_name(:email) and User.model_name.human
95
+ ##
96
+ ## To implement your own, please see `I18n::Tasks::Scanners::AstMatchers::BaseMatcher`.
97
+ <%# I18n::Tasks.add_ast_matcher('I18n::Tasks::Scanners::AstMatchers::RailsModelMatcher') %>
98
+
81
99
  ## Multiple scanners can be used. Their results are merged.
82
100
  ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
83
101
  ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example
@@ -90,6 +108,8 @@ search:
90
108
  # # DeepL Pro Translate
91
109
  # # Get an API key and subscription at https://www.deepl.com/pro to use DeepL Pro
92
110
  # deepl_api_key: "48E92789-57A3-466A-9959-1A1A1A1A1A1A"
111
+ # # deepl_host: "https://api.deepl.com"
112
+ # # deepl_version: "v2"
93
113
 
94
114
  ## Do not consider these keys missing:
95
115
  # ignore_missing:
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.33
4
+ version: 1.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-21 00:00:00.000000000 Z
11
+ date: 2022-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,26 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: better_html
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '3.0'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '1.0'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
41
61
  - !ruby/object:Gem::Dependency
42
62
  name: erubi
43
63
  requirement: !ruby/object:Gem::Requirement
@@ -143,12 +163,15 @@ dependencies:
143
163
  - !ruby/object:Gem::Version
144
164
  version: 1.5.1
145
165
  - !ruby/object:Gem::Dependency
146
- name: axlsx
166
+ name: bundler
147
167
  requirement: !ruby/object:Gem::Requirement
148
168
  requirements:
149
169
  - - "~>"
150
170
  - !ruby/object:Gem::Version
151
171
  version: '2.0'
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: 2.0.1
152
175
  type: :development
153
176
  prerelease: false
154
177
  version_requirements: !ruby/object:Gem::Requirement
@@ -156,26 +179,23 @@ dependencies:
156
179
  - - "~>"
157
180
  - !ruby/object:Gem::Version
158
181
  version: '2.0'
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: 2.0.1
159
185
  - !ruby/object:Gem::Dependency
160
- name: bundler
186
+ name: overcommit
161
187
  requirement: !ruby/object:Gem::Requirement
162
188
  requirements:
163
189
  - - "~>"
164
190
  - !ruby/object:Gem::Version
165
- version: '2.0'
166
- - - ">="
167
- - !ruby/object:Gem::Version
168
- version: 2.0.1
191
+ version: 0.58.0
169
192
  type: :development
170
193
  prerelease: false
171
194
  version_requirements: !ruby/object:Gem::Requirement
172
195
  requirements:
173
196
  - - "~>"
174
197
  - !ruby/object:Gem::Version
175
- version: '2.0'
176
- - - ">="
177
- - !ruby/object:Gem::Version
178
- version: 2.0.1
198
+ version: 0.58.0
179
199
  - !ruby/object:Gem::Dependency
180
200
  name: rake
181
201
  requirement: !ruby/object:Gem::Requirement
@@ -210,14 +230,14 @@ dependencies:
210
230
  requirements:
211
231
  - - "~>"
212
232
  - !ruby/object:Gem::Version
213
- version: 0.53.0
233
+ version: 1.27.0
214
234
  type: :development
215
235
  prerelease: false
216
236
  version_requirements: !ruby/object:Gem::Requirement
217
237
  requirements:
218
238
  - - "~>"
219
239
  - !ruby/object:Gem::Version
220
- version: 0.53.0
240
+ version: 1.27.0
221
241
  - !ruby/object:Gem::Dependency
222
242
  name: simplecov
223
243
  requirement: !ruby/object:Gem::Requirement
@@ -357,12 +377,18 @@ files:
357
377
  - lib/i18n/tasks/references.rb
358
378
  - lib/i18n/tasks/reports/base.rb
359
379
  - lib/i18n/tasks/reports/terminal.rb
380
+ - lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb
381
+ - lib/i18n/tasks/scanners/ast_matchers/message_receivers_matcher.rb
382
+ - lib/i18n/tasks/scanners/ast_matchers/rails_model_matcher.rb
383
+ - lib/i18n/tasks/scanners/erb_ast_processor.rb
384
+ - lib/i18n/tasks/scanners/erb_ast_scanner.rb
360
385
  - lib/i18n/tasks/scanners/file_scanner.rb
361
386
  - lib/i18n/tasks/scanners/files/caching_file_finder.rb
362
387
  - lib/i18n/tasks/scanners/files/caching_file_finder_provider.rb
363
388
  - lib/i18n/tasks/scanners/files/caching_file_reader.rb
364
389
  - lib/i18n/tasks/scanners/files/file_finder.rb
365
390
  - lib/i18n/tasks/scanners/files/file_reader.rb
391
+ - lib/i18n/tasks/scanners/local_ruby_parser.rb
366
392
  - lib/i18n/tasks/scanners/occurrence_from_position.rb
367
393
  - lib/i18n/tasks/scanners/pattern_mapper.rb
368
394
  - lib/i18n/tasks/scanners/pattern_scanner.rb
@@ -394,11 +420,14 @@ licenses:
394
420
  - MIT
395
421
  metadata:
396
422
  issue_tracker: https://github.com/glebm/i18n-tasks
423
+ rubygems_mfa_required: 'true'
397
424
  post_install_message: |
398
425
  # Install default configuration:
399
426
  cp $(bundle exec i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/
400
427
  # Add an RSpec for missing and unused keys:
401
428
  cp $(bundle exec i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/
429
+ # Or for minitest:
430
+ cp $(bundle exec i18n-tasks gem-path)/templates/minitest/i18n_test.rb test/
402
431
  rdoc_options: []
403
432
  require_paths:
404
433
  - lib
@@ -406,7 +435,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
406
435
  requirements:
407
436
  - - ">="
408
437
  - !ruby/object:Gem::Version
409
- version: '2.3'
438
+ version: '2.6'
410
439
  - - "<"
411
440
  - !ruby/object:Gem::Version
412
441
  version: '4.0'