From 718aa80f90eaf539ae75970964a51fc89787f6a1 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Fri, 18 Jul 2025 23:34:21 +0300 Subject: [PATCH 01/21] Switch to base url --- lib/detect_language.rb | 12 ++--- lib/detect_language/client.rb | 76 +++++++++------------------- lib/detect_language/configuration.rb | 57 ++------------------- spec/detect_language_spec.rb | 19 ++----- 4 files changed, 38 insertions(+), 126 deletions(-) diff --git a/lib/detect_language.rb b/lib/detect_language.rb index c02471a..1da2999 100644 --- a/lib/detect_language.rb +++ b/lib/detect_language.rb @@ -5,20 +5,18 @@ 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) diff --git a/lib/detect_language/client.rb b/lib/detect_language/client.rb index d26b25d..07226e3 100644 --- a/lib/detect_language/client.rb +++ b/lib/detect_language/client.rb @@ -1,39 +1,33 @@ -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, params = {}) + execute(Net::HTTP::Post, path, params) end - def get(method, params = {}) - execute(method, params, :http_method => Net::HTTP::Get) + def get(path, params = {}) + execute(Net::HTTP::Get, path, params) 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, params) + uri = URI.parse(config.base_url) + http = setup_http_connection(uri) + request = method.new(uri.path + path.to_s) + request.set_form_data(params) - 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['Authorization'] = 'Bearer ' + config.api_key.to_s + request['User-Agent'] = config.user_agent response = http.request(request) @@ -55,44 +49,22 @@ def parse_response(response_body) end end - def request_uri(method) - "/#{configuration.api_version}/#{method}" - 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) + def setup_http_connection(uri) + http = Net::HTTP::Proxy( + config.proxy_host, config.proxy_port, config.proxy_user, config.proxy_pass + ).new(uri.host, uri.port) - http.read_timeout = configuration.http_read_timeout - http.open_timeout = configuration.http_open_timeout + http.read_timeout = config.http_read_timeout + http.open_timeout = config.http_open_timeout - if configuration.secure? - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_PEER + if uri.scheme == 'https' + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_PEER else - http.use_ssl = false + http.use_ssl = false 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 - - def urlencode(str) - CGI::escape(str) - end - end end diff --git a/lib/detect_language/configuration.rb b/lib/detect_language/configuration.rb index ce4992f..5c5abe7 100644 --- a/lib/detect_language/configuration.rb +++ b/lib/detect_language/configuration.rb @@ -1,24 +1,13 @@ module DetectLanguage class Configuration # The API key for your project, found on your homepage after you login into detectlanguage.com website - # Defaults to 'demo', which has a limited number of requests. attr_accessor :api_key - # The API version you are using (defaults to 0.2). - attr_accessor :api_version - # HTTP request user agent (defaults to 'Detect Language API ruby gem'). attr_accessor :user_agent - # The host to connect to (defaults to ws.detectlanguage.com). - attr_accessor :host - - # The port on which your DetectLanguage server runs (defaults to 443 for secure - # connections, 80 for insecure connections). - attr_accessor :port - - # +true+ for https connections, +false+ for http connections. - attr_accessor :secure + # API base URL + attr_accessor :base_url # The HTTP open timeout in seconds. attr_accessor :http_open_timeout @@ -38,46 +27,10 @@ class Configuration # The password to use when logging into your proxy server (if using a proxy). attr_accessor :proxy_pass - alias_method :secure?, :secure - def initialize - @api_key = nil - @api_version = "0.2" - @host = "ws.detectlanguage.com" - @user_agent = "detectlanguage-ruby/#{VERSION}" - end - - def protocol - if secure? - 'https' - else - 'http' - end - end - - def port - @port || default_port - end - - # Allows config options to be read like a hash - # - # @param [Symbol] option Key for a given attribute - def [](option) - send(option) + @api_key = nil + @base_url = "https://ws.detectlanguage.com/0.2/" + @user_agent = "detectlanguage-ruby/#{VERSION}" end - - private - - # Determines what port should we use for sending requests. - # @return [Fixnum] Returns 443 if you've set secure to true in your - # configuration, and 80 otherwise. - def default_port - if secure? - 443 - else - 80 - end - end - end end diff --git a/spec/detect_language_spec.rb b/spec/detect_language_spec.rb index ee86c9b..cb917ff 100644 --- a/spec/detect_language_spec.rb +++ b/spec/detect_language_spec.rb @@ -2,19 +2,16 @@ RSpec.describe DetectLanguage do let(:api_key) { ENV['DETECTLANGUAGE_API_KEY'] } - let(:secure) { true } before do - described_class.configuration.api_key = api_key - described_class.configuration.secure = secure + described_class.config.api_key = api_key end - describe '.configuration' do - subject { described_class.configuration } + describe '.config' do + subject { described_class.config } it 'has default configuration values' do - expect(subject.api_version).to eq('0.2') - expect(subject.host).to eq('ws.detectlanguage.com') + expect(subject.base_url).to eq('https://ws.detectlanguage.com/0.2/') expect(subject.user_agent).to eq("detectlanguage-ruby/#{DetectLanguage::VERSION}") end end @@ -90,13 +87,5 @@ it 'fetches list of detectable languages' do expect(subject).to include('code' => 'en', 'name' => 'ENGLISH') end - - context 'with http' do - let(:secure) { false } - - it 'fetches languages over http' do - expect(subject).to include('code' => 'en', 'name' => 'ENGLISH') - end - end end end From 19402cf0e525190c3c46fa0c109fd9f8670dabc2 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 00:39:09 +0300 Subject: [PATCH 02/21] Update to v3 api --- lib/detect_language.rb | 26 +++++++------ lib/detect_language/client.rb | 2 +- lib/detect_language/configuration.rb | 2 +- spec/detect_language_spec.rb | 56 ++++++++++++++++++---------- 4 files changed, 53 insertions(+), 33 deletions(-) diff --git a/lib/detect_language.rb b/lib/detect_language.rb index 1da2999..248ed54 100644 --- a/lib/detect_language.rb +++ b/lib/detect_language.rb @@ -19,24 +19,26 @@ def client 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 detect(query) + client.post('detect', q: query) end - def simple_detect(text) + def detect_batch(queries) + raise(ArgumentError, 'Expected an Array of queries') unless queries.is_a?(Array) + + client.post('detect-batch', 'q[]': queries) + end + + 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') + def account_status + client.get('account/status') end def languages diff --git a/lib/detect_language/client.rb b/lib/detect_language/client.rb index 07226e3..f2bc539 100644 --- a/lib/detect_language/client.rb +++ b/lib/detect_language/client.rb @@ -23,7 +23,7 @@ def get(path, params = {}) def execute(method, path, params) uri = URI.parse(config.base_url) http = setup_http_connection(uri) - request = method.new(uri.path + path.to_s) + request = method.new(uri.path + path) request.set_form_data(params) request['Authorization'] = 'Bearer ' + config.api_key.to_s diff --git a/lib/detect_language/configuration.rb b/lib/detect_language/configuration.rb index 5c5abe7..3c68d42 100644 --- a/lib/detect_language/configuration.rb +++ b/lib/detect_language/configuration.rb @@ -29,7 +29,7 @@ class Configuration def initialize @api_key = nil - @base_url = "https://ws.detectlanguage.com/0.2/" + @base_url = "https://ws.detectlanguage.com/v3/" @user_agent = "detectlanguage-ruby/#{VERSION}" end end diff --git a/spec/detect_language_spec.rb b/spec/detect_language_spec.rb index cb917ff..91b4c8f 100644 --- a/spec/detect_language_spec.rb +++ b/spec/detect_language_spec.rb @@ -11,7 +11,7 @@ subject { described_class.config } it 'has default configuration values' do - expect(subject.base_url).to eq('https://ws.detectlanguage.com/0.2/') + expect(subject.base_url).to eq('https://ws.detectlanguage.com/v3/') expect(subject.user_agent).to eq("detectlanguage-ruby/#{DetectLanguage::VERSION}") end end @@ -35,18 +35,6 @@ end end - context 'with batch requests' do - let(:query) { ['', 'Hello world', 'Jau saulelė vėl atkopdama budino svietą'] } - - it 'detects languages in batch' do - expect(subject).to be_an(Array) - expect(subject.size).to eq(3) - expect(subject[0]).to be_empty - expect(subject[1][0]['language']).to eq('en') - expect(subject[2][0]['language']).to eq('lt') - end - end - context 'invalid api key' do let(:api_key) { 'invalid' } @@ -56,20 +44,50 @@ end end - describe '.simple_detect' do - subject { described_class.simple_detect(query) } + describe '.detect_code' do + subject { described_class.detect_code(query) } let(:query) { 'Hello world' } it 'detects language' do expect(subject).to eq('en') end + + context 'with empty query' do + let(:query) { ' ' } + + it 'returns nil for empty query' do + expect(subject).to be_nil + end + end + end + + describe '.detect_batch' do + subject { described_class.detect_batch(queries) } + + let(:queries) { ['', 'Hello world', 'Jau saulelė vėl atkopdama budino svietą'] } + + it 'detects languages in batch' do + expect(subject).to be_an(Array) + expect(subject.size).to eq(3) + expect(subject[0]).to be_empty + expect(subject[1][0]['language']).to eq('en') + expect(subject[2][0]['language']).to eq('lt') + end + + context 'when queries is not an array' do + let(:queries) { 'Hello world' } + + it 'raises an ArgumentError' do + expect { subject }.to raise_error(ArgumentError, "Expected an Array of queries") + end + end end - describe '.user_status' do - subject { DetectLanguage.user_status } + describe '.account_status' do + subject { described_class.account_status } - it 'fetches user status' do + it 'fetches account status' do expect(subject).to include( 'date' => kind_of(String), 'requests' => kind_of(Integer), @@ -85,7 +103,7 @@ subject { DetectLanguage.languages } it 'fetches list of detectable languages' do - expect(subject).to include('code' => 'en', 'name' => 'ENGLISH') + expect(subject).to include('code' => 'en', 'name' => 'English') end end end From 70d722e14c93ed98402a534160577e07edc184bd Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 01:03:11 +0300 Subject: [PATCH 03/21] Use JSON payloads --- README.md | 27 +++++++-------------------- lib/detect_language.rb | 2 +- lib/detect_language/client.rb | 15 ++++++++------- 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 63a0efa..abd7c8b 100644 --- a/README.md +++ b/README.md @@ -6,9 +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 Add this line to your application's Gemfile: @@ -17,23 +14,13 @@ Add this line to your application's Gemfile: gem 'detect_language' ``` -Or install it yourself as: - -``` -gem install detect_language -``` - ### 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 end ``` @@ -51,12 +38,12 @@ DetectLanguage.detect("Buenos dias señor") [{"language"=>"es", "isReliable"=>true, "confidence"=>6.62}] ``` -### Simple language detection +### Language code detection -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("Buenos dias señor") ``` #### Result @@ -69,10 +56,10 @@ DetectLanguage.simple_detect("Buenos dias señor") 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(["Buenos dias señor", "Labas rytas"]) ``` #### Result @@ -87,7 +74,7 @@ Result is array of detections in the same order as the texts were passed. ### Getting your account status ```ruby -DetectLanguage.user_status +DetectLanguage.account_status ``` #### Result diff --git a/lib/detect_language.rb b/lib/detect_language.rb index 248ed54..8f8f46f 100644 --- a/lib/detect_language.rb +++ b/lib/detect_language.rb @@ -26,7 +26,7 @@ def detect(query) def detect_batch(queries) raise(ArgumentError, 'Expected an Array of queries') unless queries.is_a?(Array) - client.post('detect-batch', 'q[]': queries) + client.post('detect-batch', q: queries) end def detect_code(text) diff --git a/lib/detect_language/client.rb b/lib/detect_language/client.rb index f2bc539..c70576f 100644 --- a/lib/detect_language/client.rb +++ b/lib/detect_language/client.rb @@ -10,22 +10,23 @@ def initialize(config) @config = config end - def post(path, params = {}) - execute(Net::HTTP::Post, path, params) + def post(path, payload = {}) + execute(Net::HTTP::Post, path, body: payload.to_json) end - def get(path, params = {}) - execute(Net::HTTP::Get, path, params) + def get(path) + execute(Net::HTTP::Get, path) end private - def execute(method, path, params) - uri = URI.parse(config.base_url) + def execute(method, path, body: nil) + uri = URI(config.base_url) http = setup_http_connection(uri) request = method.new(uri.path + path) - request.set_form_data(params) + request.body = body + request['Content-Type'] = 'application/json' request['Authorization'] = 'Bearer ' + config.api_key.to_s request['User-Agent'] = config.user_agent From 408e32466026db446613353054bb253e180b8483 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 01:05:34 +0300 Subject: [PATCH 04/21] Adjust ruby versions --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f12f55a..6d13fe5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,9 +6,9 @@ jobs: strategy: matrix: ruby-version: - - 2.0 + - 2.0.0 - 2.7 - - 3.0 + - 3.0.0 - 3.4 - ruby-head - jruby-head From 941821f5bdea6ef80b535b57d844513e30d778a7 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 01:08:12 +0300 Subject: [PATCH 05/21] Disable arm test --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6d13fe5..c15ea29 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: - 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 From 47f56c5f7a548f5b16f3c954f3bbe179e8c57986 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 10:05:35 +0300 Subject: [PATCH 06/21] Refactor proxy --- Gemfile | 4 +-- lib/detect_language.rb | 4 +++ lib/detect_language/client.rb | 36 +++++++++++++++----------- lib/detect_language/configuration.rb | 22 +++++----------- spec/{ => lib}/detect_language_spec.rb | 11 ++++++++ 5 files changed, 45 insertions(+), 32 deletions(-) rename spec/{ => lib}/detect_language_spec.rb (91%) diff --git a/Gemfile b/Gemfile index 5b8f682..d9d312b 100644 --- a/Gemfile +++ b/Gemfile @@ -6,5 +6,5 @@ gem 'rake' gem 'json' group :test do - gem "rspec" -end \ No newline at end of file + gem 'rspec' +end diff --git a/lib/detect_language.rb b/lib/detect_language.rb index 8f8f46f..c3e1b1d 100644 --- a/lib/detect_language.rb +++ b/lib/detect_language.rb @@ -19,6 +19,10 @@ def client Thread.current[:detect_language_client] ||= Client.new(config) end + def client=(client) + Thread.current[:detect_language_client] = client + end + def detect(query) client.post('detect', q: query) end diff --git a/lib/detect_language/client.rb b/lib/detect_language/client.rb index c70576f..39e20fe 100644 --- a/lib/detect_language/client.rb +++ b/lib/detect_language/client.rb @@ -21,19 +21,17 @@ def get(path) private def execute(method, path, body: nil) - uri = URI(config.base_url) - http = setup_http_connection(uri) - request = method.new(uri.path + path) + request = method.new(base_uri.path + path) request.body = body 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}") @@ -50,21 +48,29 @@ def parse_response(response_body) end end - def setup_http_connection(uri) - http = Net::HTTP::Proxy( - config.proxy_host, config.proxy_port, config.proxy_user, config.proxy_pass - ).new(uri.host, uri.port) + def base_uri + @base_uri ||= URI(config.base_url) + end - http.read_timeout = config.http_read_timeout - http.open_timeout = config.http_open_timeout + def connection + @connection ||= setup_connection + end - if uri.scheme == 'https' - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_PEER + def setup_connection + http = if config.proxy + proxy = URI(config.proxy) + proxy_use_ssl = proxy.scheme == 'https' + Net::HTTP.new(base_uri.hostname, base_uri.port, + proxy.hostname, proxy.port, proxy.user, proxy.password, nil, proxy_use_ssl) else - http.use_ssl = false + Net::HTTP.new(base_uri.hostname, base_uri.port) 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 + http end end diff --git a/lib/detect_language/configuration.rb b/lib/detect_language/configuration.rb index 3c68d42..6db4c88 100644 --- a/lib/detect_language/configuration.rb +++ b/lib/detect_language/configuration.rb @@ -1,31 +1,23 @@ module DetectLanguage class Configuration - # The API key for your project, found on your homepage after you login into detectlanguage.com website + # The API key for your project, found on your homepage after you log in into + # https://detectlanguage.com website attr_accessor :api_key - # HTTP request user agent (defaults to 'Detect Language API ruby gem'). - attr_accessor :user_agent - # API base URL attr_accessor :base_url + # HTTP request user agent (defaults to 'Detect Language API ruby gem'). + attr_accessor :user_agent + # The HTTP open timeout in seconds. attr_accessor :http_open_timeout # The HTTP read timeout in seconds. attr_accessor :http_read_timeout - # The hostname of your proxy server (if using a proxy). - attr_accessor :proxy_host - - # The port of your proxy server (if using a proxy). - attr_accessor :proxy_port - - # The username to use when logging into your proxy server (if using a proxy). - attr_accessor :proxy_user - - # The password to use when logging into your proxy server (if using a proxy). - attr_accessor :proxy_pass + # The HTTP proxy to use for requests. Example: 'http://my-proxy:8080' + attr_accessor :proxy def initialize @api_key = nil diff --git a/spec/detect_language_spec.rb b/spec/lib/detect_language_spec.rb similarity index 91% rename from spec/detect_language_spec.rb rename to spec/lib/detect_language_spec.rb index 91b4c8f..66aa0d8 100644 --- a/spec/detect_language_spec.rb +++ b/spec/lib/detect_language_spec.rb @@ -2,9 +2,12 @@ RSpec.describe DetectLanguage do let(:api_key) { ENV['DETECTLANGUAGE_API_KEY'] } + let(:proxy) { nil } before do + described_class.client = nil described_class.config.api_key = api_key + described_class.config.proxy = proxy end describe '.config' do @@ -42,6 +45,14 @@ expect { subject }.to raise_error(DetectLanguage::Error) end end + + xcontext 'with proxy' do + let(:proxy) { 'http://my-proxy:8080' } + + it 'uses the proxy for requests' do + expect { subject }.not_to raise_error + end + end end describe '.detect_code' do From c0ee98c0e0eeea7113b0c004df80ffc844d6e4e3 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 19:44:17 +0300 Subject: [PATCH 07/21] Implement proxy spec --- spec/lib/detect_language_spec.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/spec/lib/detect_language_spec.rb b/spec/lib/detect_language_spec.rb index 66aa0d8..f79502c 100644 --- a/spec/lib/detect_language_spec.rb +++ b/spec/lib/detect_language_spec.rb @@ -46,11 +46,15 @@ end end - xcontext 'with proxy' do - let(:proxy) { 'http://my-proxy:8080' } + context 'with proxy' do + let(:proxy) { 'https://dummy:pass@my-proxy:8080' } it 'uses the proxy for requests' do - expect { subject }.not_to raise_error + allow(Net::HTTP).to receive(:new) + .with('ws.detectlanguage.com', 443, 'my-proxy', 8080, 'dummy', 'pass', nil, true) + .and_call_original + + expect { subject }.to raise_error(Socket::ResolutionError) end end end From c157288533617db1609cf059c06ebb2964d96698 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 20:17:37 +0300 Subject: [PATCH 08/21] Add changelog --- CHANGELOG.md | 22 ++++++++++++++++++++++ README.md | 11 ++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..813ebf1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,22 @@ +# 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). + + +## [2.0.0] + +### Added +- `detect_batch` method for batch detections + +### Changed +- Switched to v3 API which uses updated language detection model +- ⚠️ `simple_detect` method renamed to `detect_code` +- ⚠️ `detect` method result fields are `language` and `score` +- ⚠️ `detect` method no longer accept arrays - use `detect_batch` instead +- ⚠️ `user_status` method renamed to `account_status` +- ⚠️ Proxy URL configured using `config.proxy` +- HTTPS is used by default. Removed secure_mode configuration +- Client connection is reused. If you change configuration after client is initialized, you need to reset client using `DetectLanguage.client = nil`. diff --git a/README.md b/README.md index abd7c8b..32c8ab9 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Detect Language API Ruby Client Detects language of the given text. Returns detected language codes and scores. + ## Installation Add this line to your application's Gemfile: @@ -14,6 +15,10 @@ Add this line to your application's Gemfile: gem 'detect_language' ``` +### Upgrading + +When upgrading please check [changelog](CHANGELOG.md) for breaking changes. + ### Configuration Get your personal API key by signing up at https://detectlanguage.com @@ -35,7 +40,7 @@ DetectLanguage.detect("Buenos dias señor") #### Result ```ruby -[{"language"=>"es", "isReliable"=>true, "confidence"=>6.62}] +[{"language"=>"es", "score"=>0.95}] ``` ### Language code detection @@ -67,8 +72,8 @@ DetectLanguage.detect_batch(["Buenos dias señor", "Labas rytas"]) 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"=>"es", "score"=>0.95}], + [{"language"=>"lt", "score"=>0.98}] ] ``` ### Getting your account status From 7cef5df0e3f8fd009ce8a6592ef54df56c0c6d9f Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 20:18:59 +0300 Subject: [PATCH 09/21] Add removed section --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 813ebf1..27b54d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,3 +20,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ⚠️ Proxy URL configured using `config.proxy` - HTTPS is used by default. Removed secure_mode configuration - Client connection is reused. If you change configuration after client is initialized, you need to reset client using `DetectLanguage.client = nil`. + +### Removed +- Ruby 1.x support \ No newline at end of file From c6a8b088def0ba8236abd4bf6db78a33410ab142 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 20:22:52 +0300 Subject: [PATCH 10/21] Adjust proxy spec --- spec/lib/detect_language_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/detect_language_spec.rb b/spec/lib/detect_language_spec.rb index f79502c..96cd382 100644 --- a/spec/lib/detect_language_spec.rb +++ b/spec/lib/detect_language_spec.rb @@ -54,7 +54,7 @@ .with('ws.detectlanguage.com', 443, 'my-proxy', 8080, 'dummy', 'pass', nil, true) .and_call_original - expect { subject }.to raise_error(Socket::ResolutionError) + expect { subject }.to raise_error(SocketError) end end end From 72b8ee94a9d46e775defe410789b319f406f33c9 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 20:27:43 +0300 Subject: [PATCH 11/21] Disable ruby 2.0 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c15ea29..cebcdeb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,7 +6,7 @@ jobs: strategy: matrix: ruby-version: - - 2.0.0 + # - 2.0.0 - 2.7 - 3.0.0 - 3.4 From 3d13cc2d605dc9fc88d8fb5f330a8489185e27ab Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 19 Jul 2025 20:31:41 +0300 Subject: [PATCH 12/21] Adjust proxy --- .github/workflows/main.yml | 2 +- lib/detect_language/client.rb | 4 +--- spec/lib/detect_language_spec.rb | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cebcdeb..c15ea29 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,7 +6,7 @@ jobs: strategy: matrix: ruby-version: - # - 2.0.0 + - 2.0.0 - 2.7 - 3.0.0 - 3.4 diff --git a/lib/detect_language/client.rb b/lib/detect_language/client.rb index 39e20fe..ab69be9 100644 --- a/lib/detect_language/client.rb +++ b/lib/detect_language/client.rb @@ -59,9 +59,7 @@ def connection def setup_connection http = if config.proxy proxy = URI(config.proxy) - proxy_use_ssl = proxy.scheme == 'https' - Net::HTTP.new(base_uri.hostname, base_uri.port, - proxy.hostname, proxy.port, proxy.user, proxy.password, nil, proxy_use_ssl) + Net::HTTP.new(base_uri.hostname, base_uri.port, proxy.hostname, proxy.port, proxy.user, proxy.password) else Net::HTTP.new(base_uri.hostname, base_uri.port) end diff --git a/spec/lib/detect_language_spec.rb b/spec/lib/detect_language_spec.rb index 96cd382..9fff07f 100644 --- a/spec/lib/detect_language_spec.rb +++ b/spec/lib/detect_language_spec.rb @@ -47,11 +47,11 @@ end context 'with proxy' do - let(:proxy) { 'https://dummy:pass@my-proxy:8080' } + let(:proxy) { 'http://dummy:pass@my-proxy:8080' } it 'uses the proxy for requests' do allow(Net::HTTP).to receive(:new) - .with('ws.detectlanguage.com', 443, 'my-proxy', 8080, 'dummy', 'pass', nil, true) + .with('ws.detectlanguage.com', 443, 'my-proxy', 8080, 'dummy', 'pass') .and_call_original expect { subject }.to raise_error(SocketError) From 410b4eb2a62d5bfaf9a0de68c927e45829da4c9a Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sun, 20 Jul 2025 09:39:28 +0300 Subject: [PATCH 13/21] Adjust changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27b54d4..e23d6ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ⚠️ `detect` method no longer accept arrays - use `detect_batch` instead - ⚠️ `user_status` method renamed to `account_status` - ⚠️ Proxy URL configured using `config.proxy` -- HTTPS is used by default. Removed secure_mode configuration +- HTTPS is used by default. Removed secure mode configuration. - Client connection is reused. If you change configuration after client is initialized, you need to reset client using `DetectLanguage.client = nil`. ### Removed From b8bb6c3dd66763b70e025e3bb5654e83484ca834 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sun, 20 Jul 2025 09:55:16 +0300 Subject: [PATCH 14/21] Update examples --- README.md | 15 +++++++-------- spec/lib/detect_language_spec.rb | 5 +---- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 32c8ab9..3f04283 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Get your personal API key by signing up at https://detectlanguage.com ```ruby DetectLanguage.configure do |config| - config.api_key = "YOUR API KEY" + config.api_key = 'YOUR API KEY' end ``` @@ -34,13 +34,13 @@ end ### Language detection ```ruby -DetectLanguage.detect("Buenos dias señor") +DetectLanguage.detect('Dolce far niente') ``` #### Result ```ruby -[{"language"=>"es", "score"=>0.95}] +[{"language" => "it", "score" => 0.5074}] ``` ### Language code detection @@ -48,13 +48,13 @@ DetectLanguage.detect("Buenos dias señor") If you need just a language code you can use `detect_code`. ```ruby -DetectLanguage.detect_code("Buenos dias señor") +DetectLanguage.detect_code('Dolce far niente') ``` #### Result ```ruby -"es" +"it" ``` ### Batch detection @@ -64,7 +64,7 @@ This method is significantly faster than doing one request per text. To use batch detection just pass array of texts to `detect_batch` method. ```ruby -DetectLanguage.detect_batch(["Buenos dias señor", "Labas rytas"]) +DetectLanguage.detect_batch(['Dolce far niente', 'Labas rytas']) ``` #### Result @@ -72,8 +72,7 @@ DetectLanguage.detect_batch(["Buenos dias señor", "Labas rytas"]) Result is array of detections in the same order as the texts were passed. ```ruby -[ [{"language"=>"es", "score"=>0.95}], - [{"language"=>"lt", "score"=>0.98}] ] +[[{"language" => "it", "score" => 0.5074}], [{"language" => "lt", "score" => 0.3063}]] ``` ### Getting your account status diff --git a/spec/lib/detect_language_spec.rb b/spec/lib/detect_language_spec.rb index 9fff07f..590961e 100644 --- a/spec/lib/detect_language_spec.rb +++ b/spec/lib/detect_language_spec.rb @@ -13,10 +13,7 @@ describe '.config' do subject { described_class.config } - it 'has default configuration values' do - expect(subject.base_url).to eq('https://ws.detectlanguage.com/v3/') - expect(subject.user_agent).to eq("detectlanguage-ruby/#{DetectLanguage::VERSION}") - end + it { is_expected.to be_a(DetectLanguage::Configuration) } end describe '.detect' do From 8040fc8649fad57e760a7eae40d638e392eda302 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sun, 20 Jul 2025 09:56:25 +0300 Subject: [PATCH 15/21] Bump version --- lib/detect_language/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/detect_language/version.rb b/lib/detect_language/version.rb index 1b7e14c..e6711fd 100644 --- a/lib/detect_language/version.rb +++ b/lib/detect_language/version.rb @@ -1,3 +1,3 @@ module DetectLanguage - VERSION = '1.1.2' + VERSION = '2.0.0' end From 1c647544bd72c672265540f7e2032087b2f02696 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sun, 20 Jul 2025 09:57:37 +0300 Subject: [PATCH 16/21] Adjust version --- .../lib/detect_language/configuratino_spec.rb | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 spec/lib/detect_language/configuratino_spec.rb diff --git a/spec/lib/detect_language/configuratino_spec.rb b/spec/lib/detect_language/configuratino_spec.rb new file mode 100644 index 0000000..6aea8cd --- /dev/null +++ b/spec/lib/detect_language/configuratino_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +RSpec.describe DetectLanguage::Configuration do + describe '#api_key' do + it 'returns the api key' do + expect(subject.api_key).to be_nil + end + end + + describe '#base_url' do + it 'returns the base url' do + expect(subject.base_url).to eq('https://ws.detectlanguage.com/v3/') + end + end + + describe '#user_agent' do + it 'returns the user agent' do + expect(subject.user_agent).to eq("detectlanguage-ruby/#{DetectLanguage::VERSION}") + end + end +end \ No newline at end of file From 863f96508c9d840081fe52a0830fe0cbe1bab241 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sun, 20 Jul 2025 09:59:41 +0300 Subject: [PATCH 17/21] Add blank lines --- CHANGELOG.md | 4 ++-- spec/lib/detect_language/configuratino_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e23d6ee..e742fb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ 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). -## [2.0.0] +## v2.0.0 ### Added - `detect_batch` method for batch detections @@ -22,4 +22,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Client connection is reused. If you change configuration after client is initialized, you need to reset client using `DetectLanguage.client = nil`. ### Removed -- Ruby 1.x support \ No newline at end of file +- Ruby 1.x support diff --git a/spec/lib/detect_language/configuratino_spec.rb b/spec/lib/detect_language/configuratino_spec.rb index 6aea8cd..7c57fb6 100644 --- a/spec/lib/detect_language/configuratino_spec.rb +++ b/spec/lib/detect_language/configuratino_spec.rb @@ -18,4 +18,4 @@ expect(subject.user_agent).to eq("detectlanguage-ruby/#{DetectLanguage::VERSION}") end end -end \ No newline at end of file +end From 009596381509ec4b4b2ecfe783e38db05be4df0c Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sun, 20 Jul 2025 21:13:43 +0300 Subject: [PATCH 18/21] Adjust readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f04283..9072737 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ DetectLanguage.account_status "daily_requests_limit"=>5000, "daily_bytes_limit"=>1048576, "status"=>"ACTIVE"} ``` -### Getting list supported languages +### Getting list of supported languages ```ruby DetectLanguage.languages From 658c44145db6a86ca12db731925ea8a029dbbf77 Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sun, 20 Jul 2025 21:20:12 +0300 Subject: [PATCH 19/21] Update readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9072737..4a299cf 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ end ## Usage -### Language detection +### Detect language ```ruby DetectLanguage.detect('Dolce far niente') @@ -43,7 +43,7 @@ DetectLanguage.detect('Dolce far niente') [{"language" => "it", "score" => 0.5074}] ``` -### Language code detection +### Detect single code If you need just a language code you can use `detect_code`. @@ -75,7 +75,7 @@ Result is array of detections in the same order as the texts were passed. [[{"language" => "it", "score" => 0.5074}], [{"language" => "lt", "score" => 0.3063}]] ``` -### Getting your account status +### Get your account status ```ruby DetectLanguage.account_status @@ -88,7 +88,7 @@ DetectLanguage.account_status "daily_requests_limit"=>5000, "daily_bytes_limit"=>1048576, "status"=>"ACTIVE"} ``` -### Getting list of supported languages +### Get list of supported languages ```ruby DetectLanguage.languages From 36218f84713d98cde49c325eccb2e5815785b2fc Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Wed, 23 Jul 2025 20:42:39 +0300 Subject: [PATCH 20/21] Add deprecations --- CHANGELOG.md | 13 ++++++------ lib/detect_language.rb | 33 ++++++++++++++++++++++++++++++ spec/lib/detect_language_spec.rb | 35 ++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e742fb6..366d043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,14 +12,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `detect_batch` method for batch detections ### Changed -- Switched to v3 API which uses updated language detection model -- ⚠️ `simple_detect` method renamed to `detect_code` +- Switched to v3 API which uses an updated language detection model - ⚠️ `detect` method result fields are `language` and `score` -- ⚠️ `detect` method no longer accept arrays - use `detect_batch` instead -- ⚠️ `user_status` method renamed to `account_status` +- ⚠️ `detect` for batch detection is deprecated, use `detect_batch` instead +- ⚠️ `simple_detect` deprecated, use `detect_code` instead +- ⚠️ `user_status` deprecated, use `account_status` instead +- ⚠️ `configuration` deprecated, use `config` instead - ⚠️ Proxy URL configured using `config.proxy` -- HTTPS is used by default. Removed secure mode configuration. -- Client connection is reused. If you change configuration after client is initialized, you need to reset client using `DetectLanguage.client = nil`. +- Client connection is reused. If you change configuration after the client is initialized, you need to reset client using `DetectLanguage.client = nil`. ### Removed +- Secure mode configuration. HTTPS is always used. - Ruby 1.x support diff --git a/lib/detect_language.rb b/lib/detect_language.rb index c3e1b1d..ebafea8 100644 --- a/lib/detect_language.rb +++ b/lib/detect_language.rb @@ -23,16 +23,27 @@ def client=(client) Thread.current[:detect_language_client] = client end + # @param query String + # @return [Array] 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 Array of queries to detect languages for + # @return [Array>] 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) @@ -41,12 +52,34 @@ def detect_code(text) detections[0]['language'] end + # @return [Hash] Account status information def account_status client.get('account/status') end + # @return [Array] 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 diff --git a/spec/lib/detect_language_spec.rb b/spec/lib/detect_language_spec.rb index 590961e..f8bcd29 100644 --- a/spec/lib/detect_language_spec.rb +++ b/spec/lib/detect_language_spec.rb @@ -16,6 +16,15 @@ it { is_expected.to be_a(DetectLanguage::Configuration) } end + describe '.configuration' do + subject { described_class.configuration } + + it 'delegates to config' do + expect(described_class).to receive(:config) + expect { subject }.to output(/DEPRECATED/).to_stderr + end + end + describe '.detect' do subject { described_class.detect(query) } @@ -35,6 +44,23 @@ end end + context 'with array of queries' do + let(:query) { ['Hello world', 'Bonjour le monde'] } + let(:result) { double } + + before do + allow(described_class).to receive(:detect_batch).with(query).and_return(result) + end + + it 'delegates to detect_batch' do + expect(subject).to be(result) + end + + it 'issues a deprecation warning' do + expect { described_class.detect(query) }.to output(/DEPRECATED/).to_stderr + end + end + context 'invalid api key' do let(:api_key) { 'invalid' } @@ -111,6 +137,15 @@ end end + describe '.user_status' do + subject { described_class.user_status } + + it 'delegates to account_status' do + expect(described_class).to receive(:account_status) + expect { subject }.to output(/DEPRECATED/).to_stderr + end + end + describe '.languages' do subject { DetectLanguage.languages } From 8d36970776dd552c486b52e95382d5173f9fc88b Mon Sep 17 00:00:00 2001 From: Laurynas Butkus Date: Sat, 26 Jul 2025 10:09:23 +0300 Subject: [PATCH 21/21] Add deprecations --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 366d043..a553184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,13 +14,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Switched to v3 API which uses an updated language detection model - ⚠️ `detect` method result fields are `language` and `score` -- ⚠️ `detect` for batch detection is deprecated, use `detect_batch` instead -- ⚠️ `simple_detect` deprecated, use `detect_code` instead -- ⚠️ `user_status` deprecated, use `account_status` instead -- ⚠️ `configuration` deprecated, use `config` instead - ⚠️ 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