Skip to content

V2 SDK #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ jobs:
strategy:
matrix:
ruby-version:
- 2.0
- 2.0.0
- 2.7
- 3.0
- 3.0.0
- 3.4
- ruby-head
- jruby-head
image:
- ubuntu-24.04
- ubuntu-24.04-arm
# - ubuntu-24.04-arm
name: Ruby ${{ matrix.ruby-version }} on ${{ matrix.image }}
steps:
- uses: actions/checkout@v3
Expand Down
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## v2.0.0

### Added
- `detect_batch` method for batch detections

### Changed
- Switched to v3 API which uses an updated language detection model
- ⚠️ `detect` method result fields are `language` and `score`
- ⚠️ Proxy URL configured using `config.proxy`
- Client connection is reused. If you change configuration after the client is initialized, you need to reset client using `DetectLanguage.client = nil`.

### Deprecated
- Calling `detect` with array argument. Use `detect_batch` instead.
- `simple_detect` - Use `detect_code` instead.
- `user_status` - Use `account_status` instead.
- `configuration` - Use `config` instead.

### Removed
- Secure mode configuration. HTTPS is always used.
- Ruby 1.x support
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ gem 'rake'
gem 'json'

group :test do
gem "rspec"
end
gem 'rspec'
end
43 changes: 17 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ Detect Language API Ruby Client

Detects language of the given text. Returns detected language codes and scores.

Before using Detect Language API client you have to setup your personal API key.
You can get it by signing up at https://detectlanguage.com

## Installation

Expand All @@ -17,77 +15,70 @@ Add this line to your application's Gemfile:
gem 'detect_language'
```

Or install it yourself as:
### Upgrading

```
gem install detect_language
```
When upgrading please check [changelog](CHANGELOG.md) for breaking changes.

### Configuration

If you are using Rails, create initializer `config/initializers/detect_language.rb` and add following code there.
Otherwise just integrate following code into your apps configuration.
Get your personal API key by signing up at https://detectlanguage.com

```ruby
DetectLanguage.configure do |config|
config.api_key = "YOUR API KEY"

# enable secure mode (SSL) if you are passing sensitive data
# config.secure = true
config.api_key = 'YOUR API KEY'
end
```

## Usage

### Language detection
### Detect language

```ruby
DetectLanguage.detect("Buenos dias señor")
DetectLanguage.detect('Dolce far niente')
```

#### Result

```ruby
[{"language"=>"es", "isReliable"=>true, "confidence"=>6.62}]
[{"language" => "it", "score" => 0.5074}]
```

### Simple language detection
### Detect single code

If you need just a language code you can use `simple_detect`. It returns just the language code.
If you need just a language code you can use `detect_code`.

```ruby
DetectLanguage.simple_detect("Buenos dias señor")
DetectLanguage.detect_code('Dolce far niente')
```

#### Result

```ruby
"es"
"it"
```

### Batch detection

It is possible to detect language of several texts with one request.
This method is significantly faster than doing one request per text.
To use batch detection just pass array of texts to `detect` method.
To use batch detection just pass array of texts to `detect_batch` method.

```ruby
DetectLanguage.detect(["Buenos dias señor", "Labas rytas"])
DetectLanguage.detect_batch(['Dolce far niente', 'Labas rytas'])
```

#### Result

Result is array of detections in the same order as the texts were passed.

```ruby
[ [{"language"=>"es", "isReliable"=>true, "confidence"=>6.62}],
[{"language"=>"lt", "isReliable"=>true, "confidence"=>6.82}] ]
[[{"language" => "it", "score" => 0.5074}], [{"language" => "lt", "score" => 0.3063}]]
```

### Getting your account status
### Get your account status

```ruby
DetectLanguage.user_status
DetectLanguage.account_status
```

#### Result
Expand All @@ -97,7 +88,7 @@ DetectLanguage.user_status
"daily_requests_limit"=>5000, "daily_bytes_limit"=>1048576, "status"=>"ACTIVE"}
```

### Getting list supported languages
### Get list of supported languages

