extract_i18n 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.
- checksums.yaml +7 -0
- data/.github/workflows/verify.yml +23 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.rubocop.yml +35 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +21 -0
- data/README.md +52 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/extract-i18n +7 -0
- data/extract_i18n.gemspec +34 -0
- data/lib/extract_i18n.rb +41 -0
- data/lib/extract_i18n/adapters/adapter.rb +35 -0
- data/lib/extract_i18n/adapters/ruby_adapter.rb +126 -0
- data/lib/extract_i18n/adapters/slim_adapter.rb +70 -0
- data/lib/extract_i18n/adapters/slim_adapter_wip.rb +130 -0
- data/lib/extract_i18n/adapters/vue_adapter.rb +31 -0
- data/lib/extract_i18n/cli.rb +76 -0
- data/lib/extract_i18n/file_processor.rb +99 -0
- data/lib/extract_i18n/slimkeyfy/slim_transformer.rb +151 -0
- data/lib/extract_i18n/slimkeyfy/vue_transformer.rb +84 -0
- data/lib/extract_i18n/slimkeyfy/whitespacer.rb +46 -0
- data/lib/extract_i18n/slimkeyfy/word.rb +88 -0
- data/lib/extract_i18n/source_change.rb +98 -0
- data/lib/extract_i18n/version.rb +3 -0
- metadata +156 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExtractI18n::Adapters
|
4
|
+
class SlimAdapter < Adapter
|
5
|
+
def self.supports_relative_keys?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(original_content)
|
10
|
+
@content = self.class.join_multiline(original_content.split("\n"))
|
11
|
+
@content << "" # new line at the end
|
12
|
+
@transformer = ExtractI18n::Slimkeyfy::SlimTransformer
|
13
|
+
|
14
|
+
@new_content =
|
15
|
+
@content.map do |old_line|
|
16
|
+
process_line(old_line)
|
17
|
+
end
|
18
|
+
@new_content.join("\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
def process_line(old_line)
|
22
|
+
word = ExtractI18n::Slimkeyfy::Word.for('.slim').new(old_line)
|
23
|
+
ExtractI18n::Slimkeyfy::SlimTransformer.new(word, @file_key).transform do |change|
|
24
|
+
if change.nil? # nothing to do
|
25
|
+
return old_line
|
26
|
+
end
|
27
|
+
|
28
|
+
if @on_ask.call(change)
|
29
|
+
change.i18n_t(relative: @options[:relative])
|
30
|
+
else
|
31
|
+
old_line
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.join_multiline(strings_array)
|
37
|
+
result = []
|
38
|
+
joining_str = ''
|
39
|
+
indent_length = 0
|
40
|
+
long_str_start = /^[ ]+\| */
|
41
|
+
long_str_indent = /^[ ]+/
|
42
|
+
long_str_indent_with_vertical_bar = /^[ ]+\| */
|
43
|
+
strings_array.each do |str|
|
44
|
+
if joining_str.empty?
|
45
|
+
if str[long_str_start]
|
46
|
+
joining_str = str
|
47
|
+
indent_length = str[long_str_start].length
|
48
|
+
else
|
49
|
+
result << str
|
50
|
+
end
|
51
|
+
# multiline string continues with spaces
|
52
|
+
elsif str[long_str_indent] && str[long_str_indent].length.to_i >= indent_length
|
53
|
+
joining_str << str.gsub(long_str_indent, ' ')
|
54
|
+
# muliline string continues with spaces and vertical bar with same indentation
|
55
|
+
elsif str[long_str_indent_with_vertical_bar] && str[long_str_indent_with_vertical_bar].length.to_i == indent_length
|
56
|
+
joining_str << str.gsub(long_str_indent_with_vertical_bar, ' ')
|
57
|
+
# multiline string ends
|
58
|
+
else
|
59
|
+
result << joining_str
|
60
|
+
joining_str = ''
|
61
|
+
indent_length = 0
|
62
|
+
result << str
|
63
|
+
end
|
64
|
+
end
|
65
|
+
result << joining_str unless joining_str.empty?
|
66
|
+
|
67
|
+
result
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'slim'
|
4
|
+
|
5
|
+
module ExtractI18n::Adapters
|
6
|
+
class SlimAdapterWip < Adapter
|
7
|
+
def run(original_content)
|
8
|
+
parser = SlimRewriterParser.new(file_key: file_key, on_ask: on_ask)
|
9
|
+
parser.call(original_content)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class SlimRewriterParser < Slim::Engine
|
14
|
+
class CustomFilter < Slim::Filter
|
15
|
+
define_options file_key: :dynamic, on_ask: :dynamic
|
16
|
+
def call(exp)
|
17
|
+
@indent = 0
|
18
|
+
super.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_multi(*exps)
|
22
|
+
super[1..-1].join
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_newline
|
26
|
+
"\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_static(*args)
|
30
|
+
args[0].include?('"') ? "'#{args.join(' ')}'" : %["#{args.join(' ')}"]
|
31
|
+
end
|
32
|
+
|
33
|
+
def on_html_doctype(name)
|
34
|
+
"#{indent}doctype #{name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def on_html_tag(name, attrs, content = nil)
|
38
|
+
ret = "#{indent}#{name}#{compile attrs}"
|
39
|
+
if content
|
40
|
+
ret << ' ' << block(content)
|
41
|
+
end
|
42
|
+
ret
|
43
|
+
end
|
44
|
+
|
45
|
+
def block(content)
|
46
|
+
@indent += 1
|
47
|
+
result = compile(content).to_s # todo remove to_s
|
48
|
+
if result.is_a?(String)
|
49
|
+
extract_from_string(result)
|
50
|
+
else
|
51
|
+
result
|
52
|
+
end
|
53
|
+
ensure
|
54
|
+
@indent -= 1
|
55
|
+
end
|
56
|
+
|
57
|
+
def extract_from_string(string)
|
58
|
+
i18n_key = ExtractI18n.key(string)
|
59
|
+
change = ExtractI18n::SourceChange.new(
|
60
|
+
i18n_key: "#{@options[:file_key]}.#{i18n_key}",
|
61
|
+
i18n_string: string,
|
62
|
+
interpolate_arguments: {},
|
63
|
+
source_line: string,
|
64
|
+
remove: string
|
65
|
+
)
|
66
|
+
puts change.format
|
67
|
+
if @options[:on_ask].call(change)
|
68
|
+
change.i18n_t
|
69
|
+
else
|
70
|
+
string
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def on_html_attrs(*attrs)
|
75
|
+
attrs.empty? ? '' : "(#{super[2..-1].join(' ')})"
|
76
|
+
end
|
77
|
+
|
78
|
+
def on_slim_interpolate(text)
|
79
|
+
compile(text)
|
80
|
+
end
|
81
|
+
|
82
|
+
def on_slim_text(type, text)
|
83
|
+
block(text)
|
84
|
+
end
|
85
|
+
|
86
|
+
def on_slim_embedded(type, text)
|
87
|
+
"#{indent}#{block text}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def on_html_comment(exp)
|
91
|
+
"#{indent}/ #{block exp}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def on_slim_control(line, block)
|
95
|
+
"#{indent}- #{line}#{block block}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def on_html_attr(name, content)
|
99
|
+
"#{name}=#{compile content}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def indent
|
103
|
+
' ' * @indent
|
104
|
+
end
|
105
|
+
|
106
|
+
# def parse_text_block(first_line = nil, text_indent = nil)
|
107
|
+
# source_line = @_lines[@lineno - 1]
|
108
|
+
|
109
|
+
# binding.pry
|
110
|
+
# result = super
|
111
|
+
|
112
|
+
# change = ExtractI18n::SourceChange.new(
|
113
|
+
# i18n_key: "#{@file_key}.#{i18n_key}",
|
114
|
+
# i18n_string: i18n_string,
|
115
|
+
# interpolate_arguments: {},
|
116
|
+
# source_line: source_line,
|
117
|
+
# remove: node.loc.expression.source
|
118
|
+
# )
|
119
|
+
# binding.pry
|
120
|
+
|
121
|
+
# result
|
122
|
+
# end
|
123
|
+
end
|
124
|
+
remove //
|
125
|
+
filter :Encoding
|
126
|
+
filter :RemoveBOM
|
127
|
+
use Slim::Parser
|
128
|
+
use CustomFilter
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExtractI18n::Adapters
|
4
|
+
class VueAdapter < SlimAdapter
|
5
|
+
def process_line(old_line)
|
6
|
+
@mode ||= :template
|
7
|
+
if old_line[/^<template/]
|
8
|
+
@mode = :template
|
9
|
+
elsif old_line[/^<script/]
|
10
|
+
@mode = :script
|
11
|
+
elsif old_line[/^<style/]
|
12
|
+
@mode = :style
|
13
|
+
end
|
14
|
+
if @mode != :template
|
15
|
+
return old_line
|
16
|
+
end
|
17
|
+
word = ExtractI18n::Slimkeyfy::Word.for('.vue').new(old_line)
|
18
|
+
ExtractI18n::Slimkeyfy::VueTransformer.new(word, @file_key).transform do |change|
|
19
|
+
if change.nil? # nothing to do
|
20
|
+
return old_line
|
21
|
+
end
|
22
|
+
|
23
|
+
if @on_ask.call(change)
|
24
|
+
change.i18n_t
|
25
|
+
else
|
26
|
+
old_line
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Layout/LineLength
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require 'extract_i18n'
|
7
|
+
require 'extract_i18n/file_processor'
|
8
|
+
require 'extract_i18n/version'
|
9
|
+
require 'open-uri'
|
10
|
+
|
11
|
+
module ExtractI18n
|
12
|
+
# Cli Class
|
13
|
+
class CLI
|
14
|
+
def initialize
|
15
|
+
@options = {}
|
16
|
+
ARGV << '-h' if ARGV.empty?
|
17
|
+
OptionParser.new do |opts|
|
18
|
+
opts.banner = "Usage: extract-i18n -l <locale> -w <target-yml> [path*]"
|
19
|
+
|
20
|
+
opts.on('--version', 'Print version number') do
|
21
|
+
puts ExtractI18n::VERSION
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on('-lLOCALE', '--locale=LOCALE', 'default locale for extraction (Default = en)') do |f|
|
26
|
+
@options[:locale] = f || 'en'
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on('-nNAMESPACE', '--namespace=NAMESPACE', 'Locale base key to wrap locations in') do |f|
|
30
|
+
@options[:base_key] = f
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on('-r', '--slim-relative', 'When activated, will use relative keys like t(".title")') do |f|
|
34
|
+
@options[:relative] = f
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on('-yYAML', '--yaml=YAML-FILE', 'Write extracted keys to YAML file (default = config/locales/unsorted.LOCALE.yml)') do |f|
|
38
|
+
@options[:write_to] = f || "config/locales/unsorted.#{@options[:locale]}"
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on('-h', '--help', 'Prints this help') do
|
42
|
+
puts opts
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
end.parse!
|
46
|
+
|
47
|
+
@options[:write_to] ||= "config/locales/unsorted.#{@options[:locale]}.yml"
|
48
|
+
@options[:locale] ||= 'en'
|
49
|
+
@files = ARGV
|
50
|
+
end
|
51
|
+
|
52
|
+
def run
|
53
|
+
paths = @files.empty? ? [] : @files
|
54
|
+
paths.each do |path|
|
55
|
+
if File.directory?(path)
|
56
|
+
glob_path = File.join(path, '**', '*.rb')
|
57
|
+
Dir.glob(glob_path) do |file_path|
|
58
|
+
process_file file_path
|
59
|
+
end
|
60
|
+
else
|
61
|
+
process_file path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def process_file(file_path)
|
67
|
+
puts "Processing: #{file_path}"
|
68
|
+
ExtractI18n::FileProcessor.new(
|
69
|
+
file_path: file_path,
|
70
|
+
write_to: @options[:write_to],
|
71
|
+
locale: @options[:locale],
|
72
|
+
options: @options
|
73
|
+
).run
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'parser/current'
|
4
|
+
require 'tty/prompt'
|
5
|
+
require 'diffy'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
module ExtractI18n
|
9
|
+
class FileProcessor
|
10
|
+
PROMPT = TTY::Prompt.new
|
11
|
+
PASTEL = Pastel.new
|
12
|
+
|
13
|
+
def initialize(file_path:, write_to:, locale:, options: {})
|
14
|
+
@file_path = file_path
|
15
|
+
@file_key = ExtractI18n.file_key(@file_path)
|
16
|
+
|
17
|
+
@locale = locale
|
18
|
+
@write_to = write_to
|
19
|
+
@options = options
|
20
|
+
@i18n_changes = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
puts " reading #{@file_path}"
|
25
|
+
read_and_transform do |result|
|
26
|
+
puts Diffy::Diff.new(original_content, result, context: 1).to_s(:color)
|
27
|
+
if PROMPT.yes?("Save changes?")
|
28
|
+
File.write(@file_path, result)
|
29
|
+
update_i18n_yml_file
|
30
|
+
puts PASTEL.green("Saved #{@file_path}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def read_and_transform(&_block)
|
38
|
+
key = if @options[:namespace]
|
39
|
+
"#{@options[:namespace]}.#{@file_key}"
|
40
|
+
else
|
41
|
+
@file_key
|
42
|
+
end
|
43
|
+
adapter_class = ExtractI18n::Adapters::Adapter.for(@file_path)
|
44
|
+
if adapter_class
|
45
|
+
adapter = adapter_class.new(
|
46
|
+
file_key: key,
|
47
|
+
on_ask: ->(change) { ask_one_change?(change) },
|
48
|
+
options: @options,
|
49
|
+
)
|
50
|
+
output = adapter.run(original_content)
|
51
|
+
if output != original_content
|
52
|
+
yield(output)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def ask_one_change?(change)
|
58
|
+
check_for_unique!(change)
|
59
|
+
puts change.format
|
60
|
+
if PROMPT.no?("replace line ?")
|
61
|
+
false
|
62
|
+
else
|
63
|
+
@i18n_changes[change.key] = change.i18n_string
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def check_for_unique!(change)
|
69
|
+
if @i18n_changes[change.key] && @i18n_changes[change.key] != change.i18n_string
|
70
|
+
change.increment_key!
|
71
|
+
check_for_unique!(change)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def update_i18n_yml_file
|
76
|
+
base = if File.exist?(@write_to)
|
77
|
+
YAML.load_file(@write_to)
|
78
|
+
else
|
79
|
+
{}
|
80
|
+
end
|
81
|
+
@i18n_changes.each do |key, value|
|
82
|
+
tree = base
|
83
|
+
keys = key.split('.').unshift(@locale)
|
84
|
+
keys.each_with_index do |part, i|
|
85
|
+
if i == keys.length - 1
|
86
|
+
tree[part] = value
|
87
|
+
else
|
88
|
+
tree = tree[part] ||= {}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
File.write(@write_to, base.to_yaml)
|
93
|
+
end
|
94
|
+
|
95
|
+
def original_content
|
96
|
+
@original_content ||= File.read(@file_path)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExtractI18n
|
4
|
+
class Slimkeyfy::SlimTransformer
|
5
|
+
TRANSLATED = /t\s*\(?\s*(".*?"|'.*?')\s*\)?/.freeze
|
6
|
+
STRING = /(\".*\"|\'.*\')/.freeze
|
7
|
+
STRING_WITHOUT_QUOTES = /("(?<double_quot>.*)"|'(?<single_quot>.*)')/.freeze
|
8
|
+
|
9
|
+
HTML_TAGS = /^(?<html_tag>'|\||([a-z\.]+[0-9\-]*)+)/.freeze
|
10
|
+
EQUALS = /#?([a-z0-9\.\-\s]+)?\=.*/.freeze
|
11
|
+
|
12
|
+
BEFORE = /(?<before>.*)/.freeze
|
13
|
+
TRANSLATION = /(?<translation>(".*?"|'.*?'))/.freeze
|
14
|
+
AFTER = /(?<after>,?.*)?/.freeze
|
15
|
+
|
16
|
+
HTML_ARGUMENTS = {
|
17
|
+
hint: /(?<html_tag>hint:\s*)/,
|
18
|
+
link_to: /(?<html_tag>link_to\s*\(?)/,
|
19
|
+
inconified: /(?<html_tag>(iconified\s*\(?))/,
|
20
|
+
placeholder: /(?<html_tag>placeholder:\s*)/,
|
21
|
+
title: /(?<html_tag>title:\s*)/,
|
22
|
+
prepend: /(?<html_tag>prepend:\s*)/,
|
23
|
+
append: /(?<html_tag>append:\s*)/,
|
24
|
+
label: /(?<html_tag>[a-z]*_?label:\s*)/,
|
25
|
+
optionals: /(?<html_tag>(default|include_blank|alt):\s*)/,
|
26
|
+
input: /(?<html_tag>[a-z]*\.?input:?\s*)/,
|
27
|
+
button: /(?<html_tag>[a-z]*\.?button:?\s*(\:[a-z]+\s*,\s*)?)/,
|
28
|
+
tag: /(?<html_tag>(submit|content)_tag[\:\(]?\s*)/,
|
29
|
+
data_naive: /(?<html_tag>data:\s*\{\s*(confirm|content):\s*)/
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
LINK_TO = /#{HTML_ARGUMENTS[:link_to]}#{TRANSLATION}/.freeze
|
33
|
+
|
34
|
+
def transform(&block)
|
35
|
+
return yield(nil) if should_not_be_processed?(@word.as_list)
|
36
|
+
unindented_line = @word.unindented_line
|
37
|
+
|
38
|
+
if unindented_line.match(EQUALS)
|
39
|
+
parse_html_arguments(unindented_line, &block)
|
40
|
+
elsif @word.head.match(HTML_TAGS)
|
41
|
+
parse_html(&block)
|
42
|
+
else
|
43
|
+
yield(nil)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(word, file_key)
|
48
|
+
@word = word
|
49
|
+
@file_key = file_key
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def parse_html(&_block)
|
55
|
+
return @word.line if @word.line.match(TRANSLATED)
|
56
|
+
|
57
|
+
tagged_with_equals = Slimkeyfy::Whitespacer.convert_slim(@word.head)
|
58
|
+
body = @word.tail.join(" ")
|
59
|
+
body, tagged_with_equals = Slimkeyfy::Whitespacer.convert_nbsp(body, tagged_with_equals)
|
60
|
+
|
61
|
+
if body.match(LINK_TO) != nil
|
62
|
+
body = link_tos(body)
|
63
|
+
end
|
64
|
+
|
65
|
+
interpolate_arguments, body = extract_arguments(body)
|
66
|
+
change = ExtractI18n::SourceChange.new(
|
67
|
+
source_line: @word.line,
|
68
|
+
remove: body,
|
69
|
+
interpolate_arguments: interpolate_arguments,
|
70
|
+
i18n_key: "#{@file_key}.#{ExtractI18n.key(body)}",
|
71
|
+
i18n_string: body,
|
72
|
+
t_template: "#{@word.indentation}#{tagged_with_equals} t('%s'%s)"
|
73
|
+
)
|
74
|
+
yield(change)
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse_html_arguments(line, token_skipped_before = nil, &block)
|
78
|
+
final_line = line
|
79
|
+
regex_list.each do |regex|
|
80
|
+
line.scan(regex) do |m_data|
|
81
|
+
next if m_data == token_skipped_before
|
82
|
+
before = m_data[0]
|
83
|
+
html_tag = m_data[1]
|
84
|
+
translation = match_string(m_data[2])
|
85
|
+
after = m_data[3]
|
86
|
+
interpolate_arguments, translation = extract_arguments(translation)
|
87
|
+
change = ExtractI18n::SourceChange.new(
|
88
|
+
source_line: final_line,
|
89
|
+
i18n_string: translation,
|
90
|
+
i18n_key: "#{@file_key}.#{ExtractI18n.key(translation)}",
|
91
|
+
remove: m_data[2],
|
92
|
+
interpolate_arguments: interpolate_arguments,
|
93
|
+
t_template: "#{before}#{html_tag}t('%s'%s)#{after}"
|
94
|
+
)
|
95
|
+
final_line = yield(change)
|
96
|
+
return parse_html_arguments(final_line, &block)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
final_line
|
100
|
+
end
|
101
|
+
|
102
|
+
def link_tos(line)
|
103
|
+
m = line.match(LINK_TO)
|
104
|
+
if m != nil
|
105
|
+
_ = m[:html_tag]
|
106
|
+
translation = match_string(m[:translation])
|
107
|
+
translation_key = update_hashes(translation)
|
108
|
+
line = line.gsub(m[:translation], translation_key)
|
109
|
+
link_tos(line)
|
110
|
+
else
|
111
|
+
line
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def should_not_be_processed?(tokens)
|
116
|
+
(tokens.nil? or tokens.size < 2)
|
117
|
+
end
|
118
|
+
|
119
|
+
def matches_string?(translation)
|
120
|
+
m = translation.match(STRING_WITHOUT_QUOTES)
|
121
|
+
return false if m.nil?
|
122
|
+
(m[:double_quot] != nil or m[:single_quot] != nil)
|
123
|
+
end
|
124
|
+
|
125
|
+
def match_string(translation)
|
126
|
+
m = translation.match(STRING_WITHOUT_QUOTES)
|
127
|
+
return translation if m.nil?
|
128
|
+
if m[:double_quot] != nil
|
129
|
+
m[:double_quot]
|
130
|
+
else
|
131
|
+
(m[:single_quot] != nil ? m[:single_quot] : translation)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def regex_list
|
136
|
+
HTML_ARGUMENTS.map { |_, regex| /#{BEFORE}#{regex}#{TRANSLATION}#{AFTER}/ }
|
137
|
+
end
|
138
|
+
|
139
|
+
def extract_arguments(translation)
|
140
|
+
args = {}
|
141
|
+
translation.scan(/\#{[^}]*}/).each_with_index do |arg, index|
|
142
|
+
stripped_arg = arg[2..-2]
|
143
|
+
key = ExtractI18n.key(arg)
|
144
|
+
key += index.to_s if index > 0
|
145
|
+
translation = translation.gsub(arg, "%{#{key}}")
|
146
|
+
args[key] = stripped_arg
|
147
|
+
end
|
148
|
+
[args, translation]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|