i18n-processes 0.1.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.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile.lock +102 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +46 -0
  5. data/Rakefile +12 -0
  6. data/bin/i18n-processes +28 -0
  7. data/bin/i18n-processes.cmd +2 -0
  8. data/config/locales/en.yml +2 -0
  9. data/config/locales/zh-CN.yml +2 -0
  10. data/i18n-processes.gemspec +64 -0
  11. data/lib/i18n/processes/base_process.rb +47 -0
  12. data/lib/i18n/processes/cli.rb +208 -0
  13. data/lib/i18n/processes/command/collection.rb +21 -0
  14. data/lib/i18n/processes/command/commander.rb +43 -0
  15. data/lib/i18n/processes/command/commands/data.rb +107 -0
  16. data/lib/i18n/processes/command/commands/eq_base.rb +21 -0
  17. data/lib/i18n/processes/command/commands/health.rb +26 -0
  18. data/lib/i18n/processes/command/commands/meta.rb +38 -0
  19. data/lib/i18n/processes/command/commands/missing.rb +86 -0
  20. data/lib/i18n/processes/command/commands/preprocessing.rb +90 -0
  21. data/lib/i18n/processes/command/commands/tree.rb +119 -0
  22. data/lib/i18n/processes/command/commands/usages.rb +69 -0
  23. data/lib/i18n/processes/command/commands/xlsx.rb +29 -0
  24. data/lib/i18n/processes/command/dsl.rb +56 -0
  25. data/lib/i18n/processes/command/option_parsers/enum.rb +55 -0
  26. data/lib/i18n/processes/command/option_parsers/locale.rb +60 -0
  27. data/lib/i18n/processes/command/options/common.rb +41 -0
  28. data/lib/i18n/processes/command/options/data.rb +95 -0
  29. data/lib/i18n/processes/command/options/locales.rb +36 -0
  30. data/lib/i18n/processes/command_error.rb +13 -0
  31. data/lib/i18n/processes/commands.rb +31 -0
  32. data/lib/i18n/processes/configuration.rb +132 -0
  33. data/lib/i18n/processes/console_context.rb +76 -0
  34. data/lib/i18n/processes/data/adapter/json_adapter.rb +29 -0
  35. data/lib/i18n/processes/data/adapter/yaml_adapter.rb +27 -0
  36. data/lib/i18n/processes/data/file_formats.rb +111 -0
  37. data/lib/i18n/processes/data/file_system.rb +14 -0
  38. data/lib/i18n/processes/data/file_system_base.rb +205 -0
  39. data/lib/i18n/processes/data/router/conservative_router.rb +66 -0
  40. data/lib/i18n/processes/data/router/pattern_router.rb +60 -0
  41. data/lib/i18n/processes/data/tree/node.rb +204 -0
  42. data/lib/i18n/processes/data/tree/nodes.rb +97 -0
  43. data/lib/i18n/processes/data/tree/siblings.rb +333 -0
  44. data/lib/i18n/processes/data/tree/traversal.rb +190 -0
  45. data/lib/i18n/processes/data.rb +87 -0
  46. data/lib/i18n/processes/google_translation.rb +125 -0
  47. data/lib/i18n/processes/html_keys.rb +16 -0
  48. data/lib/i18n/processes/ignore_keys.rb +30 -0
  49. data/lib/i18n/processes/key_pattern_matching.rb +37 -0
  50. data/lib/i18n/processes/locale_list.rb +19 -0
  51. data/lib/i18n/processes/locale_pathname.rb +17 -0
  52. data/lib/i18n/processes/logging.rb +37 -0
  53. data/lib/i18n/processes/missing_keys.rb +122 -0
  54. data/lib/i18n/processes/path.rb +42 -0
  55. data/lib/i18n/processes/plural_keys.rb +41 -0
  56. data/lib/i18n/processes/rainbow_utils.rb +13 -0
  57. data/lib/i18n/processes/references.rb +101 -0
  58. data/lib/i18n/processes/reports/base.rb +71 -0
  59. data/lib/i18n/processes/reports/spreadsheet.rb +72 -0
  60. data/lib/i18n/processes/reports/terminal.rb +252 -0
  61. data/lib/i18n/processes/scanners/file_scanner.rb +65 -0
  62. data/lib/i18n/processes/scanners/files/caching_file_finder.rb +34 -0
  63. data/lib/i18n/processes/scanners/files/caching_file_finder_provider.rb +33 -0
  64. data/lib/i18n/processes/scanners/files/caching_file_reader.rb +28 -0
  65. data/lib/i18n/processes/scanners/files/file_finder.rb +60 -0
  66. data/lib/i18n/processes/scanners/files/file_reader.rb +19 -0
  67. data/lib/i18n/processes/scanners/occurrence_from_position.rb +27 -0
  68. data/lib/i18n/processes/scanners/pattern_mapper.rb +60 -0
  69. data/lib/i18n/processes/scanners/pattern_scanner.rb +103 -0
  70. data/lib/i18n/processes/scanners/pattern_with_scope_scanner.rb +98 -0
  71. data/lib/i18n/processes/scanners/relative_keys.rb +53 -0
  72. data/lib/i18n/processes/scanners/results/key_occurrences.rb +54 -0
  73. data/lib/i18n/processes/scanners/results/occurrence.rb +69 -0
  74. data/lib/i18n/processes/scanners/ruby_ast_call_finder.rb +62 -0
  75. data/lib/i18n/processes/scanners/ruby_ast_scanner.rb +206 -0
  76. data/lib/i18n/processes/scanners/ruby_key_literals.rb +30 -0
  77. data/lib/i18n/processes/scanners/scanner.rb +17 -0
  78. data/lib/i18n/processes/scanners/scanner_multiplexer.rb +41 -0
  79. data/lib/i18n/processes/split_key.rb +68 -0
  80. data/lib/i18n/processes/stats.rb +24 -0
  81. data/lib/i18n/processes/string_interpolation.rb +16 -0
  82. data/lib/i18n/processes/unused_keys.rb +23 -0
  83. data/lib/i18n/processes/used_keys.rb +177 -0
  84. data/lib/i18n/processes/version.rb +7 -0
  85. data/lib/i18n/processes.rb +69 -0
  86. data/source/p1/_messages/zh/article.properties +9 -0
  87. data/source/p1/_messages/zh/company.properties +62 -0
  88. data/source/p1/_messages/zh/devices.properties +40 -0
  89. data/source/p1/_messages/zh/meeting-rooms.properties +99 -0
  90. data/source/p1/_messages/zh/meetingBooking.properties +18 -0
  91. data/source/p1/_messages/zh/office-areas.properties +64 -0
  92. data/source/p1/_messages/zh/orders.properties +25 -0
  93. data/source/p1/_messages/zh/schedulings.properties +7 -0
  94. data/source/p1/_messages/zh/tag.properties +2 -0
  95. data/source/p1/_messages/zh/ticket.properties +9 -0
  96. data/source/p1/_messages/zh/visitor.properties +5 -0
  97. data/source/p1/messages +586 -0
  98. data/source/p2/orders.properties +25 -0
  99. data/source/p2/schedulings.properties +7 -0
  100. data/source/p2/tag.properties +2 -0
  101. data/source/p2/ticket.properties +9 -0
  102. data/source/p2/visitor.properties +5 -0
  103. data/source/zh.messages.ts +30 -0
  104. data/translated/en/p1/_messages/zh/article.properties +9 -0
  105. data/translated/en/p1/_messages/zh/company.properties +62 -0
  106. data/translated/en/p1/_messages/zh/devices.properties +40 -0
  107. data/translated/en/p1/_messages/zh/meeting-rooms.properties +99 -0
  108. data/translated/en/p1/_messages/zh/meetingBooking.properties +18 -0
  109. data/translated/en/p1/_messages/zh/office-areas.properties +64 -0
  110. data/translated/en/p1/_messages/zh/orders.properties +25 -0
  111. data/translated/en/p1/_messages/zh/schedulings.properties +7 -0
  112. data/translated/en/p1/_messages/zh/tag.properties +2 -0
  113. data/translated/en/p1/_messages/zh/ticket.properties +9 -0
  114. data/translated/en/p1/_messages/zh/visitor.properties +5 -0
  115. data/translated/en/p1/messages +586 -0
  116. data/translated/en/p2/orders.properties +25 -0
  117. data/translated/en/p2/schedulings.properties +7 -0
  118. data/translated/en/p2/tag.properties +2 -0
  119. data/translated/en/p2/ticket.properties +9 -0
  120. data/translated/en/p2/visitor.properties +5 -0
  121. data/translated/en/zh.messages.ts +30 -0
  122. data/translation/en/article.properties +9 -0
  123. data/translation/en/company.properties +56 -0
  124. data/translation/en/meeting-rooms.properties +87 -0
  125. data/translation/en/meetingBooking.properties +14 -0
  126. data/translation/en/messages.en +164 -0
  127. data/translation/en/office-areas.properties +51 -0
  128. data/translation/en/orders.properties +26 -0
  129. data/translation/en/tag.properties +2 -0
  130. data/translation/en/translated +1263 -0
  131. data/translation/en/visitor.properties +4 -0
  132. metadata +408 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4a3c64fbecf9527d7bc551b27b06e2a8ebaae26f
