langouste 0.1.2 → 0.1.3

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/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: