i18n-tasks 1.0.11 → 1.0.12
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|