4
+ data.tar.gz: 5698f8ba6eec69a68205b101afe5a9d922a63032
5
+ SHA512:
6
+ metadata.gz: ab7236cd1ba6da353561a7b31b27334b00181d7af119df8c30a755c4bd41d5ba40e9bbfc91b6f11b6d9b3a764559fbea99f4a8774bfb2594e2ae7a0c2148e68c
7
+ data.tar.gz: 7898211f013a1f1e99b27ff88aba20dd9238a16bf8c879e1cb14d8bd25a38a2c8d75c24eb0db248412403122d7529523096cd26a2ea42f666c6757abb735d093
data/Gemfile.lock ADDED
@@ -0,0 +1,102 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ i18n-processes (0.1.0)
5
+ activesupport (>= 4.0.2)
6
+ ast (>= 2.1.0)
7
+ easy_translate (>= 0.5.1)
8
+ erubi
9
+ highline (>= 1.7.3)
10
+ i18n
11
+ parser (>= 2.2.3.0)
12
+ rainbow (>= 2.2.2, < 4.0)
13
+ terminal-table (>= 1.5.1)
14
+
15
+ GEM
16
+ remote: https://rubygems.org/
17
+ specs:
18
+ activesupport (5.1.5)
19
+ concurrent-ruby (~> 1.0, >= 1.0.2)
20
+ i18n (~> 0.7)
21
+ minitest (~> 5.1)
22
+ tzinfo (~> 1.1)
23
+ ast (2.4.0)
24
+ axlsx (2.0.1)
25
+ htmlentities (~> 4.3.1)
26
+ nokogiri (>= 1.4.1)
27
+ rubyzip (~> 1.2.1)
28
+ concurrent-ruby (1.0.5)
29
+ diff-lcs (1.3)
30
+ docile (1.3.0)
31
+ easy_translate (0.5.1)
32
+ thread
33
+ thread_safe
34
+ erubi (1.7.1)
35
+ highline (1.7.10)
36
+ htmlentities (4.3.4)
37
+ i18n (0.9.5)
38
+ concurrent-ruby (~> 1.0)
39
+ json (2.1.0)
40
+ mini_portile2 (2.3.0)
41
+ minitest (5.11.3)
42
+ nokogiri (1.8.2)
43
+ mini_portile2 (~> 2.3.0)
44
+ parallel (1.12.1)
45
+ parser (2.5.0.4)
46
+ ast (~> 2.4.0)
47
+ powerpack (0.1.1)
48
+ racc (1.4.14)
49
+ rainbow (3.0.0)
50
+ rake (10.4.2)
51
+ rspec (3.7.0)
52
+ rspec-core (~> 3.7.0)
53
+ rspec-expectations (~> 3.7.0)
54
+ rspec-mocks (~> 3.7.0)
55
+ rspec-core (3.7.0)
56
+ rspec-support (~> 3.7.0)
57
+ rspec-expectations (3.7.0)
58
+ diff-lcs (>= 1.2.0, < 2.0)
59
+ rspec-support (~> 3.7.0)
60
+ rspec-mocks (3.7.0)
61
+ diff-lcs (>= 1.2.0, < 2.0)
62
+ rspec-support (~> 3.7.0)
63
+ rspec-support (3.7.0)
64
+ rubocop (0.53.0)
65
+ parallel (~> 1.10)
66
+ parser (>= 2.5)
67
+ powerpack (~> 0.1)
68
+ rainbow (>= 2.2.2, < 4.0)
69
+ ruby-progressbar (~> 1.7)
70
+ unicode-display_width (~> 1.0, >= 1.0.1)
71
+ ruby-progressbar (1.9.0)
72
+ rubyzip (1.2.1)
73
+ simplecov (0.16.1)
74
+ docile (~> 1.1)
75
+ json (>= 1.8, < 3)
76
+ simplecov-html (~> 0.10.0)
77
+ simplecov-html (0.10.2)
78
+ terminal-table (1.8.0)
79
+ unicode-display_width (~> 1.1, >= 1.1.1)
80
+ thread (0.2.2)
81
+ thread_safe (0.3.6)
82
+ tzinfo (1.2.5)
83
+ thread_safe (~> 0.1)
84
+ unicode-display_width (1.3.0)
85
+ yard (0.9.12)
86
+
87
+ PLATFORMS
88
+ ruby
89
+
90
+ DEPENDENCIES
91
+ axlsx (~> 2.0)
92
+ bundler (~> 1.3)
93
+ i18n-processes!
94
+ racc
95
+ rake
96
+ rspec (~> 3.3)
97
+ rubocop (~> 0.53.0)
98
+ simplecov
99
+ yard
100
+
101
+ BUNDLED WITH
102
+ 1.16.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Lucia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # I18n::Processes
2
+
3
+ 给到目标语言, 针对指定格式的中文文档,输出相对应的翻译文件。
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'i18n-processes'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install i18n-processes
20
+
21
+ ## Usage
22
+
23
+ - 在config/i18n-processes.yml中,设置三个路径:
24
+ - source: base_locale zh-CN原始文件存放路径
25
+ - translation: 翻译文件存放路径
26
+ - translated:翻译后的文件存放路径
27
+
28
+ - 将需要翻译的中文文件夹放入设置好的目录下,比如source/
29
+ - 运行:`i18n-processes preprocessing`, 会提取出所有的keys
30
+ - 运行:`i18n-processes missing`
31
+ - 在你设置的翻译文件存放路径下,比如translated/,会生成与原文件同结构的文件,内含对应的翻译文件
32
+
33
+
34
+ ## Development
35
+
36
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
+
38
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
+
40
+ ## Contributing
41
+
42
+ Bug reports and pull requests are welcome on GitHub at [i18n-processes](https://github.com/Lupeipei/i18n-processes).
43
+
44
+ ## License
45
+
46
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ task :irb do
9
+ require 'i18n/processes'
10
+ require 'i18n/processes/commands'
11
+ I18n::Processes::Commands.new(I18n::Processes::BaseProcess.new).irb
12
+ end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # require "bundler/setup"
4
+ # require "i18n/processes"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ # require "irb"
14
+ # IRB.start(__FILE__)
15
+
16
+
17
+ require_relative '../spec/bin_simplecov_helper' if ENV['I18N_TASKS_BIN_SIMPLECOV_COVERAGE']
18
+
19
+ # prevent i18n gem warning
20
+ require 'i18n'
21
+ i18n_gem_config = I18n.config
22
+ if i18n_gem_config.respond_to?(:enforce_available_locales=) && i18n_gem_config.enforce_available_locales.nil?
23
+ i18n_gem_config.enforce_available_locales = true
24
+ end
25
+
26
+ require 'i18n/processes/cli'
27
+
28
+ I18n::Processes::CLI.start(ARGV)
@@ -0,0 +1,2 @@
1
+ @echo off
2
+ ruby %~dp0\i18n-processes %*
@@ -0,0 +1,2 @@
1
+ ---
2
+ en:
@@ -0,0 +1,2 @@
1
+ ---
2
+ zh-CN:
@@ -0,0 +1,64 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "i18n/processes/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "i18n-processes"
8
+ spec.version = I18n::Processes::VERSION
9
+ spec.authors = ["Lucia"]
10
+ spec.email = ["learningleadtorebirth@gmail.com"]
11
+
12
+ spec.summary = 'manage synced translation'
13
+ spec.description = <<-TEXT
14
+ i18n-processes helps you to synchronize your translation.
15
+ TEXT
16
+ spec.homepage = 'https://github.com/Lupeipei/i18n-processes'
17
+ spec.license = 'MIT'
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
21
+ spec.metadata = { 'issue_tracker' => 'https://github.com/Lupeipei/i18n-processes' } if spec.respond_to?(:metadata=)
22
+
23
+ # if spec.respond_to?(:metadata)
24
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
25
+ # else
26
+ # raise "RubyGems 2.0 or newer is required to protect against " \
27
+ # "public gem pushes."
28
+ # end
29
+
30
+ # spec.files = `git ls-files -z`.split("\x0").reject do |f|
31
+ # f.match(%r{^(test|spec|features)/})
32
+ # end
33
+ # spec.bindir = "exe"
34
+ # spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ # spec.require_paths = ["lib"]
36
+ #
37
+ # spec.add_development_dependency "bundler", "~> 1.16"
38
+ # spec.add_development_dependency "rake", "~> 10.0"
39
+ # spec.add_development_dependency "rspec", "~> 3.0"
40
+
41
+
42
+ spec.files = `git ls-files`.split($/)
43
+ spec.files -= spec.files.grep(%r{^(doc/|\.|spec/)}) + %w[config/i18n-processes.yml Gemfile]
44
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } - %w[i18n-processes.cmd]
45
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
46
+ spec.require_paths = ['lib']
47
+
48
+ spec.add_dependency 'activesupport', '>= 4.0.2'
49
+ spec.add_dependency 'ast', '>= 2.1.0'
50
+ spec.add_dependency 'easy_translate', '>= 0.5.1'
51
+ spec.add_dependency 'erubi'
52
+ spec.add_dependency 'highline', '>= 1.7.3'
53
+ spec.add_dependency 'i18n'
54
+ spec.add_dependency 'parser', '>= 2.2.3.0'
55
+ spec.add_dependency 'rainbow', '>= 2.2.2', '< 4.0'
56
+ spec.add_dependency 'terminal-table', '>= 1.5.1'
57
+ spec.add_development_dependency 'axlsx', '~> 2.0'
58
+ spec.add_development_dependency 'bundler', '~> 1.3'
59
+ spec.add_development_dependency 'rake'
60
+ spec.add_development_dependency 'rspec', '~> 3.3'
61
+ spec.add_development_dependency 'rubocop', '~> 0.53.0'
62
+ spec.add_development_dependency 'simplecov'
63
+ spec.add_development_dependency 'yard'
64
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/processes/command_error'
4
+ require 'i18n/processes/split_key'
5
+ require 'i18n/processes/key_pattern_matching'
6
+ require 'i18n/processes/logging'
7
+ require 'i18n/processes/plural_keys'
8
+ require 'i18n/processes/references'
9
+ require 'i18n/processes/html_keys'
10
+ require 'i18n/processes/used_keys'
11
+ require 'i18n/processes/ignore_keys'
12
+ require 'i18n/processes/missing_keys'
13
+ require 'i18n/processes/unused_keys'
14
+ require 'i18n/processes/google_translation'
15
+ require 'i18n/processes/locale_pathname'
16
+ require 'i18n/processes/locale_list'
17
+ require 'i18n/processes/string_interpolation'
18
+ require 'i18n/processes/data'
19
+ require 'i18n/processes/configuration'
20
+ require 'i18n/processes/stats'
21
+
22
+ module I18n::Processes
23
+ class BaseProcess
24
+ include SplitKey
25
+ include KeyPatternMatching
26
+ include PluralKeys
27
+ include References
28
+ include HtmlKeys
29
+ include UsedKeys
30
+ include IgnoreKeys
31
+ include MissingKeys
32
+ include UnusedKeys
33
+ include GoogleTranslation
34
+ include Logging
35
+ include Configuration
36
+ include Data
37
+ include Stats
38
+
39
+ def initialize(config = {})
40
+ self.config = config || {}
41
+ end
42
+
43
+ def inspect
44
+ "#{self.class.name}#{config_for_inspect}"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/processes'
4
+ require 'i18n/processes/commands'
5
+ require 'optparse'
6
+
7
+ module I18n::Processes
8
+ class CLI
9
+ include I18n::Processes::Logging
10
+
11
+ def self.start(argv)
12
+ new.start(argv)
13
+ end
14
+
15
+ def initialize; end
16
+
17
+ def start(argv)
18
+ auto_output_coloring do
19
+ begin
20
+ exit 1 if run(argv) == :exit_1
21
+ rescue OptionParser::ParseError => e
22
+ error e.message, 64
23
+ rescue I18n::Processes::CommandError => e
24
+ begin
25
+ error e.message, 78
26
+ ensure
27
+ log_verbose e.backtrace * "\n"
28
+ end
29
+ rescue Errno::EPIPE
30
+ # ignore Errno::EPIPE which is throw when pipe breaks, e.g.:
31
+ # i18n-processes missing | head
32
+ exit 1
33
+ end
34
+ end
35
+ rescue ExecutionError => e
36
+ exit e.exit_code
37
+ end
38
+
39
+ def run(argv)
40
+ I18n.with_locale(base_task.internal_locale) do
41
+ name, *options = parse!(argv.dup)
42
+ context.run(name, *options)
43
+ end
44
+ end
45
+
46
+ def context
47
+ @context ||= ::I18n::Processes::Commands.new(base_task)
48
+ end
49
+
50
+ def commands
51
+ # load base task to initialize plugins
52
+ base_task
53
+ @commands ||= ::I18n::Processes::Commands.cmds.transform_keys { |k| k.to_s.tr('_', '-') }
54
+ end
55
+
56
+ private
57
+
58
+ def base_task
59
+ @base_task ||= I18n::Processes::BaseProcess.new
60
+ end
61
+
62
+ def parse!(argv)
63
+ command = parse_command! argv
64
+ options = optparse! command, argv
65
+ parse_options! options, command, argv
66
+ [command.tr('-', '_'), options.update(arguments: argv)]
67
+ end
68
+
69
+ def optparse!(command, argv)
70
+ if command
71
+ optparse_command!(command, argv)
72
+ else
73
+ optparse_no_command!(argv)
74
+ end
75
+ end
76
+
77
+ def optparse_command!(command, argv)
78
+ cmd_conf = commands[command]
79
+ flags = cmd_conf[:args].dup
80
+ options = {}
81
+ OptionParser.new("Usage: #{program_name} #{command} [options] #{cmd_conf[:pos]}".strip) do |op|
82
+ flags.each do |flag|
83
+ op.on(*optparse_args(flag)) { |v| options[option_name(flag)] = v }
84
+ end
85
+ verbose_option op
86
+ help_option op
87
+ end.parse!(argv)
88
+ options
89
+ end
90
+
91
+ def optparse_no_command!(argv)
92
+ argv << '--help' if argv.empty?
93
+ OptionParser.new("Usage: #{program_name} [command] [options]") do |op|
94
+ op.on('-v', '--version', 'Print the version') do
95
+ puts I18n::Processes::VERSION
96
+ exit
97
+ end
98
+ help_option op
99
+ commands_summary op
100
+ end.parse!(argv)
101
+ end
102
+
103
+ def allow_help_arg_first!(argv)
104
+ # allow `i18n-tasks --help command` in addition to `i18n-tasks command --help`
105
+ argv[0], argv[1] = argv[1], argv[0] if %w[-h --help].include?(argv[0]) && argv[1] && !argv[1].start_with?('-')
106
+ end
107
+
108
+ def parse_command!(argv)
109
+ allow_help_arg_first! argv
110
+ if argv[0] && !argv[0].start_with?('-')
111
+ if commands.keys.include?(argv[0])
112
+ argv.shift
113
+ else
114
+ error "unknown command: #{argv[0]}", 64
115
+ end
116
+ end
117
+ end
118
+
119
+ def verbose_option(op)
120
+ op.on('--verbose', 'Verbose output') do
121
+ ::I18n::Processes.verbose = true
122
+ end
123
+ end
124
+
125
+ def help_option(op)
126
+ op.on('-h', '--help', 'Show this message') do
127
+ $stderr.puts op
128
+ exit
129
+ end
130
+ end
131
+
132
+ # @param [OptionParser] op
133
+ def commands_summary(op)
134
+ op.separator ''
135
+ op.separator 'Available commands:'
136
+ op.separator ''
137
+ commands.each do |cmd, cmd_conf|
138
+ op.separator " #{cmd.ljust(op.summary_width + 1, ' ')}#{try_call cmd_conf[:desc]}"
139
+ end
140
+ op.separator ''
141
+ op.separator 'See `i18n-processes <command> --help` for more information on a specific command.'
142
+ end
143
+
144
+ def optparse_args(flag)
145
+ args = flag.dup
146
+ args.map! { |v| try_call v }
147
+ conf = args.extract_options!
148
+ if conf.key?(:default)
149
+ args[-1] = "#{args[-1]}.Default: #{conf[:default]}"
150
+ end
151
+ args
152
+ end
153
+
154
+ def parse_options!(options, command, argv)
155
+ commands[command][:args].each do |flag|
156
+ name = option_name flag
157
+ options[name] = parse_option flag, options[name], argv, context
158
+ end
159
+ end
160
+
161
+ def parse_option(flag, val, argv, context)
162
+ conf = flag.last.is_a?(Hash) ? flag.last : {}
163
+ if conf[:consume_positional]
164
+ val = Array(val) + Array(flag.include?(Array) ? argv.flat_map { |x| x.split(',') } : argv)
165
+ end
166
+ val = conf[:default] if val.nil? && conf.key?(:default)
167
+
168
+ val = conf[:parser].call(val, context) if conf.key?(:parser)
169
+ val
170
+ end
171
+
172
+ def option_name(flag)
173
+ flag.detect do |f|
174
+ f.start_with?('--')
175
+ end.sub(/\A--(\[no-\])?/, '').sub(/[^\-\w].*\z/, '').to_sym
176
+ end
177
+
178
+ def try_call(v)
179
+ if v.respond_to? :call
180
+ v.call
181
+ else
182
+ v
183
+ end
184
+ end
185
+
186
+ def error(message, exit_code)
187
+ log_error message
188
+ fail ExecutionError.new(message, exit_code)
189
+ end
190
+
191
+ class ExecutionError < RuntimeError
192
+ attr_reader :exit_code
193
+
194
+ def initialize(message, exit_code)
195
+ super(message)
196
+ @exit_code = exit_code
197
+ end
198
+ end
199
+
200
+ def auto_output_coloring(coloring = ENV['I18N_TASKS_COLOR'] || STDOUT.isatty)
201
+ coloring_was = Rainbow.enabled
202
+ Rainbow.enabled = coloring
203
+ yield
204
+ ensure
205
+ Rainbow.enabled = coloring_was
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/processes/command/dsl'
4
+ require 'i18n/processes/command/options/common'
5
+ require 'i18n/processes/command/options/locales'
6
+ require 'i18n/processes/command/options/data'
7
+
8
+ module I18n::Processes
9
+ module Command
10
+ module Collection
11
+ def self.included(base)
12
+ base.module_eval do
13
+ include Command::DSL
14
+ include Command::Options::Common
15
+ include Command::Options::Locales
16
+ include Command::Options::Data
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/processes/cli'
4
+ require 'i18n/processes/reports/terminal'
5
+ require 'i18n/processes/reports/spreadsheet'
6
+
7
+ module I18n::Processes
8
+ module Command
9
+ class Commander
10
+ include ::I18n::Processes::Logging
11
+
12
+ attr_reader :i18n
13
+
14
+ # @param [I18n::Processes::BaseTask] i18n
15
+ def initialize(i18n)
16
+ @i18n = i18n
17
+ end
18
+
19
+ def run(name, opts = {})
20
+ name = name.to_sym
21
+ public_name = name.to_s.tr '_', '-'
22
+ log_verbose "task: #{public_name}(#{opts.map { |k, v| "#{k}: #{v.inspect}" } * ', '})"
23
+ if opts.empty? || method(name).arity.zero?
24
+ send name
25
+ else
26
+ send name, opts
27
+ end
28
+ end
29
+
30
+ protected
31
+
32
+ def terminal_report
33
+ @terminal_report ||= I18n::Processes::Reports::Terminal.new(i18n)
34
+ end
35
+
36
+ def spreadsheet_report
37
+ @spreadsheet_report ||= I18n::Processes::Reports::Spreadsheet.new(i18n)
38
+ end
39
+
40
+ delegate :base_locale, :locales, :t, to: :i18n
41
+ end
42
+ end
43
+ end