extract_i18n 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +5 -2
- data/extract_i18n.gemspec +1 -0
- data/lib/extract_i18n.rb +5 -1
- data/lib/extract_i18n/adapters/erb_adapter.rb +43 -0
- data/lib/extract_i18n/html_extractor/erb_document.rb +83 -0
- data/lib/extract_i18n/html_extractor/match.rb +43 -0
- data/lib/extract_i18n/html_extractor/match/attribute_match.rb +25 -0
- data/lib/extract_i18n/html_extractor/match/base_match.rb +18 -0
- data/lib/extract_i18n/html_extractor/match/erb_directive_match.rb +33 -0
- data/lib/extract_i18n/html_extractor/match/node_match.rb +28 -0
- data/lib/extract_i18n/html_extractor/match/plain_text_match.rb +19 -0
- data/lib/extract_i18n/html_extractor/runner.rb +94 -0
- data/lib/extract_i18n/html_extractor/two_way_regexp.rb +70 -0
- data/lib/extract_i18n/version.rb +1 -1
- metadata +26 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e8c03edd94a9dd0fd99ecb17c2f2140b9ba96894a3e36b29ae623b5a79cfec8
|
4
|
+
data.tar.gz: 2c7bd0bae8c25e443d7f33c31dbdc5eb0832ad0d9bf2367a051555e16dcc8176
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3b44e7bdc8c7b4db6a8391c6cdfc2b82ec9bde4c0fc4cf4feffc982cbeb016dec5ee979799a77b7ed96029693cc059082161882b8e7443aceee50be8651e9fe
|
7
|
+
data.tar.gz: 637756d6127ccb0a719e723a6d155206a5b87a485e3b91c2698bd8749ab24f73765df1fb66cf79ec3e1af253e3fe28c8333bf009ffce7db79ea58f535e1e13c1
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# ExtractI18n
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/extract_i18n.svg)](https://badge.fury.io/rb/extract_i18n)
|
4
|
+
|
3
5
|
CLI helper program to automatically extract bare text strings into Rails I18n interactively.
|
4
6
|
|
5
7
|
Useful when adding i18n to a medium/large Rails app.
|
@@ -7,13 +9,14 @@ Useful when adding i18n to a medium/large Rails app.
|
|
7
9
|
This Gem **supports** the following source files:
|
8
10
|
|
9
11
|
- Ruby files (controllers, models etc.) via Ruby-Parser, e.g. walking all Ruby Strings
|
10
|
-
- Slim Views (via Regexp parser by SlimKeyfy)
|
12
|
+
- Slim Views (via Regexp parser by [SlimKeyfy](https://github.com/phrase/slimkeyfy) (MIT License))
|
11
13
|
- Vue Pug views
|
12
14
|
- Pug is very similar to slim and thus relatively good extractable via Regexp.
|
15
|
+
- ERB views
|
16
|
+
- by vendoring/extending https://github.com/ProGM/i18n-html_extractor (MIT License)
|
13
17
|
|
14
18
|
CURRENTLY THERE IS **NO SUPPORT** FOR:
|
15
19
|
|
16
|
-
- erb ( integrating/forking https://github.com/zigzag/ready_for_i18n or https://github.com/ProGM/i18n-html_extractor)
|
17
20
|
- haml ( integrating https://github.com/shaiguitar/haml-i18n-extractor)
|
18
21
|
- vue html templates ([Check out my vue pug converting script](https://gist.github.com/zealot128/6c41df1d33a810856a557971a04989f6))
|
19
22
|
|
data/extract_i18n.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
|
+
spec.add_runtime_dependency 'nokogiri'
|
28
29
|
spec.add_runtime_dependency 'parser', '>= 2.6'
|
29
30
|
spec.add_runtime_dependency 'slim'
|
30
31
|
spec.add_runtime_dependency 'tty-prompt'
|
data/lib/extract_i18n.rb
CHANGED
@@ -4,11 +4,14 @@ require "extract_i18n/version"
|
|
4
4
|
|
5
5
|
require "zeitwerk"
|
6
6
|
loader = Zeitwerk::Loader.for_gem
|
7
|
+
loader.inflector.inflect(
|
8
|
+
"html_extractor" => "HTMLExtractor",
|
9
|
+
)
|
7
10
|
loader.setup # ready!
|
8
11
|
|
9
12
|
module ExtractI18n
|
10
13
|
class << self
|
11
|
-
attr_accessor :strip_path, :ignore_hash_keys, :ignore_functions, :ignorelist
|
14
|
+
attr_accessor :strip_path, :ignore_hash_keys, :ignore_functions, :ignorelist, :html_fields_with_plaintext
|
12
15
|
end
|
13
16
|
|
14
17
|
self.strip_path = %r{^app/(javascript|controllers|views)|^lib|^src|^app}
|
@@ -20,6 +23,7 @@ module ExtractI18n
|
|
20
23
|
'_',
|
21
24
|
'::'
|
22
25
|
]
|
26
|
+
self.html_fields_with_plaintext = %w[title placeholder alt label aria-label modal-title]
|
23
27
|
|
24
28
|
def self.key(string, length: 25)
|
25
29
|
string.strip.
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ExtractI18n::Adapters
|
2
|
+
class ErbAdapter < Adapter
|
3
|
+
def run(original_content)
|
4
|
+
unless valid_erb?(original_content)
|
5
|
+
puts "ERB invalid!"
|
6
|
+
return original_content
|
7
|
+
end
|
8
|
+
document = ExtractI18n::HTMLExtractor::ErbDocument.parse_string(original_content)
|
9
|
+
nodes_to_translate = ExtractI18n::HTMLExtractor::Match::Finder.new(document).matches
|
10
|
+
nodes_to_translate.each { |node|
|
11
|
+
next if node.text == ""
|
12
|
+
|
13
|
+
process_change(node)
|
14
|
+
}
|
15
|
+
result = document.save
|
16
|
+
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid_erb?(content)
|
21
|
+
Parser::CurrentRuby.parse(ERB.new(content).src)
|
22
|
+
true
|
23
|
+
rescue StandardError => e
|
24
|
+
warn e.inspect
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_change(node)
|
29
|
+
change = ExtractI18n::SourceChange.new(
|
30
|
+
i18n_key: "#{@file_key}.#{ExtractI18n.key(node.text.strip)}",
|
31
|
+
i18n_string: node.text,
|
32
|
+
interpolate_arguments: {},
|
33
|
+
source_line: node.to_s,
|
34
|
+
remove: node.text,
|
35
|
+
t_template: %{ t('%s') },
|
36
|
+
interpolation_type: :ruby
|
37
|
+
)
|
38
|
+
if @on_ask.call(change)
|
39
|
+
node.replace_text!(change.key, change.i18n_t)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module ExtractI18n
|
4
|
+
module HTMLExtractor
|
5
|
+
class ErbDocument
|
6
|
+
ERB_REGEXPS = [
|
7
|
+
TwoWayRegexp.new(/<%=(?<inner_text>.+?)%>/m, /@@=(?<inner_text>[a-z0-9\-\._]+)@@/m),
|
8
|
+
TwoWayRegexp.new(/<%#(?<inner_text>.+?)%>/m, /@@#(?<inner_text>[a-z0-9\-\._]+)@@/m),
|
9
|
+
TwoWayRegexp.new(/<%(?<inner_text>.+?)%>/m, /@@(?<inner_text>[a-z0-9\-\._]+)@@/m)
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
attr_reader :erb_directives
|
13
|
+
|
14
|
+
def initialize(document, erb_directives)
|
15
|
+
@document = document
|
16
|
+
@erb_directives = erb_directives
|
17
|
+
end
|
18
|
+
|
19
|
+
def save
|
20
|
+
result = @document.to_html(indent: 2, encoding: 'UTF-8')
|
21
|
+
ERB_REGEXPS.each do |regexp|
|
22
|
+
regexp.inverse_replace!(result) do |string_format, data|
|
23
|
+
string_format % { inner_text: erb_directives[data[:inner_text]] }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
def method_missing(name, *args, &block)
|
30
|
+
@document.public_send(name, *args, &block) if @document.respond_to? name
|
31
|
+
end
|
32
|
+
|
33
|
+
class <<self
|
34
|
+
def parse(filename, verbose: false)
|
35
|
+
file_content = ''
|
36
|
+
File.open(filename) do |file|
|
37
|
+
file.read(nil, file_content)
|
38
|
+
return parse_string(file_content, verbose: verbose)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_string(string, verbose: false)
|
43
|
+
erb_directives = extract_erb_directives! string
|
44
|
+
document = create_document(string)
|
45
|
+
log_errors(document.errors, string) if verbose
|
46
|
+
ErbDocument.new(document, erb_directives)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def create_document(file_content)
|
52
|
+
if file_content.start_with?('<!DOCTYPE')
|
53
|
+
Nokogiri::HTML(file_content)
|
54
|
+
else
|
55
|
+
Nokogiri::HTML.fragment(file_content)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def log_errors(errors, file_content)
|
60
|
+
return if errors.empty?
|
61
|
+
text = file_content.split("\n")
|
62
|
+
errors.each do |e|
|
63
|
+
puts "Error at line #{e.line}: #{e}".red
|
64
|
+
puts text[e.line - 1]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def extract_erb_directives!(text)
|
69
|
+
erb_directives = {}
|
70
|
+
|
71
|
+
ERB_REGEXPS.each do |regexp|
|
72
|
+
regexp.replace!(text) do |string_format, data|
|
73
|
+
key = SecureRandom.uuid
|
74
|
+
erb_directives[key] = data[:inner_text]
|
75
|
+
string_format % { inner_text: key }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
erb_directives
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ExtractI18n
|
2
|
+
module HTMLExtractor
|
3
|
+
module Match
|
4
|
+
class Finder
|
5
|
+
attr_reader :document
|
6
|
+
|
7
|
+
def initialize(document)
|
8
|
+
@document = document
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches
|
12
|
+
erb_nodes(document) + plain_text_nodes(document) + form_fields(document)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def erb_nodes(document)
|
18
|
+
document.erb_directives.map do |fragment_id, _|
|
19
|
+
ErbDirectiveMatch.create(document, fragment_id)
|
20
|
+
end.flatten.compact
|
21
|
+
end
|
22
|
+
|
23
|
+
def plain_text_nodes(document)
|
24
|
+
leaf_nodes.map! { |node| PlainTextMatch.create(document, node) }.flatten.compact
|
25
|
+
end
|
26
|
+
|
27
|
+
def form_fields(document)
|
28
|
+
ExtractI18n.html_fields_with_plaintext.flat_map do |field|
|
29
|
+
document.
|
30
|
+
css("[#{field}]").
|
31
|
+
select { |input| input[field] && !input[field].empty? }.
|
32
|
+
reject { |n| n[field] =~ /\@\@(=?)[a-z0-9\-]+\@\@/ }.
|
33
|
+
flat_map { |node| AttributeMatch.create(document, node, field) }
|
34
|
+
end.compact
|
35
|
+
end
|
36
|
+
|
37
|
+
def leaf_nodes
|
38
|
+
@leaf_nodes ||= document.css('*:not(:has(*))').select { |n| n.text && !n.text.empty? }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ExtractI18n
|
2
|
+
module HTMLExtractor
|
3
|
+
module Match
|
4
|
+
class AttributeMatch < BaseMatch
|
5
|
+
def initialize(document, node, text, attribute)
|
6
|
+
super(document, node, text)
|
7
|
+
@attribute = attribute
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.create(document, node, attribute)
|
11
|
+
if node[attribute] && !node[attribute].empty?
|
12
|
+
[new(document, node, node[attribute], attribute)]
|
13
|
+
else
|
14
|
+
[]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def replace_text!(key, i18n_t)
|
19
|
+
document.erb_directives[key] = i18n_t
|
20
|
+
node[@attribute] = "@@=#{key}@@"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ExtractI18n
|
2
|
+
module HTMLExtractor
|
3
|
+
module Match
|
4
|
+
class BaseMatch < NodeMatch
|
5
|
+
attr_reader :node
|
6
|
+
|
7
|
+
def initialize(document, node, text)
|
8
|
+
super(document, text)
|
9
|
+
@node = node
|
10
|
+
end
|
11
|
+
|
12
|
+
def replace_text!
|
13
|
+
node.content = translation_key_object
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ExtractI18n
|
2
|
+
module HTMLExtractor
|
3
|
+
module Match
|
4
|
+
class ErbDirectiveMatch < NodeMatch
|
5
|
+
REGEXPS = [
|
6
|
+
[/^([ \t]*link_to )(("[^"]+")|('[^']+'))/, '\1%s', 2],
|
7
|
+
[/^([ \t]*link_to (.*),[ ]?title:[ ]?)(("[^"]+")|('[^']+'))/, '\1%s', 3],
|
8
|
+
[/^([ \t]*[a-z_]+\.[a-z_]+_field (.*),[ ]?placeholder:[ ]?)(("[^"]+")|('[^']+'))/, '\1%s', 3],
|
9
|
+
[/^([ \t]*[a-z_]+\.text_area (.*),[ ]?placeholder:[ ]?)(("[^"]+")|('[^']+'))/, '\1%s', 3],
|
10
|
+
[/^([ \t]*[a-z_]+\.submit )(("[^"]+")|('[^']+'))/, '\1%s', 2],
|
11
|
+
[/^([ \t]*[a-z_]+\.label\s+\:[a-z_]+\,\s+)(("[^"]+")|('[^']+'))/, '\1%s', 2]
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
def initialize(document, fragment_id, text, regexp)
|
15
|
+
super(document, text)
|
16
|
+
@fragment_id = fragment_id
|
17
|
+
@regexp = regexp
|
18
|
+
end
|
19
|
+
|
20
|
+
def replace_text!(key, i18n_t)
|
21
|
+
document.erb_directives[@fragment_id].gsub!(@regexp[0], @regexp[1] % i18n_t.strip)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.create(document, fragment_id)
|
25
|
+
REGEXPS.map do |r|
|
26
|
+
match = document.erb_directives[fragment_id].match(r[0])
|
27
|
+
new(document, fragment_id, match[r[2]][1...-1], r) if match && match[r[2]]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ExtractI18n
|
2
|
+
module HTMLExtractor
|
3
|
+
module Match
|
4
|
+
class NodeMatch
|
5
|
+
attr_reader :document, :text
|
6
|
+
|
7
|
+
def initialize(document, text)
|
8
|
+
@document = document
|
9
|
+
@text = text
|
10
|
+
end
|
11
|
+
|
12
|
+
def translation_key_object
|
13
|
+
"t('.#{key}')"
|
14
|
+
end
|
15
|
+
|
16
|
+
def replace_text!
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_writer :key
|
21
|
+
|
22
|
+
def key
|
23
|
+
@key ||= text.parameterize.underscore
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ExtractI18n
|
2
|
+
module HTMLExtractor
|
3
|
+
module Match
|
4
|
+
class PlainTextMatch < BaseMatch
|
5
|
+
def self.create(document, node)
|
6
|
+
return nil if node.name.start_with?('script')
|
7
|
+
node.text.split(/\@\@(=?)[a-z0-9\-]+\@\@/).map! do |text|
|
8
|
+
new(document, node, text.strip) if !text.nil? && !text.empty?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def replace_text!(key, i18n_t)
|
13
|
+
document.erb_directives[key] = i18n_t
|
14
|
+
node.content = node.content.gsub(text, "@@=#{key}@@")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module ExtractI18
|
2
|
+
module HTMLExtractor
|
3
|
+
class Runner
|
4
|
+
include Cli
|
5
|
+
|
6
|
+
def initialize(args = {})
|
7
|
+
@files = file_list_from_pattern(args[:file_pattern])
|
8
|
+
@locale = args[:locale].presence
|
9
|
+
@verbose = args[:verbose]
|
10
|
+
end
|
11
|
+
|
12
|
+
def run_interactive
|
13
|
+
each_translation do |file, document, node|
|
14
|
+
puts "Found \"#{node.text}\" in #{file}:#{node.text}".green
|
15
|
+
next unless confirm 'Create a translation?', 'Yes', 'No', default: 'Yes'
|
16
|
+
|
17
|
+
node.key = prompt 'Choose i18n key', default: node.key
|
18
|
+
node.replace_text!
|
19
|
+
|
20
|
+
document.save!(file)
|
21
|
+
|
22
|
+
add_translations! node.key, node.text, default_locale: @locale
|
23
|
+
puts
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
each_translation do |file, document, node|
|
29
|
+
puts "Found \"#{node.text}\" in #{file}:#{node.text}".green
|
30
|
+
node.replace_text!
|
31
|
+
document.save!(file)
|
32
|
+
|
33
|
+
add_translation! I18n.default_locale, node.key, node.text
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_run
|
38
|
+
each_translation do |file, _, node|
|
39
|
+
puts "Found \"#{node.text}\" in #{file}:#{node.text}".green
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def file_list_from_pattern(pattern)
|
46
|
+
if pattern.present?
|
47
|
+
Dir[Rails.root.join(pattern)]
|
48
|
+
else
|
49
|
+
Dir[Rails.root.join('app', 'views', '**', '*.erb')] -
|
50
|
+
Dir[Rails.root.join('app', 'views', '**', '*.*.*.erb')]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_translations!(key, text, default_locale: nil)
|
55
|
+
return prompt_and_add_translation!(default_locale, key, default_text: text) if default_locale
|
56
|
+
prompt_and_add_translation!(I18n.default_locale, key, default_text: text)
|
57
|
+
|
58
|
+
I18n.available_locales.each do |locale|
|
59
|
+
next if locale == I18n.default_locale
|
60
|
+
|
61
|
+
prompt_and_add_translation!(locale.to_s, key)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def prompt_and_add_translation!(locale, key, default_text: nil)
|
66
|
+
out_text = prompt "Choose #{locale} value", default: default_text
|
67
|
+
add_translation! locale, key, out_text
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_translation!(locale, key, value)
|
71
|
+
new_keys = i18n.missing_keys(locales: [locale]).set_each_value!(value)
|
72
|
+
i18n.data.merge! new_keys
|
73
|
+
puts "Added t(.#{key}), translated in #{locale} as #{value}:".green
|
74
|
+
puts new_keys.inspect
|
75
|
+
end
|
76
|
+
|
77
|
+
def i18n
|
78
|
+
I18n::Tasks::BaseTask.new
|
79
|
+
end
|
80
|
+
|
81
|
+
def each_translation
|
82
|
+
@files.each do |file|
|
83
|
+
document = I18n::HTMLExtractor::ErbDocument.parse file
|
84
|
+
nodes_to_translate = extract_all_nodes_to_translate(document)
|
85
|
+
nodes_to_translate.each { |node| yield(file, document, node) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def extract_all_nodes_to_translate(document)
|
90
|
+
Match::Finder.new(document).matches
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module ExtractI18n
|
2
|
+
module HTMLExtractor
|
3
|
+
class TwoWayRegexp
|
4
|
+
attr_reader :from, :to
|
5
|
+
|
6
|
+
def initialize(from, to)
|
7
|
+
@from = from
|
8
|
+
@to = to
|
9
|
+
end
|
10
|
+
|
11
|
+
def replace(text)
|
12
|
+
if block_given?
|
13
|
+
text.gsub(@from) do |matched_text|
|
14
|
+
yield(to_as_format, Regexp.last_match, matched_text)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
text.gsub(@from, reverse_to)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def replace!(text)
|
22
|
+
if block_given?
|
23
|
+
text.gsub!(@from) do |matched_text|
|
24
|
+
yield(to_as_format, Regexp.last_match, matched_text)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
text.gsub!(@from, reverse_to)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def inverse_replace(text)
|
32
|
+
if block_given?
|
33
|
+
text.gsub(@to) do |matched_text|
|
34
|
+
yield(from_as_format, Regexp.last_match, matched_text)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
text.gsub(@to, reverse_from)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def inverse_replace!(text)
|
42
|
+
if block_given?
|
43
|
+
text.gsub!(@to) do |matched_text|
|
44
|
+
yield(from_as_format, Regexp.last_match, matched_text)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
text.gsub!(@to, reverse_from)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def to_as_format
|
54
|
+
@to_as_format ||= @to.source.gsub('%', '%%').gsub!(/\(\?<([a-z_]+)>.*\)/, '%{\1}')
|
55
|
+
end
|
56
|
+
|
57
|
+
def from_as_format
|
58
|
+
@from_as_format ||= @from.source.gsub('%', '%%').gsub!(/\(\?<([a-z_]+)>.*\)/, '%{\1}')
|
59
|
+
end
|
60
|
+
|
61
|
+
def reverse_from
|
62
|
+
@reverse_from ||= @from.source.gsub(/\(\?<([a-z_]+)>.*\)/, '\k{\1}')
|
63
|
+
end
|
64
|
+
|
65
|
+
def reverse_to
|
66
|
+
@reverse_to ||= @to.source.gsub(/\(\?<([a-z_]+)>.*\)/, '\k{\1}')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/extract_i18n/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extract_i18n
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Wienert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: parser
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,12 +131,22 @@ files:
|
|
117
131
|
- extract_i18n.gemspec
|
118
132
|
- lib/extract_i18n.rb
|
119
133
|
- lib/extract_i18n/adapters/adapter.rb
|
134
|
+
- lib/extract_i18n/adapters/erb_adapter.rb
|
120
135
|
- lib/extract_i18n/adapters/ruby_adapter.rb
|
121
136
|
- lib/extract_i18n/adapters/slim_adapter.rb
|
122
137
|
- lib/extract_i18n/adapters/slim_adapter_wip.rb
|
123
138
|
- lib/extract_i18n/adapters/vue_adapter.rb
|
124
139
|
- lib/extract_i18n/cli.rb
|
125
140
|
- lib/extract_i18n/file_processor.rb
|
141
|
+
- lib/extract_i18n/html_extractor/erb_document.rb
|
142
|
+
- lib/extract_i18n/html_extractor/match.rb
|
143
|
+
- lib/extract_i18n/html_extractor/match/attribute_match.rb
|
144
|
+
- lib/extract_i18n/html_extractor/match/base_match.rb
|
145
|
+
- lib/extract_i18n/html_extractor/match/erb_directive_match.rb
|
146
|
+
- lib/extract_i18n/html_extractor/match/node_match.rb
|
147
|
+
- lib/extract_i18n/html_extractor/match/plain_text_match.rb
|
148
|
+
- lib/extract_i18n/html_extractor/runner.rb
|
149
|
+
- lib/extract_i18n/html_extractor/two_way_regexp.rb
|
126
150
|
- lib/extract_i18n/slimkeyfy/slim_transformer.rb
|
127
151
|
- lib/extract_i18n/slimkeyfy/vue_transformer.rb
|
128
152
|
- lib/extract_i18n/slimkeyfy/whitespacer.rb
|