Skip to content

Commit 84ca2c4

Browse files
committed
inital
0 parents  commit 84ca2c4

17 files changed

+594
-0
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/.bundle/
2+
/.yardoc
3+
/_yardoc/
4+
/coverage/
5+
/doc/
6+
/pkg/
7+
/spec/reports/
8+
/tmp/

.rspec

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--require spec_helper

Gemfile

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
source "https://rubygems.org"
2+
3+
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4+
5+
# Specify your gem's dependencies in extract_i18n.gemspec
6+
gemspec
7+
8+
gem 'pry'
9+
gem 'rspec'

LICENSE.txt

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2020 Stefan Wienert
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.

README.md

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# ExtractI18n
2+
3+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/extract_i18n`. To experiment with that code, run `bin/console` for an interactive prompt.
4+
5+
TODO: Delete this and the text above, and describe your gem
6+
7+
## Installation
8+
9+
Add this line to your application's Gemfile:
10+
11+
```ruby
12+
gem 'extract_i18n'
13+
```
14+
15+
And then execute:
16+
17+
$ bundle
18+
19+
Or install it yourself as:
20+
21+
$ gem install extract_i18n
22+
23+
## Usage
24+
25+
TODO: Write usage instructions here
26+
27+
## Development
28+
29+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30+
31+
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).
32+
33+
## Contributing
34+
35+
Bug reports and pull requests are welcome on GitHub at https://github.com/zealot128/extract_i18n.
36+
37+
## License
38+
39+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

Rakefile

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require "bundler/gem_tasks"
2+
task :default => :spec

bin/console

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env ruby
2+
3+
require "bundler/setup"
4+
require "extract_i18n"
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__)

bin/setup

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
IFS=$'\n\t'
4+
set -vx
5+
6+
bundle install
7+
8+
# Do any other automated setup that you need to do here

exe/extract-i18n

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env ruby
2+
3+
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
4+
require 'extract_i18n/cli'
5+
6+
result = ExtractI18n::CLI.new.run
7+
exit(result ? 0 : 1)

extract_i18n.gemspec

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
lib = File.expand_path("../lib", __FILE__)
2+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3+
require "extract_i18n/version"
4+
5+
Gem::Specification.new do |spec|
6+
spec.name = "extract_i18n"
7+
spec.version = ExtractI18n::VERSION
8+
spec.authors = ["Stefan Wienert"]
9+
spec.email = ["[email protected]"]
10+
11+
spec.summary = %q{Extact i18n from RUBY Files using Ruby parser}
12+
spec.description = %q{Extact i18n from RUBY Files using Ruby parser}
13+
spec.homepage = "https://github.com/pludoni/extract_i18n"
14+
spec.license = "MIT"
15+
16+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17+
# to allow pushing to a single host or delete this section to allow pushing to any host.
18+
19+
# Specify which files should be added to the gem when it is released.
20+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
22+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23+
end
24+
spec.bindir = "exe"
25+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26+
spec.require_paths = ["lib"]
27+
28+
spec.add_runtime_dependency 'parser', '>= 2.6'
29+
spec.add_runtime_dependency 'tty-prompt'
30+
spec.add_dependency "diff-lcs"
31+
spec.add_dependency "diffy"
32+
end

lib/extract_i18n.rb

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# frozen_string_literal: true
2+
3+
require "extract_i18n/version"
4+
5+
module ExtractI18n
6+
class Error < StandardError; end
7+
end
8+
9+
require 'extract_i18n/version'
10+
require 'extract_i18n/file_processor'

lib/extract_i18n/cli.rb

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
require 'optparse'
2+
require 'extract_i18n/file_processor'
3+
require 'extract_i18n/version'
4+
require 'open-uri'
5+
6+
module ExtractI18n
7+
# Cli Class
8+
class CLI
9+
def initialize
10+
@options = {}
11+
ARGV << '-h' if ARGV.empty?
12+
OptionParser.new do |opts|
13+
opts.banner = "Usage: #{__FILE__} -l <locale> -w <target-yml> [path*]"
14+
15+
opts.on('--version', 'Print version number') do
16+
puts ExtractI18n::VERSION
17+
exit
18+
end
19+
20+
opts.on('-lLOCALE', '--locale=LOCALE', 'default locale for extraction (Default = en)') do |f|
21+
@options[:locale] = f || 'en'
22+
end
23+
24+
opts.on('-wYAML', '--write=YAML-FILE', 'Write extracted keys to YAML file (default = config/locales/unsorted.LOCALE.yml)') do |f|
25+
@options[:write_to] = f || "config/locales/unsorted.#{@options[:locale]}"
26+
end
27+
28+
opts.on('-h', '--help', 'Prints this help') do
29+
puts opts
30+
exit
31+
end
32+
end.parse!
33+
34+
@files = ARGV
35+
end
36+
37+
def run
38+
paths = @files.empty? ? [] : @files
39+
paths.each do |path|
40+
if File.directory?(path)
41+
glob_path = File.join(path, '**', '*.rb')
42+
Dir.glob(glob_path) do |file_path|
43+
process_file file_path
44+
end
45+
else
46+
process_file path
47+
end
48+
end
49+
end
50+
51+
def process_file(file_path)
52+
puts "Processing: #{file_path}"
53+
ExtractI18n::FileProcessor.new(
54+
file_path: file_path,
55+
write_to: @options[:write_to],
56+
locale: @options[:locale]
57+
).run
58+
end
59+
end
60+
end

lib/extract_i18n/file_processor.rb

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
require 'extract_i18n/transform'
2+
require 'parser/current'
3+
require 'diffy'
4+
5+
module ExtractI18n
6+
class FileProcessor
7+
PROMPT = TTY::Prompt.new
8+
9+
def initialize(file_path:, write_to:, locale:)
10+
@file_path = file_path
11+
@file_key = @file_path.gsub(%r{^app/|\.rb|^lib/$}, '').gsub('/', '.')
12+
@locale = locale
13+
@write_to = write_to
14+
end
15+
16+
def run
17+
puts " reading #{@file_path}"
18+
read_and_transform do |result, i18n_changes|
19+
puts Diffy::Diff.new(original_content, result, context: 1).to_s(:color)
20+
if PROMPT.yes?("Save changes?")
21+
File.write(@file_path, result)
22+
update_i18n_yml_file(i18n_changes)
23+
puts PASTEL.green("Saved")
24+
end
25+
end
26+
end
27+
28+
private
29+
30+
def update_i18n_yml_file(i18n_changes)
31+
base = if File.exist?(@write_to)
32+
YAML.load_file(@write_to)
33+
else
34+
{}
35+
end
36+
i18n_changes.each do |key, value|
37+
tree = base
38+
keys = key.split('.').unshift(@locale)
39+
keys.each_with_index do |part, i|
40+
if i == keys.length - 1
41+
tree[part] = value
42+
else
43+
tree = tree[part] ||= {}
44+
end
45+
end
46+
end
47+
File.write(@write_to, base.to_yaml)
48+
end
49+
50+
def original_content
51+
@original_content ||= File.read(file_path)
52+
end
53+
54+
def read_and_transform(&block)
55+
buffer = Parser::Source::Buffer.new('(example)')
56+
buffer.source = original_content
57+
begin
58+
temp = Parser::CurrentRuby.parse(original_content)
59+
rewriter = ExtractI18n::Transform.new(file_key: @file_key)
60+
61+
# Rewrite the AST, returns a String with the new form.
62+
output = rewriter.rewrite(buffer, temp)
63+
if output != original_content
64+
yield(output, rewriter.i18n_changes)
65+
end
66+
rescue StandardError => e
67+
puts 'Parsing error'
68+
puts e.inspect
69+
nil
70+
end
71+
end
72+
end
73+
end

0 commit comments

Comments
 (0)