langouste 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem and console tool for translation through various online services (google translate, babelfish, pereklad, etc).
4
4
 
5
- With the configuration yaml-file can be configured to work with another service (look at langouste.yaml).
5
+ With the configuration yaml-file can be configured to work with another service (look at config/langouste.yaml).
6
6
 
7
7
  Full list of service defined in config:
8
8
  langouste --list
@@ -20,7 +20,7 @@ Or shorter:
20
20
  langouste -f ru -t en Я список кораблей прочел до середины
21
21
 
22
22
  Or even so:
23
- langouste -f e -t r Я список кораблей прочел до середины
23
+ langouste -f r -t e Я список кораблей прочел до середины
24
24
 
25
25
  More help:
26
26
  langouste --help
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ begin
11
11
  gem.executables = %w(langouste)
12
12
  gem.authors = ["Hariton Mizgir"]
13
13
  gem.add_dependency "mechanize", ">= 1.0.0"
14
+ gem.add_dependency "symboltable", ">= 0.2.0"
14
15
  gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
15
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
17
  gem.files.include %w(config/langouste.yaml)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.3
data/bin/langouste CHANGED
@@ -6,6 +6,7 @@ options = {
6
6
  :from_lang => :russian,
7
7
  :to_lang => :english,
8
8
  :service => :google,
9
+ :path => nil
9
10
  }
10
11
 
11
12
  if ARGV.any?
@@ -13,15 +14,15 @@ if ARGV.any?
13
14
  opts = OptionParser.new {|op|
14
15
  op.banner = "Usage: #{File.basename($0)} [options] text"
15
16
 
16
- op.on('-f language', '--from language', "") {|v| options[:from_lang] = v.to_sym }
17
- op.on('-t language', '--to language', "") {|v| options[:to_lang] = v.to_sym }
18
- op.on('-l', '--list', 'List of available services') { puts Langouste.list }
19
- op.on('-s', '--service services', "") {|v| options[:services] = v.to_sym }
20
- op.on('-c path', '--config path', "Path to config yaml-file") {|v| options[:config] = v }
17
+ op.on('-f language', '--from language', 'Source language') {|v| options[:from_lang] = v.to_sym }
18
+ op.on('-t language', '--to language', 'Destination language') {|v| options[:to_lang] = v.to_sym }
19
+ op.on('-s', '--service services', 'Service (google translate, babelfish, etc)') {|v| options[:service] = v.to_sym }
20
+ op.on('-c path', '--config path', 'Path to config file') {|v| options[:path] = v }
21
+ op.on('-l', '--list', 'List of available services') { puts Langouste::Configuration.list options[:path] }
21
22
  op.on('-h', '--help', 'Shows this help message') {puts op; exit}
22
23
 
23
24
  }.parse!(ARGV.dup)
24
25
  text = opts.join(' ')
25
26
  end
26
27
 
27
- puts Langouste.new(options).translate(text)
28
+ puts Langouste::Translator.new(options).translate(text) if text.any?
@@ -17,154 +17,6 @@ google_languages: &google_languages
17
17
  :french: fr
18
18
  :italian: it
19
19
 