```ruby
DetectLanguage.languages
Expand Down
75 changes: 56 additions & 19 deletions lib/detect_language.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,81 @@

module DetectLanguage
class << self
attr_writer :configuration
attr_writer :config

def configure
yield(configuration)
yield(config)
end

# The configuration object.
# @see DetectLanguage.configure
def configuration
@configuration ||= Configuration.new
def config
@config ||= Configuration.new
end

def client
Thread.current[:detect_language_client] ||= Client.new(configuration)
Thread.current[:detect_language_client] ||= Client.new(config)
end

def detect(data)
key = data.is_a?(Array) ? 'q[]' : 'q'
result = client.post(:detect, key => data)
result['data']['detections']
def client=(client)
Thread.current[:detect_language_client] = client
end

def simple_detect(text)
# @param query String
# @return [Array<Hash>] Array of language detections
def detect(query)
if query.is_a?(Array)
warn '[DEPRECATED] `DetectLanguage.detect` with an array of queries is deprecated. Use `DetectLanguage.detect_batch` instead.'
return detect_batch(query)
end

client.post('detect', q: query)
end

# @param queries Array<String> Array of queries to detect languages for
# @return [Array<Array<Hash>>] Array of language detections for each query
def detect_batch(queries)
raise(ArgumentError, 'Expected an Array of queries') unless queries.is_a?(Array)

client.post('detect-batch', q: queries)
end

# @param text String
# @return [String, nil] Detected language code or nil if no detection found
def detect_code(text)
detections = detect(text)

if detections.empty?
nil
else
detections[0]['language']
end
return if detections.empty?

detections[0]['language']
end

def user_status
client.get('user/status')
# @return [Hash] Account status information
def account_status
client.get('account/status')
end

# @return [Array<Hash>] List of supported languages
def languages
client.get('languages')
end

### DEPRECATED METHODS

# @deprecated Use `DetectLanguage.config` instead
def configuration
warn '[DEPRECATED] `DetectLanguage.configuration` is deprecated. Use `DetectLanguage.config` instead.'
config
end

# @deprecated Use `detect_code` instead
def simple_detect(text)
warn '[DEPRECATED] `DetectLanguage.simple_detect` is deprecated. Use `DetectLanguage.detect_code` instead.'
detect_code(text)
end

# @deprecated Use `DetectLanguage.account_status` instead
def user_status
warn '[DEPRECATED] `DetectLanguage.user_status` is deprecated. Use `DetectLanguage.account_status` instead.'
account_status
end
end
end
83 changes: 30 additions & 53 deletions lib/detect_language/client.rb
Original file line number Diff line number Diff line change
@@ -1,44 +1,37 @@
require 'cgi'
require 'net/http'
require 'net/https'
require 'json'

module DetectLanguage
class Client
attr_reader :configuration
attr_reader :config

def initialize(configuration)
@configuration = configuration
def initialize(config)
@config = config
end

def post(method, params = {})
execute(method, params, :http_method => Net::HTTP::Post)
def post(path, payload = {})
execute(Net::HTTP::Post, path, body: payload.to_json)
end

def get(method, params = {})
execute(method, params, :http_method => Net::HTTP::Get)
def get(path)
execute(Net::HTTP::Get, path)
end

private

def execute(method, params, options)
http = setup_http_connection
http_method = options[:http_method]
request = http_method.new(request_uri(method))
def execute(method, path, body: nil)
request = method.new(base_uri.path + path)
request.body = body

if RUBY_VERSION == '1.8.7'
set_form_data_18(request, params)
else
request.set_form_data(params)
end

request['Authorization'] = 'Bearer ' + configuration.api_key.to_s
request['User-Agent'] = configuration.user_agent
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer ' + config.api_key.to_s
request['User-Agent'] = config.user_agent

response = http.request(request)
response = connection.request(request)

case response
when Net::HTTPSuccess, Net::HTTPUnauthorized then
when Net::HTTPSuccess, Net::HTTPUnauthorized
parse_response(response.body)
else
raise(Error, "Failure: #{response.class}")
Expand All @@ -55,44 +48,28 @@ def parse_response(response_body)
end
end

def request_uri(method)
"/#{configuration.api_version}/#{method}"
def base_uri
@base_uri ||= URI(config.base_url)
end

def setup_http_connection
http =
Net::HTTP::Proxy(configuration.proxy_host, configuration.proxy_port, configuration.proxy_user,
configuration.proxy_pass).
new(configuration.host, configuration.port)

http.read_timeout = configuration.http_read_timeout
http.open_timeout = configuration.http_open_timeout
def connection
@connection ||= setup_connection
end

if configuration.secure?
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
def setup_connection
http = if config.proxy
proxy = URI(config.proxy)
Net::HTTP.new(base_uri.hostname, base_uri.port, proxy.hostname, proxy.port, proxy.user, proxy.password)
else
http.use_ssl = false
Net::HTTP.new(base_uri.hostname, base_uri.port)
end

http
end

def set_form_data_18(request, params, sep = '&')
request.body = params.map {|k,v|
if v.instance_of?(Array)
v.map {|e| "#{urlencode(k.to_s)}=#{urlencode(e.to_s)}"}.join(sep)
else
"#{urlencode(k.to_s)}=#{urlencode(v.to_s)}"
end
}.join(sep)

request.content_type = 'application/x-www-form-urlencoded'
end
http.use_ssl = base_uri.scheme == 'https'
http.verify_mode = OpenSSL::SSL::VERIFY_PEER if http.use_ssl?
http.read_timeout = config.http_read_timeout
http.open_timeout = config.http_open_timeout

def urlencode(str)
CGI::escape(str)
http
end

end
end
Loading