i18n_flow 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +13 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +45 -0
  8. data/LICENSE +22 -0
  9. data/README.md +103 -0
  10. data/Rakefile +2 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/doc/rules.md +316 -0
  14. data/doc/tags.md +488 -0
  15. data/example/example.en.yml +14 -0
  16. data/example/example.ja.yml +9 -0
  17. data/exe/i18n_flow +11 -0
  18. data/i18n_flow.gemspec +28 -0
  19. data/i18n_flow.yml +8 -0
  20. data/lib/i18n_flow/cli/color.rb +18 -0
  21. data/lib/i18n_flow/cli/command_base.rb +33 -0
  22. data/lib/i18n_flow/cli/copy_command.rb +69 -0
  23. data/lib/i18n_flow/cli/help_command.rb +29 -0
  24. data/lib/i18n_flow/cli/lint_command/ascii.erb +45 -0
  25. data/lib/i18n_flow/cli/lint_command/ascii_renderer.rb +58 -0
  26. data/lib/i18n_flow/cli/lint_command/markdown.erb +49 -0
  27. data/lib/i18n_flow/cli/lint_command/markdown_renderer.rb +55 -0
  28. data/lib/i18n_flow/cli/lint_command.rb +55 -0
  29. data/lib/i18n_flow/cli/read_config_command.rb +20 -0
  30. data/lib/i18n_flow/cli/search_command/default.erb +11 -0
  31. data/lib/i18n_flow/cli/search_command/default_renderer.rb +67 -0
  32. data/lib/i18n_flow/cli/search_command/oneline.erb +5 -0
  33. data/lib/i18n_flow/cli/search_command/oneline_renderer.rb +39 -0
  34. data/lib/i18n_flow/cli/search_command.rb +59 -0
  35. data/lib/i18n_flow/cli/split_command.rb +20 -0
  36. data/lib/i18n_flow/cli/version_command.rb +9 -0
  37. data/lib/i18n_flow/cli.rb +42 -0
  38. data/lib/i18n_flow/configuration.rb +205 -0
  39. data/lib/i18n_flow/parser.rb +34 -0
  40. data/lib/i18n_flow/repository.rb +39 -0
  41. data/lib/i18n_flow/search.rb +176 -0
  42. data/lib/i18n_flow/splitter/merger.rb +60 -0
  43. data/lib/i18n_flow/splitter/strategy.rb +66 -0
  44. data/lib/i18n_flow/splitter.rb +5 -0
  45. data/lib/i18n_flow/util.rb +57 -0
  46. data/lib/i18n_flow/validator/errors.rb +99 -0
  47. data/lib/i18n_flow/validator/file_scope.rb +58 -0
  48. data/lib/i18n_flow/validator/multiplexer.rb +58 -0
  49. data/lib/i18n_flow/validator/symmetry.rb +154 -0
  50. data/lib/i18n_flow/validator.rb +4 -0
  51. data/lib/i18n_flow/version.rb +7 -0
  52. data/lib/i18n_flow/yaml_ast_proxy/mapping.rb +72 -0
  53. data/lib/i18n_flow/yaml_ast_proxy/node.rb +128 -0
  54. data/lib/i18n_flow/yaml_ast_proxy/node_meta_data.rb +86 -0
  55. data/lib/i18n_flow/yaml_ast_proxy/sequence.rb +29 -0
  56. data/lib/i18n_flow/yaml_ast_proxy.rb +57 -0
  57. data/lib/i18n_flow.rb +15 -0
  58. data/spec/lib/i18n_flow/cli/command_base_spec.rb +46 -0
  59. data/spec/lib/i18n_flow/cli/help_command_spec.rb +13 -0
  60. data/spec/lib/i18n_flow/cli/version_command_spec.rb +13 -0
  61. data/spec/lib/i18n_flow/configuration_spec.rb +334 -0
  62. data/spec/lib/i18n_flow/repository_spec.rb +40 -0
  63. data/spec/lib/i18n_flow/splitter/merger_spec.rb +149 -0
  64. data/spec/lib/i18n_flow/util_spec.rb +194 -0
  65. data/spec/lib/i18n_flow/validator/file_scope_spec.rb +74 -0
  66. data/spec/lib/i18n_flow/validator/multiplexer_spec.rb +68 -0
  67. data/spec/lib/i18n_flow/validator/symmetry_spec.rb +511 -0
  68. data/spec/lib/i18n_flow/yaml_ast_proxy/node_spec.rb +151 -0
  69. data/spec/lib/i18n_flow_spec.rb +21 -0
  70. data/spec/spec_helper.rb +16 -0
  71. data/spec/support/repository_examples.rb +60 -0
  72. data/spec/support/util_macro.rb +14 -0
  73. 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'
@@ -0,0 +1,9 @@
1
+ ja:
2
+ example:
3
+ title: 'サンプル'
4
+
5
+ # Use last name in Japanese
6
+ greeting: !ignore:args 'こんにちは %{last_name}さん'
7
+
8
+ # Should translate later
9
+ serendipity: !todo 'serendipity'
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,8 @@
1
+ base_path: example
2
+ glob_patterns:
3
+ - '**/*.yml'
4
+ valid_locales:
5
+ - en
6
+ - ja
7
+ locale_pairs:
8
+ - ['en', 'ja']
@@ -0,0 +1,18 @@
1
+ class I18nFlow::CLI
2
+ module Color
3
+ COLORS = {
4
+ black: 30,
5
+ red: 31,
6
+ green: 32,
7
+ yellow: 33,
8
+ blue: 34,
9
+ magenta: 35,
10
+ cyan: 36,
11
+ white: 37,
12
+ }.freeze
13
+
14
+ def color(str, c)
15
+ "\e[1;#{COLORS[c]}m#{str}\e[0m"
16
+ end
17
+ end
18
+ end
@@ -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