20
- :google:
21
- url: 'http://translate.google.com'
22
- input:
23
- form:
24
- selector: {:name: 'text_form'}
25
- from:
26
- field:
27
- selector: {:name: 'sl'}
28
- languages:
29
- <<: *google_languages
30
- to:
31
- field:
32
- selector: {:name: 'tl'}
33
- languages:
34
- <<: *google_languages
35
- text:
36
- selector: {:name: 'text'}
37
- output:
38
- form:
39
- selector: {:action: '/translate_suggestion'}
40
- text:
41
- selector: {:name: 'gtrans'}
42
-
43
- :babelfish:
44
- url: 'http://babelfish.yahoo.com/'
45
- input:
46
- form:
47
- selector: {:name: 'frmTrText'}
48
- directions:
49
- field:
50
- selector: {:name: 'lp'}
51
- directions:
52
- :'english-dutch': en_nl
53
- :'english-french': en_fr
54
- :'english-german': en_de
55
- :'english-greek': en_el
56
- :'english-italian': en_it
57
- :'english-japanese': en_ja
58
- :'english-korean': en_ko
59
- :'english-portuguese': en_pt
60
- :'english-russian': en_ru
61
- :'english-spanish': en_es
62
- :'dutch-english': nl_en
63
- :'dutch-french': nl_fr
64
- :'french-dutch': fr_nl
65
- :'french-english': fr_en
66
- :'french-german': fr_de
67
- :'french-greek': fr_el
68
- :'french-italian': fr_it
69
- :'french-portuguese': fr_pt
70
- :'french-spanish': fr_es
71
- :'german-english': de_en
72
- :'german-french': de_fr
73
- :'greek-english': el_en
74
- :'greek-french': el_fr
75
- :'italian-english': it_en
76
- :'italian-french': it_fr
77
- :'japanese-english': ja_en
78
- :'korean-english': ko_en
79
- :'portuguese-english': pt_en
80
- :'portuguese-french': pt_fr
81
- :'russian-english': ru_en
82
- :'spanish-english': es_en
83
- :'spanish-french': es_fr
84
- text:
85
- selector: {:name: 'trtext'}
86
- output:
87
- xpath: '//div[@id="result"]/div/text()'
88
-
89
- :pereklad:
90
- url: 'http://pereklad.online.ua'
91
- input:
92
- form:
93
- selector: {:name: 'transl'}
94
- from:
95
- field:
96
- selector: {:name: 'TranFrom'}
97
- languages:
98
- <<: *pereklad_languages
99
- to:
100
- field:
101
- selector: {:name: 'TranTo'}
102
- languages:
103
- <<: *pereklad_languages
104
- text:
105
- selector: {:name: 'SrcTxt'}
106
- output:
107
- form:
108
- selector: {:name: 'transl'}
109
- text:
110
- selector: {:name: 'DstTxt'}
111
-
112
- :meta:
113
- url: 'http://translate.meta.ua'
114
- input:
115
- form:
116
- selector: {:name: 'form1'}
117
- directions:
118
- field:
119
- selector: {:name: 'language'}
120
- directions:
121
- :'russian-english': Rus-Eng
122
- :'english-russian': Eng-Rus
123
- :'ukrainian-english': Ukr-Eng
124
- :'english-ukrainian': Eng-Ukr
125
- :'russian-ukrainian': Rus-Ukr
126
- :'ukrainian-russian': Ukr-Rus
127
- :'russian-german': Rus-Ger
128
- :'german-russian': Ger-Rus
129
- :'ukrainian-german': Ukr-Ger
130
- :'german-ukrainian': Ger-Ukr
131
- :'english-german': Eng-Ger
132
- :'german-english': Ger-Eng
133
- :'russian-latvian': Rus-Lat
134
- :'latvian-russian': Lat-Rus
135
- :'ukrainian-latvian': Ukr-Lat
136
- :'latvian-ukrainian': Lat-Ukr
137
- :'english-latvian': Eng-Lat
138
- :'latvian-english': Lat-Eng
139
- :'german-latvian': Ger-Lat
140
- :'latvian-german': Lat-Ger
141
- text:
142
- selector: {:name: 'SrcTxt'}
143
- output:
144
- form:
145
- selector: {:name: 'form1'}
146
- text:
147
- selector: {:name: 'DstTxt'}
148
-
149
- :prompt:
150
- url: 'http://online.perevodov.net/Perevodov.net/online-dictionaries/promt.php4'
151
- input:
152
- form:
153
- selector: {:name: 'trans'}
154
- directions:
155
- field:
156
- selector: {:name: 'direction'}
157
- directions:
158
- :'russian-english': re
159
- :'english-russian': er
160
- text:
161
- selector: {:name: 'source'}
162
- output:
163
- form:
164
- selector: {:name: 'trans'}
165
- text:
166
- selector: {:name: 'result'}
167
-
168
20
  abbreviations:
169
21
  languages:
170
22
  :ru: :russian
@@ -183,3 +35,152 @@ abbreviations:
183
35
  :b: :babelfish
184
36
  :p: :pereklad
185
37
  :t: :prompt
