i18n-tasks 0.9.34 → 0.9.35

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5477cbdf1fb14c575eaad7221cac570147acfcde877fa5960dcdfd958d76d270
4
- data.tar.gz: b40dbef296c01aa2c047b8ae2f6ef3567f8643b35895516a8fde281f225e6daa
3
+ metadata.gz: 8ac03642fdf45424834ce7e968e70af9d602c5d5721eda666dbd38635adcf542
4
+ data.tar.gz: 793b43903d97f1dccead925e5128142886708b279f55f04bcd62c6b349bddead
5
5
  SHA512:
6
- metadata.gz: f732fc9479ba13cd3acb1c7222401f873ace5a8db1ef248712c1ea4dbdb9d05a7fdc5da5bb3600c7c799c64b7f21b1586518b1feec508a0ad36d211110b07b3e
7
- data.tar.gz: f05241d9bd75bbecb1cb992882d84c4e9826c00c66b66263e7203603e19c9a188e96ea7f4e4131160e23216265df675f4519d190263cf14de59384bd2e62c88d
6
+ metadata.gz: 538b6490808142df807dcfa623e6907dd408dc9346e37b2ecbba2257350fa6dcf91b66f8b1f9338cc24fbd7f138ee5c20a7875633c26c9c06ac06dbb87e7e67a
7
+ data.tar.gz: f7570702d3599d229236ffd3841b33776b3bef50875b12c515b5bc3e63ace2ef2f86fd3058e957959e196c90ace5dc539a5b328a203f0e9f4460b26f3b751778
data/README.md CHANGED
@@ -22,7 +22,7 @@ i18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (def
22
22
  Add i18n-tasks to the Gemfile:
23
23
 
24
24
  ```ruby
25
- gem 'i18n-tasks', '~> 0.9.34'
25
+ gem 'i18n-tasks', '~> 0.9.35'
26
26
  ```
27
27
 
28
28
  Copy the default [configuration file](#configuration):
@@ -212,7 +212,7 @@ $ i18n-tasks missing -f yaml fr | i18n-tasks tree-set-value 'TRME %{value}' | i1
212
212
  $ i18n-tasks unused -f yaml | i18n-tasks data-remove
213
213
  ```
214
214
 
215
- Remove all keys in `fr` but not `en` from `fr`:
215
+ Remove all keys from `fr` that do not exist in `en`. Do not change `en`:
216
216
  ```console
217
217
  $ i18n-tasks missing -t diff -f yaml en | i18n-tasks tree-mv en fr | i18n-tasks data-remove
218
218
  ```
@@ -405,7 +405,9 @@ translation:
405
405
  ```yaml
406
406
  # config/i18n-tasks.yml
407
407
  translation:
408
- deepl_api_key: <Deep Pro API key>
408
+ deepl_api_key: <DeepL Pro API key>
409
+ deepl_host: <optional>
410
+ deepl_version: <optional>
409
411
  ```
410
412
 
411
413
  <a name="yandex-translation-config"></a>
@@ -11,6 +11,7 @@ en:
11
11
  desc:
12
12
  all_locales: Do not expect key patterns to start with a locale, instead apply them to all
13
13
  locales implicitly.
14
+ config: Override config location
14
15
  confirm: Confirm automatically
15
16
  data_format: 'Data format: %{valid_text}.'
16
17
  keep_order: Keep the order of the keys
@@ -39,7 +39,8 @@ module I18n
39
39
  include Data
40
40
  include Stats
41
41
 
42
- def initialize(config = {})
42
+ def initialize(config = {}, config_file: nil)
43
+ @config_override = config_file
43
44
  self.config = config || {}
44
45
  end
45
46
 
@@ -34,7 +34,18 @@ class I18n::Tasks::CLI
34
34
  end
35
35
 
36
36
  def run(argv)
37
- I18n.with_locale(base_task.internal_locale) do
37
+ argv.each_with_index do |arg, i|
38
+ if ["--config", "-c"].include?(arg)
39
+ if File.exist?(argv[i+1])
40
+ @config_file = argv[i+1]
41
+ break
42
+ else
43
+ error "Config file doesn't exist: #{argv[i+1]}", 128
44
+ end
45
+ end
46
+ end
47
+
48
+ I18n.with_locale(base_task(config_file: @config_file).internal_locale) do
38
49
  name, *options = parse!(argv.dup)
39
50
  context.run(name, *options)
40
51
  end
@@ -52,8 +63,8 @@ class I18n::Tasks::CLI
52
63
 
53
64
  private
54
65
 
55
- def base_task
56
- @base_task ||= I18n::Tasks::BaseTask.new
66
+ def base_task(config_file: nil)
67
+ @base_task ||= I18n::Tasks::BaseTask.new(config_file: config_file)
57
68
  end
58
69
 
59
70
  def parse!(argv)
@@ -9,7 +9,7 @@ module I18n::Tasks
9
9
  cmd :health,
10
10
  pos: '[locale ...]',
11
11
  desc: t('i18n_tasks.cmd.desc.health'),
12
- args: %i[locales out_format]
12
+ args: %i[locales out_format config]
13
13
 
14
14
  def health(opt = {})
15
15
  forest = i18n.data_forest(opt[:locales])
@@ -28,6 +28,12 @@ module I18n::Tasks
28
28
  '--value VALUE',
29
29
  t('i18n_tasks.cmd.args.desc.value')
30
30
 
31
+ arg :config,
32
+ '-c',
33
+ '--config FILE',
34
+ t('i18n_tasks.cmd.args.desc.config')
35
+
36
+
31
37
  def arg_or_pos!(key, opts)
32
38
  opts[key] ||= opts[:arguments].try(:shift)
33
39
  end
@@ -20,7 +20,7 @@ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
20
20
  ].freeze
21
21
 
22
22
  def file_config
23
- file = CONFIG_FILES.detect { |f| File.exist?(f) }
23
+ file = @config_override || CONFIG_FILES.detect { |f| File.exist?(f) }
24
24
  # rubocop:disable Security/Eval
25
25
  config = file && YAML.load(eval(Erubi::Engine.new(File.read(file, encoding: 'UTF-8')).src))
26
26
  # rubocop:enable Security/Eval
@@ -59,6 +59,8 @@ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
59
59
  conf = (config[:translation] || {}).with_indifferent_access
60
60
  conf[:google_translate_api_key] = ENV['GOOGLE_TRANSLATE_API_KEY'] if ENV.key?('GOOGLE_TRANSLATE_API_KEY')
61
61
  conf[:deepl_api_key] = ENV['DEEPL_AUTH_KEY'] if ENV.key?('DEEPL_AUTH_KEY')
62
+ conf[:deepl_host] = ENV['DEEPL_HOST'] if ENV.key?('DEEPL_HOST')
63
+ conf[:deepl_version] = ENV['DEEPL_VERSION'] if ENV.key?('DEEPL_VERSION')
62
64
  conf[:yandex_api_key] = ENV['YANDEX_API_KEY'] if ENV.key?('YANDEX_API_KEY')
63
65
  conf
64
66
  end
@@ -65,6 +65,7 @@ module I18n::Tasks
65
65
  plural_nodes data[locale] do |node|
66
66
  children = node.children
67
67
  present_keys = Set.new(children.map { |c| c.key.to_sym })
68
+ next if ignore_key?(node.full_key(root: false), :missing)
68
69
  next if present_keys.superset?(required_keys)
69
70
 
70
71
  tree[node.full_key] = node.derive(
@@ -9,7 +9,9 @@ module I18n
9
9
  # @param roots [Array<String>] paths to relative roots
10
10
  # @param calling_method [#call, Symbol, String, false, nil]
11
11
  # @return [String] absolute version of the key
12
- def absolute_key(key, path, roots: config[:relative_roots], calling_method: nil)
12
+ def absolute_key(key, path, roots: config[:relative_roots],
13
+ exclude_method_name_paths: config[:exclude_method_name_paths],
14
+ calling_method: nil)
13
15
  return key unless key.start_with?(DOT)
14
16
  fail 'roots argument is required' unless roots.present?
15
17
 
@@ -18,7 +20,12 @@ module I18n
18
20
  fail(CommandError, "Cannot resolve relative key \"#{key}\".\n" \
19
21
  "Set search.relative_roots in config/i18n-tasks.yml (currently #{roots.inspect})")
20
22
  normalized_path.sub!(root, '')
21
- "#{prefix(normalized_path, calling_method: calling_method)}#{key}"
23
+
24
+ if (exclude_method_name_paths || []).map { |p| expand_path(p) }.include?(root)
25
+ "#{prefix(normalized_path)}#{key}"
26
+ else
27
+ "#{prefix(normalized_path, calling_method: calling_method)}#{key}"
28
+ end
22
29
  end
23
30
 
24
31
  private
@@ -31,12 +38,19 @@ module I18n
31
38
  # @return [String] the closest ancestor root for path, with a trailing {File::SEPARATOR}.
32
39
  def path_root(path, roots)
33
40
  roots.map do |p|
34
- File.expand_path(p) + File::SEPARATOR
41
+ expand_path(p)
35
42
  end.sort.reverse_each.detect do |root|
36
43
  path.start_with?(root)
37
44
  end
38
45
  end
39
46
 
47
+ # Expand a path and add a trailing {File::SEPARATOR}
48
+ # @param [String] path relative path
49
+ # @return [String] absolute path, with a trailing {File::SEPARATOR}.
50
+ def expand_path(path)
51
+ File.expand_path(path) + File::SEPARATOR
52
+ end
53
+
40
54
  # @param normalized_path [String] path/relative/to/a/root
41
55
  # @param calling_method [#call, Symbol, String, false, nil]
42
56
  def prefix(normalized_path, calling_method: nil)
@@ -94,7 +94,7 @@ module I18n::Tasks
94
94
  end
95
95
 
96
96
  INTERPOLATION_KEY_RE = /%\{[^}]+}/.freeze
97
- UNTRANSLATABLE_STRING = 'zxzxzx'
97
+ UNTRANSLATABLE_STRING = 'X__'
98
98
 
99
99
  # @param [String] value
100
100
  # @return [String] 'hello, %{name}' => 'hello, <round-trippable string>'
@@ -67,9 +67,15 @@ module I18n::Tasks::Translators
67
67
 
68
68
  def configure_api_key!
69
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]
70
72
  fail ::I18n::Tasks::CommandError, I18n.t('i18n_tasks.deepl_translate.errors.no_api_key') if api_key.blank?
71
73
 
72
- DeepL.configure { |config| config.auth_key = api_key }
74
+ DeepL.configure { |config|
75
+ config.auth_key = api_key
76
+ config.host = host unless host.blank?
77
+ config.version = version unless version.blank?
78
+ }
73
79
  end
74
80
  end
75
81
  end
@@ -16,6 +16,7 @@ module I18n::Tasks
16
16
  module UsedKeys # rubocop:disable Metrics/ModuleLength
17
17
  SEARCH_DEFAULTS = {
18
18
  paths: %w[app/].freeze,
19
+ relative_exclude_method_name_paths: [],
19
20
  relative_roots: %w[app/controllers app/helpers app/mailers app/presenters app/views].freeze,
20
21
  scanners: [
21
22
  ['::I18n::Tasks::Scanners::RubyAstScanner', { only: %w[*.rb] }],
@@ -24,7 +25,7 @@ module I18n::Tasks
24
25
  strict: true
25
26
  }.freeze
26
27
 
27
- ALWAYS_EXCLUDE = %w[*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less
28
+ ALWAYS_EXCLUDE = %w[*.jpg *.jpeg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less
28
29
  *.yml *.json *.zip *.tar.gz *.swf *.flv *.mp3 *.wav *.flac *.webm *.mp4 *.ogg *.opus
29
30
  *.webp].freeze
30
31
 
@@ -105,7 +106,7 @@ module I18n::Tasks
105
106
 
106
107
  def merge_scanner_configs(a, b)
107
108
  a.deep_merge(b).tap do |c|
108
- %i[scanners paths relative_roots].each do |key|
109
+ %i[scanners paths relative_exclude_method_name_paths relative_roots].each do |key|
109
110
  c[key] = a[key] if b[key].blank?
110
111
  end
111
112
  %i[exclude].each do |key|
@@ -2,6 +2,6 @@
2
2
 
3
3
  module I18n
4
4
  module Tasks
5
- VERSION = '0.9.34'
5
+ VERSION = '0.9.35'
6
6
  end
7
7
  end
@@ -64,6 +64,13 @@ 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
75
  ## %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
69
76
  exclude:
@@ -90,6 +97,8 @@ search:
90
97
  # # DeepL Pro Translate
91
98
  # # Get an API key and subscription at https://www.deepl.com/pro to use DeepL Pro
92
99
  # deepl_api_key: "48E92789-57A3-466A-9959-1A1A1A1A1A1A"
100
+ # # deepl_host: "https://api.deepl.com"
101
+ # # deepl_version: "v2"
93
102
 
94
103
  ## Do not consider these keys missing:
95
104
  # 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.34
4
+ version: 0.9.35
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-04 00:00:00.000000000 Z
11
+ date: 2021-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport