tranzu-rack-tranzu 0.0.1

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.
Files changed (4) hide show
  1. data/README +0 -0
  2. data/lib/rack/tranzu.rb +107 -0
  3. data/spec/tranzu_spec.rb +99 -0
  4. metadata +65 -0
data/README ADDED
File without changes
@@ -0,0 +1,107 @@
1
+ require 'nokogiri'
2
+ require 'lib/text_block'
3
+
4
+
5
+ module Rack
6
+ class Tranzu
7
+
8
+ def initialize(app, site_key)
9
+ @app, @site_key = app, site_key
10
+ end
11
+
12
+ def call(env)
13
+ status, headers, response = @app.call(env)
14
+
15
+ if headers["Content-Type"].include? "text/html"
16
+ translate_page(status, headers, response)
17
+ else
18
+ [status, headers, response]
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def translate_page(status, headers, response)
25
+ doc = parse_web_page(response)
26
+
27
+ doc.traverse do |dom_element|
28
+ if dom_element.text? && !dom_element.inner_text.blank?
29
+ record_text_block_if_new(dom_element.inner_text.strip)
30
+ end
31
+ end
32
+
33
+ doc.traverse do |dom_element|
34
+ if dom_element.text? && !dom_element.inner_text.blank?
35
+ replace_text_with_applicable_translations(dom_element)
36
+ end
37
+ end
38
+
39
+ html = serialized_html(doc)
40
+
41
+ [status, headers, [html]]
42
+ end
43
+
44
+ def serialized_html(doc)
45
+ html = doc.search("html").to_html
46
+ html.gsub(/\>\n\</,"><")
47
+ end
48
+
49
+
50
+ def replace_text_with_applicable_translations(text_element)
51
+ new_text = text_element.inner_text
52
+ all_stored_text_blocks.each do |key, value|
53
+ new_text.gsub!(/#{key}/, value) if value # TODO: escape key for Regexp
54
+ end
55
+ text_element.parent.content = new_text
56
+ end
57
+
58
+ def parse_web_page(response)
59
+ all_content = ""
60
+ response.each do |content|
61
+ all_content << content
62
+ end
63
+ doc = Nokogiri::HTML(all_content)
64
+ end
65
+
66
+ def all_stored_text_blocks
67
+ unless @mapping
68
+ @mapping = {}
69
+ text_blocks = TextBlock.find(:all, :params => {:site_key => @site_key})
70
+
71
+ text_blocks.each do |text_block|
72
+ @mapping[text_block.source_text] = text_block.target_text
73
+ end
74
+ end
75
+ @mapping
76
+ end
77
+
78
+ def text_blocks_with_translations
79
+ all_stored_text_blocks.delete_if{|key, value| value.nil?}
80
+ end
81
+
82
+ def untranslated_text_blocks
83
+ all_stored_text_blocks.select{|key, value| value.nil?}.map{|pair| pair.first}
84
+ end
85
+
86
+ def record_text_block_if_new(source_text)
87
+ text_block = TextBlock.find(:one, :params => {:site_key => @site_key, :source_text => source_text})
88
+ unless text_block
89
+ text_block = TextBlock.create(:site_key => @site_key, :source_text => source_text)
90
+ unless text_block
91
+ raise Exception.new("unable to create text block")
92
+ end
93
+ end
94
+ end
95
+
96
+ def record_text_block_with_translation(source_text, target_text)
97
+ text_block = TextBlock.find(:one, :params => {:site_key => @site_key, :source_text => source_text})
98
+ text_block ||= TextBlock.new(:site_key => @site_key, :source_text => source_text)
99
+ text_block.target_text = target_text
100
+ unless text_block.save
101
+ raise Exception.new("unable to save text block")
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,99 @@
1
+ require 'rack'
2
+ require 'lib/text_block'
3
+ require 'lib/rack/tranzu'
4
+
5
+ describe Rack::Tranzu do
6
+ def delete_all_text_blocks
7
+ text_blocks = TextBlock.find(:all)
8
+ text_blocks.each do |text_block|
9
+ text_block.destroy
10
+ end
11
+ end
12
+
13
+ before (:each) do
14
+ delete_all_text_blocks
15
+ @response_strings = []
16
+ @client_app = lambda {|env| [200, {'Content-Type' => 'text/html'}, @response_strings] }
17
+ @app = Rack::Tranzu.new(@client_app, "1234ABCD")
18
+ @app.send(:record_text_block_with_translation, "This is an example of already translated text.", "Se ejemplifica texto ya traducido.")
19
+ end
20
+
21
+ it "should store all text blocks returned by the web site" do
22
+ delete_all_text_blocks # re-delete items for this test case only
23
+ @response_strings << "<html><body><p>This is an example of already translated text.</p><p>This is an example of untranslated text.</p><p>This is another example of untranslated text.</p></body></html>"
24
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/html')
25
+
26
+
27
+ source_text_items = TextBlock.find(:all).map {|text_block_translations| text_block_translations.source_text}
28
+ source_text_items.sort.should == ["This is an example of already translated text.", "This is an example of untranslated text.", "This is another example of untranslated text."].sort
29
+ end
30
+
31
+ it "should identify stored text blocks with no corresponding translations" do
32
+ @response_strings << "<html><body><p>This is an example of already translated text.</p><p>This is an example of untranslated text.</p><p>This is another example of untranslated text.</p></body></html>"
33
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/html')
34
+ untranslated_text_blocks = @app.send(:untranslated_text_blocks)
35
+ untranslated_text_blocks.sort.should == ["This is an example of untranslated text.", "This is another example of untranslated text."].sort
36
+ end
37
+
38
+ it "should identify stored text blocks with corresponding translations" do
39
+ @response_strings << "<html><body><p>This is an example of already translated text.</p><p>This is an example of untranslated text.</p><p>This is another example of untranslated text.</p></body></html>"
40
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/html')
41
+ text_blocks_with_translations = @app.send(:text_blocks_with_translations)
42
+ text_blocks_with_translations.should == {"This is an example of already translated text." => "Se ejemplifica texto ya traducido."}
43
+ end
44
+
45
+ it "should pass-through stored text blocks that lack translated equivalents" do
46
+ @response_strings << "<html><body><p>This is an example of untranslated text.</p></body></html>"
47
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/html')
48
+ response.body.should == @response_strings[0]
49
+ end
50
+
51
+ it "should replace stored text blocks with translated equivalents" do
52
+ @response_strings << "<html><body><p>This is an example of already translated text.</p></body></html>"
53
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/html')
54
+ response.body.should == "<html><body><p>Se ejemplifica texto ya traducido.</p></body></html>"
55
+ end
56
+
57
+ it "should replace text blocks with translated equivalents and leave those that lack translated equivalents untranslated" do
58
+ @response_strings << "<html><body><p>This is an example of already translated text.</p><p>This is an example of untranslated text.</p></body></html>"
59
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/html')
60
+ response.body.should == "<html><body><p>Se ejemplifica texto ya traducido.</p><p>This is an example of untranslated text.</p></body></html>"
61
+ end
62
+
63
+ it "should not translate any text blocks if the site id is not valid" do
64
+ @app = Rack::Tranzu.new(@client_app, "X1234ABCD")
65
+ source_text = "<html><body><p>This is an example of already translated text.</p><p>This is an example of untranslated text.</p></body></html>"
66
+ @response_strings << source_text
67
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/html')
68
+ response.body.should == source_text
69
+ end
70
+
71
+ describe "translating is partial to html" do
72
+ it "should attempt to translate html requests" do
73
+ @response_strings << "<html><body><p>This is an example of already translated text.</p></body></html>"
74
+ @app.should_receive(:translate_page).and_return([200, {'Content-Type' => 'text/html'}, @response_strings])
75
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/html')
76
+ end
77
+
78
+ it "should not attempt to translate non-html requests" do
79
+ @response_strings << "<adam>adam is studly</adam>"
80
+ @client_app = lambda {|env| [201, {'Content-Type' => 'text/xml', 'Content-Encoding' => 'gzip'}, @response_strings] }
81
+ @app = Rack::Tranzu.new(@client_app, "1234ABCD")
82
+ @app.should_not_receive(:translate_page)
83
+ response = Rack::MockRequest.new(@app).get('/', 'HTTP_ACCEPT' => 'text/xml')
84
+ response.body.should == @response_strings[0]
85
+ response.status.should == 201
86
+ response.headers.should == {'Content-Type' => 'text/xml', 'Content-Encoding' => 'gzip'}
87
+ end
88
+ end
89
+
90
+ it "should not strip out linefeeds from html"
91
+
92
+ it "should not strip out leading or trailing whitespace from text nodes"
93
+
94
+ it "should not change DOCTYPE if it exists in the application response'"
95
+
96
+ it "should not add DOCTYPE if it is not in the application response"
97
+
98
+ end
99
+
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tranzu-rack-tranzu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - John Reitano
8
+ - Adam King
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-09-01 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rack
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: "0.4"
25
+ version:
26
+ description: Website translation middleware.
27
+ email: tranzuapp@gmail.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - README
36
+ - lib/rack/tranzu.rb
37
+ has_rdoc: false
38
+ homepage: http://github.com/tranzu/rack-tranzu
39
+ licenses:
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.3.5
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: Website translation middleware.
64
+ test_files:
65
+ - spec/tranzu_spec.rb