i18n-tasks 0.9.24 → 0.9.25
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 +4 -1
- data/config/locales/en.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/i18n-tasks.gemspec +10 -12
- data/lib/i18n/tasks/command/commands/usages.rb +7 -1
- data/lib/i18n/tasks/command/option_parsers/locale.rb +1 -1
- data/lib/i18n/tasks/concurrent/cache.rb +22 -0
- data/lib/i18n/tasks/concurrent/cached_value.rb +27 -0
- data/lib/i18n/tasks/console_context.rb +30 -30
- data/lib/i18n/tasks/data/file_formats.rb +2 -2
- data/lib/i18n/tasks/data/file_system_base.rb +13 -12
- data/lib/i18n/tasks/data/tree/node.rb +1 -1
- data/lib/i18n/tasks/data/tree/traversal.rb +1 -1
- data/lib/i18n/tasks/locale_pathname.rb +1 -1
- data/lib/i18n/tasks/logging.rb +1 -3
- data/lib/i18n/tasks/reports/base.rb +1 -1
- data/lib/i18n/tasks/scanners/files/caching_file_finder.rb +7 -3
- data/lib/i18n/tasks/scanners/files/caching_file_finder_provider.rb +7 -9
- data/lib/i18n/tasks/scanners/files/caching_file_reader.rb +4 -4
- data/lib/i18n/tasks/scanners/relative_keys.rb +1 -1
- data/lib/i18n/tasks/scanners/ruby_ast_call_finder.rb +1 -1
- data/lib/i18n/tasks/translators/base_translator.rb +11 -7
- data/lib/i18n/tasks/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c701c96d03c3226bb8c9a6e2bed8477c7846645ee384a93c569c090cfe9b76ae
|
4
|
+
data.tar.gz: 5209c23392064c0d0a15cc61f2a82d0a08294e58afd7b1466b433295ae861e98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a573608dff03c12f15920a84ed5c01d2377c593e43ed1cf27c0f9a1951b75fa4211be678b1ad150df7a129365f09a77e398c45d6260c87213f62985dbad58d9
|
7
|
+
data.tar.gz: 9bf7f845ef28e04b87bbbdc9b0e293ef7187b808ce7a7b690434441a725d6b61ef74759f77e26d5df756d49220f04ff6d0a716581cda040979c41d2d1d374b4c
|
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.
|
25
|
+
gem 'i18n-tasks', '~> 0.9.25'
|
26
26
|
```
|
27
27
|
|
28
28
|
Copy the default [configuration file](#configuration):
|
@@ -125,6 +125,9 @@ $ i18n-tasks remove-unused
|
|
125
125
|
These tasks can infer [dynamic keys](#dynamic-keys) such as `t("category.\#{category.name}")` if you set
|
126
126
|
`search.strict` to false, or pass `--no-strict` on the command line.
|
127
127
|
|
128
|
+
If you want to keep the ordering from the original language file when using remove-unused, pass
|
129
|
+
`-k` or `--keep-order`.
|
130
|
+
|
128
131
|
### Normalize data
|
129
132
|
|
130
133
|
Sort the keys:
|
data/config/locales/en.yml
CHANGED
@@ -13,6 +13,7 @@ en:
|
|
13
13
|
locales implicitly.
|
14
14
|
confirm: Confirm automatically
|
15
15
|
data_format: 'Data format: %{valid_text}.'
|
16
|
+
keep_order: Keep the order of the keys
|
16
17
|
key_pattern: Filter by key pattern (e.g. 'common.*')
|
17
18
|
key_pattern_to_rename: Full key (pattern) to rename. Required
|
18
19
|
locale: :i18n_tasks.common.locale
|
data/config/locales/ru.yml
CHANGED
@@ -10,6 +10,7 @@ ru:
|
|
10
10
|
all_locales: Не ожидать, что маски ключа начинаются с локали. Применять маски ко всем локалям.
|
11
11
|
confirm: Подтвердить автоматом
|
12
12
|
data_format: 'Формат данных: %{valid_text}. %{default_text}.'
|
13
|
+
keep_order: Keep the order of the keys
|
13
14
|
key_pattern: Маска ключа (например, common.*)
|
14
15
|
key_pattern_to_rename: Полный ключ (шаблон) для переименования. Необходимый параметр.
|
15
16
|
locale: 'Язык. По умолчанию: base'
|
data/i18n-tasks.gemspec
CHANGED
@@ -11,23 +11,21 @@ Gem::Specification.new do |s| # rubocop:disable Metrics/BlockLength
|
|
11
11
|
s.email = ['glex.spb@gmail.com']
|
12
12
|
s.license = 'MIT'
|
13
13
|
s.summary = 'Manage localization and translation with the awesome power of static analysis'
|
14
|
-
s.description =
|
15
|
-
i18n-tasks helps you find and manage missing and unused translations.
|
14
|
+
s.description = <<~TEXT
|
15
|
+
i18n-tasks helps you find and manage missing and unused translations.
|
16
16
|
|
17
|
-
It analyses code statically for key usages, such as `I18n.t('some.key')`, in order to report keys that are missing or unused,
|
18
|
-
pre-fill missing keys (optionally from Google Translate), and remove unused keys.
|
17
|
+
It analyses code statically for key usages, such as `I18n.t('some.key')`, in order to report keys that are missing or unused,
|
18
|
+
pre-fill missing keys (optionally from Google Translate), and remove unused keys.
|
19
19
|
TEXT
|
20
|
-
s.post_install_message =
|
21
|
-
# Install default configuration:
|
22
|
-
cp $(i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/
|
23
|
-
# Add an RSpec for missing and unused keys:
|
24
|
-
cp $(i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/
|
20
|
+
s.post_install_message = <<~TEXT
|
21
|
+
# Install default configuration:
|
22
|
+
cp $(i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/
|
23
|
+
# Add an RSpec for missing and unused keys:
|
24
|
+
cp $(i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/
|
25
25
|
TEXT
|
26
26
|
s.homepage = 'https://github.com/glebm/i18n-tasks'
|
27
27
|
s.metadata = { 'issue_tracker' => 'https://github.com/glebm/i18n-tasks' } if s.respond_to?(:metadata=)
|
28
|
-
|
29
|
-
s.required_ruby_version = '~> 2.1' if s.respond_to?(:required_ruby_version=)
|
30
|
-
# rubocop:enable Gemspec/RequiredRubyVersion
|
28
|
+
s.required_ruby_version = '~> 2.3' if s.respond_to?(:required_ruby_version=)
|
31
29
|
|
32
30
|
s.files = `git ls-files`.split($/)
|
33
31
|
s.files -= s.files.grep(%r{^(doc/|\.|spec/)}) + %w[CHANGES.md config/i18n-tasks.yml Gemfile]
|
@@ -10,6 +10,11 @@ module I18n::Tasks
|
|
10
10
|
'--[no-]strict',
|
11
11
|
t('i18n_tasks.cmd.args.desc.strict')
|
12
12
|
|
13
|
+
arg :keep_order,
|
14
|
+
'-k',
|
15
|
+
'--keep-order',
|
16
|
+
t('i18n_tasks.cmd.args.desc.keep_order')
|
17
|
+
|
13
18
|
cmd :find,
|
14
19
|
pos: '[pattern]',
|
15
20
|
desc: t('i18n_tasks.cmd.desc.find'),
|
@@ -35,13 +40,14 @@ module I18n::Tasks
|
|
35
40
|
cmd :remove_unused,
|
36
41
|
pos: '[locale ...]',
|
37
42
|
desc: t('i18n_tasks.cmd.desc.remove_unused'),
|
38
|
-
args: %i[locales out_format strict confirm]
|
43
|
+
args: %i[locales out_format strict keep_order confirm]
|
39
44
|
|
40
45
|
def remove_unused(opt = {})
|
41
46
|
unused_keys = i18n.unused_keys(opt.slice(:locales, :strict))
|
42
47
|
if unused_keys.present?
|
43
48
|
terminal_report.unused_keys(unused_keys)
|
44
49
|
confirm_remove_unused!(unused_keys, opt)
|
50
|
+
i18n.data.config = i18n.data.config.merge(sort: false) if opt[:'keep-order']
|
45
51
|
removed = i18n.data.remove_by_key!(unused_keys)
|
46
52
|
log_stderr t('i18n_tasks.remove_unused.removed', count: unused_keys.leaves.count)
|
47
53
|
print_forest removed, opt
|
@@ -47,7 +47,7 @@ module I18n::Tasks
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def move_base_locale_to_front!(locales, base_locale)
|
50
|
-
if (pos = locales.index(base_locale)) && pos
|
50
|
+
if (pos = locales.index(base_locale)) && pos.positive?
|
51
51
|
locales[pos], locales[0] = locales[0], locales[pos]
|
52
52
|
end
|
53
53
|
locales
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'i18n/tasks/concurrent/cached_value'
|
4
|
+
|
5
|
+
module I18n::Tasks::Concurrent
|
6
|
+
# A thread-safe cache.
|
7
|
+
# @since 0.9.25
|
8
|
+
class Cache
|
9
|
+
def initialize
|
10
|
+
@mutex = Mutex.new
|
11
|
+
@map = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [Object] key
|
15
|
+
# @return [Object] Cached or computed value.
|
16
|
+
def fetch(key, &block)
|
17
|
+
@mutex.synchronize do
|
18
|
+
@map[key] ||= CachedValue.new(&block)
|
19
|
+
end.get
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'i18n/tasks/concurrent/cached_value'
|
4
|
+
|
5
|
+
module I18n::Tasks::Concurrent
|
6
|
+
# A thread-safe memoized value.
|
7
|
+
# The given computation is guaranteed to be invoked at most once.
|
8
|
+
# @since 0.9.25
|
9
|
+
class CachedValue
|
10
|
+
NULL = Object.new
|
11
|
+
|
12
|
+
# @param [Proc] computation The computation that returns the value to cache.
|
13
|
+
def initialize(&computation)
|
14
|
+
@computation = computation
|
15
|
+
@mutex = Mutex.new
|
16
|
+
@result = NULL
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Object] Result of the computation.
|
20
|
+
def get
|
21
|
+
return @result unless @result == NULL
|
22
|
+
@mutex.synchronize do
|
23
|
+
@result = @computation.call
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -34,41 +34,41 @@ module I18n::Tasks
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def guide
|
37
|
-
Rainbow('i18n-tasks IRB Quick Start guide').green.bright + "\n" +
|
38
|
-
#{Rainbow('Data as trees').yellow}
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
Rainbow('i18n-tasks IRB Quick Start guide').green.bright + "\n" + <<~TEXT
|
38
|
+
#{Rainbow('Data as trees').yellow}
|
39
|
+
tree(locale)
|
40
|
+
used_tree(key_filter: nil, strict: nil)
|
41
|
+
unused_tree(locale: base_locale, strict: nil)
|
42
|
+
build_tree('es' => {'hello' => 'Hola'})
|
43
43
|
|
44
|
-
#{Rainbow('Traversal').yellow}
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
#{Rainbow('Traversal').yellow}
|
45
|
+
tree = missing_diff_tree('es')
|
46
|
+
tree.nodes { |node| }
|
47
|
+
tree.nodes.to_a
|
48
|
+
tree.leaves { |node| }
|
49
|
+
tree.each { |root_node| }
|
50
|
+
# also levels, depth_first, and breadth_first
|
51
51
|
|
52
|
-
#{Rainbow('Select nodes').yellow}
|
53
|
-
|
52
|
+
#{Rainbow('Select nodes').yellow}
|
53
|
+
tree.select_nodes { |node| } # new tree with only selected nodes
|
54
54
|
|
55
|
-
#{Rainbow('Match by full key').yellow}
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
#{Rainbow('Match by full key').yellow}
|
56
|
+
tree.select_keys { |key, leaf| } # new tree with only selected keys
|
57
|
+
tree.grep_keys(/hello/) # grep, using ===
|
58
|
+
tree.keys { |key, leaf| } # enumerate over [full_key, leaf_node]
|
59
|
+
# Pass {root: true} to include root node in full_key (usually locale)
|
60
60
|
|
61
|
-
#{Rainbow('Nodes').yellow}
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
61
|
+
#{Rainbow('Nodes').yellow}
|
62
|
+
node = node(key, locale)
|
63
|
+
node.key # only the part after the last dot
|
64
|
+
node.full_key # full key. Includes root key, pass {root: false} to override.
|
65
|
+
# also: value, value_or_children_hash, data, walk_to_root, walk_from_root
|
66
|
+
Tree::Node.new(key: 'en')
|
67
67
|
|
68
|
-
#{Rainbow('Keys').yellow}
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
#{Rainbow('Keys').yellow}
|
69
|
+
t(key, locale)
|
70
|
+
key_value?(key, locale)
|
71
|
+
depluralize_key(key, locale) # convert 'hat.one' to 'hat'
|
72
72
|
TEXT
|
73
73
|
end
|
74
74
|
end
|
@@ -45,8 +45,8 @@ module I18n
|
|
45
45
|
::File.read(path, encoding: 'UTF-8')
|
46
46
|
end
|
47
47
|
|
48
|
-
def write_tree(path, tree)
|
49
|
-
hash = tree.to_hash(
|
48
|
+
def write_tree(path, tree, sort = true)
|
49
|
+
hash = tree.to_hash(sort)
|
50
50
|
adapter = self.class.adapter_name_for_path(path)
|
51
51
|
content = adapter_dump(hash, adapter)
|
52
52
|
# Ignore unchanged data
|
@@ -21,7 +21,8 @@ module I18n::Tasks
|
|
21
21
|
}.freeze
|
22
22
|
|
23
23
|
def initialize(config = {})
|
24
|
-
self.config
|
24
|
+
self.config = config.except(:base_locale, :locales)
|
25
|
+
self.config[:sort] = !config[:keep_order]
|
25
26
|
@base_locale = config[:base_locale]
|
26
27
|
locales = config[:locales].presence
|
27
28
|
@locales = LocaleList.normalize_locale_list(locales || available_locales, base_locale, true)
|
@@ -55,17 +56,17 @@ module I18n::Tasks
|
|
55
56
|
# @param [::I18n::Tasks::Data::Siblings] tree
|
56
57
|
def set(locale, tree)
|
57
58
|
locale = locale.to_s
|
58
|
-
@trees
|
59
|
+
@trees&.delete(locale)
|
59
60
|
paths_before = Set.new(get(locale)[locale].leaves.map { |node| node.data[:path] })
|
60
61
|
paths_after = Set.new([])
|
61
62
|
router.route locale, tree do |path, tree_slice|
|
62
63
|
paths_after << path
|
63
|
-
write_tree path, tree_slice
|
64
|
+
write_tree path, tree_slice, config[:sort]
|
64
65
|
end
|
65
66
|
(paths_before - paths_after).each do |path|
|
66
67
|
FileUtils.remove_file(path) if File.exist?(path)
|
67
68
|
end
|
68
|
-
@trees
|
69
|
+
@trees&.delete(locale)
|
69
70
|
@available_locales = nil
|
70
71
|
end
|
71
72
|
|
@@ -179,14 +180,14 @@ module I18n::Tasks
|
|
179
180
|
data.each do |key, value|
|
180
181
|
if key.nil?
|
181
182
|
data.delete(key)
|
182
|
-
log_warn
|
183
|
-
Skipping a nil key found in #{path.inspect}:
|
184
|
-
|
185
|
-
|
186
|
-
Nil keys are not supported by i18n.
|
187
|
-
The following unquoted YAML keys result in a nil key:
|
188
|
-
|
189
|
-
See http://yaml.org/type/null.html
|
183
|
+
log_warn <<~TEXT
|
184
|
+
Skipping a nil key found in #{path.inspect}:
|
185
|
+
key: #{suffix.join('.')}.`nil`
|
186
|
+
value: #{value.inspect}
|
187
|
+
Nil keys are not supported by i18n.
|
188
|
+
The following unquoted YAML keys result in a nil key:
|
189
|
+
#{%w[null Null NULL ~].join(', ')}
|
190
|
+
See http://yaml.org/type/null.html
|
190
191
|
TEXT
|
191
192
|
elsif value.is_a?(Hash)
|
192
193
|
filter_nil_keys! path, value, suffix + [key]
|
data/lib/i18n/tasks/logging.rb
CHANGED
@@ -23,10 +23,8 @@ module I18n::Tasks::Logging
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def log_stderr(*args)
|
26
|
+
# We don't want output from different threads to get intermixed.
|
26
27
|
MUTEX.synchronize do
|
27
|
-
# 1. We don't want output from different threads to get intermixed.
|
28
|
-
# 2. StringIO is currently not thread-safe (blows up) on JRuby:
|
29
|
-
# https://github.com/jruby/jruby/issues/4417
|
30
28
|
$stderr.puts(*args)
|
31
29
|
end
|
32
30
|
end
|
@@ -32,7 +32,7 @@ module I18n::Tasks::Reports
|
|
32
32
|
def used_title(keys_nodes, filter)
|
33
33
|
used_n = keys_nodes.map { |_k, node| node.data[:occurrences].size }.reduce(:+).to_i
|
34
34
|
"#{keys_nodes.size} key#{'s' if keys_nodes.size != 1}#{" matching '#{filter}'" if filter}"\
|
35
|
-
"#{" (#{used_n} usage#{'s' if used_n != 1})" if used_n
|
35
|
+
"#{" (#{used_n} usage#{'s' if used_n != 1})" if used_n.positive?}"
|
36
36
|
end
|
37
37
|
|
38
38
|
# Sort keys by their attributes in order
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'i18n/tasks/concurrent/cached_value'
|
3
4
|
require 'i18n/tasks/scanners/files/file_finder'
|
5
|
+
|
4
6
|
module I18n::Tasks::Scanners::Files
|
5
7
|
# Finds the files in the specified search paths with support for exclusion / inclusion patterns.
|
6
8
|
# Wraps a {FileFinder} and caches the results.
|
@@ -11,8 +13,7 @@ module I18n::Tasks::Scanners::Files
|
|
11
13
|
# @param (see FileFinder#initialize)
|
12
14
|
def initialize(**args)
|
13
15
|
super
|
14
|
-
@
|
15
|
-
@cached_paths = nil
|
16
|
+
@cached_value = ::I18n::Tasks::Concurrent::CachedValue.new { uncached_find_files }
|
16
17
|
end
|
17
18
|
|
18
19
|
# Traverse the paths and yield the matching ones.
|
@@ -25,10 +26,13 @@ module I18n::Tasks::Scanners::Files
|
|
25
26
|
super
|
26
27
|
end
|
27
28
|
|
29
|
+
alias uncached_find_files find_files
|
30
|
+
private :uncached_find_files
|
31
|
+
|
28
32
|
# @note This method is cached, it will only access the filesystem on the first invocation.
|
29
33
|
# @return (see FileFinder#find_files)
|
30
34
|
def find_files
|
31
|
-
@
|
35
|
+
@cached_value.get
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'i18n/tasks/concurrent/cache'
|
3
4
|
require 'i18n/tasks/scanners/files/caching_file_finder'
|
4
5
|
|
5
6
|
module I18n::Tasks::Scanners::Files
|
@@ -10,8 +11,7 @@ module I18n::Tasks::Scanners::Files
|
|
10
11
|
class CachingFileFinderProvider
|
11
12
|
# @param exclude [Array<String>]
|
12
13
|
def initialize(exclude: [])
|
13
|
-
@cache =
|
14
|
-
@mutex = Mutex.new
|
14
|
+
@cache = ::I18n::Tasks::Concurrent::Cache.new
|
15
15
|
@defaults = { exclude: exclude }
|
16
16
|
end
|
17
17
|
|
@@ -20,13 +20,11 @@ module I18n::Tasks::Scanners::Files
|
|
20
20
|
# @param (see FileFinder#initialize)
|
21
21
|
# @return [CachingFileFinder]
|
22
22
|
def get(**file_finder_args)
|
23
|
-
@cache
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
CachingFileFinder.new(**args)
|
29
|
-
end
|
23
|
+
@cache.fetch(file_finder_args) do
|
24
|
+
args = file_finder_args.dup
|
25
|
+
args[:exclude] = @defaults[:exclude] + (args[:exclude] || [])
|
26
|
+
args[:exclude].uniq!
|
27
|
+
CachingFileFinder.new(**args)
|
30
28
|
end
|
31
29
|
end
|
32
30
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'i18n/tasks/concurrent/cache'
|
3
4
|
require 'i18n/tasks/scanners/files/file_reader'
|
5
|
+
|
4
6
|
module I18n::Tasks::Scanners::Files
|
5
7
|
# Reads the files in 'rb' mode and UTF-8 encoding.
|
6
8
|
# Wraps a {FileReader} and caches the results.
|
@@ -10,8 +12,7 @@ module I18n::Tasks::Scanners::Files
|
|
10
12
|
class CachingFileReader < FileReader
|
11
13
|
def initialize
|
12
14
|
super
|
13
|
-
@
|
14
|
-
@cache = {}
|
15
|
+
@cache = ::I18n::Tasks::Concurrent::Cache.new
|
15
16
|
end
|
16
17
|
|
17
18
|
# Return the contents of the file at the given path.
|
@@ -21,8 +22,7 @@ module I18n::Tasks::Scanners::Files
|
|
21
22
|
# @return (see FileReader#read_file)
|
22
23
|
# @note This method is cached, it will only access the filesystem on the first invocation.
|
23
24
|
def read_file(path)
|
24
|
-
|
25
|
-
@cache[absolute_path] || @mutex.synchronize { @cache[absolute_path] ||= super }
|
25
|
+
@cache.fetch(File.expand_path(path)) { super }
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -41,7 +41,7 @@ module I18n
|
|
41
41
|
def prefix(normalized_path, calling_method: nil)
|
42
42
|
file_key = normalized_path.gsub(%r{(\.[^/]+)*$}, '').tr(File::SEPARATOR, DOT)
|
43
43
|
calling_method = calling_method.call if calling_method.respond_to?(:call)
|
44
|
-
if calling_method
|
44
|
+
if calling_method&.present?
|
45
45
|
# Relative keys in mailers have a `_mailer` infix, but relative keys in controllers do not have one:
|
46
46
|
"#{file_key.sub(/_controller$/, '')}.#{calling_method}"
|
47
47
|
else
|
@@ -48,7 +48,7 @@ module I18n::Tasks::Scanners
|
|
48
48
|
message = send_node.children[1]
|
49
49
|
valid_receivers = @message_receivers[message]
|
50
50
|
# use `any?` because `include?` checks type equality, but the receiver is a Parser::AST::Node != AST::Node.
|
51
|
-
@callback.call(send_node, @method_name) if valid_receivers
|
51
|
+
@callback.call(send_node, @method_name) if valid_receivers&.any? { |r| r == receiver }
|
52
52
|
# always invoke handler_missing to get nested translations in children
|
53
53
|
handler_missing send_node
|
54
54
|
nil
|
@@ -68,7 +68,7 @@ module I18n::Tasks
|
|
68
68
|
# dump recursively
|
69
69
|
value.map { |v| dump_value v }
|
70
70
|
when String
|
71
|
-
replace_interpolations value
|
71
|
+
replace_interpolations value unless value.empty?
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
@@ -82,7 +82,11 @@ module I18n::Tasks
|
|
82
82
|
# implode array
|
83
83
|
untranslated.map { |from| parse_value(from, each_translated) }
|
84
84
|
when String
|
85
|
-
|
85
|
+
if untranslated.empty?
|
86
|
+
untranslated
|
87
|
+
else
|
88
|
+
restore_interpolations untranslated, each_translated.next
|
89
|
+
end
|
86
90
|
else
|
87
91
|
untranslated
|
88
92
|
end
|
@@ -115,11 +119,11 @@ module I18n::Tasks
|
|
115
119
|
end
|
116
120
|
|
117
121
|
def raise_interpolation_error(untranslated, translated, e)
|
118
|
-
fail CommandError.new(e,
|
119
|
-
Error when restoring interpolations:
|
120
|
-
|
121
|
-
|
122
|
-
|
122
|
+
fail CommandError.new(e, <<~TEXT.strip)
|
123
|
+
Error when restoring interpolations:
|
124
|
+
original: "#{untranslated}"
|
125
|
+
response: "#{translated}"
|
126
|
+
error: #{e.message} (#{e.class.name})
|
123
127
|
TEXT
|
124
128
|
end
|
125
129
|
|
data/lib/i18n/tasks/version.rb
CHANGED
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.
|
4
|
+
version: 0.9.25
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- glebm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -294,6 +294,8 @@ files:
|
|
294
294
|
- lib/i18n/tasks/command/options/locales.rb
|
295
295
|
- lib/i18n/tasks/command_error.rb
|
296
296
|
- lib/i18n/tasks/commands.rb
|
297
|
+
- lib/i18n/tasks/concurrent/cache.rb
|
298
|
+
- lib/i18n/tasks/concurrent/cached_value.rb
|
297
299
|
- lib/i18n/tasks/configuration.rb
|
298
300
|
- lib/i18n/tasks/console_context.rb
|
299
301
|
- lib/i18n/tasks/data.rb
|
@@ -368,7 +370,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
368
370
|
requirements:
|
369
371
|
- - "~>"
|
370
372
|
- !ruby/object:Gem::Version
|
371
|
-
version: '2.
|
373
|
+
version: '2.3'
|
372
374
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
373
375
|
requirements:
|
374
376
|
- - ">="
|