├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .rspec
├── Gemfile
├── README.md
├── Rakefile
├── easy_translate.gemspec
├── lib
├── easy_translate.rb
└── easy_translate
│ ├── detection.rb
│ ├── easy_translate_exception.rb
│ ├── languages.rb
│ ├── request.rb
│ ├── threadable.rb
│ ├── translation.rb
│ ├── translation_target.rb
│ └── version.rb
└── spec
├── examples
├── detection_spec.rb
├── easy_translate_spec.rb
├── real_world_spec.rb
├── request_spec.rb
├── translation_spec.rb
└── translation_target_spec.rb
└── spec_helper.rb
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 | on:
3 | push:
4 | branches: [ main ]
5 | pull_request:
6 | branches: ['*']
7 |
8 | jobs:
9 | test_sqlite:
10 | runs-on: ubuntu-latest
11 | strategy:
12 | fail-fast: false
13 | matrix:
14 | include:
15 | ### TEST ALL RUBY VERSIONS
16 | - ruby: 2.3 ### min version supported by Bundler 2.x, ruby: 2.3
17 | - ruby: 2.4
18 | - ruby: 2.5
19 | - ruby: 2.6
20 | - ruby: 2.7
21 | - ruby: "3.0" ### must be quoted otherwise will be treated as "3" which resolves to latest 3.x version
22 | - ruby: 3.1
23 |
24 | env:
25 | BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
26 |
27 | steps:
28 | - uses: actions/checkout@v2
29 |
30 | - name: Install ruby
31 | uses: ruby/setup-ruby@v1
32 | with:
33 | ruby-version: "${{ matrix.ruby }}"
34 | bundler-cache: true
35 |
36 | - name: Run tests
37 | run: |
38 | bundle exec rake
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *.swo
3 | *.gem
4 | .ruby-version
5 | coverage/*
6 |
7 | Gemfile.lock
8 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | -c -fd
2 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## EasyTranslate
2 |
3 |
4 |
5 | This is a Ruby library for Google Translate that makes working with bulk calls,
6 | user_ips and access via API Key easy.
7 |
8 | Unlike the official google client, `easy_translate` does not have a dependency on the `grpc` gem. This can be an advantage because `grpc` may be difficult to install on some systems or configurations.
9 |
10 | ---
11 |
12 | ### Installation
13 |
14 | ```bash
15 | $ gem install easy_translate
16 | ```
17 |
18 | Or in your Gemfile:
19 |
20 | ```ruby
21 | gem 'easy_translate'
22 | ```
23 |
24 | ---
25 |
26 | ## Single translation
27 |
28 | ```ruby
29 | # auto-detect
30 | EasyTranslate.translate('Hello, world', to: :spanish) # => "Hola, mundo"
31 | EasyTranslate.translate('Hello, world', to: 'es') # => "Hola, mundo"
32 |
33 | # feel free to specify explicitly
34 | EasyTranslate.translate('Hola, mundo', from: :spanish, to: :en) # => "Hello, world"
35 | ```
36 |
37 | ## Batch translation (Yay!)
38 |
39 | ```ruby
40 | # multiple strings
41 | EasyTranslate.translate(['Hello', 'Goodbye'], to: :spanish) # => ["¡Hola", "Despedida"]
42 | ```
43 |
44 | ## API Keys
45 |
46 | ```ruby
47 | # make google happy - (NOTE: use these anywhere)
48 | EasyTranslate.translate('Hello, world', to: :es, key: 'xxx')
49 |
50 | # don't want to set the key on every call? ** Me either! **
51 | EasyTranslate.api_key = 'xxx'
52 | ```
53 |
54 | ## You want language detection too?
55 |
56 | ```ruby
57 | # detect language
58 | EasyTranslate.detect "This is definitely English!" # => 'en'
59 | ```
60 |
61 | ## Batch detection (Woohoo!)
62 |
63 | ```ruby
64 | # detect language
65 | EasyTranslate.detect ['Hello World', '我姓譚'] # => ['en', 'zh-CN']
66 | ```
67 |
68 | ## Need confidence in your detections?
69 |
70 | ```ruby
71 | # detect language with confidence
72 | EasyTranslate.detect "This is definitely English!", confidence: true # => { :language => 'en', :confidence => 0.77272725 }
73 | ```
74 |
75 | ```ruby
76 | # detect batch languages with confidence
77 | EasyTranslate.detect ['This is definitely English!', '我姓譚'], confidence: true # => [{ :language => 'en', :confidence => 0.77272725 }, { :language => 'zh-CN', :confidence => 1.0 }]
78 | ```
79 |
80 | ## Explicitly select translation model (NMT, PBMT)
81 | Google Translate now replaces Phrase Based Machine Translation (PBMT) with Neural Machine Translation (NMT) automatically where possible. If you prefer PBMT or need to compare the results, you can use the `model:` parameter with either `nmt` or `base` to force the model selection:
82 |
83 | ```ruby
84 | EasyTranslate.translate("El cuervo americano es un ave con plumas negras iridiscentes sobre todo su cuerpo.", from: "es", to: "en", model: "nmt")
85 | # => "The American Raven is a bird with iridescent black feathers over its entire body."
86 | ```
87 |
88 | ```ruby
89 | EasyTranslate.translate("El cuervo americano es un ave con plumas negras iridiscentes sobre todo su cuerpo.", from: "es", to: "en", model: "base")
90 | # => "The American crow is a bird with iridescent black feathers over her body."
91 | ```
92 |
93 | See https://research.googleblog.com/2016/09/a-neural-network-for-machine.html for more background
94 |
95 | ## Google Translate supports HTML (default) and plain text formats
96 |
97 | ```ruby
98 | EasyTranslate.translate "Las doce en punto", format: 'text', to: :en
99 | # => "Twelve o'clock"
100 | EasyTranslate.translate "Las doce en punto", format: 'html', to: :en
101 | # => "Twelve o'clock"
102 | ```
103 |
104 | ---
105 |
106 | ## A note on concurrency as of v0.4.0
107 |
108 | Due to limitations with the Google Translate batch API, above a certain
109 | number of translations - this library will begin making calls concurrently.
110 |
111 | The default concurrency is 4, but if you'd prefer to run without threads,
112 | you can set `:concurrency => 1` to run the translation calls serially.
113 |
114 | ---
115 |
116 | ## List of languages
117 |
118 | ```ruby
119 | # list from
120 | EasyTranslate::LANGUAGES # => { 'en' => 'english', ... }
121 | ```
122 |
123 | ### List of supported languages
124 |
125 | ```ruby
126 | # List all languages (from API)
127 | EasyTranslate.translations_available
128 |
129 | # List all languages supported by some language
130 | EasyTranslate.translations_available('zh-CN')
131 | ```
132 |
133 | ---
134 |
135 | ### EasyTranslate in PHP
136 |
137 | [Kofel](https://github.com/Kofel) ported this library to PHP.
138 | You can find the port [on GitHub](https://github.com/Kofel/EasyTranslate)
139 |
140 | ---
141 |
142 | ### Contributors
143 |
144 | * John Crepezzi - john.crepezzi@gmail.com
145 | * Guy Maliar - gmaliar@gmail.com
146 | * [Gleb Mazovetskiy](https://github.com/glebm)
147 |
148 | Full contributor data at:
149 | https://github.com/seejohnrun/easy_translate/contributors
150 |
151 | ---
152 |
153 | ### License
154 |
155 | (The MIT License)
156 |
157 | Copyright © 2010-2018 John Crepezzi
158 |
159 | Permission is hereby granted, free of charge, to any person obtaining a copy of
160 | this software and associated documentation files (the ‘Software’), to deal in
161 | the Software without restriction, including without limitation the rights to
162 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
163 | of the Software, and to permit persons to whom the Software is furnished to do
164 | so, subject to the following conditions:
165 |
166 | The above copyright notice and this permission notice shall be included in all
167 | copies or substantial portions of the Software.
168 |
169 | THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
170 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
171 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
172 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
173 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
174 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
175 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rspec/core/rake_task'
2 | require 'bundler'
3 |
4 | task :build => :test do
5 | system "gem build easy_translate.gemspec"
6 | end
7 |
8 | task :release => :build do
9 | # tag and push
10 | version = Bundler.load_gemspec('easy_translate.gemspec').version
11 | system "git tag v#{version}"
12 | system "git push origin --tags"
13 | # push the gem
14 | system "gem push easy_translate-#{version}.gem"
15 | end
16 |
17 | RSpec::Core::RakeTask.new(:test) do |t|
18 | t.pattern = 'spec/**/*_spec.rb'
19 | fail_on_error = true # be explicit
20 | end
21 |
22 | task :default => :test
23 |
24 | desc "Cache API languages into lib/easy_translate/languages.rb, must set GOOGLE_TRANSLATE_API_KEY"
25 | task :cache_languages do
26 | $: << "lib"
27 | require "easy_translate"
28 | EasyTranslate.api_key = ENV.fetch("GOOGLE_TRANSLATE_API_KEY")
29 |
30 | language_filename = "lib/easy_translate/languages.rb"
31 | previous_contents = File.read(language_filename)
32 |
33 | response = JSON.parse(EasyTranslate::TranslationTarget::TranslationTargetRequest.new("en").perform_raw)
34 | language_keys = response.dig("data", "languages").map do |info|
35 | [info["name"].downcase.gsub(/[^a-z ]/, "").tr(" ", "_"), info["language"]]
36 | end.sort.map do |n, l|
37 | " '#{l}' => '#{n}'"
38 | end.join(",\n")
39 | new_contents = previous_contents.sub(/(LANGUAGES = {).*?(})/m, "\\1\n#{language_keys}\n \\2")
40 |
41 | File.open(language_filename, "w") do |f|
42 | f.write(new_contents)
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/easy_translate.gemspec:
--------------------------------------------------------------------------------
1 | require File.expand_path('lib/easy_translate/version', File.dirname(__FILE__))
2 |
3 | spec = Gem::Specification.new do |s|
4 | s.name = 'easy_translate'
5 | s.author = 'John Crepezzi'
6 | s.add_development_dependency('rspec')
7 | s.add_development_dependency('rake')
8 | s.add_dependency 'thread'
9 | s.add_dependency 'thread_safe'
10 | s.description = 'easy_translate is a wrapper for the google translate API that makes sense programatically, and implements API keys'
11 | s.email = 'john.crepezzi@gmail.com'
12 | s.files = Dir['lib/**/*.rb']
13 | s.has_rdoc = true
14 | s.homepage = 'https://github.com/seejohnrun/easy_translate'
15 | s.platform = Gem::Platform::RUBY
16 | s.require_paths = ['lib']
17 | s.summary = 'Google Translate API Wrapper for Ruby'
18 | s.test_files = Dir.glob('spec/*.rb')
19 | s.version = EasyTranslate::VERSION
20 | s.license = 'MIT'
21 | end
22 |
--------------------------------------------------------------------------------
/lib/easy_translate.rb:
--------------------------------------------------------------------------------
1 | require 'easy_translate/detection'
2 | require 'easy_translate/translation'
3 | require 'easy_translate/translation_target'
4 |
5 | module EasyTranslate
6 |
7 | autoload :EasyTranslateException, 'easy_translate/easy_translate_exception'
8 | autoload :Request, 'easy_translate/request'
9 |
10 | autoload :LANGUAGES, 'easy_translate/languages'
11 | autoload :VERSION, 'easy_translate/version'
12 |
13 | extend Detection # Language Detection
14 | extend Translation # Language Translation
15 | extend TranslationTarget # Language Translation Targets
16 |
17 | class << self
18 | attr_accessor :api_key
19 | end
20 |
21 | end
22 |
--------------------------------------------------------------------------------
/lib/easy_translate/detection.rb:
--------------------------------------------------------------------------------
1 | require 'json'
2 | require 'cgi'
3 | require 'easy_translate/request'
4 | require 'easy_translate/threadable'
5 |
6 | module EasyTranslate
7 |
8 | module Detection
9 | include Threadable
10 |
11 | # Detect language
12 | # @param [String, Array] texts - A single string or set of strings to detect for
13 | # @param [Hash] options - Extra options to pass along with the request
14 | # @return [String, Array] The resultant language or languages
15 | def detect(texts, options = {}, http_options = {})
16 | threaded_process(:request_detection, texts, options, http_options)
17 | end
18 |
19 | private
20 | def request_detection(texts, options, http_options)
21 | request = DetectionRequest.new(texts, options, http_options)
22 | raw = request.perform_raw
23 | detections = JSON.parse(raw)['data']['detections'].map do |res|
24 | res.empty? ? nil :
25 | options[:confidence] ?
26 | { :language => res.first['language'], :confidence => res.first['confidence'] } : res.first['language']
27 | end
28 | end
29 |
30 | # A convenience class for wrapping a detection request
31 | class DetectionRequest < EasyTranslate::Request
32 |
33 | # Set the texts and options
34 | # @param [String, Array] texts - The text (or texts) to translate
35 | # @param [Hash] options - Options to override or pass along with the request
36 | def initialize(texts, options = {}, http_options = {})
37 | super(options, http_options)
38 | if replacement_api_key = @options.delete(:api_key)
39 | @options[:key] = replacement_api_key
40 | end
41 | self.texts = texts
42 | end
43 |
44 | # The params for this request
45 | # @return [Hash] the params for the request
46 | def params
47 | params = super || {}
48 | params.merge! @options if @options
49 | params
50 | end
51 |
52 | # The path for the request
53 | # @return [String] The path for the request
54 | def path
55 | '/language/translate/v2/detect'
56 | end
57 |
58 | # The body for the request
59 | # @return [String] the body for the request, URL escaped
60 | def body
61 | @texts.map { |t| "q=#{CGI::escape(t)}" }.join '&'
62 | end
63 |
64 | # Whether or not this was a request for multiple texts
65 | # @return [Boolean]
66 | def multi?
67 | @multi
68 | end
69 |
70 | private
71 |
72 | # Set the texts for this request
73 | # @param [String, Array] texts - The text or texts for this request
74 | def texts=(texts)
75 | if texts.is_a?(String)
76 | @multi = false
77 | @texts = [texts]
78 | else
79 | @multi = true
80 | @texts = texts
81 | end
82 | end
83 |
84 | end
85 |
86 | end
87 |
88 | end
89 |
--------------------------------------------------------------------------------
/lib/easy_translate/easy_translate_exception.rb:
--------------------------------------------------------------------------------
1 | module EasyTranslate
2 |
3 | class EasyTranslateException < StandardError
4 | end
5 |
6 | end
7 |
--------------------------------------------------------------------------------
/lib/easy_translate/languages.rb:
--------------------------------------------------------------------------------
1 | module EasyTranslate
2 |
3 | LANGUAGES = {
4 | 'af' => 'afrikaans',
5 | 'sq' => 'albanian',
6 | 'am' => 'amharic',
7 | 'ar' => 'arabic',
8 | 'hy' => 'armenian',
9 | 'as' => 'assamese',
10 | 'ay' => 'aymara',
11 | 'az' => 'azerbaijani',
12 | 'bm' => 'bambara',
13 | 'eu' => 'basque',
14 | 'be' => 'belarusian',
15 | 'bn' => 'bengali',
16 | 'bho' => 'bhojpuri',
17 | 'bs' => 'bosnian',
18 | 'bg' => 'bulgarian',
19 | 'ca' => 'catalan',
20 | 'ceb' => 'cebuano',
21 | 'ny' => 'chichewa',
22 | 'zh' => 'chinese_simplified',
23 | 'zh-CN' => 'chinese_simplified',
24 | 'zh-TW' => 'chinese_traditional',
25 | 'co' => 'corsican',
26 | 'hr' => 'croatian',
27 | 'cs' => 'czech',
28 | 'da' => 'danish',
29 | 'dv' => 'divehi',
30 | 'doi' => 'dogri',
31 | 'nl' => 'dutch',
32 | 'en' => 'english',
33 | 'eo' => 'esperanto',
34 | 'et' => 'estonian',
35 | 'ee' => 'ewe',
36 | 'tl' => 'filipino',
37 | 'fi' => 'finnish',
38 | 'fr' => 'french',
39 | 'fy' => 'frisian',
40 | 'gl' => 'galician',
41 | 'lg' => 'ganda',
42 | 'ka' => 'georgian',
43 | 'de' => 'german',
44 | 'el' => 'greek',
45 | 'gn' => 'guarani',
46 | 'gu' => 'gujarati',
47 | 'ht' => 'haitian_creole',
48 | 'ha' => 'hausa',
49 | 'haw' => 'hawaiian',
50 | 'he' => 'hebrew',
51 | 'iw' => 'hebrew',
52 | 'hi' => 'hindi',
53 | 'hmn' => 'hmong',
54 | 'hu' => 'hungarian',
55 | 'is' => 'icelandic',
56 | 'ig' => 'igbo',
57 | 'ilo' => 'iloko',
58 | 'id' => 'indonesian',
59 | 'ga' => 'irish_gaelic',
60 | 'it' => 'italian',
61 | 'ja' => 'japanese',
62 | 'jv' => 'javanese',
63 | 'jw' => 'javanese',
64 | 'kn' => 'kannada',
65 | 'kk' => 'kazakh',
66 | 'km' => 'khmer',
67 | 'rw' => 'kinyarwanda',
68 | 'gom' => 'konkani',
69 | 'ko' => 'korean',
70 | 'kri' => 'krio',
71 | 'ku' => 'kurdish_kurmanji',
72 | 'ckb' => 'kurdish_sorani',
73 | 'ky' => 'kyrgyz',
74 | 'lo' => 'lao',
75 | 'la' => 'latin',
76 | 'lv' => 'latvian',
77 | 'ln' => 'lingala',
78 | 'lt' => 'lithuanian',
79 | 'lb' => 'luxembourgish',
80 | 'mk' => 'macedonian',
81 | 'mai' => 'maithili',
82 | 'mg' => 'malagasy',
83 | 'ms' => 'malay',
84 | 'ml' => 'malayalam',
85 | 'mt' => 'maltese',
86 | 'mi' => 'maori',
87 | 'mr' => 'marathi',
88 | 'mni-Mtei' => 'meiteilon_manipuri',
89 | 'lus' => 'mizo',
90 | 'mn' => 'mongolian',
91 | 'my' => 'myanmar_burmese',
92 | 'ne' => 'nepali',
93 | 'nso' => 'northern_sotho',
94 | 'no' => 'norwegian',
95 | 'or' => 'odia_oriya',
96 | 'om' => 'oromo',
97 | 'ps' => 'pashto',
98 | 'fa' => 'persian',
99 | 'pl' => 'polish',
100 | 'pt' => 'portuguese',
101 | 'pa' => 'punjabi',
102 | 'qu' => 'quechua',
103 | 'ro' => 'romanian',
104 | 'ru' => 'russian',
105 | 'sm' => 'samoan',
106 | 'sa' => 'sanskrit',
107 | 'gd' => 'scots_gaelic',
108 | 'sr' => 'serbian',
109 | 'st' => 'sesotho',
110 | 'sn' => 'shona',
111 | 'sd' => 'sindhi',
112 | 'si' => 'sinhala',
113 | 'sk' => 'slovak',
114 | 'sl' => 'slovenian',
115 | 'so' => 'somali',
116 | 'es' => 'spanish',
117 | 'su' => 'sundanese',
118 | 'sw' => 'swahili',
119 | 'sv' => 'swedish',
120 | 'tg' => 'tajik',
121 | 'ta' => 'tamil',
122 | 'tt' => 'tatar',
123 | 'te' => 'telugu',
124 | 'th' => 'thai',
125 | 'ti' => 'tigrinya',
126 | 'ts' => 'tsonga',
127 | 'tr' => 'turkish',
128 | 'tk' => 'turkmen',
129 | 'ak' => 'twi',
130 | 'uk' => 'ukrainian',
131 | 'ur' => 'urdu',
132 | 'ug' => 'uyghur',
133 | 'uz' => 'uzbek',
134 | 'vi' => 'vietnamese',
135 | 'cy' => 'welsh',
136 | 'xh' => 'xhosa',
137 | 'yi' => 'yiddish',
138 | 'yo' => 'yoruba',
139 | 'zu' => 'zulu'
140 | }
141 |
142 | end
143 |
--------------------------------------------------------------------------------
/lib/easy_translate/request.rb:
--------------------------------------------------------------------------------
1 | require 'net/http'
2 | require 'net/https'
3 | require 'uri'
4 |
5 | module EasyTranslate
6 |
7 | class Request
8 | attr_accessor :http_options
9 |
10 | def initialize(options = {}, http_options = {})
11 | @options = options
12 | @http_options = http_options
13 | end
14 |
15 | # Body, blank by default
16 | # @return [String] The body for this request
17 | def body
18 | ''
19 | end
20 |
21 | # The path for the request
22 | # @return [String] The path for this request
23 | def path
24 | raise NotImplementedError.new('path is not implemented')
25 | end
26 |
27 | # The base params for a request
28 | # @return [Hash] a hash of the base parameters for any request
29 | def params
30 | params = {}
31 | params[:key] = EasyTranslate.api_key if EasyTranslate.api_key
32 | params[:prettyPrint] = 'false' # eliminate unnecessary overhead
33 | params
34 | end
35 |
36 | # Perform the given request
37 | # @return [String] The response String
38 | def perform_raw
39 | # Construct the request
40 | request = Net::HTTP::Post.new(uri.request_uri)
41 | request.add_field('X-HTTP-Method-Override', 'GET')
42 | request.body = body
43 | # Fire and return
44 | response = http.request(request)
45 | raise_exception(response) unless response.code == '200'
46 | response.body
47 | end
48 |
49 | private
50 |
51 | def raise_exception(response)
52 | err = JSON.parse(response.body)['error']['errors'].first['message']
53 | rescue JSON::ParserError => _e
54 | err = "#{response.code} - #{response.message}"
55 | ensure
56 | raise EasyTranslateException.new(err)
57 | end
58 |
59 | def uri
60 | @uri ||= URI.parse("https://translation.googleapis.com#{path}?#{param_s}")
61 | end
62 |
63 | def http
64 | @http ||= Net::HTTP.new(uri.host, uri.port).tap do |http|
65 | configure_timeouts(http)
66 | configure_ssl(http)
67 | end
68 | end
69 |
70 | def configure_timeouts(http)
71 | http.read_timeout = http.open_timeout = http_options[:timeout] if http_options[:timeout]
72 | http.open_timeout = http_options[:open_timeout] if http_options[:open_timeout]
73 | end
74 |
75 | def configure_ssl(http)
76 | http.use_ssl = true
77 | http.verify_mode = OpenSSL::SSL::VERIFY_PEER
78 | http.cert_store = ssl_cert_store
79 |
80 | http.cert = ssl_options[:client_cert] if ssl_options[:client_cert]
81 | http.key = ssl_options[:client_key] if ssl_options[:client_key]
82 | http.ca_file = ssl_options[:ca_file] if ssl_options[:ca_file]
83 | http.ca_path = ssl_options[:ca_path] if ssl_options[:ca_path]
84 | http.verify_depth = ssl_options[:verify_depth] if ssl_options[:verify_depth]
85 | http.ssl_version = ssl_options[:version] if ssl_options[:version]
86 | end
87 |
88 | def ssl_cert_store
89 | return ssl_options[:cert_store] if ssl_options[:cert_store]
90 | # Use the default cert store by default, i.e. system ca certs
91 | cert_store = OpenSSL::X509::Store.new
92 | cert_store.set_default_paths
93 | cert_store
94 | end
95 |
96 | def ssl_options
97 | http_options[:ssl] || {}
98 | end
99 |
100 | # Stringify the params
101 | # @return [String] The params as a string
102 | def param_s
103 | params.map do |k, v|
104 | "#{k}=#{v}" unless v.nil?
105 | end.compact.join('&')
106 | end
107 |
108 | end
109 |
110 | end
111 |
--------------------------------------------------------------------------------
/lib/easy_translate/threadable.rb:
--------------------------------------------------------------------------------
1 | require 'thread/pool'
2 | require 'thread_safe'
3 |
4 | module EasyTranslate
5 |
6 | module Threadable
7 | def threaded_process(method, *args)
8 | texts = args[0]
9 | options = args[1]
10 | http_options = args[2]
11 | options = options.dup
12 | batch_size = options.delete(:batch_size) || 100
13 | concurrency = options.delete(:concurrency) || 4
14 | batches = Array(texts).each_slice(batch_size).to_a
15 | if concurrency > 1 && batches.size > 1
16 | pool = Thread::Pool.new([concurrency, 1 + (texts.length - 1) / batch_size].min)
17 | batch_results = ThreadSafe::Array.new
18 | batches.each_with_index do |texts_batch, i|
19 | pool.process { batch_results[i] = self.send(method, texts_batch, options, http_options) }
20 | end
21 | pool.shutdown
22 | results = batch_results.reduce(:+)
23 | else
24 | results = batches.map { |texts_batch| self.send(method, texts_batch, options, http_options) }.reduce(:+)
25 | end
26 | # if they only asked for one, only give one back
27 | texts.is_a?(String) ? results[0] : results
28 | ensure
29 | pool.shutdown! if pool && !pool.shutdown?
30 | end
31 | end
32 |
33 | end
34 |
--------------------------------------------------------------------------------
/lib/easy_translate/translation.rb:
--------------------------------------------------------------------------------
1 | require 'json'
2 | require 'cgi'
3 | require 'easy_translate/request'
4 | require 'easy_translate/threadable'
5 |
6 | module EasyTranslate
7 |
8 | module Translation
9 | include Threadable
10 |
11 | # Translate text
12 | # @param [String, Array] texts - A single string or set of strings to translate
13 | # @option options [Fixnum] :batch_size - Maximum keys per request (optional, default 100)
14 | # @option options [Fixnum] :concurrency - Maximum concurrent requests (optional, default 4)
15 | # @option options [String, Symbol] :source - The source language (optional)
16 | # @option options [String, Symbol] :target - The target language (required)
17 | # @option options [Boolean] :html - Whether or not the supplied string is HTML (optional)
18 | # @return [String, Array] Translated text or texts
19 | def translate(texts, options = {}, http_options = {})
20 | threaded_process(:request_translations, texts, options, http_options)
21 | end
22 |
23 | private
24 |
25 | # Perform a single request to translate texts
26 | # @param [Array] texts - Texts to translate
27 | # @option options [String, Symbol] :source - The source language (optional)
28 | # @option options [String, Symbol] :target - The target language (required)
29 | # @option options [Boolean] :html - Whether or not the supplied string is HTML (optional)
30 | # @return [String, Array] Translated text or texts
31 | def request_translations(texts, options = {}, http_options = {})
32 | request = TranslationRequest.new(texts, options, http_options)
33 | # Turn the response into an array of translations
34 | raw = request.perform_raw
35 | JSON.parse(raw)['data']['translations'].map do |res|
36 | raw_translation = res['translatedText']
37 | CGI.unescapeHTML(raw_translation)
38 | end
39 | end
40 |
41 | # A convenience class for wrapping a translation request
42 | class TranslationRequest < EasyTranslate::Request
43 |
44 | # Set the texts and options
45 | # @param [String, Array] texts - the text (or texts) to translate
46 | # @param [Hash] options - Options to override or pass along with the request
47 | def initialize(texts, options, http_options = {})
48 | options = options.dup
49 | self.texts = texts
50 | self.html = options.delete(:html)
51 | @source = options.delete(:from)
52 | @target = options.delete(:to)
53 | @model = options.delete(:model)
54 | raise ArgumentError.new('No target language provided') unless @target
55 | raise ArgumentError.new('Support for multiple targets dropped in V2') if @target.is_a?(Array)
56 | @http_options = http_options
57 | if options
58 | @options = options
59 | if replacement_api_key = @options.delete(:api_key)
60 | @options[:key] = replacement_api_key
61 | end
62 | end
63 | end
64 |
65 | # The params for this request
66 | # @return [Hash] the params for the request
67 | def params
68 | params = super || {}
69 | params[:source] = lang(@source) unless @source.nil?
70 | params[:target] = lang(@target) unless @target.nil?
71 | params[:model] = @model unless @model.nil?
72 | params[:format] = @format unless @format.nil?
73 | params.merge! @options if @options
74 | params
75 | end
76 |
77 | # The path for the request
78 | # @return [String] The path for the request
79 | def path
80 | '/language/translate/v2'
81 | end
82 |
83 | # The body for the request
84 | # @return [String] the body for the request, URL escaped
85 | def body
86 | @texts.map { |t| "q=#{CGI::escape(t)}" }.join '&'
87 | end
88 |
89 | # Whether or not this was a request for multiple texts
90 | # @return [Boolean]
91 | def multi?
92 | @multi
93 | end
94 |
95 | private
96 |
97 | # Look up a language in the table (if needed)
98 | def lang(orig)
99 | look = orig.is_a?(String) ? orig : orig.to_s
100 | return look if LANGUAGES[look] # shortcut iteration
101 | if val = LANGUAGES.detect { |k, v| v == look }
102 | return val.first
103 | end
104 | look
105 | end
106 |
107 | # Set the HTML attribute, if true add a format
108 | # @param [Boolean] b - Whether or not the text supplied iS HTML
109 | def html=(b)
110 | @format = b ? 'html' : nil
111 | end
112 |
113 | # Set the texts for this request
114 | # @param [String, Array] texts - The text or texts for this request
115 | def texts=(texts)
116 | if texts.is_a?(String)
117 | @multi = false
118 | @texts = [texts]
119 | else
120 | @multi = true
121 | @texts = texts
122 | end
123 | end
124 |
125 | end
126 |
127 | end
128 |
129 | end
130 |
--------------------------------------------------------------------------------
/lib/easy_translate/translation_target.rb:
--------------------------------------------------------------------------------
1 | require 'json'
2 | require 'easy_translate/request'
3 |
4 | module EasyTranslate
5 |
6 | module TranslationTarget
7 |
8 | # Determine what translations are available
9 | # @param [String] source - The source language (optional)
10 | # @param [Hash] options - extra options
11 | # @return [Array] an array of strings representing languages
12 | def translations_available(target = nil, options = {})
13 | request = TranslationTargetRequest.new(target, options)
14 | raw = request.perform_raw
15 | languages = JSON.parse(raw)['data']['languages'].map do |res|
16 | res['language']
17 | end
18 |
19 | languages.push('zh-CN') if !languages.index('zh').nil?
20 |
21 | languages
22 | end
23 |
24 | class TranslationTargetRequest < EasyTranslate::Request
25 |
26 | def initialize(target = nil, options = nil)
27 | super(options)
28 | @target = target
29 | if @options
30 | if replacement_api_key = @options.delete(:api_key)
31 | @options[:key] = replacement_api_key
32 | end
33 | end
34 | end
35 |
36 | def params
37 | params = super || {}
38 | params[:target] = @target unless @target.nil?
39 | params.merge! @options if @options
40 | params
41 | end
42 |
43 | def path
44 | '/language/translate/v2/languages'
45 | end
46 |
47 | end
48 |
49 | end
50 |
51 | end
52 |
--------------------------------------------------------------------------------
/lib/easy_translate/version.rb:
--------------------------------------------------------------------------------
1 | module EasyTranslate
2 |
3 | VERSION = '0.5.0'
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/spec/examples/detection_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 |
3 | require 'spec_helper'
4 |
5 | describe EasyTranslate::Detection do
6 |
7 | it 'should return a single if given a single - from doc' do
8 | expect(EasyTranslate::Detection::DetectionRequest).to receive(:new).and_return(OpenStruct.new({
9 | :perform_raw => '{"data":{"detections":[[{"language":"en","isReliable":false,"confidence":0.6595744}]]}}',
10 | :multi? => false
11 | }))
12 | lang = EasyTranslate.detect 'Google Translate Rocks'
13 | expect(lang).to eq('en')
14 | end
15 |
16 | it 'should return a single with confidence if given a single with confidence - from doc' do
17 | expect(EasyTranslate::Detection::DetectionRequest).to receive(:new).and_return(OpenStruct.new({
18 | :perform_raw => '{"data":{"detections":[[{"language":"en","isReliable":false,"confidence":0.6595744}]]}}',
19 | :multi? => false
20 | }))
21 | lang = EasyTranslate.detect 'Google Translate Rocks', :confidence => true
22 | expect(lang).to eq({ :language => 'en', :confidence => 0.6595744 })
23 | end
24 |
25 | it 'should return a multiple if given multiple - from doc' do
26 | expect(EasyTranslate::Detection::DetectionRequest).to receive(:new).and_return(OpenStruct.new({
27 | :perform_raw => '{"data":{"detections":[[{"language":"en","isReliable":false,"confidence":0.6315789}],[{"language":"zh-CN","isReliable":false,"confidence":1.0}]]}}',
28 | :multi? => true
29 | }))
30 | lang = EasyTranslate.detect ['Hello World', '我姓譚']
31 | expect(lang).to eq(['en', 'zh-CN'])
32 | end
33 |
34 | it 'should return a multiple with confidence if given multiple with confidence - from doc' do
35 | expect(EasyTranslate::Detection::DetectionRequest).to receive(:new).and_return(OpenStruct.new({
36 | :perform_raw => '{"data":{"detections":[[{"language":"en","isReliable":false,"confidence":0.6315789}],[{"language":"zh-CN","isReliable":false,"confidence":1.0}]]}}',
37 | :multi? => true
38 | }))
39 | lang = EasyTranslate.detect ['Hello World', '我姓譚'], :confidence => true
40 | expect(lang).to eq([{ :language => 'en', :confidence => 0.6315789 }, { :language => 'zh-CN', :confidence => 1.0 }])
41 | end
42 |
43 | klass = EasyTranslate::Detection::DetectionRequest
44 | describe klass do
45 |
46 | describe :path do
47 |
48 | it 'should have a valid path' do
49 | request = klass.new('abc')
50 | expect(request.path).not_to be_empty
51 | end
52 |
53 | end
54 |
55 | describe :body do
56 |
57 | it 'should insert the texts into the body' do
58 | request = klass.new(['abc', 'def'])
59 | expect(request.body).to eq('q=abc&q=def')
60 | end
61 |
62 | it 'should insert the text into the body' do
63 | request = klass.new('abc')
64 | expect(request.body).to eq('q=abc')
65 | end
66 |
67 | it 'should URI escape the body' do
68 | request = klass.new('%')
69 | expect(request.body).to eq('q=%25')
70 | end
71 |
72 | end
73 |
74 | describe :params do
75 |
76 | it 'should use default params' do
77 | EasyTranslate.api_key = 'abc'
78 | request = klass.new('abc')
79 | expect(request.params[:key]).to eq('abc')
80 | end
81 |
82 | it 'should allow overriding of params' do
83 | EasyTranslate.api_key = 'abc'
84 | request = klass.new('abc', :key => 'def')
85 | expect(request.params[:key]).to eq('def')
86 | end
87 |
88 | it 'should allow overriding of key as api_key' do
89 | EasyTranslate.api_key = 'abc'
90 | request = klass.new('abc', :api_key => 'def')
91 | expect(request.params[:key]).to eq('def')
92 | expect(request.params[:api_key]).to be_nil
93 | end
94 |
95 | end
96 |
97 | describe :options do
98 |
99 | it 'should accept timeouts options' do
100 | request = EasyTranslate::Detection::DetectionRequest.new "test", {}, {:timeout => 1, :open_timeout => 2}
101 | http = request.send(:http)
102 | expect(http.open_timeout).to eq(2)
103 | expect(http.read_timeout).to eq(1)
104 | end
105 |
106 | it 'should accept ssl options' do
107 | request = EasyTranslate::Detection::DetectionRequest.new "test", {}, {:ssl => {:verify_depth => 3, :ca_file => 'path/to/ca/file'}}
108 | http = request.send(:http)
109 | expect(http.verify_depth).to eq(3)
110 | expect(http.ca_file).to eq('path/to/ca/file')
111 | end
112 |
113 | it 'should accept confidence option' do
114 | request = EasyTranslate::Detection::DetectionRequest.new "test", {:confidence => true}, {}
115 | expect(request.params[:confidence]).to eq(true)
116 | end
117 |
118 | end
119 |
120 | describe :multi? do
121 |
122 | it 'should be true if multiple are passed' do
123 | request = klass.new(['abc', 'def'])
124 | expect(request).to be_multi
125 | end
126 |
127 | it 'should be true if one is passed, but in an array' do
128 | request = klass.new(['abc'])
129 | expect(request).to be_multi
130 | end
131 |
132 | it 'should be true if one is passed as a string' do
133 | request = klass.new('abc')
134 | expect(request).not_to be_multi
135 | end
136 |
137 | end
138 |
139 | end
140 |
141 | end
142 |
--------------------------------------------------------------------------------
/spec/examples/easy_translate_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe EasyTranslate do
4 |
5 | it 'should have LANGUAGES' do
6 | expect(EasyTranslate::LANGUAGES).to be_a(Hash)
7 | expect(EasyTranslate::LANGUAGES['en']).to eq('english')
8 | end
9 |
10 | it 'should have a version' do
11 | expect(EasyTranslate::VERSION.split('.').length).to eq(3)
12 | end
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/spec/examples/real_world_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe EasyTranslate do
5 |
6 | before :each do
7 | if ENV['API_KEY']
8 | EasyTranslate.api_key = ENV['API_KEY']
9 | else
10 | pending 'please provide an API_KEY for this suite'
11 | end
12 | end
13 |
14 | describe :translate do
15 |
16 | it 'should be able to translate one' do
17 | res = EasyTranslate.translate 'hello world', :to => :spanish
18 | expect(res).to eq('Hola Mundo')
19 | end
20 |
21 | it 'should be able to translate multiple' do
22 | res = EasyTranslate.translate ['hello world', 'i love you'], :to => :spanish
23 | expect(res).to eq(['Hola Mundo', 'te quiero'])
24 | end
25 |
26 | it 'should work concurrently' do
27 | res = EasyTranslate.translate ['hello world', 'i love you', 'good morning'], :to => :spanish, :concurrency => 2, :batch_size => 1
28 | expect(res).to eq(['Hola Mundo', 'te quiero', 'Buenos días'])
29 | end
30 | end
31 |
32 | describe :detect do
33 |
34 | it 'should be able to detect one' do
35 | res = EasyTranslate.detect 'hello world'
36 | expect(res).to eq('en')
37 | end
38 |
39 | it 'should be able to detect multiple' do
40 | res = EasyTranslate.detect ['hello world', 'hola mundo']
41 | expect(res).to eq(['en', 'es'])
42 | end
43 |
44 | end
45 |
46 | describe :translations_available_from do
47 |
48 | it 'should be able to get a list of all' do
49 | res = EasyTranslate.translations_available
50 | expect(res).to be_a Array
51 | end
52 |
53 | it 'should be able to get a list of all from es' do
54 | res = EasyTranslate.translations_available('yi')
55 | expect(res).to be_a Array
56 | end
57 |
58 | end
59 |
60 | end
61 |
--------------------------------------------------------------------------------
/spec/examples/request_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe EasyTranslate::Request do
4 |
5 | describe :path do
6 |
7 | it 'should raise a NotImplementedError on this base class' do
8 | request = EasyTranslate::Request.new
9 | expect do
10 | request.path
11 | end.to raise_error NotImplementedError
12 | end
13 |
14 | end
15 |
16 | describe :body do
17 |
18 | it 'should be blank by default' do
19 | request = EasyTranslate::Request.new
20 | expect(request.body).to be_empty
21 | end
22 |
23 | end
24 |
25 | describe :params do
26 |
27 | it 'should include the key if given at the base' do
28 | EasyTranslate.api_key = 'abc'
29 | request = EasyTranslate::Request.new
30 | expect(request.params[:key]).to eq('abc')
31 | end
32 |
33 | it 'should turn off prettyPrint' do
34 | request = EasyTranslate::Request.new
35 | expect(request.params[:prettyPrint]).to eq('false')
36 | end
37 |
38 | end
39 |
40 | describe :param_s do
41 |
42 | it 'should skip nil parameters' do
43 | request = EasyTranslate::Request.new
44 | expect(request).to receive(:params).and_return({ :something => nil })
45 | expect(request.send(:param_s)).to be_empty
46 | end
47 |
48 | end
49 |
50 | end
51 |
--------------------------------------------------------------------------------
/spec/examples/translation_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe EasyTranslate::Translation do
4 |
5 | it 'should return a single if given a single - from doc' do
6 | fake_request(
7 | :perform_raw => '{"data":{"translations":[{"translatedText":"Hallo Welt"}]}}',
8 | :multi? => false
9 | )
10 | trans = EasyTranslate.translate 'Hello world', :to => 'de'
11 | expect(trans).to eq('Hallo Welt')
12 | end
13 |
14 | it 'should return a multiple if given multiple - from doc' do
15 | fake_request(
16 | :perform_raw => '{"data":{"translations":[{"translatedText": "Hallo Welt"},{"translatedText":"Mein Name ist Jeff"}]}}',
17 | :multi? => true
18 | )
19 | trans = EasyTranslate.translate ['Hello world', 'my name is jeff'], :to => 'de'
20 | expect(trans).to eq(['Hallo Welt', 'Mein Name ist Jeff'])
21 | end
22 |
23 | it 'should decode HTML entities in the response' do
24 | fake_request(
25 | :perform_raw => '{"data":{"translations":[{"translatedText":"Hallo ' & " Welt"}]}}',
26 | :multi? => false
27 | )
28 | trans = EasyTranslate.translate %{Hello ' & " world}, :to => 'de'
29 | expect(trans).to eq(%{Hallo ' & " Welt})
30 | end
31 |
32 | context 'detecting availale language' do
33 | before :each do
34 | pending 'please provide an API_KEY for this suite' if ENV['API_KEY'].nil?
35 |
36 | EasyTranslate.api_key = ENV['API_KEY']
37 | end
38 |
39 | it 'should detect simplified chinese as zh-CN' do
40 | expect(EasyTranslate.translations_available.include?('zh-CN')).to eq(true)
41 | expect(EasyTranslate.translations_available.include?('zh')).to eq(true)
42 | end
43 | end
44 |
45 | def fake_request(hash)
46 | expect(EasyTranslate::Translation::TranslationRequest).to receive(:new).and_return(OpenStruct.new(hash))
47 | end
48 |
49 | klass = EasyTranslate::Translation::TranslationRequest
50 | describe klass do
51 |
52 | describe :path do
53 |
54 | it 'should have a valid path' do
55 | request = klass.new('abc', :to => 'en')
56 | expect(request.path).not_to be_empty
57 | end
58 |
59 | end
60 |
61 | describe :initialize do
62 |
63 | it 'should raise an error when there is no to given' do
64 | expect do
65 | req = klass.new('abc', :from => 'en')
66 | end.to raise_error ArgumentError
67 | end
68 |
69 | it 'should raise an error when tos are given as an array' do
70 | expect do
71 | req = klass.new('abc', :from => 'en', :to => ['es', 'de'])
72 | end.to raise_error ArgumentError
73 | end
74 |
75 | end
76 |
77 | describe :params do
78 |
79 | it 'should include from in params if given' do
80 | req = klass.new('abc', :from => 'en', :to => 'es')
81 | expect(req.params[:source]).to eq('en')
82 | end
83 |
84 | it 'should not include from by default' do
85 | req = klass.new('abc', :to => 'es')
86 | expect(req.params[:source]).to be_nil
87 | end
88 |
89 | it 'should include to' do
90 | req = klass.new('abc', :to => 'es')
91 | expect(req.params[:target]).to eq('es')
92 | end
93 |
94 | it 'should not include format by default' do
95 | req = klass.new('abc', :to => 'es')
96 | expect(req.params[:format]).to be_nil
97 | end
98 |
99 | it 'should not include format when given as false' do
100 | req = klass.new('abc', :html => false, :to => 'es')
101 | expect(req.params[:format]).to be_nil
102 | end
103 |
104 | it 'should include format when html is true' do
105 | req = klass.new('abc', :html => true, :to => 'es')
106 | expect(req.params[:format]).to eq('html')
107 | end
108 |
109 | it 'should include format when specified as text' do
110 | req = klass.new('abc', :format => 'text', :to => 'es')
111 | expect(req.params[:format]).to eq('text')
112 | end
113 |
114 | it 'should use default params' do
115 | EasyTranslate.api_key = 'abc'
116 | request = klass.new('abc', :to => 'es')
117 | expect(request.params[:key]).to eq('abc')
118 | end
119 |
120 | it 'should allow overriding of params' do
121 | EasyTranslate.api_key = 'abc'
122 | request = klass.new('abc', :key => 'def', :to => 'es')
123 | expect(request.params[:key]).to eq('def')
124 | end
125 |
126 | it 'should allow overriding of key as api_key' do
127 | EasyTranslate.api_key = 'abc'
128 | request = klass.new('abc', :api_key => 'def', :to => 'es')
129 | expect(request.params[:key]).to eq('def')
130 | expect(request.params[:api_key]).to be_nil
131 | end
132 |
133 | it 'should be able to supply a language as a string' do
134 | request = klass.new('abc', :to => 'es')
135 | expect(request.params[:target]).to eq('es')
136 | end
137 |
138 | it 'should be able to supply a language as a symbol' do
139 | request = klass.new('abc', :to => :es)
140 | expect(request.params[:target]).to eq('es')
141 | end
142 |
143 | it 'should be able to supply a language as a word' do
144 | request = klass.new('abc', :to => 'spanish')
145 | expect(request.params[:target]).to eq('es')
146 | end
147 |
148 | it 'should be able to supply a language as a word symbol' do
149 | request = klass.new('abc', :to => :spanish)
150 | expect(request.params[:target]).to eq('es')
151 | end
152 |
153 | it 'should fall back when a word is not in the lookup' do
154 | request = klass.new('abc', :to => 'zzz')
155 | expect(request.params[:target]).to eq('zzz')
156 | end
157 |
158 | end
159 |
160 | describe :multi? do
161 |
162 | it 'should be true if multiple are passed' do
163 | request = klass.new(['abc', 'def'], :to => 'es')
164 | expect(request).to be_multi
165 | end
166 |
167 | it 'should be true if one is passed, but in an array' do
168 | request = klass.new(['abc'], :to => 'es')
169 | expect(request).to be_multi
170 | end
171 |
172 | it 'should be true if one is passed as a string' do
173 | request = klass.new('abc', :to => 'es')
174 | expect(request).not_to be_multi
175 | end
176 |
177 | end
178 |
179 | describe :body do
180 |
181 | it 'should insert the texts into the body' do
182 | request = klass.new(['abc', 'def'], :to => 'es')
183 | expect(request.body).to eq('q=abc&q=def')
184 | end
185 |
186 | it 'should insert the text into the body' do
187 | request = klass.new('abc', :to => 'es')
188 | expect(request.body).to eq('q=abc')
189 | end
190 |
191 | it 'should URI escape the body' do
192 | request = klass.new('%', :to => 'es')
193 | expect(request.body).to eq('q=%25')
194 | end
195 |
196 | end
197 |
198 | end
199 |
200 | end
201 |
--------------------------------------------------------------------------------
/spec/examples/translation_target_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | klass = EasyTranslate::TranslationTarget::TranslationTargetRequest
4 | describe klass do
5 |
6 | describe :params do
7 |
8 | it 'should include target in params if given' do
9 | req = klass.new('en')
10 | expect(req.params[:target]).to eq('en')
11 | end
12 |
13 | it 'should not include target by default' do
14 | req = klass.new
15 | expect(req.params[:target]).to be_nil
16 | end
17 |
18 | it 'should use default key' do
19 | EasyTranslate.api_key = 'abc'
20 | request = klass.new('en')
21 | expect(request.params[:key]).to eq('abc')
22 | end
23 |
24 | it 'should allow overriding of params' do
25 | EasyTranslate.api_key = 'abc'
26 | request = klass.new('en', :key => 'def')
27 | expect(request.params[:key]).to eq('def')
28 | end
29 |
30 | it 'should allow overriding of key as api_key' do
31 | EasyTranslate.api_key = 'abc'
32 | request = klass.new('abc', :api_key => 'def', :to => 'es')
33 | expect(request.params[:key]).to eq('def')
34 | expect(request.params[:api_key]).to be_nil
35 | end
36 |
37 | end
38 |
39 | end
40 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # Start SimpleCov
2 | begin
3 | require 'ostruct'
4 | require 'simplecov'
5 | SimpleCov.start
6 | rescue LoadError
7 | puts 'for coverage please install SimpleCov'
8 | end
9 |
10 | require 'ostruct'
11 |
12 | # Require the actual project
13 | $: << File.expand_path('../lib', __FILE__)
14 | require 'easy_translate'
15 |
--------------------------------------------------------------------------------