extract_i18n 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|