herbgobbler 0.2.2 → 0.3.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.
- 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
|
-
|