38
+
39
+ services:
40
+ :google:
41
+ url: 'http://translate.google.com'
42
+ input:
43
+ form:
44
+ selector: {:name: 'text_form'}
45
+ from:
46
+ field:
47
+ selector: {:name: 'sl'}
48
+ languages:
49
+ <<: *google_languages
50
+ to:
51
+ field:
52
+ selector: {:name: 'tl'}
53
+ languages:
54
+ <<: *google_languages
55
+ text:
56
+ selector: {:name: 'text'}
57
+ output:
58
+ form:
59
+ selector: {:action: '/translate_suggestion'}
60
+ text:
61
+ selector: {:name: 'gtrans'}
62
+
63
+ :babelfish:
64
+ url: 'http://babelfish.yahoo.com/'
65
+ input:
66
+ form:
67
+ selector: {:name: 'frmTrText'}
68
+ directions:
69
+ field:
70
+ selector: {:name: 'lp'}
71
+ directions:
72
+ :'english-dutch': en_nl
73
+ :'english-french': en_fr
74
+ :'english-german': en_de
75
+ :'english-greek': en_el
76
+ :'english-italian': en_it
77
+ :'english-japanese': en_ja
78
+ :'english-korean': en_ko
79
+ :'english-portuguese': en_pt
80
+ :'english-russian': en_ru
81
+ :'english-spanish': en_es
82
+ :'dutch-english': nl_en
83
+ :'dutch-french': nl_fr
84
+ :'french-dutch': fr_nl
85
+ :'french-english': fr_en
86
+ :'french-german': fr_de
87
+ :'french-greek': fr_el
88
+ :'french-italian': fr_it
89
+ :'french-portuguese': fr_pt
90
+ :'french-spanish': fr_es
91
+ :'german-english': de_en
92
+ :'german-french': de_fr
93
+ :'greek-english': el_en
94
+ :'greek-french': el_fr
95
+ :'italian-english': it_en
96
+ :'italian-french': it_fr
97
+ :'japanese-english': ja_en
98
+ :'korean-english': ko_en
99
+ :'portuguese-english': pt_en
100
+ :'portuguese-french': pt_fr
101
+ :'russian-english': ru_en
102
+ :'spanish-english': es_en
103
+ :'spanish-french': es_fr
104
+ text:
105
+ selector: {:name: 'trtext'}
106
+ output:
107
+ xpath: '//div[@id="result"]/div/text()'
108
+
109
+ :pereklad:
110
+ url: 'http://pereklad.online.ua'
111
+ input:
112
+ form:
113
+ selector: {:name: 'transl'}
114
+ from:
115
+ field:
116
+ selector: {:name: 'TranFrom'}
117
+ languages:
118
+ <<: *pereklad_languages
119
+ to:
120
+ field:
121
+ selector: {:name: 'TranTo'}
122
+ languages:
123
+ <<: *pereklad_languages
124
+ text:
125
+ selector: {:name: 'SrcTxt'}
126
+ output:
127
+ form:
128
+ selector: {:name: 'transl'}
129
+ text:
130
+ selector: {:name: 'DstTxt'}
131
+
132
+ :meta:
133
+ url: 'http://translate.meta.ua'
134
+ input:
135
+ form:
136
+ selector: {:name: 'form1'}
137
+ directions:
138
+ field:
139
+ selector: {:name: 'language'}
140
+ directions:
141
+ :'russian-english': Rus-Eng
142
+ :'english-russian': Eng-Rus
143
+ :'ukrainian-english': Ukr-Eng
144
+ :'english-ukrainian': Eng-Ukr
145
+ :'russian-ukrainian': Rus-Ukr
146
+ :'ukrainian-russian': Ukr-Rus
147
+ :'russian-german': Rus-Ger
148
+ :'german-russian': Ger-Rus
149
+ :'ukrainian-german': Ukr-Ger
150
+ :'german-ukrainian': Ger-Ukr
151
+ :'english-german': Eng-Ger
152
+ :'german-english': Ger-Eng
153
+ :'russian-latvian': Rus-Lat
154
+ :'latvian-russian': Lat-Rus
155
+ :'ukrainian-latvian': Ukr-Lat
156
+ :'latvian-ukrainian': Lat-Ukr
157
+ :'english-latvian': Eng-Lat
158
+ :'latvian-english': Lat-Eng
159
+ :'german-latvian': Ger-Lat
160
+ :'latvian-german': Lat-Ger
161
+ text:
162
+ selector: {:name: 'SrcTxt'}
163
+ output:
164
+ form:
165
+ selector: {:name: 'form1'}
166
+ text:
167
+ selector: {:name: 'DstTxt'}
168
+
169
+ :prompt:
170
+ url: 'http://online.perevodov.net/Perevodov.net/online-dictionaries/promt.php4'
171
+ input:
172
+ form:
173
+ selector: {:name: 'trans'}
174
+ directions:
175
+ field:
176
+ selector: {:name: 'direction'}
177
+ directions:
178
+ :'russian-english': re
179
+ :'english-russian': er
180
+ text:
181
+ selector: {:name: 'source'}
182
+ output:
183
+ form:
184
+ selector: {:name: 'trans'}
185
+ text:
186
+ selector: {:name: 'result'}
data/langouste.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{langouste}
8
- s.version = "0.1.2"
8
+ s.version = "0.1.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Hariton Mizgir"]
12
- s.date = %q{2010-05-05}
12
+ s.date = %q{2010-05-07}
13
13
  s.default_executable = %q{langouste}
14
14
  s.email = %q{hmizgir@gmail.com}
15
15
  s.executables = ["langouste"]
