i18n_flow 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +13 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +45 -0
- data/LICENSE +22 -0
- data/README.md +103 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/doc/rules.md +316 -0
- data/doc/tags.md +488 -0
- data/example/example.en.yml +14 -0
- data/example/example.ja.yml +9 -0
- data/exe/i18n_flow +11 -0
- data/i18n_flow.gemspec +28 -0
- data/i18n_flow.yml +8 -0
- data/lib/i18n_flow/cli/color.rb +18 -0
- data/lib/i18n_flow/cli/command_base.rb +33 -0
- data/lib/i18n_flow/cli/copy_command.rb +69 -0
- data/lib/i18n_flow/cli/help_command.rb +29 -0
- data/lib/i18n_flow/cli/lint_command/ascii.erb +45 -0
- data/lib/i18n_flow/cli/lint_command/ascii_renderer.rb +58 -0
- data/lib/i18n_flow/cli/lint_command/markdown.erb +49 -0
- data/lib/i18n_flow/cli/lint_command/markdown_renderer.rb +55 -0
- data/lib/i18n_flow/cli/lint_command.rb +55 -0
- data/lib/i18n_flow/cli/read_config_command.rb +20 -0
- data/lib/i18n_flow/cli/search_command/default.erb +11 -0
- data/lib/i18n_flow/cli/search_command/default_renderer.rb +67 -0
- data/lib/i18n_flow/cli/search_command/oneline.erb +5 -0
- data/lib/i18n_flow/cli/search_command/oneline_renderer.rb +39 -0
- data/lib/i18n_flow/cli/search_command.rb +59 -0
- data/lib/i18n_flow/cli/split_command.rb +20 -0
- data/lib/i18n_flow/cli/version_command.rb +9 -0
- data/lib/i18n_flow/cli.rb +42 -0
- data/lib/i18n_flow/configuration.rb +205 -0
- data/lib/i18n_flow/parser.rb +34 -0
- data/lib/i18n_flow/repository.rb +39 -0
- data/lib/i18n_flow/search.rb +176 -0
- data/lib/i18n_flow/splitter/merger.rb +60 -0
- data/lib/i18n_flow/splitter/strategy.rb +66 -0
- data/lib/i18n_flow/splitter.rb +5 -0
- data/lib/i18n_flow/util.rb +57 -0
- data/lib/i18n_flow/validator/errors.rb +99 -0
- data/lib/i18n_flow/validator/file_scope.rb +58 -0
- data/lib/i18n_flow/validator/multiplexer.rb +58 -0
- data/lib/i18n_flow/validator/symmetry.rb +154 -0
- data/lib/i18n_flow/validator.rb +4 -0
- data/lib/i18n_flow/version.rb +7 -0
- data/lib/i18n_flow/yaml_ast_proxy/mapping.rb +72 -0
- data/lib/i18n_flow/yaml_ast_proxy/node.rb +128 -0
- data/lib/i18n_flow/yaml_ast_proxy/node_meta_data.rb +86 -0
- data/lib/i18n_flow/yaml_ast_proxy/sequence.rb +29 -0
- data/lib/i18n_flow/yaml_ast_proxy.rb +57 -0
- data/lib/i18n_flow.rb +15 -0
- data/spec/lib/i18n_flow/cli/command_base_spec.rb +46 -0
- data/spec/lib/i18n_flow/cli/help_command_spec.rb +13 -0
- data/spec/lib/i18n_flow/cli/version_command_spec.rb +13 -0
- data/spec/lib/i18n_flow/configuration_spec.rb +334 -0
- data/spec/lib/i18n_flow/repository_spec.rb +40 -0
- data/spec/lib/i18n_flow/splitter/merger_spec.rb +149 -0
- data/spec/lib/i18n_flow/util_spec.rb +194 -0
- data/spec/lib/i18n_flow/validator/file_scope_spec.rb +74 -0
- data/spec/lib/i18n_flow/validator/multiplexer_spec.rb +68 -0
- data/spec/lib/i18n_flow/validator/symmetry_spec.rb +511 -0
- data/spec/lib/i18n_flow/yaml_ast_proxy/node_spec.rb +151 -0
- data/spec/lib/i18n_flow_spec.rb +21 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/repository_examples.rb +60 -0
- data/spec/support/util_macro.rb +14 -0
- metadata +214 -0
data/doc/tags.md
ADDED
@@ -0,0 +1,488 @@
|
|
1
|
+
Tags
|
2
|
+
====
|
3
|
+
|
4
|
+
!only
|
5
|
+
-----
|
6
|
+
|
7
|
+
With `!only`, you can explicitly claim that a key *may* not exist on both files.
|
8
|
+
Linter won't complain even if a key *does* exist. If you don't prefer this behavior, use stricter `!only:LOCALES`.
|
9
|
+
|
10
|
+
It comes in handy when you have texts that don't need to be translated into another language, still want to manage in a locale file.
|
11
|
+
|
12
|
+
<table><thead><tr>
|
13
|
+
<th></th>
|
14
|
+
<th>master</th>
|
15
|
+
<th>foreign</th>
|
16
|
+
</tr></thead><tbody><tr><th>👎</th><td>
|
17
|
+
|
18
|
+
```yaml
|
19
|
+
en:
|
20
|
+
title: 'Non zero sum'
|
21
|
+
desc: 'A situation in...'
|
22
|
+
```
|
23
|
+
|
24
|
+
</td><td>
|
25
|
+
|
26
|
+
```yaml
|
27
|
+
ja:
|
28
|
+
title: '非ゼロ和'
|
29
|
+
|
30
|
+
```
|
31
|
+
|
32
|
+
</td></tr><tr><td colspan=3>
|
33
|
+
|
34
|
+
Missing `ja.desc`
|
35
|
+
|
36
|
+
</td></tr></tbody></table>
|
37
|
+
|
38
|
+
|
39
|
+
<table><thead><tr>
|
40
|
+
<th></th>
|
41
|
+
<th>master</th>
|
42
|
+
<th>foreign</th>
|
43
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
44
|
+
|
45
|
+
```yaml
|
46
|
+
en:
|
47
|
+
title: 'Non zero sum'
|
48
|
+
desc: !only 'A situation in...'
|
49
|
+
```
|
50
|
+
|
51
|
+
</td><td>
|
52
|
+
|
53
|
+
```yaml
|
54
|
+
ja:
|
55
|
+
title: '非ゼロ和'
|
56
|
+
|
57
|
+
```
|
58
|
+
|
59
|
+
</td></tr><tr><td colspan=3>
|
60
|
+
|
61
|
+
Linter won't complain about `ja.desc` even if it doesn't exist
|
62
|
+
|
63
|
+
</td></tr></tbody></table>
|
64
|
+
|
65
|
+
<table><thead><tr>
|
66
|
+
<th></th>
|
67
|
+
<th>master</th>
|
68
|
+
<th>foreign</th>
|
69
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
70
|
+
|
71
|
+
```yaml
|
72
|
+
en:
|
73
|
+
title: 'Non zero sum'
|
74
|
+
desc: !only 'A situation in...'
|
75
|
+
```
|
76
|
+
|
77
|
+
</td><td>
|
78
|
+
|
79
|
+
```yaml
|
80
|
+
ja:
|
81
|
+
title: '非ゼロ和'
|
82
|
+
desc: '複数の人が相互...'
|
83
|
+
```
|
84
|
+
|
85
|
+
</td></tr><tr><td colspan=3>
|
86
|
+
|
87
|
+
Linter won't complain about `ja.desc` even if it does exist
|
88
|
+
|
89
|
+
</td></tr></tbody></table>
|
90
|
+
|
91
|
+
|
92
|
+
<table><thead><tr>
|
93
|
+
<th></th>
|
94
|
+
<th>master</th>
|
95
|
+
<th>foreign</th>
|
96
|
+
</tr></thead><tbody><tr><th>👎</th><td>
|
97
|
+
|
98
|
+
```yaml
|
99
|
+
en:
|
100
|
+
title: 'Non zero sum'
|
101
|
+
|
102
|
+
```
|
103
|
+
|
104
|
+
</td><td>
|
105
|
+
|
106
|
+
```yaml
|
107
|
+
ja:
|
108
|
+
title: '非ゼロ和'
|
109
|
+
desc: '複数の人が相互...'
|
110
|
+
```
|
111
|
+
|
112
|
+
</td></tr><tr><td colspan=3>
|
113
|
+
|
114
|
+
Having the extra `ja.desc`
|
115
|
+
|
116
|
+
</td></tr></tbody></table>
|
117
|
+
|
118
|
+
<table><thead><tr>
|
119
|
+
<th></th>
|
120
|
+
<th>master</th>
|
121
|
+
<th>foreign</th>
|
122
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
123
|
+
|
124
|
+
```yaml
|
125
|
+
en:
|
126
|
+
title: 'Non zero sum'
|
127
|
+
|
128
|
+
```
|
129
|
+
|
130
|
+
</td><td>
|
131
|
+
|
132
|
+
```yaml
|
133
|
+
ja:
|
134
|
+
title: '非ゼロ和'
|
135
|
+
desc: !only '複数の人が相互...'
|
136
|
+
```
|
137
|
+
|
138
|
+
</td></tr><tr><td colspan=3>
|
139
|
+
|
140
|
+
Linter won't complain about `ja.desc`
|
141
|
+
|
142
|
+
</td></tr></tbody></table>
|
143
|
+
|
144
|
+
<table><thead><tr>
|
145
|
+
<th></th>
|
146
|
+
<th>master</th>
|
147
|
+
<th>foreign</th>
|
148
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
149
|
+
|
150
|
+
```yaml
|
151
|
+
en:
|
152
|
+
title: 'Non zero sum'
|
153
|
+
desc: 'A situation in...'
|
154
|
+
```
|
155
|
+
|
156
|
+
</td><td>
|
157
|
+
|
158
|
+
```yaml
|
159
|
+
ja:
|
160
|
+
title: '非ゼロ和'
|
161
|
+
desc: !only '複数の人が相互...'
|
162
|
+
```
|
163
|
+
|
164
|
+
</td></tr><tr><td colspan=3>
|
165
|
+
|
166
|
+
Linter won't complain about `ja.desc`
|
167
|
+
|
168
|
+
</td></tr></tbody></table>
|
169
|
+
|
170
|
+
|
171
|
+
!only:LOCALES
|
172
|
+
-------------
|
173
|
+
|
174
|
+
It's similar to `!only`, but is stricter.
|
175
|
+
It can take comma-separated locales as a parameter just like `!only:en` or `!only:en,ja,zh-HK`, and ensures that a key only exists in files of the specified locales.
|
176
|
+
|
177
|
+
<table><thead><tr>
|
178
|
+
<th></th>
|
179
|
+
<th>master</th>
|
180
|
+
<th>foreign</th>
|
181
|
+
</tr></thead><tbody><tr><th>👎</th><td>
|
182
|
+
|
183
|
+
```yaml
|
184
|
+
en:
|
185
|
+
title: 'Non zero sum'
|
186
|
+
desc: !only:en 'A situation in...'
|
187
|
+
```
|
188
|
+
|
189
|
+
</td><td>
|
190
|
+
|
191
|
+
```yaml
|
192
|
+
ja:
|
193
|
+
title: '非ゼロ和'
|
194
|
+
desc: '複数の人が相互...'
|
195
|
+
```
|
196
|
+
|
197
|
+
</td></tr><tr><td colspan=3>
|
198
|
+
|
199
|
+
Linter will complain about `ja.desc`, because the key is supposed to exist only in `en`.
|
200
|
+
|
201
|
+
</td></tr></tbody></table>
|
202
|
+
|
203
|
+
<table><thead><tr>
|
204
|
+
<th></th>
|
205
|
+
<th>master</th>
|
206
|
+
<th>foreign</th>
|
207
|
+
</tr></thead><tbody><tr><th>👎</th><td>
|
208
|
+
|
209
|
+
```yaml
|
210
|
+
en:
|
211
|
+
title: 'Non zero sum'
|
212
|
+
desc: 'A situation in...'
|
213
|
+
```
|
214
|
+
|
215
|
+
</td><td>
|
216
|
+
|
217
|
+
```yaml
|
218
|
+
ja:
|
219
|
+
title: '非ゼロ和'
|
220
|
+
desc: !only:ja '複数の人が相互...'
|
221
|
+
```
|
222
|
+
|
223
|
+
</td></tr><tr><td colspan=3>
|
224
|
+
|
225
|
+
Linter will complain about `en.desc`, because the key is supposed to exist only in `ja`.
|
226
|
+
|
227
|
+
</td></tr></tbody></table>
|
228
|
+
|
229
|
+
<table><thead><tr>
|
230
|
+
<th></th>
|
231
|
+
<th>master</th>
|
232
|
+
<th>foreign</th>
|
233
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
234
|
+
|
235
|
+
```yaml
|
236
|
+
en:
|
237
|
+
title: 'Non zero sum'
|
238
|
+
desc: !only:en,ja 'A situation in...'
|
239
|
+
```
|
240
|
+
|
241
|
+
</td><td>
|
242
|
+
|
243
|
+
```yaml
|
244
|
+
ja:
|
245
|
+
title: '非ゼロ和'
|
246
|
+
desc: '複数の人が相互...'
|
247
|
+
```
|
248
|
+
|
249
|
+
</td></tr><tr><td colspan=3>
|
250
|
+
|
251
|
+
The key can exist in the specified locales `en,ja`
|
252
|
+
|
253
|
+
</td></tr></tbody></table>
|
254
|
+
|
255
|
+
<table><thead><tr>
|
256
|
+
<th></th>
|
257
|
+
<th>master</th>
|
258
|
+
<th>foreign</th>
|
259
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
260
|
+
|
261
|
+
```yaml
|
262
|
+
en:
|
263
|
+
title: 'Non zero sum'
|
264
|
+
desc: !only:en,ja 'A situation in...'
|
265
|
+
```
|
266
|
+
|
267
|
+
</td><td>
|
268
|
+
|
269
|
+
```yaml
|
270
|
+
ja:
|
271
|
+
title: '非ゼロ和'
|
272
|
+
|
273
|
+
```
|
274
|
+
|
275
|
+
</td></tr><tr><td colspan=3>
|
276
|
+
|
277
|
+
Note that it doesn't mean to ensure existance of the key.
|
278
|
+
|
279
|
+
</td></tr></tbody></table>
|
280
|
+
|
281
|
+
|
282
|
+
!ignore:key
|
283
|
+
-----------
|
284
|
+
|
285
|
+
With `!ignore:key`, you can suppress any error on a certain key.
|
286
|
+
|
287
|
+
<table><thead><tr>
|
288
|
+
<th></th>
|
289
|
+
<th>master</th>
|
290
|
+
<th>foreign</th>
|
291
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
292
|
+
|
293
|
+
```yaml
|
294
|
+
en:
|
295
|
+
title: 'Non zero sum'
|
296
|
+
|
297
|
+
```
|
298
|
+
|
299
|
+
</td><td>
|
300
|
+
|
301
|
+
```yaml
|
302
|
+
ja:
|
303
|
+
title: '非ゼロ和'
|
304
|
+
desc: !ignore:key '複数の人が相互...'
|
305
|
+
```
|
306
|
+
|
307
|
+
</td></tr><tr><td colspan=3>
|
308
|
+
|
309
|
+
Linter won't complain about an asymmetric key
|
310
|
+
|
311
|
+
</td></tr></tbody></table>
|
312
|
+
|
313
|
+
|
314
|
+
<table><thead><tr>
|
315
|
+
<th></th>
|
316
|
+
<th>master</th>
|
317
|
+
<th>foreign</th>
|
318
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
319
|
+
|
320
|
+
```yaml
|
321
|
+
en:
|
322
|
+
follower_count:
|
323
|
+
one: '1 follower'
|
324
|
+
other: '%{count} followers'
|
325
|
+
```
|
326
|
+
|
327
|
+
</td><td>
|
328
|
+
|
329
|
+
```yaml
|
330
|
+
ja:
|
331
|
+
follower_count: !ignore:key '%{count} フォロワ'
|
332
|
+
|
333
|
+
|
334
|
+
```
|
335
|
+
|
336
|
+
</td></tr><tr><td colspan=3>
|
337
|
+
|
338
|
+
Linter won't complain about a structural mismatch
|
339
|
+
|
340
|
+
</td></tr></tbody></table>
|
341
|
+
|
342
|
+
|
343
|
+
<table><thead><tr>
|
344
|
+
<th></th>
|
345
|
+
<th>master</th>
|
346
|
+
<th>foreign</th>
|
347
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
348
|
+
|
349
|
+
```yaml
|
350
|
+
en:
|
351
|
+
key: !ignore:key '%{alpha}'
|
352
|
+
```
|
353
|
+
|
354
|
+
</td><td>
|
355
|
+
|
356
|
+
```yaml
|
357
|
+
ja:
|
358
|
+
key: '%{gamma}'
|
359
|
+
```
|
360
|
+
|
361
|
+
</td></tr><tr><td colspan=3>
|
362
|
+
|
363
|
+
Linter won't complain about a difference in interpolation arguments
|
364
|
+
|
365
|
+
</td></tr></tbody></table>
|
366
|
+
|
367
|
+
|
368
|
+
!ignore:args
|
369
|
+
------------
|
370
|
+
|
371
|
+
With `!ignore:args`, you can suppress an error of asymmetric interpolation arguments.
|
372
|
+
|
373
|
+
<table><thead><tr>
|
374
|
+
<th></th>
|
375
|
+
<th>master</th>
|
376
|
+
<th>foreign</th>
|
377
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
378
|
+
|
379
|
+
```yaml
|
380
|
+
en:
|
381
|
+
key: '%{alpha}'
|
382
|
+
```
|
383
|
+
|
384
|
+
</td><td>
|
385
|
+
|
386
|
+
```yaml
|
387
|
+
ja:
|
388
|
+
key: !ignore:args '%{gamma}'
|
389
|
+
```
|
390
|
+
|
391
|
+
</td></tr><tr><td colspan=3>
|
392
|
+
|
393
|
+
Linter won't complain about a difference in interpolation arguments
|
394
|
+
|
395
|
+
</td></tr></tbody></table>
|
396
|
+
|
397
|
+
|
398
|
+
!todo
|
399
|
+
-----
|
400
|
+
|
401
|
+
With `!todo`, you can annotate that a key needs to be translated in the future.
|
402
|
+
It can be only annotated on scalar values, mappings and sequences are not accepted.
|
403
|
+
|
404
|
+
<table><thead><tr>
|
405
|
+
<th></th>
|
406
|
+
<th>master</th>
|
407
|
+
<th>foreign</th>
|
408
|
+
</tr></thead><tbody><tr><th>✅</th><td>
|
409
|
+
|
410
|
+
```yaml
|
411
|
+
en:
|
412
|
+
follower_count:
|
413
|
+
one: '1 follower'
|
414
|
+
other: '%{count} followers'
|
415
|
+
```
|
416
|
+
|
417
|
+
</td><td>
|
418
|
+
|
419
|
+
```yaml
|
420
|
+
ja:
|
421
|
+
follower_count:
|
422
|
+
one: !todo '1 follower'
|
423
|
+
other: !todo '%{count} followers'
|
424
|
+
```
|
425
|
+
|
426
|
+
</td></tr><tr><td colspan=3>
|
427
|
+
|
428
|
+
Two keys need to be translated
|
429
|
+
|
430
|
+
</td></tr></tbody></table>
|
431
|
+
|
432
|
+
<table><thead><tr>
|
433
|
+
<th></th>
|
434
|
+
<th>master</th>
|
435
|
+
<th>foreign</th>
|
436
|
+
</tr></thead><tbody><tr><th>👎</th><td>
|
437
|
+
|
438
|
+
```yaml
|
439
|
+
en:
|
440
|
+
follower_count:
|
441
|
+
one: '1 follower'
|
442
|
+
other: '%{count} followers'
|
443
|
+
```
|
444
|
+
|
445
|
+
</td><td>
|
446
|
+
|
447
|
+
```yaml
|
448
|
+
ja:
|
449
|
+
follower_count: !todo
|
450
|
+
one: '1 follower'
|
451
|
+
other: '%{count} followers'
|
452
|
+
```
|
453
|
+
|
454
|
+
</td></tr><tr><td colspan=3>
|
455
|
+
|
456
|
+
You can't annotate on a mapping or a sequence.
|
457
|
+
|
458
|
+
</td></tr></tbody></table>
|
459
|
+
|
460
|
+
|
461
|
+
<table><thead><tr>
|
462
|
+
<th></th>
|
463
|
+
<th>master</th>
|
464
|
+
<th>foreign</th>
|
465
|
+
</tr></thead><tbody><tr><th>👎</th><td>
|
466
|
+
|
467
|
+
```yaml
|
468
|
+
en:
|
469
|
+
follower_count:
|
470
|
+
one: 'a follower'
|
471
|
+
other: '%{count} followers'
|
472
|
+
```
|
473
|
+
|
474
|
+
</td><td>
|
475
|
+
|
476
|
+
```yaml
|
477
|
+
ja:
|
478
|
+
follower_count:
|
479
|
+
one: !todo '1 follower'
|
480
|
+
other: !todo '%{count} followers'
|
481
|
+
```
|
482
|
+
|
483
|
+
</td></tr><tr><td colspan=3>
|
484
|
+
|
485
|
+
Linter will complain `ja.follower_count.one` has different content.
|
486
|
+
This usually indicates that there has been updates on the master file, or that it has been translated but forgotten to remove `!todo`.
|
487
|
+
|
488
|
+
</td></tr></tbody></table>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
en:
|
2
|
+
example:
|
3
|
+
title: 'Example'
|
4
|
+
|
5
|
+
# Use first name in English
|
6
|
+
greeting: 'Hello %{first_name},'
|
7
|
+
|
8
|
+
# Might be hard to translate into other langs
|
9
|
+
serendipity: 'serendipity'
|
10
|
+
|
11
|
+
# Only available in English version
|
12
|
+
follower_count: !only:en
|
13
|
+
one: '1 follower'
|
14
|
+
other: '%{count} followers'
|
data/exe/i18n_flow
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# enable local usage from cloned repo
|
4
|
+
root = File.expand_path('../..', __FILE__)
|
5
|
+
$LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile")
|
6
|
+
|
7
|
+
require 'i18n_flow'
|
8
|
+
require 'i18n_flow/cli'
|
9
|
+
|
10
|
+
I18nFlow.config.auto_configure!
|
11
|
+
I18nFlow::CLI.new(ARGV).run
|
data/i18n_flow.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'i18n_flow/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'i18n_flow'
|
7
|
+
spec.version = I18nFlow::VERSION
|
8
|
+
spec.authors = ['Yuki Iwanaga']
|
9
|
+
spec.email = ['yuki@creasty.com']
|
10
|
+
|
11
|
+
spec.summary = %q{Manage translation status in yaml file}
|
12
|
+
spec.description = %q{Manage translation status in yaml file}
|
13
|
+
spec.homepage = 'https://github.com/creasty/i18n_flow'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.bindir = 'exe'
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'psych', '>= 3.0'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.7'
|
26
|
+
spec.add_development_dependency 'fakefs'
|
27
|
+
spec.add_development_dependency 'pry'
|
28
|
+
end
|
data/i18n_flow.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../util'
|
2
|
+
|
3
|
+
class I18nFlow::CLI
|
4
|
+
class CommandBase
|
5
|
+
attr_reader(*%i[
|
6
|
+
args
|
7
|
+
options
|
8
|
+
])
|
9
|
+
|
10
|
+
def initialize(args)
|
11
|
+
@args = args.dup
|
12
|
+
@options = I18nFlow::Util::parse_options(@args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def invoke!
|
16
|
+
raise 'Not implemented'
|
17
|
+
end
|
18
|
+
|
19
|
+
def exit_with_message(status, *args)
|
20
|
+
if status.zero?
|
21
|
+
puts(*args)
|
22
|
+
else
|
23
|
+
$stderr.puts(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
exit status
|
27
|
+
end
|
28
|
+
|
29
|
+
def color_enabled?
|
30
|
+
options['nocolor'].nil?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'psych'
|
2
|
+
require_relative 'command_base'
|
3
|
+
require_relative '../util'
|
4
|
+
require_relative '../parser'
|
5
|
+
|
6
|
+
class I18nFlow::CLI
|
7
|
+
class CopyCommand < CommandBase
|
8
|
+
def invoke!
|
9
|
+
unless src_file && dst_file
|
10
|
+
exit_with_message(1, 'usage: i18n_flow copy [--locale=LOCALE] SRC_FILE DST_FILE')
|
11
|
+
end
|
12
|
+
|
13
|
+
parser.parse!
|
14
|
+
|
15
|
+
mark_as_todo(parser.root_proxy)
|
16
|
+
|
17
|
+
if locale && first_key_node
|
18
|
+
first_key_node.value = locale
|
19
|
+
end
|
20
|
+
|
21
|
+
File.write(dst_file, parser.root_proxy.to_yaml)
|
22
|
+
end
|
23
|
+
|
24
|
+
def src_file
|
25
|
+
args[0]
|
26
|
+
end
|
27
|
+
|
28
|
+
def dst_file
|
29
|
+
args[1]
|
30
|
+
end
|
31
|
+
|
32
|
+
def locale
|
33
|
+
options['locale']
|
34
|
+
end
|
35
|
+
|
36
|
+
def first_key_node
|
37
|
+
return @first_key_node if defined?(@first_key_node)
|
38
|
+
@first_key_node = parser.root_proxy
|
39
|
+
.send(:indexed_object)
|
40
|
+
.node
|
41
|
+
.tap { |n| break unless n.is_a?(Psych::Nodes::Mapping) }
|
42
|
+
&.tap { |n| break n.children.first }
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def parser
|
48
|
+
@parser ||= I18nFlow::Parser.new(File.read(src_file), file_path: src_file)
|
49
|
+
end
|
50
|
+
|
51
|
+
def mark_as_todo(ast)
|
52
|
+
if ast.alias?
|
53
|
+
return
|
54
|
+
end
|
55
|
+
if ast.scalar?
|
56
|
+
ast.node.tag = '!todo'
|
57
|
+
|
58
|
+
# https://github.com/ruby/psych/blob/f30b65befa4f0a5a8548d482424a84a2383b0284/ext/psych/yaml/emitter.c#L1187
|
59
|
+
ast.node.plain = ast.node.quoted = false
|
60
|
+
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
64
|
+
ast.each do |k, v|
|
65
|
+
mark_as_todo(v)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'command_base'
|
2
|
+
|
3
|
+
class I18nFlow::CLI
|
4
|
+
class HelpCommand < CommandBase
|
5
|
+
TEXT = <<-HELP
|
6
|
+
Manage translation status in yaml file
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
i18n_flow COMMAND [args...]
|
10
|
+
i18n_flow [options]
|
11
|
+
|
12
|
+
Options:
|
13
|
+
-v, --version Show version
|
14
|
+
-h Show help
|
15
|
+
|
16
|
+
Commands:
|
17
|
+
lint Validate files
|
18
|
+
search Search contents and keys
|
19
|
+
copy Copy translations and mark as todo
|
20
|
+
split Split a file into proper-sized files
|
21
|
+
version Show version
|
22
|
+
help Show help
|
23
|
+
HELP
|
24
|
+
|
25
|
+
def invoke!
|
26
|
+
puts TEXT
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|