slimkeyfy 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/.rspec +3 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +22 -0
- data/LICENSE +21 -0
- data/README.md +172 -0
- data/bin/slimkeyfy +5 -0
- data/lib/.DS_Store +0 -0
- data/lib/slimkeyfy/console/command_line.rb +90 -0
- data/lib/slimkeyfy/console/io_action.rb +30 -0
- data/lib/slimkeyfy/console/printer.rb +50 -0
- data/lib/slimkeyfy/console/translate.rb +101 -0
- data/lib/slimkeyfy/console.rb +8 -0
- data/lib/slimkeyfy/slimutils/file_utils.rb +61 -0
- data/lib/slimkeyfy/slimutils/hash_merging.rb +84 -0
- data/lib/slimkeyfy/slimutils/key_generator.rb +70 -0
- data/lib/slimkeyfy/slimutils/yaml_processor.rb +56 -0
- data/lib/slimkeyfy/slimutils.rb +8 -0
- data/lib/slimkeyfy/transformer/base_transformer.rb +42 -0
- data/lib/slimkeyfy/transformer/controller_transformer.rb +20 -0
- data/lib/slimkeyfy/transformer/slim_transformer.rb +92 -0
- data/lib/slimkeyfy/transformer/whitespacer.rb +48 -0
- data/lib/slimkeyfy/transformer/word.rb +49 -0
- data/lib/slimkeyfy/transformer.rb +9 -0
- data/lib/slimkeyfy/version.rb +3 -0
- data/lib/slimkeyfy.rb +12 -0
- data/slimkeyfy.gemspec +21 -0
- data/vendor/bundle/bin/htmldiff +25 -0
- data/vendor/bundle/bin/ldiff +25 -0
- data/vendor/bundle/bin/rspec +23 -0
- data/vendor/bundle/build_info/diff-lcs-1.2.5.info +1 -0
- data/vendor/bundle/build_info/rspec-3.0.0.info +1 -0
- data/vendor/bundle/build_info/rspec-core-3.0.2.info +1 -0
- data/vendor/bundle/build_info/rspec-expectations-3.0.2.info +1 -0
- data/vendor/bundle/build_info/rspec-mocks-3.0.2.info +1 -0
- data/vendor/bundle/build_info/rspec-support-3.0.2.info +1 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/.autotest +3 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/.gemtest +0 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/.hoerc +2 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/.rspec +2 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/.travis.yml +22 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/Contributing.rdoc +64 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/Gemfile +20 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/History.rdoc +152 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/License.rdoc +39 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/Manifest.txt +38 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/README.rdoc +85 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/Rakefile +41 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/autotest/discover.rb +1 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/bin/htmldiff +32 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/bin/ldiff +6 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/docs/COPYING.txt +339 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/docs/artistic.txt +127 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/array.rb +7 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/block.rb +37 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/callbacks.rb +322 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/change.rb +177 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/htmldiff.rb +149 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/hunk.rb +276 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/internals.rb +301 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/ldiff.rb +195 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/string.rb +5 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff/lcs.rb +805 -0
- data/vendor/bundle/gems/diff-lcs-1.2.5/lib/diff-lcs.rb +3 -0
- data/vendor/bundle/gems/rspec-3.0.0/License.txt +24 -0
- data/vendor/bundle/gems/rspec-3.0.0/README.md +47 -0
- data/vendor/bundle/gems/rspec-3.0.0/lib/rspec.rb +3 -0
- data/vendor/bundle/gems/rspec-core-3.0.2/.document +5 -0
- data/vendor/bundle/gems/rspec-core-3.0.2/.yardopts +7 -0
- data/vendor/bundle/gems/rspec-core-3.0.2/Changelog.md +1466 -0
- data/vendor/bundle/gems/rspec-core-3.0.2/License.txt +25 -0
- data/vendor/bundle/gems/rspec-core-3.0.2/README.md +243 -0
- data/vendor/bundle/gems/rspec-core-3.0.2/exe/rspec +4 -0
- data/vendor/bundle/gems/rspec-expectations-3.0.2/.document +5 -0
- data/vendor/bundle/gems/rspec-expectations-3.0.2/.yardopts +6 -0
- data/vendor/bundle/gems/rspec-expectations-3.0.2/Changelog.md +749 -0
- data/vendor/bundle/gems/rspec-expectations-3.0.2/License.txt +24 -0
- data/vendor/bundle/gems/rspec-expectations-3.0.2/README.md +278 -0
- data/vendor/bundle/gems/rspec-mocks-3.0.2/.document +5 -0
- data/vendor/bundle/gems/rspec-mocks-3.0.2/.yardopts +6 -0
- data/vendor/bundle/gems/rspec-mocks-3.0.2/Changelog.md +733 -0
- data/vendor/bundle/gems/rspec-mocks-3.0.2/License.txt +24 -0
- data/vendor/bundle/gems/rspec-mocks-3.0.2/README.md +380 -0
- data/vendor/bundle/gems/rspec-support-3.0.2/Changelog.md +30 -0
- data/vendor/bundle/gems/rspec-support-3.0.2/LICENSE.txt +22 -0
- data/vendor/bundle/gems/rspec-support-3.0.2/README.md +17 -0
- data/vendor/bundle/specifications/diff-lcs-1.2.5.gemspec +68 -0
- data/vendor/bundle/specifications/rspec-3.0.0.gemspec +43 -0
- data/vendor/bundle/specifications/rspec-core-3.0.2.gemspec +66 -0
- data/vendor/bundle/specifications/rspec-expectations-3.0.2.gemspec +51 -0
- data/vendor/bundle/specifications/rspec-mocks-3.0.2.gemspec +48 -0
- data/vendor/bundle/specifications/rspec-support-3.0.2.gemspec +42 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 51e9f1359e2f3cec0cca00636171ddcdb452fc13
|
4
|
+
data.tar.gz: f8fe3487b10951a60283ff911bb7acd9d080d8e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6ec0ec5446e2fa6853695ea7fb96d3ac4921666e001c449b39d9da379c7b6a253fd7a5b955e5e6f796ffc0314164a925f37da1ee6144ae7c4e072a61ed7ed633
|
7
|
+
data.tar.gz: 65b12829f6513726748d6a646da5524343af0b19de8f74cdefdf489fd7eeabc1fb1214e4812cbd326ab77a7567797c05fb77b4b2f3830fa1d78d8325e8b97333
|
data/.gitignore
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
# Gemfile.lock
|
30
|
+
# .ruby-version
|
31
|
+
# .ruby-gemset
|
32
|
+
|
33
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
+
.rvmrc
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.2.5)
|
5
|
+
rspec (3.0.0)
|
6
|
+
rspec-core (~> 3.0.0)
|
7
|
+
rspec-expectations (~> 3.0.0)
|
8
|
+
rspec-mocks (~> 3.0.0)
|
9
|
+
rspec-core (3.0.2)
|
10
|
+
rspec-support (~> 3.0.0)
|
11
|
+
rspec-expectations (3.0.2)
|
12
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
13
|
+
rspec-support (~> 3.0.0)
|
14
|
+
rspec-mocks (3.0.2)
|
15
|
+
rspec-support (~> 3.0.0)
|
16
|
+
rspec-support (3.0.2)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 PhraseApp.com
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
Slimkeyfy
|
2
|
+
=
|
3
|
+
Extract plain Strings from .slim views and Rails controllers to replace them with I18n's t() method. Keys with it's translations will be streamed to a YAML file.
|
4
|
+
```ruby
|
5
|
+
slimkeyfy app/views/users/show.html.slim en
|
6
|
+
# users/show.html.slim
|
7
|
+
h1 Hello World!
|
8
|
+
# converts to
|
9
|
+
h1= t('.hello_world')
|
10
|
+
# config/locales/users.en.yaml
|
11
|
+
# en:
|
12
|
+
# user:
|
13
|
+
# show:
|
14
|
+
# hello_world: Hello World!
|
15
|
+
```
|
16
|
+
|
17
|
+
Install
|
18
|
+
-
|
19
|
+
|
20
|
+
With Ruby Gems
|
21
|
+
```ruby
|
22
|
+
> gem install slimkeyfy
|
23
|
+
```
|
24
|
+
|
25
|
+
With Bundler
|
26
|
+
```ruby
|
27
|
+
group :development do
|
28
|
+
# Github
|
29
|
+
gem 'slimkeyfy', github: 'https://github.com/phrase/slimkeyfy.git'
|
30
|
+
# or with concrete version
|
31
|
+
gem 'slimkeyfy', '~> 0.1'
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
Approach
|
36
|
+
-
|
37
|
+
Most of the time tools like this go for a 80/20 approach stating that 80% can be done right and 20% have to be done manually. Our approach is similar but a bit different. Translating and tagging your Rails app can be error prone. In order to reduce this Slimkeyfy streams in every line that matches the regular expression engine and prompts you to take an action. This guarantees a higher quality but also gets us closer to the 90%. It might take a little more time than full automation. The collected data is then processed into a YAML file. If you don't provide a YAML one will be created. All your processed views and resulting translations will be merged with the existing YAML.
|
38
|
+
|
39
|
+
Usage
|
40
|
+
-
|
41
|
+
```unix
|
42
|
+
slimkeyfy INPUT_FILENAME_OR_DIRECTORY LOCALE (e.g. en, fr) [YAML_FILE] [Options]
|
43
|
+
```
|
44
|
+
- If you do not provide a YAML file - one will be created at configs/locales/view_folder_name.locale.yml
|
45
|
+
- If you provide one make sure that the top level locale matches your provided locale
|
46
|
+
- The YAML file will be loaded as a hash and deep_merged with the new found translations
|
47
|
+
|
48
|
+
**Stream** - walks through the given file/files and if a regex hits you will be prompted to apply (y)es, discard (n)o, tag (x) (comments suggestions above the processed line) or (a)bort (only aborts the current file).
|
49
|
+
|
50
|
+
without YAML file
|
51
|
+
```unix
|
52
|
+
slimkeyfy path/to/your/file.html.slim en
|
53
|
+
```
|
54
|
+
with given YAML file (has to be valid YAML! with the top level locale matching your provided locale)
|
55
|
+
```unix
|
56
|
+
slimkeyfy path/to/your/dir/ en path/to/your/en.yml
|
57
|
+
```
|
58
|
+
A Backup (.bak) of the old file will be created e.g. index.html.slim => index.html.slim.bak.
|
59
|
+
Providing ---no-backup creates the backups temporarily and deletes them right after you apply your changes. (be careful!)
|
60
|
+
|
61
|
+
Example Usage
|
62
|
+
-
|
63
|
+
```unix
|
64
|
+
your_app_name/
|
65
|
+
|- app/
|
66
|
+
|- views/
|
67
|
+
|- user/
|
68
|
+
new.html.slim
|
69
|
+
show.html.slim
|
70
|
+
|- project/
|
71
|
+
index.html.slim
|
72
|
+
...
|
73
|
+
...
|
74
|
+
|- config/
|
75
|
+
|- locales/
|
76
|
+
en.yml
|
77
|
+
...
|
78
|
+
...
|
79
|
+
|
80
|
+
> pwd
|
81
|
+
../your_app_name/
|
82
|
+
|
83
|
+
> slimkeyfy app/views/users/ en
|
84
|
+
... choose your changes here (y/n/x/a)
|
85
|
+
|
86
|
+
> ls app/views/users/
|
87
|
+
new.html.slim
|
88
|
+
show.html.slim
|
89
|
+
new.html.slim.bak
|
90
|
+
show.html.slim.bak
|
91
|
+
|
92
|
+
> ls config/locales/
|
93
|
+
user.en.yml
|
94
|
+
en.yml
|
95
|
+
|
96
|
+
> cat ../users/new.html.slim.bak
|
97
|
+
h1 Hello World!
|
98
|
+
|
99
|
+
> cat ../users/new.html.slim
|
100
|
+
h1= t('.hello_world')
|
101
|
+
|
102
|
+
> cat config/locales/en.yml
|
103
|
+
--
|
104
|
+
en:
|
105
|
+
keys..
|
106
|
+
|
107
|
+
> cat config/locales/users.en.yml
|
108
|
+
---
|
109
|
+
en:
|
110
|
+
users:
|
111
|
+
new:
|
112
|
+
hello_world: Hello World!
|
113
|
+
show:
|
114
|
+
...
|
115
|
+
```
|
116
|
+
Suggested Workflow
|
117
|
+
-
|
118
|
+
As HTML is not 100% parsable there will be errors in the conversion. To minimize your error rate we suggest to approach each view or view_folder individually. The i18n-tasks gem helped a lot by finding errors. Always double check your views and make sure that everything went smoothly. Especially double check all your links. Here is an example workflow:
|
119
|
+
```ruby
|
120
|
+
# 1. create a branch for a view folder
|
121
|
+
> git checkout -b users_localization
|
122
|
+
|
123
|
+
# 2. slimkeyfy the view folder you would like to tag
|
124
|
+
> slimkeyfy app/views/users/ en
|
125
|
+
|
126
|
+
# 3. go through all files and verify/add missing translations
|
127
|
+
# (check against the .bak files (use git diff))
|
128
|
+
> git diff app/views/users/views.html.slim
|
129
|
+
|
130
|
+
# 4. add your translations + keys to your locale file(s)
|
131
|
+
# 4.1 optional: Use the I18n-tasks gem to find missing translations
|
132
|
+
|
133
|
+
# 5. go through all your views and click through everything to actually "see" what changed
|
134
|
+
|
135
|
+
# 6. If everything is fine - clean up (remove .baks)
|
136
|
+
> rm app/views/users/*.bak
|
137
|
+
# Optional: remove temporary YAML files
|
138
|
+
> rm config/locales/users.en.yml
|
139
|
+
```
|
140
|
+
Testing
|
141
|
+
-
|
142
|
+
To test the application simply call rspec spec/.. from the root directory of slimkeyfy
|
143
|
+
```unix
|
144
|
+
bundle install
|
145
|
+
bundle exec rspec spec/
|
146
|
+
```
|
147
|
+
PhraseApp Integration
|
148
|
+
-
|
149
|
+
Now that you processed your views and moved the generated keys to your localization files it is quite easy to push it to PhraseApp. If you have not set up your account yet [take a look here](https://phraseapp.com/docs/about/setup-your-translations-with-phraseapp?language=en). Make sure that the latest gem of PhraseApp is installed by simply typing:
|
150
|
+
```unix
|
151
|
+
> gem install phrase
|
152
|
+
```
|
153
|
+
If you are already familiar with the PhraseApp gem you can upload your translation/localization files now. For more details on your setup have a look at our [detailed guide](https://phraseapp.com/docs/about/access-your-locale-files-with-the-api-client?language=en).
|
154
|
+
|
155
|
+
Todo
|
156
|
+
-
|
157
|
+
- YAML placeholders are currently not supported (We are working on it!).
|
158
|
+
- a dry run option where you can see what will happen if you convert.
|
159
|
+
- currently you are prompted for all hits - We would like to do 70-80% automatically and prompt for the 20-30% that cannot be decided upon.
|
160
|
+
- adding / generalizing Regular Expressions for better hit rate
|
161
|
+
|
162
|
+
Issues
|
163
|
+
-
|
164
|
+
- If you choose to take a lot of files at one time make sure to go through with it. It is not an issue to completely rerun everything (already translated strings are ignored) but should be avoided.
|
165
|
+
- some hits will not be correct, some things that should be found are not and sometimes the regex engine won't work for mysterious reasons. Slimkeyfy is a helper, it does not provide full automation. It might make your work a little easier.
|
166
|
+
|
167
|
+
References
|
168
|
+
-
|
169
|
+
* Other tools, not slim specific for this task is the [i15r gem](https://github.com/balinterdi/i15r). It can process .haml and .erb.
|
170
|
+
* I strongly recommend checking your translated app with the [i18n-tasks gem](https://github.com/glebm/i18n-tasks). It is a great tool in finding missing and unused translations.
|
171
|
+
* Always consult the [Official Rails Internationalization guide](http://guides.rubyonrails.org/i18n.html) if in doubt.
|
172
|
+
* Visit [PhraseApp on Github](https://github.com/phrase/phrase)
|
data/bin/slimkeyfy
ADDED
data/lib/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
class SlimKeyfy::Console::Commandline
|
4
|
+
def initialize(args)
|
5
|
+
@options = {}
|
6
|
+
@args = args
|
7
|
+
OptionParser.new(&method(:opt_scan)).parse!(@args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def wrong_usage
|
11
|
+
puts "Please provide a path to .slims and a locale name. See -h for more information."
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
|
15
|
+
def opt_scan(opts)
|
16
|
+
opts.banner = "
|
17
|
+
#{"Usage".white}: slimkeyfy #{"INPUT_FILENAME_OR_DIRECTORY".green} #{"LOCALE".red} #{"[YAML_FILE]".yellow} [Options]
|
18
|
+
e.g. slimkeyfy #{"app/views/users/".green} #{"en".red} #{"phrase/locales/en.yml".yellow} [Options]
|
19
|
+
|
20
|
+
#{"Description".white}: Extract plain Strings from .slim views and Rails controllers to
|
21
|
+
replace them with I18n's t() method. Keys with it's translations will be streamed
|
22
|
+
to a YAML file.
|
23
|
+
|
24
|
+
the following options are available:
|
25
|
+
|
26
|
+
"
|
27
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
28
|
+
puts opts
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
opts.on_tail('-v', '--version', 'Show current version') do
|
32
|
+
puts "0.1"
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
opts.on_tail('-R', '--recursive', 'If a directory is given all subdirectories will be walked either.
|
36
|
+
Without -r and a directory just the files within the first level are walked.
|
37
|
+
') do
|
38
|
+
@options[:recursive] = true
|
39
|
+
end
|
40
|
+
opts.on_tail('-b', '--no-backup', 'No Backups - for safety reasons - are created. For minimum safety we
|
41
|
+
recommend a version control like git. Backups will still be created for
|
42
|
+
comparison but deleted right after you agree to the changes.
|
43
|
+
') do
|
44
|
+
@options[:no_backup] = true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def run
|
49
|
+
@options[:input] = input = @args.shift
|
50
|
+
@options[:locale] = locale = @args.shift
|
51
|
+
@options[:yaml_output] = @args.shift
|
52
|
+
|
53
|
+
wrong_usage if (input.nil? or locale.nil?)
|
54
|
+
|
55
|
+
if File.directory?(input) then
|
56
|
+
directory_translate(input)
|
57
|
+
elsif File.file?(input) then
|
58
|
+
translate
|
59
|
+
else
|
60
|
+
raise "Please provide a file or directory!"
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def directory_translate(input)
|
66
|
+
rec = @options.fetch(:recursive, false)
|
67
|
+
SlimKeyfy::Slimutils::MFileUtils.walk(input, rec).each do |rec_input|
|
68
|
+
if File.file?(rec_input) and is_valid_ext?(rec_input) then
|
69
|
+
@options[:input] = rec_input
|
70
|
+
translate
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def translate
|
76
|
+
unless SlimKeyfy::Slimutils::MFileUtils.is_valid_extension?(@options[:input]) then
|
77
|
+
puts "invalid extension!"
|
78
|
+
return
|
79
|
+
end
|
80
|
+
@options[:ext] = SlimKeyfy::Slimutils::MFileUtils.file_extension(@options[:input])
|
81
|
+
|
82
|
+
puts "file=#{@options[:input]}"
|
83
|
+
translate_slim = SlimKeyfy::Console::Translate.new(@options)
|
84
|
+
begin
|
85
|
+
translate_slim.stream_mode
|
86
|
+
rescue Interrupt
|
87
|
+
SlimKeyfy::Slimutils::MFileUtils.restore(translate_slim.bak_path, translate_slim.original_file_path)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class SlimKeyfy::Console::IOAction
|
2
|
+
def self.yes_or_no?(msg)
|
3
|
+
puts "#{msg} (y|n)"
|
4
|
+
arg = STDIN.gets.chomp
|
5
|
+
if arg =~ /[yY](es)?/ then
|
6
|
+
true
|
7
|
+
elsif arg =~ /[nN]o?/ then
|
8
|
+
false
|
9
|
+
else
|
10
|
+
puts "Provide either (y)es or (n)o!"
|
11
|
+
self.yes_or_no?(msg)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
def self.choose(msg)
|
15
|
+
puts "#{msg} (y|n) (x for tagging | (a)bort)"
|
16
|
+
arg = STDIN.gets.chomp
|
17
|
+
if arg =~ /[yY](es)?/ then
|
18
|
+
"y"
|
19
|
+
elsif arg =~ /[nN]o?/ then
|
20
|
+
"n"
|
21
|
+
elsif arg =~ /x/ then
|
22
|
+
"x"
|
23
|
+
elsif arg =~ /a/ then
|
24
|
+
"a"
|
25
|
+
else
|
26
|
+
puts "Either (y)es, (n)o, (x) for tagging or (a) to abort"
|
27
|
+
self.choose(msg)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class SlimKeyfy::Console::Printer
|
2
|
+
def self.difference(old_line, new_line, translations)
|
3
|
+
puts "#{'-'.red} #{normalize(old_line).red}"
|
4
|
+
puts "#{'+'.green} #{normalize(new_line).green} => #{translations.to_s.yellow}"
|
5
|
+
puts "-"*40
|
6
|
+
end
|
7
|
+
def self.unix_diff(bak_path, file_path)
|
8
|
+
result = "Please install colordiff or diff (brew install colordiff)"
|
9
|
+
colordiff, diff = `which colordiff`, `which diff`
|
10
|
+
if not colordiff.empty? then
|
11
|
+
result = `colordiff #{bak_path} #{file_path}`
|
12
|
+
elsif not diff.empty? then
|
13
|
+
result =`diff #{bak_path} #{file_path}`
|
14
|
+
end
|
15
|
+
if result.nil? or result.strip.empty? then
|
16
|
+
puts "No changes for comparison found!"
|
17
|
+
else
|
18
|
+
puts "#{result}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
def self.normalize(line)
|
22
|
+
line.sub(/^\s*/, " ")
|
23
|
+
end
|
24
|
+
def self.tag(old_line, translations, comment_tag)
|
25
|
+
prettified_translations = translations.map{|k, v| "#{k}: #{v}, t('.#{k.split(".").last}')" }.join(" | ")
|
26
|
+
"#{indentation(old_line)}#{comment_tag} #{prettified_translations}\n#{old_line}"
|
27
|
+
end
|
28
|
+
def self.indentation(line)
|
29
|
+
return "" if line.nil? or line.empty?
|
30
|
+
" " * (line.size - line.gsub(/^\s+/, "").size)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class String
|
35
|
+
def colorize(color_code)
|
36
|
+
"\e[#{color_code}m#{self}\e[0m"
|
37
|
+
end
|
38
|
+
def red
|
39
|
+
colorize(31)
|
40
|
+
end
|
41
|
+
def green
|
42
|
+
colorize(32)
|
43
|
+
end
|
44
|
+
def yellow
|
45
|
+
colorize(34)
|
46
|
+
end
|
47
|
+
def white
|
48
|
+
colorize(37)
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
class SlimKeyfy::Console::Translate
|
2
|
+
|
3
|
+
attr_reader :original_file_path, :bak_path
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@extension = options[:ext]
|
7
|
+
@transformer = transformer
|
8
|
+
@original_file_path = options[:input]
|
9
|
+
@no_backup = options.fetch(:no_backup, false)
|
10
|
+
@bak_path = SlimKeyfy::Slimutils::MFileUtils.backup(@original_file_path)
|
11
|
+
@content = SlimKeyfy::Slimutils::FileReader.read(@bak_path).split("\n")
|
12
|
+
@file_path = SlimKeyfy::Slimutils::MFileUtils.create_new_file(@original_file_path)
|
13
|
+
@key_base = generate_key_base
|
14
|
+
@yaml_processor = create_yaml_processor(options)
|
15
|
+
@new_content = []
|
16
|
+
@changes = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def transformer
|
20
|
+
if @extension == "slim" then
|
21
|
+
SlimKeyfy::Transformer::SlimTransformer
|
22
|
+
elsif @extension == "rb" then
|
23
|
+
SlimKeyfy::Transformer::ControllerTransformer
|
24
|
+
else
|
25
|
+
puts "Unknown extension type!"
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_yaml_processor(options)
|
31
|
+
SlimKeyfy::Slimutils::YamlProcessor.new(options[:locale], @key_base, options.fetch(:yaml_output, nil))
|
32
|
+
end
|
33
|
+
|
34
|
+
def generate_key_base
|
35
|
+
SlimKeyfy::Slimutils::BaseKeyGenerator.generate_key_base_from_path(@original_file_path, @extension)
|
36
|
+
end
|
37
|
+
|
38
|
+
def stream_mode
|
39
|
+
@content.each_with_index do |old_line, idx|
|
40
|
+
word = SlimKeyfy::Transformer::Word.new(old_line, @key_base, @extension)
|
41
|
+
new_line, translations = @transformer.new(word, @yaml_processor).transform
|
42
|
+
if translations_are_invalid?(translations)
|
43
|
+
@yaml_processor.delete_translations(translations)
|
44
|
+
update_with(idx, old_line)
|
45
|
+
else
|
46
|
+
process_new_line(idx, old_line, new_line, translations)
|
47
|
+
@changes = true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
SlimKeyfy::Slimutils::FileWriter.write(@file_path, @new_content.join("\n"))
|
51
|
+
finalize!
|
52
|
+
end
|
53
|
+
|
54
|
+
def process_new_line(idx, old_line, new_line, translations)
|
55
|
+
SlimKeyfy::Console::Printer.difference(old_line, new_line, translations)
|
56
|
+
case SlimKeyfy::Console::IOAction.choose("Changes wanted?")
|
57
|
+
when "y" then update_with(idx, new_line)
|
58
|
+
when "n" then
|
59
|
+
update_with(idx, old_line)
|
60
|
+
@yaml_processor.delete_translations(translations)
|
61
|
+
when "x" then
|
62
|
+
update_with(idx, SlimKeyfy::Console::Printer.tag(old_line, translations, comment_tag))
|
63
|
+
@yaml_processor.delete_translations(translations)
|
64
|
+
when "a" then
|
65
|
+
SlimKeyfy::Slimutils::MFileUtils.restore(@bak_path, @original_file_path)
|
66
|
+
puts "Aborted!"
|
67
|
+
exit
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def finalize!
|
72
|
+
if @changes then
|
73
|
+
if SlimKeyfy::Console::IOAction.yes_or_no?("Do you like to review your changes?") then
|
74
|
+
SlimKeyfy::Console::Printer.unix_diff(@bak_path, @original_file_path)
|
75
|
+
end
|
76
|
+
if SlimKeyfy::Console::IOAction.yes_or_no?("Do you like to save your changes?") then
|
77
|
+
@yaml_processor.store!
|
78
|
+
puts "Saved! at #{@original_file_path}"
|
79
|
+
SlimKeyfy::Slimutils::MFileUtils.rm(@bak_path) if @no_backup
|
80
|
+
else
|
81
|
+
SlimKeyfy::Slimutils::MFileUtils.restore(@bak_path, @original_file_path)
|
82
|
+
puts "Restored!"
|
83
|
+
end
|
84
|
+
else
|
85
|
+
SlimKeyfy::Slimutils::MFileUtils.restore(@bak_path, @original_file_path)
|
86
|
+
puts "Nothing was changed!"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def update_with(idx, line)
|
91
|
+
@new_content[idx] = line
|
92
|
+
end
|
93
|
+
|
94
|
+
def translations_are_invalid?(translations)
|
95
|
+
translations.nil? or translations.empty?
|
96
|
+
end
|
97
|
+
|
98
|
+
def comment_tag
|
99
|
+
@transformer.slim? ? "//" : "#"
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'find'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class SlimKeyfy::Slimutils::MFileUtils
|
5
|
+
def self.restore(backup_path, original_file_path)
|
6
|
+
FileUtils.cp(backup_path, original_file_path)
|
7
|
+
FileUtils.rm(backup_path)
|
8
|
+
end
|
9
|
+
def self.rm(file_path)
|
10
|
+
FileUtils.rm(file_path)
|
11
|
+
end
|
12
|
+
def self.backup(input)
|
13
|
+
original_file_path = abs_path(input)
|
14
|
+
backup_path = "#{original_file_path}.bak"
|
15
|
+
FileUtils.cp(original_file_path, backup_path)
|
16
|
+
backup_path
|
17
|
+
end
|
18
|
+
def self.create_new_file(input)
|
19
|
+
new_file_path = self.abs_path(input)
|
20
|
+
SlimKeyfy::Slimutils::FileWriter.write(new_file_path, "")
|
21
|
+
new_file_path
|
22
|
+
end
|
23
|
+
def self.abs_path(file)
|
24
|
+
File.absolute_path(file)
|
25
|
+
end
|
26
|
+
def self.walk(arg, recursive=false)
|
27
|
+
directory = abs_path(arg)
|
28
|
+
files = []
|
29
|
+
if recursive then
|
30
|
+
Find.find(directory) do |f|
|
31
|
+
files << f if File.file?(f)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
files = Dir["#{directory}/*"]
|
35
|
+
end
|
36
|
+
files
|
37
|
+
end
|
38
|
+
def self.file_extension(file_path)
|
39
|
+
file_path.split(".").last
|
40
|
+
end
|
41
|
+
def self.is_valid_extension?(file_path)
|
42
|
+
ext = self.file_extension(file_path)
|
43
|
+
return false if (ext.nil? or ext.empty?)
|
44
|
+
(ext.end_with?("slim") or ext.end_with?("rb"))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class SlimKeyfy::Slimutils::FileReader
|
49
|
+
def self.read(file)
|
50
|
+
File.read(File.expand_path(file))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class SlimKeyfy::Slimutils::FileWriter
|
55
|
+
def self.write(full_path, content)
|
56
|
+
File.open(full_path, "w+") { |f| f.write(content) }
|
57
|
+
end
|
58
|
+
def self.append(full_path, content)
|
59
|
+
open(full_path, 'a') { |f| f.puts content}
|
60
|
+
end
|
61
|
+
end
|