@@ -47,13 +47,16 @@ Gem::Specification.new do |s|
47
47
 
48
48
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
49
  s.add_runtime_dependency(%q<mechanize>, [">= 1.0.0"])
50
+ s.add_runtime_dependency(%q<symboltable>, [">= 0.2.0"])
50
51
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
51
52
  else
52
53
  s.add_dependency(%q<mechanize>, [">= 1.0.0"])
54
+ s.add_dependency(%q<symboltable>, [">= 0.2.0"])
53
55
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
54
56
  end
55
57
  else
56
58
  s.add_dependency(%q<mechanize>, [">= 1.0.0"])
59
+ s.add_dependency(%q<symboltable>, [">= 0.2.0"])
57
60
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
58
61
  end
59
62
  end
data/lib/langouste.rb CHANGED
@@ -2,117 +2,122 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'mechanize'
5
+ require 'symboltable'
5
6
 
6
- class Langouste
7
- attr_accessor :from_lang, :to_lang, :service, :config
7
+ # Translation through various online services
8
+ module Langouste
8
9
 
9
- @@config_path = File.join(File.expand_path(File.dirname(__FILE__)), '../config/langouste.yaml')
10
+ # Singleton configuration class
11
+ class Configuration
12
+ attr_accessor :path, :data
10
13
 
11
- def self.config
12
- @@config ||= YAML.load(File.open(@@config_path))
13
- end
14
-
15
- def self.config=(config)
16
- @@config = config
17
- end
14
+ def initialize(path = nil)
15
+ @path = path || File.join(File.expand_path(File.dirname(__FILE__)), '../config/langouste.yaml')
16
+ @data = SymbolTable.new YAML.load_file @path
17
+ end
18
18
 
19
- def initialize(options = {})
20
- options = {
21
- :from_lang => :russian,
22
- :to_lang => :english,
23
- :service => :google,
24
- :config => @@config_path
25
- }.merge options
19
+ def self.instance(path = nil)
20
+ @__instance__ ||= new
21
+ end
26
22
 
27
- Langouste.config = YAML.load(File.open(options[:config]))
23
+ def self.list(config_path = nil)
24
+ Configuration.instance(config_path).data.services.keys
25
+ end
28
26
 
29
- @from_lang = deabbreviate_language(options[:from_lang])
30
- @to_lang = deabbreviate_language(options[:to_lang])
31
- @service = deabbreviate_service(options[:service])
32
- @config = Langouste.config[@service]
33
27
  end
34
28
 
35
- def translate(input_text)
29
+ # Langouste translator
30
+ class Translator
31
+ attr_accessor :service, :from_lang, :to_lang
36
32
 
37
- output_text = ''
33
+ def initialize(options = {})
34
+ options = {
35
+ :from_lang => :russian,
36
+ :to_lang => :english,
37
+ :service => :google,
38
+ :path => nil
39
+ }.merge options
38
40
 
39
- begin
40
- input_form = config['input']['form']
41
- rescue
42
- raise "Bad service: '#{service}'"
43
- end
41
+ config = Configuration.instance(options[:path])
44
42
 
45
- # если у переводчика нет нужных языков - запрос не выполняется
46
- if input_form['to'] and input_form['from']
47
- return '' unless input_form['to']['languages'][to_lang] and input_form['from']['languages'][from_lang]
48
- elsif input_form['directions']
49
- return '' unless input_form['directions']['directions']["#{from_lang}-#{to_lang}".to_sym]
50
- else
51
- raise "Bad YAML-config for service: '#{service}'"
52
- end
43
+ @service = deabbreviate_service(options[:service])
44
+ @from_lang = deabbreviate_language(options[:from_lang])
45
+ @to_lang = deabbreviate_language(options[:to_lang])
46
+ @direction = "#{@from_lang}-#{@to_lang}"
47
+ @config = config.data.services[@service]
53
48
 
54
- agent = Mechanize.new {|a| a.user_agent_alias = 'Linux Konqueror'}
55
-
56
- agent.get(config['url']) do |page|
57
-
58
- translated_page = page.form_with(input_form['selector']) do |form|
59
-
60
- text = form.field_with(input_form['text']['selector'])
61
- text.value = input_text
49
+ end
62
50
 
63
- if input_form['directions'] and input_form['directions']['field']['selector']
51
+ def translate(input_text)
64
52
 
65
- value = input_form['directions']['directions']["#{from_lang}-#{to_lang}".to_sym]
66
- direction = form.field_with(input_form['directions']['field']['selector'])
67
- direction.option_with(:value => value).select
53
+ return '' if not has_languages? or input_text.empty?
68
54
 
