i18n-tasks 1.1.2 → 1.2.0
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 +321 -242
- data/Rakefile +5 -1
- data/benchmarks/bench_helper.rb +156 -0
- data/benchmarks/data_bench.rb +173 -0
- data/benchmarks/end_to_end_bench.rb +138 -0
- data/benchmarks/fixtures/generator.rb +257 -0
- data/benchmarks/results/baseline.json +250 -0
- data/benchmarks/run_all.rb +60 -0
- data/benchmarks/scanning_bench.rb +135 -0
- data/benchmarks/tree_bench.rb +205 -0
- data/config/locales/en.yml +10 -0
- data/config/locales/ru.yml +14 -0
- data/i18n-tasks.gemspec +1 -1
- data/lib/i18n/tasks/base_task.rb +2 -0
- data/lib/i18n/tasks/command/commands/check_prism.rb +67 -15
- data/lib/i18n/tasks/command/commands/prune.rb +57 -0
- data/lib/i18n/tasks/commands.rb +2 -0
- data/lib/i18n/tasks/data/adapter/json_adapter.rb +1 -1
- data/lib/i18n/tasks/data/file_formats.rb +4 -1
- data/lib/i18n/tasks/data/router/conservative_router.rb +13 -22
- data/lib/i18n/tasks/data/router/pattern_router.rb +26 -14
- data/lib/i18n/tasks/data/tree/node.rb +3 -3
- data/lib/i18n/tasks/data/tree/siblings.rb +11 -3
- data/lib/i18n/tasks/data/tree/traversal.rb +20 -14
- data/lib/i18n/tasks/interpolations.rb +61 -3
- data/lib/i18n/tasks/logging.rb +1 -2
- data/lib/i18n/tasks/missing_keys.rb +7 -38
- data/lib/i18n/tasks/plural_keys.rb +56 -0
- data/lib/i18n/tasks/prune.rb +18 -0
- data/lib/i18n/tasks/references.rb +9 -1
- data/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb +11 -2
- data/lib/i18n/tasks/scanners/ast_matchers/rails_model_matcher.rb +16 -2
- data/lib/i18n/tasks/scanners/erb_ast_scanner.rb +6 -3
- data/lib/i18n/tasks/scanners/file_scanner.rb +4 -1
- data/lib/i18n/tasks/scanners/files/file_finder.rb +29 -6
- data/lib/i18n/tasks/scanners/files/parse_cache.rb +24 -0
- data/lib/i18n/tasks/scanners/prism_scanners/arguments_visitor.rb +33 -0
- data/lib/i18n/tasks/scanners/prism_scanners/nodes.rb +57 -23
- data/lib/i18n/tasks/scanners/prism_scanners/visitor.rb +70 -16
- data/lib/i18n/tasks/scanners/relative_keys.rb +21 -11
- data/lib/i18n/tasks/scanners/ruby_scanner.rb +37 -5
- data/lib/i18n/tasks/split_key.rb +16 -6
- data/lib/i18n/tasks/translators/base_translator.rb +25 -23
- data/lib/i18n/tasks/translators/deepl_translator.rb +18 -15
- data/lib/i18n/tasks/translators/google_translator.rb +41 -14
- data/lib/i18n/tasks/translators/openai_translator.rb +31 -17
- data/lib/i18n/tasks/translators/watsonx_translator.rb +8 -10
- data/lib/i18n/tasks/translators/yandex_translator.rb +4 -0
- data/lib/i18n/tasks/unused_keys.rb +35 -5
- data/lib/i18n/tasks/used_keys.rb +6 -1
- data/lib/i18n/tasks/version.rb +1 -1
- data/script/report_test_results.rb +58 -0
- data/templates/config/i18n-tasks.yml +11 -3
- metadata +17 -7
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# i18n-tasks [![Build Status][badge-ci]][ci] [![
|
|
1
|
+
# i18n-tasks [![Build Status][badge-ci]][ci] [](https://gitter.im/glebm/i18n-tasks?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
2
2
|
|
|
3
3
|
[](https://stand-with-ukraine.pp.ua/)
|
|
4
4
|
|
|
@@ -8,75 +8,140 @@ i18n-tasks helps you find and manage missing and unused translations.
|
|
|
8
8
|
|
|
9
9
|
This gem analyses code statically for key usages, such as `I18n.t('some.key')`, in order to:
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
- Report keys that are missing or unused.
|
|
12
|
+
- Pre-fill missing keys, optionally from Google Translate or DeepL (Pro or Free).
|
|
13
|
+
- Remove unused keys.
|
|
14
14
|
|
|
15
15
|
Thus addressing the two main problems of [i18n gem][i18n-gem] design:
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
##
|
|
17
|
+
- Missing keys only blow up at runtime.
|
|
18
|
+
- Keys no longer in use may accumulate and introduce overhead, without you knowing it.
|
|
19
|
+
|
|
20
|
+
## Table of Contents
|
|
21
|
+
|
|
22
|
+
- [Quick Start](#quick-start)
|
|
23
|
+
- [Commands](#commands)
|
|
24
|
+
- [Check health](#check-health)
|
|
25
|
+
- [Find usages](#find-usages)
|
|
26
|
+
- [Add missing keys](#add-missing-keys)
|
|
27
|
+
- [Translate missing keys](#translate-missing-keys)
|
|
28
|
+
- [Remove unused keys](#remove-unused-keys)
|
|
29
|
+
- [Prune](#prune)
|
|
30
|
+
- [Normalize](#normalize)
|
|
31
|
+
- [Move / rename / merge keys](#move--rename--merge-keys)
|
|
32
|
+
- [Delete keys](#delete-keys)
|
|
33
|
+
- [Compose tasks](#compose-tasks)
|
|
34
|
+
- [Configuration](#configuration)
|
|
35
|
+
- [Locales](#locales)
|
|
36
|
+
- [Storage & locale files](#storage--locale-files)
|
|
37
|
+
- [Pattern router](#pattern-router)
|
|
38
|
+
- [Conservative router](#conservative-router)
|
|
39
|
+
- [Isolating router](#isolating-router)
|
|
40
|
+
- [Key pattern syntax](#key-pattern-syntax)
|
|
41
|
+
- [Custom adapters](#custom-adapters)
|
|
42
|
+
- [Rails credentials](#rails-credentials)
|
|
43
|
+
- [Usage search](#usage-search)
|
|
44
|
+
- [Prism-based scanner](#prism-based-scanner)
|
|
45
|
+
- [Fine-tuning](#fine-tuning)
|
|
46
|
+
- [Environment variables & dotenv](#environment-variables--dotenv)
|
|
47
|
+
- [Translation backends](#translation-backends)
|
|
48
|
+
- [Google Translate](#google-translate)
|
|
49
|
+
- [DeepL](#deepl)
|
|
50
|
+
- [Yandex](#yandex)
|
|
51
|
+
- [OpenAI](#openai)
|
|
52
|
+
- [watsonx](#watsonx)
|
|
53
|
+
- [Features & limitations](#features--limitations)
|
|
54
|
+
- [Relative keys](#relative-keys)
|
|
55
|
+
- [Plural keys](#plural-keys)
|
|
56
|
+
- [Reference keys](#reference-keys)
|
|
57
|
+
- [Dynamic keys](#dynamic-keys)
|
|
58
|
+
- [I18n.localize](#i18nlocalize)
|
|
59
|
+
- [`t()` keyword arguments](#t-keyword-arguments)
|
|
60
|
+
- [Unexpected normalization](#unexpected-normalization)
|
|
61
|
+
- [Advanced](#advanced)
|
|
62
|
+
- [Interactive console](#interactive-console)
|
|
63
|
+
- [CSV import / export](#csv-import--export)
|
|
64
|
+
- [Add custom tasks](#add-custom-tasks)
|
|
65
|
+
- [Development](#development)
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
21
68
|
|
|
22
69
|
i18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (default in Rails).
|
|
23
70
|
|
|
24
|
-
Add
|
|
71
|
+
1. Add to your `Gemfile`:
|
|
25
72
|
|
|
26
|
-
```ruby
|
|
27
|
-
gem 'i18n-tasks', '~> 1.
|
|
28
|
-
```
|
|
73
|
+
```ruby
|
|
74
|
+
gem 'i18n-tasks', '~> 1.2.0', group: :development
|
|
75
|
+
```
|
|
29
76
|
|
|
30
|
-
Copy the default [configuration file](#configuration):
|
|
77
|
+
2. Copy the default [configuration file](#configuration):
|
|
31
78
|
|
|
32
|
-
```
|
|
33
|
-
$ cp $(i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/
|
|
34
|
-
```
|
|
79
|
+
```sh
|
|
80
|
+
$ cp $(bundle exec i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/
|
|
81
|
+
```
|
|
35
82
|
|
|
36
|
-
|
|
83
|
+
3. Run your first health check:
|
|
37
84
|
|
|
38
|
-
```
|
|
39
|
-
$
|
|
40
|
-
```
|
|
85
|
+
```sh
|
|
86
|
+
$ bundle exec i18n-tasks health
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
That's it. See [Commands](#commands) for the full list of tasks, or [Configuration](#configuration) to tailor the setup to your project.
|
|
41
90
|
|
|
42
|
-
|
|
91
|
+
**Optional:** copy a test that checks for missing/unused translations on every CI run:
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
# RSpec
|
|
95
|
+
$ cp $(bundle exec i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/
|
|
43
96
|
|
|
44
|
-
|
|
45
|
-
$ cp $(i18n-tasks gem-path)/templates/minitest/i18n_test.rb test/
|
|
97
|
+
# Minitest
|
|
98
|
+
$ cp $(bundle exec i18n-tasks gem-path)/templates/minitest/i18n_test.rb test/
|
|
46
99
|
```
|
|
47
100
|
|
|
48
|
-
##
|
|
101
|
+
## Commands
|
|
49
102
|
|
|
50
103
|
Run `bundle exec i18n-tasks` to get the list of all the tasks with short descriptions.
|
|
51
104
|
|
|
52
105
|
### Check health
|
|
53
106
|
|
|
54
|
-
`i18n-tasks health` checks if any keys are missing or not used,
|
|
55
|
-
that
|
|
107
|
+
`bundle exec i18n-tasks health` checks if any keys are missing or not used,
|
|
108
|
+
that interpolation variables are consistent across locales,
|
|
56
109
|
and that all the locale files are normalized (auto-formatted):
|
|
57
110
|
|
|
58
|
-
```
|
|
59
|
-
$ i18n-tasks health
|
|
111
|
+
```sh
|
|
112
|
+
$ bundle exec i18n-tasks health
|
|
60
113
|
```
|
|
61
114
|
|
|
115
|
+
### Find usages
|
|
116
|
+
|
|
117
|
+
See where the keys are used with `bundle exec i18n-tasks find`:
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
$ bundle exec i18n-tasks find common.help
|
|
121
|
+
$ bundle exec i18n-tasks find 'auth.*'
|
|
122
|
+
$ bundle exec i18n-tasks find '{number,currency}.format.*'
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
<img width="437" height="129" src="https://i.imgur.com/VxBrSfY.png">
|
|
126
|
+
|
|
62
127
|
### Add missing keys
|
|
63
128
|
|
|
64
129
|
Add missing keys with placeholders (base value or humanized key):
|
|
65
130
|
|
|
66
|
-
```
|
|
67
|
-
$ i18n-tasks add-missing
|
|
131
|
+
```sh
|
|
132
|
+
$ bundle exec i18n-tasks add-missing
|
|
68
133
|
```
|
|
69
134
|
|
|
70
135
|
This and other tasks accept arguments:
|
|
71
136
|
|
|
72
|
-
```
|
|
73
|
-
$ i18n-tasks add-missing -v 'TRME %{value}' fr
|
|
137
|
+
```sh
|
|
138
|
+
$ bundle exec i18n-tasks add-missing -v 'TRME %{value}' fr
|
|
74
139
|
```
|
|
75
140
|
|
|
76
141
|
Pass `--help` for more information:
|
|
77
142
|
|
|
78
|
-
```
|
|
79
|
-
$ i18n-tasks add-missing --help
|
|
143
|
+
```sh
|
|
144
|
+
$ bundle exec i18n-tasks add-missing --help
|
|
80
145
|
Usage: i18n-tasks add-missing [options] [locale ...]
|
|
81
146
|
-l, --locales Comma-separated list of locale(s) to process. Default: all. Special: base.
|
|
82
147
|
-f, --format Output format: terminal-table, yaml, json, keys, inspect. Default: terminal-table.
|
|
@@ -84,41 +149,30 @@ Usage: i18n-tasks add-missing [options] [locale ...]
|
|
|
84
149
|
-h, --help Display this help message.
|
|
85
150
|
```
|
|
86
151
|
|
|
87
|
-
### Translate
|
|
152
|
+
### Translate missing keys
|
|
88
153
|
|
|
89
154
|
Translate missing keys using a backend service of your choice.
|
|
90
155
|
|
|
91
|
-
```
|
|
92
|
-
$ i18n-tasks translate-missing
|
|
156
|
+
```sh
|
|
157
|
+
$ bundle exec i18n-tasks translate-missing
|
|
93
158
|
|
|
94
159
|
# accepts backend, from and locales options
|
|
95
|
-
$ i18n-tasks translate-missing --from=base es fr --backend=google
|
|
160
|
+
$ bundle exec i18n-tasks translate-missing --from=base es fr --backend=google
|
|
96
161
|
```
|
|
97
162
|
|
|
98
163
|
Available backends:
|
|
99
|
-
- `google` - [Google Translate](#google-translation-config)
|
|
100
|
-
- `deepl` - [DeepL Pro](#deepl-translation-config)
|
|
101
|
-
- `yandex` - [Yandex Translate](#yandex-translation-config)
|
|
102
|
-
- `openai` - [OpenAI](#openai-translation-config)
|
|
103
|
-
- `watsonx` - [watsonx](#watsonx-translation-config)
|
|
104
164
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
$ i18n-tasks find common.help
|
|
111
|
-
$ i18n-tasks find 'auth.*'
|
|
112
|
-
$ i18n-tasks find '{number,currency}.format.*'
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
<img width="437" height="129" src="https://i.imgur.com/VxBrSfY.png">
|
|
165
|
+
- `google` – [Google Translate](#google-translate)
|
|
166
|
+
- `deepl` – [DeepL](#deepl)
|
|
167
|
+
- `yandex` – [Yandex](#yandex)
|
|
168
|
+
- `openai` – [OpenAI](#openai)
|
|
169
|
+
- `watsonx` – [watsonx](#watsonx)
|
|
116
170
|
|
|
117
171
|
### Remove unused keys
|
|
118
172
|
|
|
119
|
-
```
|
|
120
|
-
$ i18n-tasks unused
|
|
121
|
-
$ i18n-tasks remove-unused
|
|
173
|
+
```sh
|
|
174
|
+
$ bundle exec i18n-tasks unused
|
|
175
|
+
$ bundle exec i18n-tasks remove-unused
|
|
122
176
|
```
|
|
123
177
|
|
|
124
178
|
These tasks can infer [dynamic keys](#dynamic-keys) such as `t("category.\#{category.name}")` if you set
|
|
@@ -127,62 +181,72 @@ These tasks can infer [dynamic keys](#dynamic-keys) such as `t("category.\#{cate
|
|
|
127
181
|
If you want to keep the ordering from the original language file when using remove-unused, pass
|
|
128
182
|
`-k` or `--keep-order`.
|
|
129
183
|
|
|
130
|
-
###
|
|
184
|
+
### Prune keys not in base locale
|
|
185
|
+
|
|
186
|
+
Remove keys from non-base locales that are absent in the base locale:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
$ i18n-tasks prune
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Pass `-k` or `--keep-order` to preserve the original key ordering in the locale files.
|
|
193
|
+
|
|
194
|
+
### Normalize
|
|
131
195
|
|
|
132
196
|
Sort the keys:
|
|
133
197
|
|
|
134
|
-
```
|
|
135
|
-
$ i18n-tasks normalize
|
|
198
|
+
```sh
|
|
199
|
+
$ bundle exec i18n-tasks normalize
|
|
136
200
|
```
|
|
137
201
|
|
|
138
|
-
Sort the keys, and move them to the respective files as defined by [`config.write`](#
|
|
202
|
+
Sort the keys, and move them to the respective files as defined by [`config.write`](#storage--locale-files):
|
|
139
203
|
|
|
140
|
-
```
|
|
141
|
-
$ i18n-tasks normalize -p
|
|
204
|
+
```sh
|
|
205
|
+
$ bundle exec i18n-tasks normalize -p
|
|
142
206
|
```
|
|
143
207
|
|
|
144
208
|
### Move / rename / merge keys
|
|
145
209
|
|
|
146
|
-
`i18n-tasks mv <pattern> <target>` is a versatile task to move or delete keys matching the given pattern.
|
|
210
|
+
`bundle exec i18n-tasks mv <pattern> <target>` is a versatile task to move or delete keys matching the given pattern.
|
|
147
211
|
|
|
148
212
|
All nodes (leafs or subtrees) matching [`<pattern>`](#key-pattern-syntax) are merged together and moved to `<target>`.
|
|
149
213
|
|
|
150
214
|
Rename a node (leaf or subtree):
|
|
151
215
|
|
|
152
|
-
```
|
|
153
|
-
$ i18n-tasks mv user account
|
|
216
|
+
```sh
|
|
217
|
+
$ bundle exec i18n-tasks mv user account
|
|
154
218
|
```
|
|
155
219
|
|
|
156
220
|
Move a node:
|
|
157
221
|
|
|
158
|
-
```
|
|
159
|
-
$ i18n-tasks mv user_alerts user.alerts
|
|
222
|
+
```sh
|
|
223
|
+
$ bundle exec i18n-tasks mv user_alerts user.alerts
|
|
160
224
|
```
|
|
161
225
|
|
|
162
226
|
Move the children one level up:
|
|
163
227
|
|
|
164
|
-
```
|
|
165
|
-
$ i18n-tasks mv 'alerts.{:}' '\1'
|
|
228
|
+
```sh
|
|
229
|
+
$ bundle exec i18n-tasks mv 'alerts.{:}' '\1'
|
|
166
230
|
```
|
|
167
231
|
|
|
168
232
|
Merge-move multiple nodes:
|
|
169
233
|
|
|
170
|
-
```
|
|
171
|
-
$ i18n-tasks mv '{user,profile}' account
|
|
234
|
+
```sh
|
|
235
|
+
$ bundle exec i18n-tasks mv '{user,profile}' account
|
|
172
236
|
```
|
|
173
237
|
|
|
174
238
|
Merge (non-leaf) nodes into parent:
|
|
175
239
|
|
|
176
|
-
```
|
|
177
|
-
$ i18n-tasks mv '{pages}.{a,b}' '\1'
|
|
240
|
+
```sh
|
|
241
|
+
$ bundle exec i18n-tasks mv '{pages}.{a,b}' '\1'
|
|
178
242
|
```
|
|
179
243
|
|
|
180
244
|
### Delete keys
|
|
181
245
|
|
|
182
246
|
Delete the keys by using the `rm` task:
|
|
183
247
|
|
|
184
|
-
```
|
|
185
|
-
$ i18n-tasks rm 'user.{old_profile,old_title}' another_key
|
|
248
|
+
```sh
|
|
249
|
+
$ bundle exec i18n-tasks rm 'user.{old_profile,old_title}' another_key
|
|
186
250
|
```
|
|
187
251
|
|
|
188
252
|
### Compose tasks
|
|
@@ -190,94 +254,34 @@ $ i18n-tasks rm 'user.{old_profile,old_title}' another_key
|
|
|
190
254
|
`i18n-tasks` also provides composable tasks for reading, writing and manipulating locale data. Examples below.
|
|
191
255
|
|
|
192
256
|
`add-missing` implemented with `missing`, `tree-set-value` and `data-merge`:
|
|
193
|
-
|
|
194
|
-
|
|
257
|
+
|
|
258
|
+
```sh
|
|
259
|
+
$ bundle exec i18n-tasks missing -f yaml fr | bundle exec i18n-tasks tree-set-value 'TRME %{value}' | bundle exec i18n-tasks data-merge
|
|
195
260
|
```
|
|
196
261
|
|
|
197
262
|
`remove-unused` implemented with `unused` and `data-remove` (sans the confirmation):
|
|
198
|
-
```console
|
|
199
|
-
$ i18n-tasks unused -f yaml | i18n-tasks data-remove
|
|
200
|
-
```
|
|
201
263
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
$ i18n-tasks missing -t diff -f yaml en | i18n-tasks tree-mv en fr | i18n-tasks data-remove
|
|
264
|
+
```sh
|
|
265
|
+
$ bundle exec i18n-tasks unused -f yaml | bundle exec i18n-tasks data-remove
|
|
205
266
|
```
|
|
206
267
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
### Features and limitations
|
|
210
|
-
|
|
211
|
-
`i18n-tasks` uses an AST scanner for `.rb` and `.html.erb` files, and a regexp-based scanner for other files, such as `.haml`.
|
|
212
|
-
|
|
213
|
-
#### Relative keys
|
|
214
|
-
|
|
215
|
-
`i18n-tasks` offers support for relative keys, such as `t '.title'`.
|
|
216
|
-
|
|
217
|
-
✔ Keys relative to the file path they are used in (see [relative roots configuration](#usage-search)) are supported.
|
|
218
|
-
|
|
219
|
-
✔ Keys relative to `controller.action_name` in Rails controllers are supported. The closest `def` name is used.
|
|
220
|
-
|
|
221
|
-
#### Plural keys
|
|
222
|
-
|
|
223
|
-
✔ Plural keys, such as `key.{one,many,other,...}` are fully supported.
|
|
224
|
-
|
|
225
|
-
#### Reference keys
|
|
226
|
-
|
|
227
|
-
✔ Reference keys (keys with `:symbol` values) are fully supported. These keys are copied as-is in
|
|
228
|
-
`add/translate-missing`, and can be looked up by reference or value in `find`.
|
|
268
|
+
Remove all keys from `fr` that do not exist in `en`. Do not change `en`:
|
|
229
269
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
to use `|`, `>`, or `""` for multi-line strings. This can have some unexpected consequences, eg when normalizing:
|
|
233
|
-
```yaml
|
|
234
|
-
a: |
|
|
235
|
-
Lorem ipsum dolor sit amet, consectetur
|
|
236
|
-
Lorem ipsum dolor sit amet, consectetur
|
|
237
|
-
b: |
|
|
238
|
-
Lorem ipsum dolor sit amet, consectetur
|
|
239
|
-
Lorem ipsum dolor sit amet, consectetur
|
|
240
|
-
```
|
|
241
|
-
we get the result
|
|
242
|
-
```yaml
|
|
243
|
-
a: |
|
|
244
|
-
Lorem ipsum dolor sit amet, consectetur
|
|
245
|
-
Lorem ipsum dolor sit amet, consectetur
|
|
246
|
-
b: "Lorem ipsum dolor sit amet, consectetur \nLorem ipsum dolor sit amet, consectetur\n"
|
|
270
|
+
```sh
|
|
271
|
+
$ bundle exec i18n-tasks missing -t diff -f yaml en | bundle exec i18n-tasks tree-mv en fr | bundle exec i18n-tasks data-remove
|
|
247
272
|
```
|
|
248
|
-
The only difference between `a` and `b` is that `b` has an extra trailing space in each line.
|
|
249
|
-
This is an unfortunate side effect of `i18n-tasks` using `Psych`.
|
|
250
|
-
|
|
251
|
-
#### `t()` keyword arguments
|
|
252
|
-
|
|
253
|
-
✔ `scope` keyword argument is fully supported by the AST scanner, and also by the Regexp scanner but only when it is the first argument.
|
|
254
|
-
|
|
255
|
-
✔ `default` argument can be used to pre-fill locale files (AST scanner only).
|
|
256
|
-
|
|
257
|
-
#### Dynamic keys
|
|
258
|
-
|
|
259
|
-
By default, dynamic keys such as `t "cats.#{cat}.name"` are not recognized.
|
|
260
|
-
I encourage you to mark these with [i18n-tasks-use hints](#fine-tuning).
|
|
261
|
-
|
|
262
|
-
Alternatively, you can enable dynamic key inference by setting `search.strict` to `false` in the config. In this case,
|
|
263
|
-
all the dynamic parts of the key will be considered used, e.g. `cats.tenderlove.name` would not be reported as unused.
|
|
264
|
-
Note that only one section of the key is treated as a wildcard for each string interpolation; i.e. in this example,
|
|
265
|
-
`cats.tenderlove.special.name` *will* be reported as unused.
|
|
266
273
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
`I18n.localize` is not supported, use [i18n-tasks-use hints](#fine-tuning).
|
|
270
|
-
This is because the key generated by `I18n.localize` depends on the type of the object passed in and thus cannot be inferred statically.
|
|
274
|
+
See the full list of tasks with `bundle exec i18n-tasks --help`.
|
|
271
275
|
|
|
272
276
|
## Configuration
|
|
273
277
|
|
|
274
278
|
Configuration is read from `config/i18n-tasks.yml` or `config/i18n-tasks.yml.erb`.
|
|
275
|
-
Inspect the configuration with `i18n-tasks config`.
|
|
279
|
+
Inspect the configuration with `bundle exec i18n-tasks config`.
|
|
276
280
|
|
|
277
281
|
Install the [default config file][config] with:
|
|
278
282
|
|
|
279
|
-
```
|
|
280
|
-
$ cp $(i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/
|
|
283
|
+
```sh
|
|
284
|
+
$ cp $(bundle exec i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/
|
|
281
285
|
```
|
|
282
286
|
|
|
283
287
|
Settings are compatible with Rails by default.
|
|
@@ -287,53 +291,51 @@ Settings are compatible with Rails by default.
|
|
|
287
291
|
By default, `base_locale` is set to `en` and `locales` are inferred from the paths to data files.
|
|
288
292
|
You can override these in the [config][config].
|
|
289
293
|
|
|
290
|
-
### Storage
|
|
294
|
+
### Storage & locale files
|
|
291
295
|
|
|
292
296
|
The default data adapter supports YAML and JSON files.
|
|
293
297
|
|
|
294
|
-
#### Multiple locale files
|
|
295
|
-
|
|
296
298
|
i18n-tasks can manage multiple translation files and read translations from other gems.
|
|
297
299
|
To find out more see the `data` options in the [config][config].
|
|
298
300
|
NB: By default, only `%{locale}.yml` files are read, not `namespace.%{locale}.yml`. Make sure to check the config.
|
|
299
301
|
|
|
300
|
-
For writing to locale files i18n-tasks provides
|
|
302
|
+
For writing to locale files i18n-tasks provides three routers.
|
|
301
303
|
|
|
302
|
-
|
|
304
|
+
#### Pattern router
|
|
303
305
|
|
|
304
306
|
Pattern router organizes keys based on a list of key patterns, as in the example below:
|
|
305
307
|
|
|
306
|
-
```
|
|
308
|
+
```yaml
|
|
307
309
|
data:
|
|
308
310
|
router: pattern_router
|
|
309
311
|
# a list of {key pattern => file} routes, matched top to bottom
|
|
310
312
|
write:
|
|
311
313
|
# write models.* and views.* keys to the respective files
|
|
312
|
-
- [
|
|
314
|
+
- ["{models,views}.*", 'config/locales/\1.%{locale}.yml']
|
|
313
315
|
# or, write every top-level key namespace to its own file
|
|
314
|
-
- [
|
|
316
|
+
- ["{:}.*", 'config/locales/\1.%{locale}.yml']
|
|
315
317
|
# default, sugar for ['*', path]
|
|
316
|
-
-
|
|
318
|
+
- "config/locales/%{locale}.yml"
|
|
317
319
|
```
|
|
318
320
|
|
|
319
|
-
|
|
321
|
+
#### Conservative router
|
|
320
322
|
|
|
321
323
|
Conservative router keeps the keys where they are found, or infers the path from base locale.
|
|
322
324
|
If the key is completely new, conservative router will fall back to pattern router behaviour.
|
|
323
325
|
Conservative router is the **default** router.
|
|
324
326
|
|
|
325
|
-
```
|
|
327
|
+
```yaml
|
|
326
328
|
data:
|
|
327
329
|
router: conservative_router
|
|
328
330
|
write:
|
|
329
|
-
- [
|
|
330
|
-
-
|
|
331
|
+
- ["devise.*", "config/locales/devise.%{locale}.yml"]
|
|
332
|
+
- "config/locales/%{locale}.yml"
|
|
331
333
|
```
|
|
332
334
|
|
|
333
335
|
If you want to have i18n-tasks reorganize your existing keys using `data.write`, either set the router to
|
|
334
|
-
`pattern_router` as above, or run `i18n-tasks normalize -p` (forcing the use of the pattern router for that run).
|
|
336
|
+
`pattern_router` as above, or run `bundle exec i18n-tasks normalize -p` (forcing the use of the pattern router for that run).
|
|
335
337
|
|
|
336
|
-
|
|
338
|
+
#### Isolating router
|
|
337
339
|
|
|
338
340
|
Isolating router assumes each YAML file is independent and can contain similar keys.
|
|
339
341
|
|
|
@@ -345,31 +347,32 @@ This can be useful for example when using [ViewComponent sidecars](https://viewc
|
|
|
345
347
|
(ViewComponent assigns an implicit scope to each sidecar YAML file but `i18n-tasks` is not aware of
|
|
346
348
|
that logic, resulting in collisions):
|
|
347
349
|
|
|
348
|
-
|
|
349
|
-
```yaml
|
|
350
|
-
en:
|
|
351
|
-
title: Movies
|
|
352
|
-
```
|
|
350
|
+
- `app/components/movies_component.en.yml`:
|
|
353
351
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
352
|
+
```yaml
|
|
353
|
+
en:
|
|
354
|
+
title: Movies
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
- `app/components/games_component.en.yml`
|
|
358
|
+
```yaml
|
|
359
|
+
en:
|
|
360
|
+
title: Games
|
|
361
|
+
```
|
|
359
362
|
|
|
360
363
|
This router has a limitation, though: it does not support detecting missing keys from code usage
|
|
361
364
|
(since it is not aware of the implicit scope logic).
|
|
362
365
|
|
|
363
|
-
|
|
366
|
+
#### Key pattern syntax
|
|
364
367
|
|
|
365
368
|
A special syntax similar to file glob patterns is used throughout i18n-tasks to match translation keys:
|
|
366
369
|
|
|
367
|
-
|
|
|
368
|
-
|
|
369
|
-
|
|
|
370
|
-
|
|
|
371
|
-
|
|
|
372
|
-
|
|
|
370
|
+
| syntax | description |
|
|
371
|
+
| :--------: | :------------------------------------------------------- |
|
|
372
|
+
| `*` | matches everything |
|
|
373
|
+
| `:` | matches a single key |
|
|
374
|
+
| `*:` | matches part of a single key |
|
|
375
|
+
| `{a, b.c}` | match any in set, can use `:` and `*`, match is captured |
|
|
373
376
|
|
|
374
377
|
Example of usage:
|
|
375
378
|
|
|
@@ -389,7 +392,7 @@ If you have implemented a custom adapter please share it on [the wiki][wiki].
|
|
|
389
392
|
|
|
390
393
|
#### Rails credentials
|
|
391
394
|
|
|
392
|
-
If you use Rails credentials and want to load e.g. credentials for translation backends, convert your `i18n-tasks.yml`to `i18n-tasks.yml.erb` and add
|
|
395
|
+
If you use Rails credentials and want to load e.g. credentials for translation backends, convert your `i18n-tasks.yml` to `i18n-tasks.yml.erb` and add
|
|
393
396
|
a `require "./config/application"` line to load Rails.
|
|
394
397
|
|
|
395
398
|
```yaml
|
|
@@ -411,6 +414,47 @@ New scanners can be added easily: please refer to [this example](https://github.
|
|
|
411
414
|
See the `search` section in the [config file][config] for all available configuration options.
|
|
412
415
|
NB: By default, only the `app/` directory is searched.
|
|
413
416
|
|
|
417
|
+
#### Prism-based scanner
|
|
418
|
+
|
|
419
|
+
There is a scanner based on [Prism](https://github.com/ruby/prism) usable in two different modes.
|
|
420
|
+
|
|
421
|
+
- `rails` mode parses Rails code and handles context such as controllers, before_actions, model translations and more.
|
|
422
|
+
- `ruby` mode parses Ruby code only, and works similar to the existing whitequark/parser-implementation.
|
|
423
|
+
- The parser is used for both ruby and ERB files.
|
|
424
|
+
|
|
425
|
+
##### `rails` mode
|
|
426
|
+
|
|
427
|
+
It handles the following cases:
|
|
428
|
+
|
|
429
|
+
- Translations called in `before_actions`
|
|
430
|
+
- Translations called in nested methods
|
|
431
|
+
- `Model.human_attribute_name` calls
|
|
432
|
+
- `Model.model_name.human` calls
|
|
433
|
+
|
|
434
|
+
Enable it by adding the following to your `config/i18n-tasks.yml`:
|
|
435
|
+
|
|
436
|
+
```yaml
|
|
437
|
+
search:
|
|
438
|
+
prism: "rails"
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
##### `ruby` mode
|
|
442
|
+
|
|
443
|
+
It finds all `I18n.t`, `I18n.translate`, `t` and `translate` calls in Ruby code. Enable it by adding:
|
|
444
|
+
|
|
445
|
+
```yaml
|
|
446
|
+
search:
|
|
447
|
+
prism: "ruby"
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
The goal is to replace the whitequark/parser-based scanner with this one in the future.
|
|
451
|
+
|
|
452
|
+
##### Help us out with testing
|
|
453
|
+
|
|
454
|
+
Please install the latest version of the gem and run `bundle exec i18n-tasks check-prism` which will parse everything with the whitequark/parser-based scanner and then everything with the Prism-scanner and try to compare the results.
|
|
455
|
+
|
|
456
|
+
Open up issues with any parser crashes, missed translations or false positives.
|
|
457
|
+
|
|
414
458
|
### Fine-tuning
|
|
415
459
|
|
|
416
460
|
Add hints to static analysis with magic comment hints (lines starting with `(#|/) i18n-tasks-use` by default):
|
|
@@ -429,7 +473,7 @@ For more complex cases, you can implement a [custom scanner][custom-scanner-docs
|
|
|
429
473
|
|
|
430
474
|
See the [config file][config] to find out more.
|
|
431
475
|
|
|
432
|
-
### Environment
|
|
476
|
+
### Environment variables & dotenv
|
|
433
477
|
|
|
434
478
|
i18n-tasks supports loading environment variables from `.env` files using the [dotenv](https://github.com/bkeepers/dotenv) gem.
|
|
435
479
|
This is particularly useful for storing translation API keys and other sensitive configuration.
|
|
@@ -437,25 +481,26 @@ This is particularly useful for storing translation API keys and other sensitive
|
|
|
437
481
|
If you have `dotenv` in your Gemfile, i18n-tasks will automatically load environment variables from `.env` files
|
|
438
482
|
before executing commands. This means you can store your API keys in a `.env` file:
|
|
439
483
|
|
|
440
|
-
```
|
|
484
|
+
```sh
|
|
441
485
|
# .env
|
|
442
486
|
GOOGLE_TRANSLATE_API_KEY=your_google_api_key
|
|
443
487
|
DEEPL_AUTH_KEY=your_deepl_api_key
|
|
444
488
|
OPENAI_API_KEY=your_openai_api_key
|
|
445
489
|
```
|
|
446
490
|
|
|
447
|
-
The dotenv integration works seamlessly
|
|
491
|
+
The dotenv integration works seamlessly – no additional configuration is required. If `dotenv` is not available,
|
|
448
492
|
i18n-tasks will continue to work normally using system environment variables.
|
|
449
493
|
|
|
450
|
-
|
|
494
|
+
## Translation backends
|
|
495
|
+
|
|
451
496
|
### Google Translate
|
|
452
497
|
|
|
453
498
|
`i18n-tasks translate-missing` requires a Google Translate API key, get it at [Google API Console](https://code.google.com/apis/console).
|
|
454
499
|
|
|
455
500
|
Where this key is depends on your Google API console:
|
|
456
501
|
|
|
457
|
-
|
|
458
|
-
|
|
502
|
+
- Old console: API Access -> Simple API Access -> Key for server apps.
|
|
503
|
+
- New console: Nav Menu -> APIs & Services -> Credentials -> Create Credentials -> API Keys -> Restrict Key -> Cloud Translation API
|
|
459
504
|
|
|
460
505
|
In both cases, you may need to create the key if it doesn't exist.
|
|
461
506
|
|
|
@@ -470,25 +515,23 @@ translation:
|
|
|
470
515
|
|
|
471
516
|
or via environment variable:
|
|
472
517
|
|
|
473
|
-
```
|
|
518
|
+
```sh
|
|
474
519
|
GOOGLE_TRANSLATE_API_KEY=<Google Translate API key>
|
|
475
520
|
```
|
|
476
521
|
|
|
477
|
-
|
|
478
|
-
### DeepL Pro Translate
|
|
522
|
+
### DeepL
|
|
479
523
|
|
|
480
|
-
`i18n-tasks translate-missing` requires a DeepL Pro
|
|
524
|
+
`i18n-tasks translate-missing` requires a DeepL API key. DeepL offers both a Pro plan and a [Free plan](https://www.deepl.com/en/pro#api) (limited to 500,000 characters/month). Get your API key at [DeepL](https://www.deepl.com/en/pro#api). You can specify alias locales if you only use the simple locales internally.
|
|
481
525
|
|
|
482
526
|
```yaml
|
|
483
527
|
# config/i18n-tasks.yml
|
|
484
528
|
translation:
|
|
485
529
|
backend: deepl
|
|
486
|
-
deepl_api_key: <DeepL
|
|
487
|
-
deepl_host: <optional>
|
|
530
|
+
deepl_api_key: <DeepL API key>
|
|
531
|
+
deepl_host: <optional, see note below>
|
|
488
532
|
deepl_version: <optional>
|
|
489
533
|
deepl_glossary_ids:
|
|
490
|
-
-
|
|
491
|
-
- 2c6415be-1852-4f54-9e1b-d800463496b4
|
|
534
|
+
- uuid
|
|
492
535
|
deepl_options:
|
|
493
536
|
formality: prefer_less
|
|
494
537
|
deepl_locale_aliases:
|
|
@@ -499,13 +542,21 @@ translation:
|
|
|
499
542
|
or via environment variables:
|
|
500
543
|
|
|
501
544
|
```bash
|
|
502
|
-
DEEPL_AUTH_KEY=<DeepL
|
|
503
|
-
DEEPL_HOST=<optional>
|
|
545
|
+
DEEPL_AUTH_KEY=<DeepL API key>
|
|
546
|
+
DEEPL_HOST=<optional, see note below>
|
|
504
547
|
DEEPL_VERSION=<optional>
|
|
505
548
|
```
|
|
506
549
|
|
|
507
|
-
|
|
508
|
-
|
|
550
|
+
> **Free API:** If you are using a DeepL Free account, set `deepl_host` to `https://api-free.deepl.com` (or set the `DEEPL_HOST` environment variable).
|
|
551
|
+
>
|
|
552
|
+
> ```yaml
|
|
553
|
+
> translation:
|
|
554
|
+
> deepl_api_key: "your-free-api-key"
|
|
555
|
+
> deepl_host: "https://api-free.deepl.com"
|
|
556
|
+
> deepl_version: "v2"
|
|
557
|
+
> ```
|
|
558
|
+
|
|
559
|
+
### Yandex
|
|
509
560
|
|
|
510
561
|
`i18n-tasks translate-missing` requires a Yandex API key, get it at [Yandex](https://tech.yandex.com/translate).
|
|
511
562
|
|
|
@@ -518,14 +569,13 @@ translation:
|
|
|
518
569
|
|
|
519
570
|
or via environment variable:
|
|
520
571
|
|
|
521
|
-
```
|
|
572
|
+
```sh
|
|
522
573
|
YANDEX_API_KEY=<Yandex API key>
|
|
523
574
|
```
|
|
524
575
|
|
|
525
|
-
|
|
526
|
-
### OpenAI Translate
|
|
576
|
+
### OpenAI
|
|
527
577
|
|
|
528
|
-
`i18n-tasks translate-missing` requires
|
|
578
|
+
`i18n-tasks translate-missing` requires an OpenAI API key, get it at [OpenAI](https://openai.com/).
|
|
529
579
|
|
|
530
580
|
```yaml
|
|
531
581
|
# config/i18n-tasks.yml
|
|
@@ -533,19 +583,22 @@ translation:
|
|
|
533
583
|
backend: openai
|
|
534
584
|
openai_api_key: <OpenAI API key>
|
|
535
585
|
openai_model: <optional>
|
|
586
|
+
openai_reasoning_effort: <optional>
|
|
587
|
+
openai_temperature: <optional>
|
|
536
588
|
```
|
|
537
589
|
|
|
538
590
|
or via environment variable:
|
|
539
591
|
|
|
540
|
-
```
|
|
592
|
+
```sh
|
|
541
593
|
OPENAI_API_KEY=<OpenAI API key>
|
|
542
594
|
OPENAI_MODEL=<optional>
|
|
543
595
|
```
|
|
544
596
|
|
|
545
|
-
|
|
546
|
-
|
|
597
|
+
The translator sends temperature as usual when `openai_reasoning_effort` is unset or `none`. With other reasoning efforts, it omits temperature; do not configure `openai_temperature` at the same time.
|
|
598
|
+
|
|
599
|
+
### watsonx
|
|
547
600
|
|
|
548
|
-
`i18n-tasks translate-missing` requires a watsonx project and
|
|
601
|
+
`i18n-tasks translate-missing` requires a watsonx project and an API key, get it at [IBM watsonx](https://www.ibm.com/watsonx/).
|
|
549
602
|
|
|
550
603
|
```yaml
|
|
551
604
|
# config/i18n-tasks.yml
|
|
@@ -558,83 +611,109 @@ translation:
|
|
|
558
611
|
|
|
559
612
|
or via environment variable:
|
|
560
613
|
|
|
561
|
-
```
|
|
614
|
+
```sh
|
|
562
615
|
WATSONX_API_KEY=<watsonx API key>
|
|
563
616
|
WATSONX_PROJECT_ID=<watsonx project id>
|
|
564
617
|
WATSONX_MODEL=<optional>
|
|
565
618
|
```
|
|
566
619
|
|
|
567
|
-
|
|
620
|
+
## Features & limitations
|
|
568
621
|
|
|
569
|
-
|
|
622
|
+
`i18n-tasks` uses an AST scanner for `.rb` and `.html.erb` files, and a regexp-based scanner for other files, such as `.haml`.
|
|
570
623
|
|
|
571
|
-
|
|
572
|
-
- `ruby` mode parses Ruby code only, and works similar to the existing whitequark/parser-implementation.
|
|
573
|
-
- The parser is used for both ruby and ERB files.
|
|
624
|
+
### Relative keys
|
|
574
625
|
|
|
575
|
-
|
|
626
|
+
`i18n-tasks` offers support for relative keys, such as `t '.title'`.
|
|
576
627
|
|
|
577
|
-
|
|
578
|
-
- Translations called in `before_actions`
|
|
579
|
-
- Translations called in nested methods
|
|
580
|
-
- `Model.human_attribute_name` calls
|
|
581
|
-
- `Model.model_name.human` calls
|
|
628
|
+
✔ Keys relative to the file path they are used in (see [Usage search](#usage-search)) are supported.
|
|
582
629
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
630
|
+
✔ Keys relative to `controller.action_name` in Rails controllers are supported. The closest `def` name is used.
|
|
631
|
+
|
|
632
|
+
### Plural keys
|
|
633
|
+
|
|
634
|
+
✔ Plural keys, such as `key.{one,many,other,...}` are fully supported.
|
|
635
|
+
|
|
636
|
+
### Reference keys
|
|
637
|
+
|
|
638
|
+
✔ Reference keys (keys with `:symbol` values) are fully supported. These keys are copied as-is in
|
|
639
|
+
`add/translate-missing`, and can be looked up by reference or value in `find`.
|
|
640
|
+
|
|
641
|
+
### Dynamic keys
|
|
642
|
+
|
|
643
|
+
By default, dynamic keys such as `t "cats.#{cat}.name"` are not recognized.
|
|
644
|
+
I encourage you to mark these with [i18n-tasks-use hints](#fine-tuning).
|
|
645
|
+
|
|
646
|
+
Alternatively, you can enable dynamic key inference by setting `search.strict` to `false` in the config. In this case,
|
|
647
|
+
all the dynamic parts of the key will be considered used, e.g. `cats.tenderlove.name` would not be reported as unused.
|
|
648
|
+
Note that only one section of the key is treated as a wildcard for each string interpolation; i.e. in this example,
|
|
649
|
+
`cats.tenderlove.special.name` _will_ be reported as unused.
|
|
588
650
|
|
|
589
|
-
|
|
651
|
+
### I18n.localize
|
|
590
652
|
|
|
591
|
-
|
|
653
|
+
`I18n.localize` is not supported, use [i18n-tasks-use hints](#fine-tuning).
|
|
654
|
+
This is because the key generated by `I18n.localize` depends on the type of the object passed in and thus cannot be inferred statically.
|
|
655
|
+
|
|
656
|
+
### `t()` keyword arguments
|
|
657
|
+
|
|
658
|
+
✔ `scope` keyword argument is fully supported by the AST scanner, and also by the Regexp scanner but only when it is the first argument.
|
|
659
|
+
|
|
660
|
+
✔ `default` argument can be used to pre-fill locale files (AST scanner only).
|
|
592
661
|
|
|
593
|
-
|
|
662
|
+
### Unexpected normalization
|
|
663
|
+
|
|
664
|
+
`i18n-tasks` uses a YAML parser and emitter called `Psych` under the hood. `Psych` has its own heuristic on when
|
|
665
|
+
to use `|`, `>`, or `""` for multi-line strings. This can have some unexpected consequences, e.g. when normalizing:
|
|
594
666
|
|
|
595
667
|
```yaml
|
|
596
|
-
|
|
597
|
-
|
|
668
|
+
a: |
|
|
669
|
+
Lorem ipsum dolor sit amet, consectetur
|
|
670
|
+
Lorem ipsum dolor sit amet, consectetur
|
|
671
|
+
b: |
|
|
672
|
+
Lorem ipsum dolor sit amet, consectetur
|
|
673
|
+
Lorem ipsum dolor sit amet, consectetur
|
|
598
674
|
```
|
|
599
675
|
|
|
600
|
-
|
|
676
|
+
we get the result:
|
|
601
677
|
|
|
602
|
-
|
|
678
|
+
```yaml
|
|
679
|
+
a: |
|
|
680
|
+
Lorem ipsum dolor sit amet, consectetur
|
|
681
|
+
Lorem ipsum dolor sit amet, consectetur
|
|
682
|
+
b: "Lorem ipsum dolor sit amet, consectetur \nLorem ipsum dolor sit amet, consectetur\n"
|
|
683
|
+
```
|
|
603
684
|
|
|
604
|
-
|
|
685
|
+
The only difference between `a` and `b` is that `b` has an extra trailing space in each line.
|
|
686
|
+
This is an unfortunate side effect of `i18n-tasks` using `Psych`.
|
|
605
687
|
|
|
606
|
-
|
|
688
|
+
## Advanced
|
|
607
689
|
|
|
608
|
-
|
|
690
|
+
### Interactive console
|
|
609
691
|
|
|
610
|
-
`i18n-tasks irb` starts an IRB session in i18n-tasks context. Type `guide` for more information.
|
|
692
|
+
`bundle exec i18n-tasks irb` starts an IRB session in i18n-tasks context. Type `guide` for more information.
|
|
611
693
|
|
|
612
|
-
|
|
694
|
+
### CSV import / export
|
|
613
695
|
|
|
614
696
|
See [i18n-tasks wiki: CSV import and export tasks](https://github.com/glebm/i18n-tasks/wiki/Custom-CSV-import-and-export-tasks).
|
|
615
697
|
|
|
616
|
-
|
|
698
|
+
### Add custom tasks
|
|
617
699
|
|
|
618
700
|
Tasks that come with the gem are defined in [lib/i18n/tasks/command/commands](lib/i18n/tasks/command/commands).
|
|
619
701
|
Custom tasks can be added easily, see the examples [on the wiki](https://github.com/glebm/i18n-tasks/wiki#custom-tasks).
|
|
620
702
|
|
|
621
|
-
|
|
703
|
+
## Development
|
|
622
704
|
|
|
623
705
|
- Install dependencies using `bundle install`
|
|
624
706
|
- Run tests using `bundle exec rspec`
|
|
625
707
|
- Install [Overcommit](https://github.com/sds/overcommit) by running `overcommit --install`
|
|
626
708
|
|
|
627
|
-
|
|
709
|
+
### Skip Overcommit hooks
|
|
628
710
|
|
|
629
711
|
- `SKIP=RuboCop git commit`
|
|
630
712
|
- `OVERCOMMIT_DISABLE=1 git commit`
|
|
631
713
|
|
|
632
|
-
|
|
633
714
|
[MIT license]: /LICENSE.txt
|
|
634
715
|
[ci]: https://github.com/glebm/i18n-tasks/actions/workflows/tests.yml
|
|
635
716
|
[badge-ci]: https://github.com/glebm/i18n-tasks/actions/workflows/tests.yml/badge.svg
|
|
636
|
-
[coverage]: https://codeclimate.com/github/glebm/i18n-tasks
|
|
637
|
-
[badge-coverage]: https://api.codeclimate.com/v1/badges/5d173e90ada8df07cedc/test_coverage
|
|
638
717
|
[config]: https://github.com/glebm/i18n-tasks/blob/main/templates/config/i18n-tasks.yml
|
|
639
718
|
[wiki]: https://github.com/glebm/i18n-tasks/wiki "i18n-tasks wiki"
|
|
640
719
|
[i18n-gem]: https://github.com/svenfuchs/i18n "svenfuchs/i18n on Github"
|