i18n-tasks 1.0.11 → 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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/locales/en.yml +4 -3
- data/i18n-tasks.gemspec +1 -1
- data/lib/i18n/tasks/command/commands/missing.rb +15 -3
- data/lib/i18n/tasks/data/tree/traversal.rb +23 -9
- data/lib/i18n/tasks/locale_pathname.rb +1 -1
- data/lib/i18n/tasks/plural_keys.rb +0 -6
- data/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb +16 -0
- data/lib/i18n/tasks/scanners/ast_matchers/message_receivers_matcher.rb +7 -2
- data/lib/i18n/tasks/version.rb +1 -1
- metadata +13 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e77c4c19ca040adf1879259e8ad1d963e181eb1682e97ffa99f5b09d1b59e803
|
4
|
+
data.tar.gz: cc5ed0a16159c8f14a9006ab3908cfdc93b5dbc338603d54846d0ae4f84abb80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 978d87d9e73dc5f4e183a7fdebabeec9864c3b1ba530f722bc3a80428b1c422eeda55f2bbd2b7ec8c1a67649ee128db4ae9ab0fc24db4b8cf386f7740b0f34d4
|
7
|
+
data.tar.gz: 46a0b0cbb262c17aaf1195293edd1fc04d665dd85d5f8d1b399f1ae565db2eb99e3e281fb1a34a5cb3629aadee2c2b279642d8beca623814fcd9b75c0c502b5e
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ i18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (def
|
|
24
24
|
Add i18n-tasks to the Gemfile:
|
25
25
|
|
26
26
|
```ruby
|
27
|
-
gem 'i18n-tasks', '~> 1.0.
|
27
|
+
gem 'i18n-tasks', '~> 1.0.12'
|
28
28
|
```
|
29
29
|
|
30
30
|
Copy the default [configuration file](#configuration):
|
data/config/locales/en.yml
CHANGED
@@ -33,7 +33,7 @@ en:
|
|
33
33
|
Value. Interpolates: %{value}, %{human_key}, %{key}, %{default}, %{value_or_human_key},
|
34
34
|
%{value_or_default_or_human_key}
|
35
35
|
desc:
|
36
|
-
add_missing: add missing keys to locale data
|
36
|
+
add_missing: add missing keys to locale data, optionally match a pattern
|
37
37
|
check_consistent_interpolations: verify that all translations use correct interpolation variables
|
38
38
|
check_normalized: verify that all translation data is normalized
|
39
39
|
config: display i18n-tasks configuration
|
@@ -46,12 +46,13 @@ en:
|
|
46
46
|
gem_path: show path to the gem
|
47
47
|
health: is everything OK?
|
48
48
|
irb: start REPL session within i18n-tasks context
|
49
|
-
missing: show missing translations
|
49
|
+
missing: show missing translations, optionally match a pattern
|
50
50
|
mv: rename/merge the keys in locale data that match the given pattern
|
51
51
|
normalize: 'normalize translation data: sort and move to the right files'
|
52
52
|
remove_unused: remove unused keys
|
53
53
|
rm: remove the keys in locale data that match the given pattern
|
54
|
-
translate_missing: translate missing keys with Google Translate or DeepL Pro
|
54
|
+
translate_missing: translate missing keys with Google Translate or DeepL Pro, optionally match
|
55
|
+
a pattern
|
55
56
|
tree_convert: convert tree between formats
|
56
57
|
tree_filter: filter tree by key pattern
|
57
58
|
tree_merge: merge trees
|
data/i18n-tasks.gemspec
CHANGED
@@ -40,7 +40,7 @@ Gem::Specification.new do |s| # rubocop:disable Metrics/BlockLength
|
|
40
40
|
|
41
41
|
s.add_dependency 'activesupport', '>= 4.0.2'
|
42
42
|
s.add_dependency 'ast', '>= 2.1.0'
|
43
|
-
s.add_dependency 'better_html', '
|
43
|
+
s.add_dependency 'better_html', '>= 1.0', '< 3.0'
|
44
44
|
s.add_dependency 'erubi'
|
45
45
|
s.add_dependency 'highline', '>= 2.0.0'
|
46
46
|
s.add_dependency 'i18n'
|
@@ -25,10 +25,14 @@ module I18n::Tasks
|
|
25
25
|
cmd :missing,
|
26
26
|
pos: '[locale ...]',
|
27
27
|
desc: t('i18n_tasks.cmd.desc.missing'),
|
28
|
-
args: %i[locales out_format missing_types]
|
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))
|
32
|
+
if opt[:pattern]
|
33
|
+
pattern_re = i18n.compile_key_pattern(opt[:pattern])
|
34
|
+
forest.select_keys! { |full_key, _node| full_key =~ pattern_re }
|
35
|
+
end
|
32
36
|
print_forest forest, opt, :missing_keys
|
33
37
|
:exit1 unless forest.empty?
|
34
38
|
end
|
@@ -36,10 +40,14 @@ module I18n::Tasks
|
|
36
40
|
cmd :translate_missing,
|
37
41
|
pos: '[locale ...]',
|
38
42
|
desc: t('i18n_tasks.cmd.desc.translate_missing'),
|
39
|
-
args: [:locales, :locale_to_translate_from, arg(:out_format).from(1), :translation_backend]
|
43
|
+
args: [:locales, :locale_to_translate_from, arg(:out_format).from(1), :translation_backend, :pattern]
|
40
44
|
|
41
45
|
def translate_missing(opt = {})
|
42
46
|
missing = i18n.missing_diff_forest opt[:locales], opt[:from]
|
47
|
+
if opt[:pattern]
|
48
|
+
pattern_re = i18n.compile_key_pattern(opt[:pattern])
|
49
|
+
missing.select_keys! { |full_key, _node| full_key =~ pattern_re }
|
50
|
+
end
|
43
51
|
translated = i18n.translate_forest missing, from: opt[:from], backend: opt[:backend].to_sym
|
44
52
|
i18n.data.merge! translated
|
45
53
|
log_stderr t('i18n_tasks.translate_missing.translated', count: translated.leaves.count)
|
@@ -49,7 +57,7 @@ module I18n::Tasks
|
|
49
57
|
cmd :add_missing,
|
50
58
|
pos: '[locale ...]',
|
51
59
|
desc: t('i18n_tasks.cmd.desc.add_missing'),
|
52
|
-
args: [:locales, :out_format, arg(:value) + [{ default: '%{value_or_default_or_human_key}' }],
|
60
|
+
args: [:locales, :out_format, :pattern, arg(:value) + [{ default: '%{value_or_default_or_human_key}' }],
|
53
61
|
['--nil-value', 'Set value to nil. Takes precedence over the value argument.']]
|
54
62
|
|
55
63
|
# Merge base locale first, as this may affect the value for the other locales
|
@@ -60,6 +68,10 @@ module I18n::Tasks
|
|
60
68
|
].reject(&:empty?).each_with_object(i18n.empty_forest) do |locales, added|
|
61
69
|
forest = i18n.missing_keys(locales: locales, **opt.slice(:types, :base_locale))
|
62
70
|
.set_each_value!(opt[:'nil-value'] ? nil : opt[:value])
|
71
|
+
if opt[:pattern]
|
72
|
+
pattern_re = i18n.compile_key_pattern(opt[:pattern])
|
73
|
+
forest.select_keys! { |full_key, _node| full_key =~ pattern_re }
|
74
|
+
end
|
63
75
|
i18n.data.merge! forest
|
64
76
|
added.merge! forest
|
65
77
|
end.tap do |added|
|
@@ -174,15 +174,29 @@ module I18n::Tasks
|
|
174
174
|
human_key = ActiveSupport::Inflector.humanize(node.key.to_s)
|
175
175
|
full_key = node.full_key
|
176
176
|
default = (node.data[:occurrences] || []).detect { |o| o.default_arg.presence }.try(:default_arg)
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
177
|
+
if default.is_a?(Hash)
|
178
|
+
default.each_with_object({}) do |(k, v), h|
|
179
|
+
h[k] = StringInterpolation.interpolate_soft(
|
180
|
+
val_pattern,
|
181
|
+
value: node_value,
|
182
|
+
human_key: human_key,
|
183
|
+
key: full_key,
|
184
|
+
default: v,
|
185
|
+
value_or_human_key: node_value.presence || human_key,
|
186
|
+
value_or_default_or_human_key: node_value.presence || v || human_key
|
187
|
+
)
|
188
|
+
end
|
189
|
+
else
|
190
|
+
StringInterpolation.interpolate_soft(
|
191
|
+
val_pattern,
|
192
|
+
value: node_value,
|
193
|
+
human_key: human_key,
|
194
|
+
key: full_key,
|
195
|
+
default: default,
|
196
|
+
value_or_human_key: node_value.presence || human_key,
|
197
|
+
value_or_default_or_human_key: node_value.presence || default || human_key
|
198
|
+
)
|
199
|
+
end
|
186
200
|
end
|
187
201
|
pattern_re = I18n::Tasks::KeyPatternMatching.compile_key_pattern(key_pattern) if key_pattern.present?
|
188
202
|
keys.each do |key, node|
|
@@ -52,15 +52,9 @@ module I18n::Tasks::PluralKeys
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def plural_forms?(s)
|
55
|
-
return false if non_plural_other?(s)
|
56
|
-
|
57
55
|
s.present? && s.all? { |node| node.leaf? && plural_suffix?(node.key) }
|
58
56
|
end
|
59
57
|
|
60
|
-
def non_plural_other?(s)
|
61
|
-
s.size == 1 && s.first.leaf? && (!s.first.value.is_a?(String) || !s.first.value.include?('%{count}'))
|
62
|
-
end
|
63
|
-
|
64
58
|
def plural_suffix?(key)
|
65
59
|
PLURAL_KEY_SUFFIXES.include?(key)
|
66
60
|
end
|
@@ -54,6 +54,22 @@ module I18n::Tasks::Scanners::AstMatchers
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
# Extract the whole hash from a node of type `:hash`
|
58
|
+
#
|
59
|
+
# @param node [AST::Node] a node of type `:hash`.
|
60
|
+
# @return [Hash] the whole hash from the node
|
61
|
+
def extract_hash(node)
|
62
|
+
return {} if node.nil?
|
63
|
+
|
64
|
+
if node.type == :hash
|
65
|
+
node.children.each_with_object({}) do |pair, h|
|
66
|
+
key = pair.children[0].children[0].to_s
|
67
|
+
value = pair.children[1].children[0]
|
68
|
+
h[key] = value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
57
73
|
# Extract a hash pair with a given literal key.
|
58
74
|
#
|
59
75
|
# @param node [AST::Node] a node of type `:hash`.
|
@@ -77,8 +77,13 @@ module I18n::Tasks::Scanners::AstMatchers
|
|
77
77
|
|
78
78
|
key = [scope, key].join('.') unless scope == ''
|
79
79
|
end
|
80
|
-
default_arg_node = extract_hash_pair(node, 'default')
|
81
|
-
|
80
|
+
if default_arg_node = extract_hash_pair(node, 'default')
|
81
|
+
default_arg = if default_arg_node.children[1]&.type == :hash
|
82
|
+
extract_hash(default_arg_node.children[1])
|
83
|
+
else
|
84
|
+
extract_string(default_arg_node.children[1])
|
85
|
+
end
|
86
|
+
end
|
82
87
|
|
83
88
|
[key, default_arg]
|
84
89
|
end
|
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: 1.0.
|
4
|
+
version: 1.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- glebm
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -42,16 +42,22 @@ dependencies:
|
|
42
42
|
name: better_html
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.0'
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '3.0'
|
48
51
|
type: :runtime
|
49
52
|
prerelease: false
|
50
53
|
version_requirements: !ruby/object:Gem::Requirement
|
51
54
|
requirements:
|
52
|
-
- - "
|
55
|
+
- - ">="
|
53
56
|
- !ruby/object:Gem::Version
|
54
57
|
version: '1.0'
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.0'
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
62
|
name: erubi
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -439,8 +445,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
439
445
|
- !ruby/object:Gem::Version
|
440
446
|
version: '0'
|
441
447
|
requirements: []
|
442
|
-
rubygems_version: 3.2
|
443
|
-
signing_key:
|
448
|
+
rubygems_version: 3.1.2
|
449
|
+
signing_key:
|
444
450
|
specification_version: 4
|
445
451
|
summary: Manage localization and translation with the awesome power of static analysis
|
446
452
|
test_files: []
|