69
- else
55
+ agent = Mechanize.new {|a| a.user_agent_alias = 'Linux Konqueror'}
70
56
 
71
- if input_form['from'] and input_form['from']['field'] and input_form['from']['field']['selector']
57
+ input_form = @config.input.form
58
+ page = agent.get(@config.url)
59
+ translated_page = page.form_with(input_form.selector) do |form|
60
+ fill_form form, input_form, input_text
61
+ end.submit
72
62
 
73
- value = input_form['from']['languages'][from_lang]
74
- from_lang = form.field_with(input_form['from']['field']['selector'])
75
- from_lang.option_with(:value => value).select
63
+ get_translation translated_page, @config.output
76
64
 
77
- end
65
+ end
78
66
 
79
- if input_form['to'] and input_form['to']['field'] and input_form['to']['field']['selector']
67
+ private
80
68
 
81
- value = input_form['to']['languages'][to_lang]
82
- to_lang = form.field_with(input_form['to']['field']['selector'])
83
- to_lang.option_with(:value => value).select
69
+ def deabbreviate_language(language)
70
+ Configuration.instance.data.abbreviations.languages[language] || language
71
+ end
84
72
 
85
- end
73
+ def deabbreviate_service(service)
74
+ Configuration.instance.data.abbreviations.services[service] || service
75
+ end
86
76
 
87
- end
77
+ def has_languages?
78
+ input_form = @config.input.form
79
+ if input_form.to and input_form.from
80
+ return false unless input_form.to.languages[@to_lang] and input_form.from.languages[@from_lang]
81
+ elsif input_form.directions
82
+ return false unless input_form.directions.directions[@direction]
83
+ end
84
+ return true
85
+ end
88
86
 
89
- end.submit
87
+ def fill_form(form, config_form, input_text)
88
+ to, from, directions, text = config_form.to, config_form.from, config_form.directions, config_form.text
90
89
 
91
- output_text = if config['output']['xpath']
92
- xpath = config['output']['xpath']
93
- translated_page.search(xpath)
90
+ if directions and directions.field and directions.field.selector
91
+ set_form_option form.field_with(directions.field.selector), directions.directions[@direction]
94
92
  else
95
- output_form = config['output']['form']
96
- translated_page.form_with(output_form['selector']).field_with(output_form['text']['selector']).value
93
+ if from and from.field and from.field.selector
94
+ set_form_option form.field_with(from.field.selector), from.languages[@from_lang]
95
+ end
96
+ if to and to.field and to.field.selector
97
+ set_form_option form.field_with(to.field.selector), to.languages[@to_lang]
98
+ end
97
99
  end
98
100
 
101
+ form_text_field = form.field_with(text.selector)
102
+ form_text_field.value = input_text
99
103
  end
100
104
 
101
- output_text.to_s
102
- end
105
+ def set_form_option(field, value)
106
+ field.option_with(:value => value).select
107
+ end
103
108
 
104
- def self.list(config_path = nil)
105
- Langouste.config.keys.select{|k| k.is_a?(Symbol)}
106
- end
109
+ def get_translation(page, config_output)
107
110
 
108
- private
111
+ translation = if config_output.xpath
112
+ page.search(config_output.xpath)
113
+ else
114
+ output_form = config_output.form
115
+ page.form_with(output_form.selector).field_with(output_form.text.selector).value
116
+ end
109
117
 
110
- def deabbreviate_language(language)
111
- Langouste.config['abbreviations']['languages'][language] || language
112
- end
118
+ translation ? translation.to_s : ''
119
+ end
113
120
 
114
- def deabbreviate_service(services)
115
- Langouste.config['abbreviations']['services'][services] || services
116
121
  end
117
122
 
118
123
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 2
9
- version: 0.1.2
8
+ - 3
9
+ version: 0.1.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Hariton Mizgir
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-05 00:00:00 +04:00
17
+ date: 2010-05-07 00:00:00 +04:00
18
18
  default_executable: langouste
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -32,9 +32,23 @@ dependencies:
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
34
  - !ruby/object:Gem::Dependency
35
- name: thoughtbot-shoulda
35
+ name: symboltable
36
36
  prerelease: false
37
37
  requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 2
44
+ - 0
45
+ version: 0.2.0
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: thoughtbot-shoulda
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
38
52
  requirements:
39
53
  - - ">="
40
54
  - !ruby/object:Gem::Version
@@ -42,7 +56,7 @@ dependencies:
42
56
  - 0
43
57
  version: "0"
44
58
  type: :development
45
- version_requirements: *id002
59
+ version_requirements: *id003
46
60
  description:
47
61
  email: hmizgir@gmail.com
48
62
  executables: