i18n-tasks 0.9.7 → 0.9.8
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 +45 -1
- data/config/locales/en.yml +3 -0
- data/config/locales/ru.yml +3 -0
- data/lib/i18n/tasks/command/commands/data.rb +26 -0
- data/lib/i18n/tasks/command/commands/tree.rb +15 -0
- data/lib/i18n/tasks/command/options/data.rb +2 -0
- data/lib/i18n/tasks/data/tree/node.rb +1 -2
- data/lib/i18n/tasks/data/tree/siblings.rb +37 -0
- data/lib/i18n/tasks/data/tree/traversal.rb +27 -14
- data/lib/i18n/tasks/reports/terminal.rb +10 -0
- data/lib/i18n/tasks/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6e30b4e85fe299dbf8f89391c84f5dea2d242b2
|
4
|
+
data.tar.gz: 9f6d31de1c84187fbad5e929c36416857f66f6e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3602fac64546ce66b2b500c3f2e010f01458e1cbd0ff708cbd5e329cca144574a47003ccb8533441e033de579147fbd00c6cb84f90c509720228d2a5e407f53
|
7
|
+
data.tar.gz: b32c4925376a24e28cf1882d1e10168374e1c8770e3e7b43028c9820a11a2b2e59515b2b260fe4fdd03462789b0710528c779c7316155df214e11bfe75d1c8ee
|
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', '~> 0.9.
|
27
|
+
gem 'i18n-tasks', '~> 0.9.8'
|
28
28
|
```
|
29
29
|
|
30
30
|
Copy the default [configuration file](#configuration):
|
@@ -122,6 +122,50 @@ Sort the keys, and move them to the respective files as defined by [`config.writ
|
|
122
122
|
$ i18n-tasks normalize -p
|
123
123
|
```
|
124
124
|
|
125
|
+
### Move / rename / merge keys
|
126
|
+
|
127
|
+
`i18n-tasks mv <pattern> <target>` is a versatile task to move or delete keys matching the given pattern.
|
128
|
+
|
129
|
+
All nodes (leafs or subtrees) matching [`<pattern>`](#key-pattern-syntax) are merged together and moved to `<target>`.
|
130
|
+
|
131
|
+
Rename a node (leaf or subtree):
|
132
|
+
|
133
|
+
``` console
|
134
|
+
$ i18n-tasks mv user account
|
135
|
+
```
|
136
|
+
|
137
|
+
Move a node:
|
138
|
+
|
139
|
+
``` console
|
140
|
+
$ i18n-tasks mv user_alerts user.alerts
|
141
|
+
```
|
142
|
+
|
143
|
+
Move the children one level up:
|
144
|
+
|
145
|
+
``` console
|
146
|
+
$ i18n-tasks mv 'alerts.{:}' '\1'
|
147
|
+
```
|
148
|
+
|
149
|
+
Merge-move multiple nodes:
|
150
|
+
|
151
|
+
``` console
|
152
|
+
$ i18n-tasks mv '{user,profile}' account
|
153
|
+
```
|
154
|
+
|
155
|
+
Merge (non-leaf) nodes into parent:
|
156
|
+
|
157
|
+
``` console
|
158
|
+
$ i18n-tasks mv '{pages}.{a,b}' '\1'
|
159
|
+
```
|
160
|
+
|
161
|
+
### Delete keys
|
162
|
+
|
163
|
+
Delete the keys by using the `rm` task:
|
164
|
+
|
165
|
+
```console
|
166
|
+
$ i18n-tasks rm 'user.{old_profile,old_title}' another_key
|
167
|
+
```
|
168
|
+
|
125
169
|
### Compose tasks
|
126
170
|
|
127
171
|
`i18n-tasks` also provides composable tasks for reading, writing and manipulating locale data. Examples below.
|
data/config/locales/en.yml
CHANGED
@@ -40,12 +40,15 @@ en:
|
|
40
40
|
health: is everything OK?
|
41
41
|
irb: start REPL session within i18n-tasks context
|
42
42
|
missing: show missing translations
|
43
|
+
mv: rename/merge the keys in locale data that match the given pattern
|
43
44
|
normalize: 'normalize translation data: sort and move to the right files'
|
44
45
|
remove_unused: remove unused keys
|
46
|
+
rm: remove the keys in locale data that match the given pattern
|
45
47
|
translate_missing: translate missing keys with Google Translate
|
46
48
|
tree_convert: convert tree between formats
|
47
49
|
tree_filter: filter tree by key pattern
|
48
50
|
tree_merge: merge trees
|
51
|
+
tree_mv_key: rename/merge/remove the keys matching the given pattern
|
49
52
|
tree_rename_key: rename tree node
|
50
53
|
tree_set_value: set values of keys, optionally match a pattern
|
51
54
|
tree_subtract: tree A minus the keys in tree B
|
data/config/locales/ru.yml
CHANGED
@@ -38,12 +38,15 @@ ru:
|
|
38
38
|
health: Всё ОК?
|
39
39
|
irb: начать REPL сессию в контексте i18n-tasks
|
40
40
|
missing: показать недостающие переводы
|
41
|
+
mv: переименовать / объединить ключи, которые соответствуют заданному шаблону
|
41
42
|
normalize: нормализовать файлы переводов (сортировка и распределение)
|
42
43
|
remove_unused: удалить неиспользуемые ключи
|
44
|
+
rm: удалить ключи, которые соответствуют заданному шаблону
|
43
45
|
translate_missing: перевести недостающие переводы с Google Translate
|
44
46
|
tree_convert: преобразовать дерево между форматами
|
45
47
|
tree_filter: фильтровать дерево по ключу
|
46
48
|
tree_merge: объединенить деревья
|
49
|
+
tree_mv_key: переименованить / объединить / удалить ключи соответствующие заданному шаблону
|
47
50
|
tree_rename_key: переименовать узел дерева
|
48
51
|
tree_set_value: заменить значения ключей
|
49
52
|
tree_subtract: дерево A минус ключи в дереве B
|
@@ -19,6 +19,32 @@ module I18n::Tasks
|
|
19
19
|
i18n.normalize_store! opt[:locales], opt[:pattern_router]
|
20
20
|
end
|
21
21
|
|
22
|
+
cmd :mv,
|
23
|
+
pos: 'FROM_KEY_PATTERN TO_KEY_PATTERN',
|
24
|
+
desc: t('i18n_tasks.cmd.desc.mv')
|
25
|
+
def mv(opt = {})
|
26
|
+
fail CommandError, 'requires FROM_KEY_PATTERN and TO_KEY_PATTERN' if opt[:arguments].size < 2
|
27
|
+
from_pattern = opt[:arguments].shift
|
28
|
+
to_pattern = opt[:arguments].shift
|
29
|
+
forest = i18n.data_forest
|
30
|
+
results = forest.mv_key!(compile_key_pattern(from_pattern), to_pattern, root: false)
|
31
|
+
i18n.data.write forest
|
32
|
+
terminal_report.mv_results results
|
33
|
+
end
|
34
|
+
|
35
|
+
cmd :rm,
|
36
|
+
pos: 'KEY_PATTERN [KEY_PATTERN...]',
|
37
|
+
desc: t('i18n_tasks.cmd.desc.rm')
|
38
|
+
def rm(opt = {})
|
39
|
+
fail CommandError, 'requires KEY_PATTERN' if opt[:arguments].empty?
|
40
|
+
forest = i18n.data_forest
|
41
|
+
results = opt[:arguments].each_with_object({}) do |key_pattern, h|
|
42
|
+
h.merge! forest.mv_key!(compile_key_pattern(key_pattern), '', root: false)
|
43
|
+
end
|
44
|
+
i18n.data.write forest
|
45
|
+
terminal_report.mv_results results
|
46
|
+
end
|
47
|
+
|
22
48
|
cmd :data,
|
23
49
|
pos: '[locale ...]',
|
24
50
|
desc: t('i18n_tasks.cmd.desc.data'),
|
@@ -4,6 +4,7 @@ module I18n::Tasks
|
|
4
4
|
module Commands
|
5
5
|
module Tree
|
6
6
|
include Command::Collection
|
7
|
+
include I18n::Tasks::KeyPatternMatching
|
7
8
|
|
8
9
|
cmd :tree_translate,
|
9
10
|
pos: '[tree (or stdin)]',
|
@@ -47,6 +48,7 @@ module I18n::Tasks
|
|
47
48
|
:data_format]
|
48
49
|
|
49
50
|
def tree_rename_key(opt = {})
|
51
|
+
warn_deprecated 'Use tree-mv instead.'
|
50
52
|
key = arg_or_pos! :key, opt
|
51
53
|
name = arg_or_pos! :name, opt
|
52
54
|
forest = forest_pos_or_stdin! opt
|
@@ -56,6 +58,19 @@ module I18n::Tasks
|
|
56
58
|
print_forest forest, opt
|
57
59
|
end
|
58
60
|
|
61
|
+
cmd :tree_mv,
|
62
|
+
pos: 'FROM_KEY_PATTERN TO_KEY_PATTERN [tree (or stdin)]',
|
63
|
+
desc: t('i18n_tasks.cmd.desc.tree_mv_key'),
|
64
|
+
args: [:data_format]
|
65
|
+
def tree_mv(opt = {})
|
66
|
+
fail CommandError, 'requires FROM_KEY_PATTERN and TO_KEY_PATTERN' if opt[:arguments].size < 2
|
67
|
+
from_pattern = opt[:arguments].shift
|
68
|
+
to_pattern = opt[:arguments].shift
|
69
|
+
forest = forest_pos_or_stdin!(opt)
|
70
|
+
forest.mv_key!(compile_key_pattern(from_pattern), to_pattern, root: false)
|
71
|
+
print_forest forest, opt
|
72
|
+
end
|
73
|
+
|
59
74
|
cmd :tree_subtract,
|
60
75
|
pos: '[[tree] [tree] ... (or stdin)]',
|
61
76
|
desc: t('i18n_tasks.cmd.desc.tree_subtract'),
|
@@ -31,6 +31,7 @@ module I18n::Tasks
|
|
31
31
|
# i18n-tasks-use t('i18n_tasks.cmd.args.desc.out_format')
|
32
32
|
format_arg.call(:out_format, OUT_FORMATS)
|
33
33
|
|
34
|
+
# @return [I18n::Tasks::Data::Tree::Siblings]
|
34
35
|
def forest_pos_or_stdin!(opt, format = opt[:format])
|
35
36
|
parse_forest(pos_or_stdin!(opt), format)
|
36
37
|
end
|
@@ -59,6 +60,7 @@ module I18n::Tasks
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
63
|
+
# @return [I18n::Tasks::Data::Tree::Siblings]
|
62
64
|
def parse_forest(src, format)
|
63
65
|
unless src
|
64
66
|
fail CommandError, I18n.t('i18n_tasks.cmd.errors.pass_forest')
|
@@ -98,8 +98,7 @@ module I18n::Tasks::Data::Tree
|
|
98
98
|
derive.append!(nodes)
|
99
99
|
end
|
100
100
|
|
101
|
-
def full_key(
|
102
|
-
root = opts.key?(:root) ? opts[:root] : true
|
101
|
+
def full_key(root: true)
|
103
102
|
@full_key ||= {}
|
104
103
|
@full_key[root] ||= "#{"#{parent.full_key(root: root)}." if parent? && (root || parent.parent?)}#{key}"
|
105
104
|
end
|
@@ -44,6 +44,43 @@ module I18n::Tasks::Data::Tree
|
|
44
44
|
self
|
45
45
|
end
|
46
46
|
|
47
|
+
# @param from_pattern [Regexp]
|
48
|
+
# @param to_pattern [Regexp]
|
49
|
+
# @param root [Boolean]
|
50
|
+
# @return {old key => new key}
|
51
|
+
def mv_key!(from_pattern, to_pattern, root: false) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
52
|
+
moved_forest = Siblings.new
|
53
|
+
moved_nodes = []
|
54
|
+
old_key_to_new_key = {}
|
55
|
+
nodes do |node|
|
56
|
+
full_key = node.full_key(root: root)
|
57
|
+
if from_pattern =~ full_key
|
58
|
+
moved_nodes << node
|
59
|
+
if to_pattern.empty?
|
60
|
+
old_key_to_new_key[full_key] = nil
|
61
|
+
next
|
62
|
+
end
|
63
|
+
match = $~
|
64
|
+
new_key = to_pattern.gsub(/\\\d+/) { |m| match[m[1..-1].to_i] }
|
65
|
+
old_key_to_new_key[full_key] = new_key
|
66
|
+
moved_forest.merge!(Siblings.new.tap do |forest|
|
67
|
+
forest[[(node.root.try(:key) unless root), new_key].compact.join('.')] =
|
68
|
+
node.derive(key: split_key(new_key).last)
|
69
|
+
end)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# Adjust references
|
73
|
+
# TODO: support nested references better
|
74
|
+
nodes do |node|
|
75
|
+
next unless node.reference?
|
76
|
+
new_target = old_key_to_new_key[node.value.to_s]
|
77
|
+
node.value = new_target.to_sym if new_target
|
78
|
+
end
|
79
|
+
remove_nodes_and_emptied_ancestors! moved_nodes
|
80
|
+
merge! moved_forest
|
81
|
+
old_key_to_new_key
|
82
|
+
end
|
83
|
+
|
47
84
|
def replace_node!(node, new_node)
|
48
85
|
@list[@list.index(node)] = new_node
|
49
86
|
key_to_node[new_node.key] = new_node
|
@@ -1,4 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'set'
|
3
|
+
|
2
4
|
module I18n::Tasks
|
3
5
|
module Data::Tree
|
4
6
|
# Any Enumerable that yields nodes can mix in this module
|
@@ -51,10 +53,9 @@ module I18n::Tasks
|
|
51
53
|
end
|
52
54
|
|
53
55
|
# @option root include root in full key
|
54
|
-
def keys(
|
55
|
-
|
56
|
-
|
57
|
-
leaves { |node| visitor.yield(node.full_key(key_opts), node) }
|
56
|
+
def keys(root: false, &visitor)
|
57
|
+
return to_enum(:keys, root: root) unless visitor
|
58
|
+
leaves { |node| visitor.yield(node.full_key(root: root), node) }
|
58
59
|
self
|
59
60
|
end
|
60
61
|
|
@@ -112,24 +113,36 @@ module I18n::Tasks
|
|
112
113
|
self
|
113
114
|
end
|
114
115
|
|
115
|
-
# @return Siblings
|
116
|
-
def select_keys(
|
117
|
-
|
118
|
-
|
116
|
+
# @return [Siblings]
|
117
|
+
def select_keys(root: false, &block)
|
118
|
+
matches = get_nodes_by_key_filter(root: root, &block)
|
119
|
+
select_nodes do |node|
|
120
|
+
matches.include?(node)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# @return [Siblings]
|
125
|
+
def select_keys!(root: false, &block)
|
126
|
+
matches = get_nodes_by_key_filter(root: root, &block)
|
127
|
+
select_nodes! do |node|
|
128
|
+
matches.include?(node)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [Set<I18n::Tasks::Data::Tree::Node>]
|
133
|
+
def get_nodes_by_key_filter(root: false, &block)
|
134
|
+
matches = Set.new
|
119
135
|
keys(root: root) do |full_key, node|
|
120
136
|
if block.yield(full_key, node)
|
121
137
|
node.walk_to_root do |p|
|
122
|
-
break
|
123
|
-
ok[p] = true
|
138
|
+
break unless matches.add?(p)
|
124
139
|
end
|
125
140
|
end
|
126
141
|
end
|
127
|
-
|
128
|
-
ok[node]
|
129
|
-
end
|
142
|
+
matches
|
130
143
|
end
|
131
144
|
|
132
|
-
# @return Siblings
|
145
|
+
# @return [Siblings]
|
133
146
|
def intersect_keys(other_tree, key_opts = {}, &block)
|
134
147
|
if block
|
135
148
|
select_keys(key_opts) do |key, node|
|
@@ -80,6 +80,16 @@ module I18n
|
|
80
80
|
print_info "#{cyan title} #{cyan text}"
|
81
81
|
end
|
82
82
|
|
83
|
+
def mv_results(results)
|
84
|
+
results.each do |(from, to)|
|
85
|
+
if to
|
86
|
+
print_info "#{cyan from} #{bold(yellow('⮕'))} #{cyan to}"
|
87
|
+
else
|
88
|
+
print_info "#{red from}#{bold(red(' 🗑'))}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
83
93
|
private
|
84
94
|
|
85
95
|
def missing_key_info(leaf)
|
data/lib/i18n/tasks/version.rb
CHANGED