herbgobbler 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/gobble +6 -4
- data/grammer/erb_grammer.treetop +70 -7
- data/lib/commandline/gobble_all.rb +35 -6
- data/lib/commandline/gobble_single_file.rb +37 -8
- data/lib/core/core.rb +2 -0
- data/lib/core/method_call_node.rb +5 -1
- data/lib/core/node_processing.rb +2 -1
- data/lib/core/pluralize_node.rb +28 -0
- data/lib/core/rails_text_extractor.rb +5 -0
- data/lib/core/text_extractor.rb +11 -0
- data/lib/core/tr8n_text_extractor.rb +107 -0
- data/lib/nodes/herb_erb_tr8n_text_call_node.rb +74 -0
- data/lib/nodes/herb_string_variable.rb +29 -2
- data/lib/nodes/herb_tr8n_string_node.rb +49 -0
- data/lib/nodes/herb_tr8n_text_call_node.rb +146 -0
- data/lib/nodes/nodes.rb +4 -0
- data/scripts/display_syntax_tree.rb +3 -2
- data/scripts/extract_text_from_erb.rb +28 -6
- data/scripts/extract_yml_from_erb.rb +3 -1
- data/scripts/save_result.rb +7 -4
- metadata +63 -80
data/bin/gobble
CHANGED
@@ -5,22 +5,24 @@ def print_usage
|
|
5
5
|
puts " ***** HerbGobbler Usage ***** "
|
6
6
|
puts
|
7
7
|
puts "Options "
|
8
|
+
puts "tr8n | i18n : Use the normal rails i18n output format or use tr8n output"
|
8
9
|
puts "-a : Process an entire Rails Code Base"
|
9
10
|
puts "-f <full path to file> : Process a single file"
|
10
11
|
puts
|
11
|
-
puts "Usage: gobble
|
12
|
+
puts "Usage: gobble tr8n -a <rails root>"
|
12
13
|
end
|
13
14
|
|
14
|
-
if( ARGV.length <
|
15
|
+
if( ARGV.length < 3 )
|
15
16
|
print_usage
|
16
17
|
else
|
18
|
+
type = ARGV.shift
|
17
19
|
option = ARGV.shift
|
18
20
|
rails_root = ARGV.pop
|
19
21
|
case option
|
20
22
|
when "-a"
|
21
|
-
command_line_object = GobbleAll.new( rails_root, ARGV )
|
23
|
+
command_line_object = GobbleAll.new( rails_root, type, ARGV )
|
22
24
|
when "-f"
|
23
|
-
command_line_object = GobbleSingleFile.new( rails_root, ARGV )
|
25
|
+
command_line_object = GobbleSingleFile.new( rails_root, type, ARGV )
|
24
26
|
else
|
25
27
|
print_usage
|
26
28
|
end
|
data/grammer/erb_grammer.treetop
CHANGED
@@ -15,7 +15,7 @@ grammar ERBGrammer
|
|
15
15
|
end
|
16
16
|
|
17
17
|
rule method_names
|
18
|
-
"link_to"
|
18
|
+
"link_to_function" / "link_to" <NonTextNode>
|
19
19
|
{
|
20
20
|
def node_name
|
21
21
|
"method_names"
|
@@ -30,7 +30,7 @@ grammar ERBGrammer
|
|
30
30
|
"," <NonTextNode>
|
31
31
|
{
|
32
32
|
def node_name
|
33
|
-
"
|
33
|
+
"comma"
|
34
34
|
end
|
35
35
|
|
36
36
|
def can_be_combined?
|
@@ -40,8 +40,61 @@ grammar ERBGrammer
|
|
40
40
|
}
|
41
41
|
end
|
42
42
|
|
43
|
+
rule not_whitespace_or_comma
|
44
|
+
((!comma !space ) . )+ <NonTextNode>
|
45
|
+
{
|
46
|
+
|
47
|
+
def can_be_combined?
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def node_name
|
52
|
+
"not_whitespace_or_comma"
|
53
|
+
end
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
rule double_quoted_non_string
|
58
|
+
'"' ( !'"' .)* '"' <NonTextNode>
|
59
|
+
{
|
60
|
+
def can_be_combined?
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
def node_name
|
65
|
+
"double_quoted_non_string"
|
66
|
+
end
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
rule single_quoted_non_string
|
71
|
+
"'" ( !"'" .)* "'" <NonTextNode>
|
72
|
+
{
|
73
|
+
def can_be_combined?
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def node_name
|
78
|
+
"single_quoted_non_string"
|
79
|
+
end
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
rule pluralize
|
84
|
+
"pluralize" space? "("? space? repetition:not_whitespace_or_comma space? comma space? string_to_pluralize:(single_quoted_non_string / double_quoted_non_string) space? ")"? space? <PluralizeNode>
|
85
|
+
{
|
86
|
+
def can_be_combined?
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
def node_name
|
91
|
+
"pluralize"
|
92
|
+
end
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
43
96
|
rule method_call_content
|
44
|
-
method_names whitespace double_quoted_ruby_string (comma erb_string_non_text_content)? <MethodCallNode>
|
97
|
+
method_names whitespace ruby_string:double_quoted_ruby_string everything_else:(comma erb_string_non_text_content)? <MethodCallNode>
|
45
98
|
end
|
46
99
|
|
47
100
|
rule erb_string_non_text_content
|
@@ -58,7 +111,7 @@ grammar ERBGrammer
|
|
58
111
|
end
|
59
112
|
|
60
113
|
rule erb_string
|
61
|
-
start_erb:erb_string_start start_space:(space) text:(method_call_content / double_quoted_ruby_string)? everything_else:erb_string_non_text_content end_erb:(erb_block_end) <NonTextNode>
|
114
|
+
start_erb:erb_string_start start_space:(space)? text:(method_call_content / double_quoted_ruby_string)? everything_else:(pluralize / erb_string_non_text_content) end_erb:(erb_block_end) <NonTextNode>
|
62
115
|
{
|
63
116
|
def node_name
|
64
117
|
"erb_string"
|
@@ -68,7 +121,8 @@ grammar ERBGrammer
|
|
68
121
|
end
|
69
122
|
|
70
123
|
rule string_variable
|
71
|
-
|
124
|
+
'#{' variable:((!'}' (pluralize / .))*) '}' <HerbStringVariable>
|
125
|
+
|
72
126
|
end
|
73
127
|
|
74
128
|
rule double_quoted_ruby_string
|
@@ -232,8 +286,17 @@ grammar ERBGrammer
|
|
232
286
|
|
233
287
|
end
|
234
288
|
|
289
|
+
rule tag_to_process
|
290
|
+
('title' space? '=' space? ('\'' / '"' ) text erb_string (!'\'' !'"' text)* ('\'' / '"') space? ) <NonTextNode>
|
291
|
+
{
|
292
|
+
def node_name
|
293
|
+
"tag_to_process"
|
294
|
+
end
|
295
|
+
}
|
296
|
+
end
|
297
|
+
|
235
298
|
rule tag_text
|
236
|
-
(!'>' !'/>' ( erb_block / erb_string / . ) )* <NonTextNode>
|
299
|
+
(!'>' !'/>' ( tag_to_process / erb_block / erb_string / . ) )* <NonTextNode>
|
237
300
|
{
|
238
301
|
def node_name
|
239
302
|
"tag_text"
|
@@ -292,7 +355,7 @@ grammar ERBGrammer
|
|
292
355
|
end
|
293
356
|
|
294
357
|
rule whitespace
|
295
|
-
((![a-zA-Z] !('<' [a-zA-Z]+) !('</' [a-zA-Z]+) !'<%' !'"' !'<!' ) . )+ <NonTextNode>
|
358
|
+
((![a-zA-Z\.] !('<' [a-zA-Z]+) !('</' [a-zA-Z]+) !'<%' !'"' !'<!' ) . )+ <NonTextNode>
|
296
359
|
{
|
297
360
|
def can_be_combined?
|
298
361
|
true
|
@@ -1,15 +1,48 @@
|
|
1
1
|
class GobbleAll
|
2
2
|
include GobbleShare
|
3
3
|
|
4
|
-
def initialize( rails_root, options )
|
4
|
+
def initialize( rails_root, type, options )
|
5
5
|
@rails_root = rails_root
|
6
6
|
@options = options
|
7
|
+
@text_extractor_type = type
|
7
8
|
end
|
8
9
|
|
9
10
|
def execute
|
10
11
|
puts "Processing all of: #{@rails_root}"
|
11
12
|
puts ""
|
13
|
+
|
14
|
+
if( @text_extractor_type == 'tr8n' )
|
15
|
+
execute_tr8n
|
16
|
+
else
|
17
|
+
execute_i18n
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid?
|
23
|
+
@options.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def execute_tr8n
|
30
|
+
rails_view_directory = "#{@rails_root}/app/views"
|
31
|
+
text_extractor = Tr8nTextExtractor.new
|
12
32
|
|
33
|
+
Dir["#{rails_view_directory}/**/*html.erb" ].each do |full_erb_file_path|
|
34
|
+
|
35
|
+
erb_file = full_erb_file_path.gsub( @rails_root, '' )
|
36
|
+
erb_file = ErbFile.load( full_erb_file_path )
|
37
|
+
erb_file.extract_text( text_extractor )
|
38
|
+
|
39
|
+
File.open(full_erb_file_path, 'w') {|f| f.write(erb_file.to_s) }
|
40
|
+
puts "Wrote #{full_erb_file_path}"
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def execute_i18n
|
13
46
|
locale_file_name = "en.yml"
|
14
47
|
|
15
48
|
rails_view_directory = "#{@rails_root}/app/views"
|
@@ -30,11 +63,7 @@ class GobbleAll
|
|
30
63
|
end
|
31
64
|
|
32
65
|
File.open(full_yml_file_path, 'w') {|f| f.write(rails_translation_store.serialize) }
|
33
|
-
puts "Wrote #{full_yml_file_path}"
|
34
|
-
end
|
35
|
-
|
36
|
-
def valid?
|
37
|
-
@options.empty?
|
66
|
+
puts "Wrote #{full_yml_file_path}"
|
38
67
|
end
|
39
68
|
|
40
69
|
end
|
@@ -1,13 +1,46 @@
|
|
1
1
|
class GobbleSingleFile
|
2
2
|
include GobbleShare
|
3
3
|
|
4
|
-
def initialize( rails_root, options )
|
4
|
+
def initialize( rails_root, type, options )
|
5
5
|
@rails_root = rails_root
|
6
6
|
@options = options
|
7
|
+
@text_extractor_type = type
|
7
8
|
end
|
8
9
|
|
9
10
|
def execute
|
10
11
|
file_name = @options.first
|
12
|
+
if( @text_extractor_type == 'tr8n' )
|
13
|
+
execute_tr8n( file_name )
|
14
|
+
else
|
15
|
+
execute_i18n( file_name )
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
@options.size == 1
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def execute_tr8n( file_name )
|
27
|
+
rails_view_directory = "#{@rails_root}/app/views"
|
28
|
+
erb_file = "/app/#{file_name.gsub( /.*\/app\//, '' )}"
|
29
|
+
puts "Gobbling file: #{file_name}"
|
30
|
+
puts ""
|
31
|
+
|
32
|
+
# load erb file into tr8n translation store
|
33
|
+
text_extractor = Tr8nTextExtractor.new
|
34
|
+
|
35
|
+
erb_file = ErbFile.load( file_name )
|
36
|
+
erb_file.extract_text( text_extractor )
|
37
|
+
|
38
|
+
# write file
|
39
|
+
File.open(file_name, 'w') {|f| f.write(erb_file.to_s) }
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute_i18n( file_name )
|
11
44
|
locale_file_name = "en.yml"
|
12
45
|
rails_view_directory = "#{@rails_root}/app/views"
|
13
46
|
full_yml_file_path = "#{@rails_root}/config/locales/#{locale_file_name}"
|
@@ -25,16 +58,12 @@ class GobbleSingleFile
|
|
25
58
|
erb_file = ErbFile.load( file_name )
|
26
59
|
erb_file.extract_text( text_extractor )
|
27
60
|
|
28
|
-
#
|
61
|
+
# write file
|
29
62
|
File.open(file_name, 'w') {|f| f.write(erb_file.to_s) }
|
30
63
|
|
31
64
|
# re-write yml file
|
32
|
-
File.open(full_yml_file_path, 'w') {|f| f.write(rails_translation_store.serialize) }
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def valid?
|
37
|
-
@options.size == 1
|
65
|
+
File.open(full_yml_file_path, 'w') {|f| f.write(rails_translation_store.serialize) }
|
38
66
|
end
|
39
67
|
|
68
|
+
|
40
69
|
end
|
data/lib/core/core.rb
CHANGED
@@ -6,6 +6,7 @@ require 'core/non_text_node'
|
|
6
6
|
require 'core/text_extractor'
|
7
7
|
require 'core/base_text_extractor'
|
8
8
|
require 'core/rails_text_extractor'
|
9
|
+
require 'core/tr8n_text_extractor'
|
9
10
|
require 'core/i18n_key'
|
10
11
|
require 'core/ignorable_tag_node'
|
11
12
|
require 'core/base_translation_store'
|
@@ -14,4 +15,5 @@ require 'core/double_quoted_text_node'
|
|
14
15
|
require 'core/erb_string_non_text_content'
|
15
16
|
require 'core/non_extracting_non_text_node'
|
16
17
|
require 'core/method_call_node'
|
18
|
+
require 'core/pluralize_node'
|
17
19
|
|
@@ -3,7 +3,7 @@ module MethodCallNode
|
|
3
3
|
|
4
4
|
def extract_text( text_extractor, node_tree, surrounding_nodes = nil )
|
5
5
|
text_string = ''
|
6
|
-
self.elements.each do |node|
|
6
|
+
self.elements.each do |node|
|
7
7
|
if( node.is_a?( TextNode ) )
|
8
8
|
translated_node = text_extractor.translate_text( node.text_value )
|
9
9
|
text_string << "(#{translated_node.text_value})"
|
@@ -22,6 +22,10 @@ module MethodCallNode
|
|
22
22
|
|
23
23
|
end
|
24
24
|
|
25
|
+
def node_name
|
26
|
+
"method_call_node"
|
27
|
+
end
|
28
|
+
|
25
29
|
private
|
26
30
|
|
27
31
|
def surrounded_by_text?( nodes )
|
data/lib/core/node_processing.rb
CHANGED
@@ -10,7 +10,8 @@ module NodeProcessing
|
|
10
10
|
node.elements.nil? ||
|
11
11
|
node.elements.empty? ||
|
12
12
|
(node.is_a?( TextNode ) && !node.has_variables?)||
|
13
|
-
node.is_a?( HerbStringVariable ) ||
|
13
|
+
node.is_a?( HerbStringVariable ) ||
|
14
|
+
node.is_a?( PluralizeNode ) ||
|
14
15
|
( node.is_a?(NonTextNode) && node.can_be_combined? ) )
|
15
16
|
leaves << node if( !node.text_value.empty? )
|
16
17
|
leaves
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PluralizeNode
|
2
|
+
include TextNode
|
3
|
+
attr_reader :variable_name, :variable_value
|
4
|
+
|
5
|
+
def extract_text( text_extractor, node_tree, surrounding_nodes = nil )
|
6
|
+
set_variable_name_and_value( text_extractor, node_tree, surrounding_nodes )
|
7
|
+
variable_name = I18nKey.new( self.repetition.text_value, get_key_hash(text_extractor, node_tree) ).to_s
|
8
|
+
text_extractor.pluralize( self, variable_name )
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def set_variable_name_and_value( text_extractor, node_tree, surrounding_nodes )
|
14
|
+
@variable_value = ''
|
15
|
+
self.elements.each do |node|
|
16
|
+
if( node.is_a?( TextNode ) )
|
17
|
+
translated_node = text_extractor.translate_text( node.text_value )
|
18
|
+
@variable_value << "(#{translated_node.text_value})"
|
19
|
+
else
|
20
|
+
@variable_value << node.text_value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
@variable_value = @variable_value.strip
|
24
|
+
@variable_name = generate_i18n_key( text_extractor, node_tree ).to_s
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -36,6 +36,11 @@ class RailsTextExtractor < BaseTextExtractor
|
|
36
36
|
return to_return + whitespace
|
37
37
|
end
|
38
38
|
|
39
|
+
def pluralize( pluralize_node, variable_name )
|
40
|
+
add_variable( variable_name,
|
41
|
+
pluralize_node.text_value )
|
42
|
+
end
|
43
|
+
|
39
44
|
def white_space( node )
|
40
45
|
if( @current_text.empty? )
|
41
46
|
@current_nodes << node
|
data/lib/core/text_extractor.rb
CHANGED
@@ -15,6 +15,10 @@ class TextExtractor
|
|
15
15
|
raise "Please implement me (add_variable)"
|
16
16
|
end
|
17
17
|
|
18
|
+
def pluralize( pluralize_node )
|
19
|
+
raise "Please implement me (pluralize)"
|
20
|
+
end
|
21
|
+
|
18
22
|
def translate_text( text_node_to_translate )
|
19
23
|
raise "Please impelement me (translate_text)"
|
20
24
|
end
|
@@ -27,5 +31,12 @@ class TextExtractor
|
|
27
31
|
raise "Please implement me (start_html_text)"
|
28
32
|
end
|
29
33
|
|
34
|
+
def white_space( node )
|
35
|
+
raise "Please implement me (white_space)"
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_non_text( non_text_node )
|
39
|
+
raise "Please implement me (add_non_text)"
|
40
|
+
end
|
30
41
|
|
31
42
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
class Tr8nTextExtractor < BaseTextExtractor
|
2
|
+
|
3
|
+
def initialize
|
4
|
+
@current_node = nil
|
5
|
+
@node_queue = []
|
6
|
+
@key_store = []
|
7
|
+
@debug = false
|
8
|
+
@html_tag_count = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
# This is called when text extraction has begun
|
12
|
+
def starting_text_extraction
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_html_text( text_node )
|
16
|
+
puts "Adding html text: #{text_node.text_value}" if @debug
|
17
|
+
@current_node.add_text( text_node.text_value )
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_variable( variable_name, variable_value )
|
21
|
+
puts "Adding variable: #{variable_name} = #{variable_value}" if @debug
|
22
|
+
@current_node.add_variable( variable_name, variable_value )
|
23
|
+
end
|
24
|
+
|
25
|
+
def translate_text( text_node_to_translate )
|
26
|
+
puts "Translating text: #{text_node_to_translate}" if @debug
|
27
|
+
# This should just return a node that responds to text_value
|
28
|
+
to_return = HerbTr8nTextCallNode.new
|
29
|
+
to_return.add_text( text_node_to_translate )
|
30
|
+
to_return
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def end_html_text
|
35
|
+
puts "End HTML Text" if @debug
|
36
|
+
to_return = @current_node
|
37
|
+
@current_node = nil
|
38
|
+
@html_tag_count = 0
|
39
|
+
@key_store = []
|
40
|
+
[to_return]
|
41
|
+
end
|
42
|
+
|
43
|
+
def pluralize( pluralize_node, variable_name )
|
44
|
+
variable = pluralize_node.repetition.text_value
|
45
|
+
singluar = pluralize_node.string_to_pluralize.text_value
|
46
|
+
variable_name
|
47
|
+
@current_node.add_pluralization( variable_name, singluar, variable )
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_html_text
|
51
|
+
puts "Starting html text" if @debug
|
52
|
+
@current_node = HerbErbTr8nTextCallNode.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def completed_text_extraction
|
56
|
+
end
|
57
|
+
|
58
|
+
def white_space( node )
|
59
|
+
puts "Whitespace" if @debug
|
60
|
+
@current_node.white_space( node.text_value )
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_non_text( non_text_node )
|
64
|
+
puts "Adding non text" if @debug
|
65
|
+
if( non_text_node.node_name == 'html_start_tag' )
|
66
|
+
start_html_tag( non_text_node )
|
67
|
+
elsif( non_text_node.node_name == 'html_end_tag' )
|
68
|
+
end_html_tag( non_text_node )
|
69
|
+
elsif( non_text_node.node_name == 'html_self_contained' )
|
70
|
+
self_contained_html_node( non_text_node )
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def start_html_tag( html_start_node )
|
75
|
+
puts "Start html tag: #{html_start_node.text_value}" if @debug
|
76
|
+
@node_queue.push( @current_node )
|
77
|
+
new_node = HerbTr8nTextCallNode.new( html_start_node, get_and_increment_tag_count, I18nKey.new( html_start_node.tag_name.text_value, @key_store ).to_s )
|
78
|
+
new_node.start_html_tag( html_start_node )
|
79
|
+
@current_node.add_child( new_node )
|
80
|
+
@current_node = new_node
|
81
|
+
end
|
82
|
+
|
83
|
+
def end_html_tag( html_end_node )
|
84
|
+
puts "End html tag: #{html_end_node.text_value}" if @debug
|
85
|
+
if( !@node_queue.empty? && @current_node.closing_tag_for_this_node?( html_end_node ) )
|
86
|
+
@current_node.end_html_tag( html_end_node )
|
87
|
+
@current_node = @node_queue.pop
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
def self_contained_html_node( html_self_contained_node )
|
93
|
+
puts "Self contained html node" if @debug
|
94
|
+
@current_node.self_contained_html_node( html_self_contained_node.tag_name.text_value )
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def get_and_increment_tag_count
|
100
|
+
to_return = @html_tag_count
|
101
|
+
@html_tag_count += 1
|
102
|
+
to_return
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class HerbErbTr8nTextCallNode < HerbTr8nTextCallNode
|
2
|
+
|
3
|
+
def add_text( text_value_as_string )
|
4
|
+
mark_as_called_and_push_whitespace
|
5
|
+
super( text_value_as_string )
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_variable( name, value )
|
9
|
+
mark_as_called_and_push_whitespace
|
10
|
+
super( name, value )
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_pluralization( variable_name, singular, variable )
|
14
|
+
mark_as_called_and_push_whitespace
|
15
|
+
super( variable_name, singular, variable )
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_child( node )
|
19
|
+
mark_as_called_and_push_whitespace
|
20
|
+
super( node )
|
21
|
+
end
|
22
|
+
def end_html_tag( html_end_tag )
|
23
|
+
mark_as_called_and_push_whitespace
|
24
|
+
super( html_end_tag )
|
25
|
+
end
|
26
|
+
|
27
|
+
def self_contained_html_node( node_name )
|
28
|
+
mark_as_called_and_push_whitespace
|
29
|
+
super( node_name )
|
30
|
+
end
|
31
|
+
|
32
|
+
def start_html_tag( html_start_tag )
|
33
|
+
mark_as_called_and_push_whitespace
|
34
|
+
super( html_start_tag )
|
35
|
+
end
|
36
|
+
|
37
|
+
def tr_call( html_end_tag = nil, count = 0 )
|
38
|
+
if( empty? )
|
39
|
+
""
|
40
|
+
else
|
41
|
+
to_return = ""
|
42
|
+
to_return += @prepended_whitespace if @prepended_whitespace
|
43
|
+
to_return += "<%= #{super(html_end_tag, count) } %>"
|
44
|
+
to_return += @last_whitespace_node if @last_whitespace_node
|
45
|
+
to_return
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def white_space( white_space_text, queue = true )
|
50
|
+
if( first_call? )
|
51
|
+
@prepended_whitespace = white_space_text
|
52
|
+
elsif( !queue )
|
53
|
+
super( white_space_text )
|
54
|
+
@last_whitespace_node = nil
|
55
|
+
else
|
56
|
+
super( @last_whitespace_node ) unless @last_whitespace_node.nil?
|
57
|
+
@last_whitespace_node = white_space_text
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def first_call?
|
65
|
+
@call_made.nil? || @call_made == false
|
66
|
+
end
|
67
|
+
|
68
|
+
def mark_as_called_and_push_whitespace
|
69
|
+
@call_made = true
|
70
|
+
white_space( @last_whitespace_node, false ) if @last_whitespace_node
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
end
|
@@ -4,10 +4,37 @@ class HerbStringVariable < Treetop::Runtime::SyntaxNode
|
|
4
4
|
def node_name
|
5
5
|
"herb_string_variable"
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def extract_text( text_extractor, node_tree )
|
9
|
-
|
9
|
+
pluralize = find_pluralize_node(variable)
|
10
|
+
|
11
|
+
# if this variable is a pluralize node, then don't treat it like a
|
12
|
+
# variable but like a pluralize
|
13
|
+
unless( pluralize.nil? )
|
14
|
+
variable_name = I18nKey.new( pluralize.repetition.text_value, get_key_hash(text_extractor, node_tree) ).to_s
|
15
|
+
text_extractor.pluralize( pluralize, variable_name )
|
16
|
+
else
|
17
|
+
text_extractor.add_variable( I18nKey.new( self.variable.text_value, get_key_hash(text_extractor, node_tree) ).to_s , self.variable.text_value )
|
18
|
+
end
|
19
|
+
|
10
20
|
end
|
11
21
|
|
22
|
+
private
|
23
|
+
|
24
|
+
# Unravel all the nodes to see if there is a pluralize node
|
25
|
+
def find_pluralize_node( node )
|
26
|
+
unless( node.elements.nil? || node.elements.empty? )
|
27
|
+
node.elements.each do |element|
|
28
|
+
if element.is_a?(PluralizeNode )
|
29
|
+
return element
|
30
|
+
else
|
31
|
+
found_node = find_pluralize_node( element )
|
32
|
+
return found_node unless found_node.nil?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
nil
|
37
|
+
end
|
12
38
|
|
39
|
+
|
13
40
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# This class is mostly responsible for all of the escaping that needs
|
2
|
+
# to occur for Tr8n to correctly understand the string.
|
3
|
+
|
4
|
+
class HerbTr8nStringNode
|
5
|
+
|
6
|
+
ESCAPE_LOOKUP_TABLE = [
|
7
|
+
["\"", "quot"],
|
8
|
+
["\n", "break"],
|
9
|
+
["–", "ndash"],
|
10
|
+
["—", "mdash"],
|
11
|
+
["¡", "iexcl"],
|
12
|
+
["¿", "iquest"],
|
13
|
+
[""", "quot"],
|
14
|
+
["“", "ldquo"],
|
15
|
+
["”", "rdquo"],
|
16
|
+
["‘", "lsquo"],
|
17
|
+
["’", "rsquo"],
|
18
|
+
["«", "laquo"],
|
19
|
+
["»", "raquo"],
|
20
|
+
[" ", "nbsp"]
|
21
|
+
]
|
22
|
+
|
23
|
+
def initialize( string )
|
24
|
+
@escaped_string = tr8n_escape( string )
|
25
|
+
end
|
26
|
+
|
27
|
+
def text_value
|
28
|
+
@escaped_string
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
text_value
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def replace_character( string, search_character, replace_character )
|
38
|
+
string.gsub( search_character, "{#{replace_character}}" )
|
39
|
+
end
|
40
|
+
|
41
|
+
def tr8n_escape( string )
|
42
|
+
ESCAPE_LOOKUP_TABLE.each do |lookup_pair|
|
43
|
+
string = replace_character( string, lookup_pair.first, lookup_pair.last )
|
44
|
+
end
|
45
|
+
string
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
class HerbTr8nTextCallNode
|
2
|
+
|
3
|
+
attr_reader :variable_name_being_assigned_to
|
4
|
+
|
5
|
+
def initialize( html_start_tag = nil, tag_count = 0, tag_variable_name = nil )
|
6
|
+
@text_values = []
|
7
|
+
@variable_names_and_values = []
|
8
|
+
@html_start_tag = html_start_tag
|
9
|
+
@variable_name_being_assigned_to = tag_variable_name
|
10
|
+
@number_of_html_nodes = tag_count
|
11
|
+
@child_nodes = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_text( text_value_as_string )
|
15
|
+
@text_values << HerbTr8nStringNode.new( text_value_as_string )
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_child( child_node )
|
19
|
+
@child_nodes << child_node
|
20
|
+
@text_values << child_node
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_variable( name, value )
|
24
|
+
@variable_names_and_values << [name, value]
|
25
|
+
@text_values << "{#{name}}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_pluralization( variable_name, singular, variable )
|
29
|
+
@text_values << "[#{variable_name} || #{singular}]"
|
30
|
+
@variable_names_and_values << [variable_name, variable ]
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def being_assigned_to_variable?
|
35
|
+
!@variable_name_being_assigned_to.nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
def closing_tag_for_this_node?( closing_tag )
|
39
|
+
( !@html_start_tag.nil? && @html_start_tag.tag_name.text_value == closing_tag.tag_name.text_value )
|
40
|
+
end
|
41
|
+
|
42
|
+
def block_variable
|
43
|
+
to_return = "[#{variable_name_being_assigned_to}: "
|
44
|
+
to_return += text_values_as_concated_string
|
45
|
+
to_return += "]"
|
46
|
+
to_return
|
47
|
+
end
|
48
|
+
|
49
|
+
def empty?
|
50
|
+
@text_values.empty? && @variable_names_and_values.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
def end_html_tag( html_end_tag )
|
54
|
+
@variable_names_and_values << [self.variable_name_being_assigned_to, self.variable_string( html_end_tag, @number_of_html_nodes) ]
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def self_contained_html_node( node_name )
|
59
|
+
@text_values << "{#{node_name}}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def start_html_tag( html_start_tag )
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def text_value
|
67
|
+
if( being_assigned_to_variable? )
|
68
|
+
block_variable
|
69
|
+
else
|
70
|
+
tr_call
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def text_values_as_concated_string
|
75
|
+
to_return = ""
|
76
|
+
@text_values.each do |text_value|
|
77
|
+
to_return += text_value.to_s
|
78
|
+
end
|
79
|
+
to_return
|
80
|
+
end
|
81
|
+
|
82
|
+
def variables
|
83
|
+
to_return = @variable_names_and_values.dup
|
84
|
+
@child_nodes.each do |child_node|
|
85
|
+
to_return += child_node.variables
|
86
|
+
end
|
87
|
+
to_return
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
text_value
|
92
|
+
end
|
93
|
+
|
94
|
+
def variable_string( html_end_tag, count )
|
95
|
+
to_return = "\""
|
96
|
+
to_return += @html_start_tag.text_value
|
97
|
+
to_return += "{$#{count}}"
|
98
|
+
to_return += html_end_tag.text_value
|
99
|
+
to_return += "\""
|
100
|
+
to_return
|
101
|
+
end
|
102
|
+
|
103
|
+
def tr_text( html_end_tag = nil, count = 0 )
|
104
|
+
to_return = "\""
|
105
|
+
unless( empty? )
|
106
|
+
to_return += @html_start_tag.text_value if being_assigned_to_variable?
|
107
|
+
|
108
|
+
if( being_assigned_to_variable? )
|
109
|
+
to_return += "{$#{count}}"
|
110
|
+
else
|
111
|
+
to_return += text_values_as_concated_string
|
112
|
+
end
|
113
|
+
|
114
|
+
to_return += html_end_tag.text_value if being_assigned_to_variable?
|
115
|
+
|
116
|
+
to_return +='"'
|
117
|
+
|
118
|
+
unless( self.variables.empty? )
|
119
|
+
to_return += ", nil, { "
|
120
|
+
self.variables.each do |variable_name_value|
|
121
|
+
to_return += ":#{variable_name_value.first} => #{variable_name_value.last}"
|
122
|
+
to_return += ", " unless variable_name_value == variables.last
|
123
|
+
end
|
124
|
+
to_return += " }"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
to_return
|
129
|
+
end
|
130
|
+
|
131
|
+
def tr_call( html_end_tag = nil, count = 0 )
|
132
|
+
to_return = ""
|
133
|
+
unless( empty? )
|
134
|
+
to_return += 'tr( '
|
135
|
+
to_return += tr_text( html_end_tag, count )
|
136
|
+
to_return += ' )'
|
137
|
+
end
|
138
|
+
to_return
|
139
|
+
end
|
140
|
+
|
141
|
+
def white_space( white_space_text )
|
142
|
+
@text_values << ( HerbTr8nStringNode.new( white_space_text ) ).to_s
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
data/lib/nodes/nodes.rb
CHANGED
@@ -10,4 +10,8 @@ require 'nodes/herb_node_retaining_text_node'
|
|
10
10
|
require 'nodes/herb_node_retaining_node'
|
11
11
|
require 'nodes/herb_node_retaining_text_node'
|
12
12
|
require 'nodes/herb_node_retaining_non_text_node'
|
13
|
+
require 'nodes/herb_tr8n_text_call_node'
|
14
|
+
require 'nodes/herb_tr8n_text_call_node'
|
15
|
+
require 'nodes/herb_erb_tr8n_text_call_node'
|
16
|
+
require 'nodes/herb_tr8n_string_node'
|
13
17
|
require 'nodes/rails_text_variable_node'
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'backports'
|
2
|
+
require_relative '../lib/herbgobbler'
|
2
3
|
|
3
4
|
|
4
5
|
file_name = ARGV.first
|
@@ -9,7 +10,7 @@ puts "---------- Original ----------------"
|
|
9
10
|
puts File.read( file_name )
|
10
11
|
puts "---------- Un-Combined Syntax Tree -------------"
|
11
12
|
top_levels.each_with_index do |top_level, index|
|
12
|
-
puts "(#{index}): #{top_level.text_value} #{top_level.is_a?(TextNode)}"
|
13
|
+
puts "(#{index}): #{top_level.text_value} #{top_level.node_name if top_level.respond_to?(:node_name)} #{top_level.is_a?(TextNode)}"
|
13
14
|
end
|
14
15
|
puts "---------- Combined Syntax Tree -------------"
|
15
16
|
erb_file.combine_nodes( erb_file.flatten_elements ).each do |element|
|
@@ -1,12 +1,34 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require '
|
2
|
+
require 'backports'
|
3
|
+
require_relative '../lib/herbgobbler'
|
4
|
+
|
5
|
+
def print_usage
|
6
|
+
puts "usage: ruby extract_text_from_erb.rb i18n|tr8n <file name>"
|
7
|
+
end
|
8
|
+
|
9
|
+
if( ARGV.length != 2 )
|
10
|
+
print_usage
|
11
|
+
else
|
12
|
+
engine = ARGV.first
|
13
|
+
file_name = ARGV.last
|
14
|
+
if( engine == 'i18n' )
|
15
|
+
text_extractor = RailsTextExtractor.new
|
16
|
+
erb_file = ErbFile.load( file_name )
|
17
|
+
erb_file.extract_text( text_extractor )
|
18
|
+
print erb_file.to_s
|
19
|
+
elsif( engine == 'tr8n' )
|
20
|
+
text_extractor = Tr8nTextExtractor.new
|
21
|
+
erb_file = ErbFile.load( file_name )
|
22
|
+
erb_file.extract_text( text_extractor )
|
23
|
+
print erb_file.to_s
|
24
|
+
else
|
25
|
+
print_usage
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
3
30
|
|
4
|
-
file_name = ARGV.first
|
5
|
-
text_extractor = RailsTextExtractor.new
|
6
|
-
erb_file = ErbFile.load( file_name )
|
7
|
-
erb_file.extract_text( text_extractor )
|
8
31
|
|
9
|
-
print erb_file.to_s
|
10
32
|
|
11
33
|
|
12
34
|
|
data/scripts/save_result.rb
CHANGED
@@ -3,9 +3,12 @@
|
|
3
3
|
test_to_save = ARGV.first
|
4
4
|
test_name = test_to_save.split( '/' ).last
|
5
5
|
|
6
|
-
`ruby scripts/extract_text_from_erb.rb #{test_to_save} > tests/integration/result/erb/#{test_name}.result`
|
6
|
+
`ruby scripts/extract_text_from_erb.rb i18n #{test_to_save} > tests/integration/result/erb/#{test_name}.i18n.result`
|
7
7
|
|
8
|
-
`ruby scripts/
|
8
|
+
`ruby scripts/extract_text_from_erb.rb tr8n #{test_to_save} > tests/integration/result/erb/#{test_name}.tr8n.result`
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
`ruby scripts/extract_yml_from_erb.rb #{test_to_save} > tests/integration/result/yml/#{test_name}.yml.i18n.result`
|
11
|
+
|
12
|
+
puts "Wrote: tests/integration/result/erb/#{test_name}.i18n.result"
|
13
|
+
puts "Wrote: tests/integration/result/erb/#{test_name}.tr8n.result"
|
14
|
+
puts "Wrote: tests/integration/result/yml/#{test_name}.yml.i18n.result"
|
metadata
CHANGED
@@ -1,80 +1,72 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: herbgobbler
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 2
|
9
|
-
- 2
|
10
|
-
version: 0.2.2
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Douglas Sellers
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-04-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: bundler
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 19
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 0
|
33
|
-
- 2
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
34
21
|
version: 1.0.2
|
35
22
|
type: :runtime
|
36
|
-
version_requirements: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: polyglot
|
39
23
|
prerelease: false
|
40
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.0.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: polyglot
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
41
33
|
none: false
|
42
|
-
requirements:
|
43
|
-
- -
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
hash: 17
|
46
|
-
segments:
|
47
|
-
- 0
|
48
|
-
- 3
|
49
|
-
- 1
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
50
37
|
version: 0.3.1
|
51
38
|
type: :runtime
|
52
|
-
version_requirements: *id002
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: treetop
|
55
39
|
prerelease: false
|
56
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
41
|
none: false
|
58
|
-
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.3.1
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: treetop
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
66
53
|
version: 1.4.8
|
67
54
|
type: :runtime
|
68
|
-
|
69
|
-
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.4.8
|
62
|
+
description: Allows english text extraction, for internationalization and localization,
|
63
|
+
from Ruby on Rails ERB files
|
70
64
|
email: douglas.sellers@gmail.com
|
71
|
-
executables:
|
65
|
+
executables:
|
72
66
|
- gobble
|
73
67
|
extensions: []
|
74
|
-
|
75
68
|
extra_rdoc_files: []
|
76
|
-
|
77
|
-
files:
|
69
|
+
files:
|
78
70
|
- bin/gobble
|
79
71
|
- lib/commandline/commandline.rb
|
80
72
|
- lib/commandline/gobble_all.rb
|
@@ -93,20 +85,25 @@ files:
|
|
93
85
|
- lib/core/node_processing.rb
|
94
86
|
- lib/core/non_extracting_non_text_node.rb
|
95
87
|
- lib/core/non_text_node.rb
|
88
|
+
- lib/core/pluralize_node.rb
|
96
89
|
- lib/core/rails_text_extractor.rb
|
97
90
|
- lib/core/rails_translation_store.rb
|
98
91
|
- lib/core/text_extractor.rb
|
99
92
|
- lib/core/text_node.rb
|
93
|
+
- lib/core/tr8n_text_extractor.rb
|
100
94
|
- lib/herbgobbler.rb
|
101
95
|
- lib/nodes/combindable_herb_non_text_node.rb
|
102
96
|
- lib/nodes/herb_combined_node.rb
|
103
97
|
- lib/nodes/herb_erb_text_call_node.rb
|
98
|
+
- lib/nodes/herb_erb_tr8n_text_call_node.rb
|
104
99
|
- lib/nodes/herb_node_retaining_node.rb
|
105
100
|
- lib/nodes/herb_node_retaining_non_text_node.rb
|
106
101
|
- lib/nodes/herb_node_retaining_text_node.rb
|
107
102
|
- lib/nodes/herb_non_text_node.rb
|
108
103
|
- lib/nodes/herb_string_variable.rb
|
109
104
|
- lib/nodes/herb_text_node.rb
|
105
|
+
- lib/nodes/herb_tr8n_string_node.rb
|
106
|
+
- lib/nodes/herb_tr8n_text_call_node.rb
|
110
107
|
- lib/nodes/herb_white_space_text_node.rb
|
111
108
|
- lib/nodes/nodes.rb
|
112
109
|
- lib/nodes/rails_text_variable_node.rb
|
@@ -116,43 +113,29 @@ files:
|
|
116
113
|
- scripts/rails_gobble_file.rb
|
117
114
|
- scripts/save_result.rb
|
118
115
|
- grammer/erb_grammer.treetop
|
119
|
-
has_rdoc: true
|
120
116
|
homepage: https://github.com/douglasjsellers/herbgobbler
|
121
117
|
licenses: []
|
122
|
-
|
123
118
|
post_install_message:
|
124
119
|
rdoc_options: []
|
125
|
-
|
126
|
-
require_paths:
|
120
|
+
require_paths:
|
127
121
|
- lib
|
128
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
123
|
none: false
|
130
|
-
requirements:
|
131
|
-
- -
|
132
|
-
- !ruby/object:Gem::Version
|
133
|
-
hash: 57
|
134
|
-
segments:
|
135
|
-
- 1
|
136
|
-
- 8
|
137
|
-
- 7
|
124
|
+
requirements:
|
125
|
+
- - ! '>='
|
126
|
+
- !ruby/object:Gem::Version
|
138
127
|
version: 1.8.7
|
139
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
129
|
none: false
|
141
|
-
requirements:
|
142
|
-
- -
|
143
|
-
- !ruby/object:Gem::Version
|
144
|
-
hash: 21
|
145
|
-
segments:
|
146
|
-
- 1
|
147
|
-
- 3
|
148
|
-
- 7
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
149
133
|
version: 1.3.7
|
150
134
|
requirements: []
|
151
|
-
|
152
135
|
rubyforge_project:
|
153
|
-
rubygems_version: 1.
|
136
|
+
rubygems_version: 1.8.21
|
154
137
|
signing_key:
|
155
138
|
specification_version: 3
|
156
|
-
summary: Allows english text extraction, for internationalization and localization,
|
139
|
+
summary: Allows english text extraction, for internationalization and localization,
|
140
|
+
from Ruby on Rails ERB files
|
157
141
|
test_files: []
|
158
|
-
|