├── .github └── workflows │ └── main.yml ├── .gitignore ├── .rspec ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── detect_language.gemspec ├── lib ├── detect_language.rb └── detect_language │ ├── client.rb │ ├── configuration.rb │ ├── errors.rb │ └── version.rb └── spec ├── detect_language_spec.rb └── spec_helper.rb /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push,pull_request] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | strategy: 7 | matrix: 8 | ruby-version: 9 | - 2.0 10 | - 2.5 11 | - 2.6 12 | - 2.7 13 | - 3.0 14 | - ruby-head 15 | - jruby-9.1 16 | - jruby-head 17 | name: Ruby ${{ matrix.ruby-version }} sample 18 | steps: 19 | - uses: actions/checkout@v3 20 | - uses: ruby/setup-ruby@v1 21 | with: 22 | ruby-version: ${{ matrix.ruby-version }} 23 | # bundler-cache: true 24 | - run: bundle install 25 | - env: 26 | DETECTLANGUAGE_API_KEY: ${{ secrets.DETECTLANGUAGE_API_KEY }} 27 | run: bundle exec rake spec 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | .idea 7 | Gemfile.lock 8 | InstalledFiles 9 | _yardoc 10 | coverage 11 | doc/ 12 | lib/bundler/man 13 | pkg 14 | rdoc 15 | spec/reports 16 | test/tmp 17 | test/version_tmp 18 | tmp 19 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format progress 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | gem 'rake' 6 | gem 'json' 7 | 8 | group :test do 9 | gem "rspec" 10 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Laurynas Butkus 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Detect Language API Ruby Client 2 | ======== 3 | 4 | [![Gem Version](https://badge.fury.io/rb/detect_language.svg)](https://badge.fury.io/rb/detect_language) 5 | [![Build Status](https://github.com/detectlanguage/detectlanguage-ruby/actions/workflows/main.yml/badge.svg)](https://github.com/detectlanguage/detectlanguage-ruby/actions) 6 | 7 | Detects language of the given text. Returns detected language codes and scores. 8 | 9 | Before using Detect Language API client you have to setup your personal API key. 10 | You can get it by signing up at https://detectlanguage.com 11 | 12 | ## Installation 13 | 14 | Add this line to your application's Gemfile: 15 | 16 | ``` 17 | gem 'detect_language' 18 | ``` 19 | 20 | Or install it yourself as: 21 | 22 | ``` 23 | gem install detect_language 24 | ``` 25 | 26 | ### Configuration 27 | 28 | If you are using Rails, create initializer `config/initializers/detect_language.rb` and add following code there. 29 | Otherwise just integrate following code into your apps configuration. 30 | 31 | ```ruby 32 | DetectLanguage.configure do |config| 33 | config.api_key = "YOUR API KEY" 34 | 35 | # enable secure mode (SSL) if you are passing sensitive data 36 | # config.secure = true 37 | end 38 | ``` 39 | 40 | ## Usage 41 | 42 | ### Language detection 43 | 44 | ```ruby 45 | DetectLanguage.detect("Buenos dias señor") 46 | ``` 47 | 48 | #### Result 49 | 50 | ```ruby 51 | [{"language"=>"es", "isReliable"=>true, "confidence"=>6.62}] 52 | ``` 53 | 54 | ### Simple language detection 55 | 56 | If you need just a language code you can use `simple_detect`. It returns just the language code. 57 | 58 | ```ruby 59 | DetectLanguage.simple_detect("Buenos dias señor") 60 | ``` 61 | 62 | #### Result 63 | 64 | ```ruby 65 | "es" 66 | ``` 67 | 68 | ### Batch detection 69 | 70 | It is possible to detect language of several texts with one request. 71 | This method is significantly faster than doing one request per text. 72 | To use batch detection just pass array of texts to `detect` method. 73 | 74 | ```ruby 75 | DetectLanguage.detect(["Buenos dias señor", "Labas rytas"]) 76 | ``` 77 | 78 | #### Result 79 | 80 | Result is array of detections in the same order as the texts were passed. 81 | 82 | ```ruby 83 | [ [{"language"=>"es", "isReliable"=>true, "confidence"=>6.62}], 84 | [{"language"=>"lt", "isReliable"=>true, "confidence"=>6.82}] ] 85 | ``` 86 | 87 | ### Getting your account status 88 | 89 | ```ruby 90 | DetectLanguage.user_status 91 | ``` 92 | 93 | #### Result 94 | 95 | ```ruby 96 | {"date"=>"2013-11-17", "requests"=>95, "bytes"=>2223, "plan"=>"FREE", "plan_expires"=>nil, 97 | "daily_requests_limit"=>5000, "daily_bytes_limit"=>1048576, "status"=>"ACTIVE"} 98 | ``` 99 | 100 | ### Getting list supported languages 101 | 102 | ```ruby 103 | DetectLanguage.languages 104 | ``` 105 | 106 | #### Result 107 | 108 | Array of language codes and names. 109 | 110 | ## License 111 | 112 | Detect Language API Client is free software, and may be redistributed under the terms specified in the MIT-LICENSE file. 113 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | require "bundler/gem_tasks" 3 | require 'rspec/core/rake_task' 4 | 5 | RSpec::Core::RakeTask.new 6 | 7 | task :default => :spec -------------------------------------------------------------------------------- /detect_language.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path('../lib/detect_language/version', __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.authors = ["Laurynas Butkus"] 6 | gem.email = ["laurynas.butkus@gmail.com"] 7 | gem.description = %q{Language Detection API Client} 8 | gem.summary = %q{Detects language of given text. Returns detected language codes and scores.} 9 | gem.homepage = "https://github.com/detectlanguage/detectlanguage-ruby" 10 | 11 | gem.files = `git ls-files`.split($\) 12 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 13 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 14 | gem.name = "detect_language" 15 | gem.require_paths = ["lib"] 16 | gem.version = DetectLanguage::VERSION 17 | gem.license = 'MIT' 18 | end 19 | -------------------------------------------------------------------------------- /lib/detect_language.rb: -------------------------------------------------------------------------------- 1 | require "detect_language/version" 2 | require "detect_language/errors" 3 | require "detect_language/configuration" 4 | require "detect_language/client" 5 | 6 | module DetectLanguage 7 | class << self 8 | attr_writer :configuration 9 | 10 | def configure 11 | yield(configuration) 12 | end 13 | 14 | # The configuration object. 15 | # @see DetectLanguage.configure 16 | def configuration 17 | @configuration ||= Configuration.new 18 | end 19 | 20 | def client 21 | Thread.current[:detect_language_client] ||= Client.new(configuration) 22 | end 23 | 24 | def detect(data) 25 | key = data.is_a?(Array) ? 'q[]' : 'q' 26 | result = client.post(:detect, key => data) 27 | result['data']['detections'] 28 | end 29 | 30 | def simple_detect(text) 31 | detections = detect(text) 32 | 33 | if detections.empty? 34 | nil 35 | else 36 | detections[0]['language'] 37 | end 38 | end 39 | 40 | def user_status 41 | client.get('user/status') 42 | end 43 | 44 | def languages 45 | client.get('languages') 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/detect_language/client.rb: -------------------------------------------------------------------------------- 1 | require 'cgi' 2 | require 'net/http' 3 | require 'net/https' 4 | require 'json' 5 | 6 | module DetectLanguage 7 | class Client 8 | attr_reader :configuration 9 | 10 | def initialize(configuration) 11 | @configuration = configuration 12 | end 13 | 14 | def post(method, params = {}) 15 | execute(method, params, :http_method => Net::HTTP::Post) 16 | end 17 | 18 | def get(method, params = {}) 19 | execute(method, params, :http_method => Net::HTTP::Get) 20 | end 21 | 22 | private 23 | 24 | def execute(method, params, options) 25 | http = setup_http_connection 26 | http_method = options[:http_method] 27 | request = http_method.new(request_uri(method)) 28 | 29 | if RUBY_VERSION == '1.8.7' 30 | set_form_data_18(request, params) 31 | else 32 | request.set_form_data(params) 33 | end 34 | 35 | request['Authorization'] = 'Bearer ' + configuration.api_key.to_s 36 | request['User-Agent'] = configuration.user_agent 37 | 38 | response = http.request(request) 39 | 40 | case response 41 | when Net::HTTPSuccess, Net::HTTPUnauthorized then 42 | parse_response(response.body) 43 | else 44 | raise(Error, "Failure: #{response.class}") 45 | end 46 | end 47 | 48 | def parse_response(response_body) 49 | response = JSON.parse(response_body) 50 | 51 | if response.is_a?(Array) || response["error"].nil? 52 | response 53 | else 54 | raise(Error, response["error"]["message"]) 55 | end 56 | end 57 | 58 | def request_uri(method) 59 | "/#{configuration.api_version}/#{method}" 60 | end 61 | 62 | def setup_http_connection 63 | http = 64 | Net::HTTP::Proxy(configuration.proxy_host, configuration.proxy_port, configuration.proxy_user, 65 | configuration.proxy_pass). 66 | new(configuration.host, configuration.port) 67 | 68 | http.read_timeout = configuration.http_read_timeout 69 | http.open_timeout = configuration.http_open_timeout 70 | 71 | if configuration.secure? 72 | http.use_ssl = true 73 | http.verify_mode = OpenSSL::SSL::VERIFY_PEER 74 | else 75 | http.use_ssl = false 76 | end 77 | 78 | http 79 | end 80 | 81 | def set_form_data_18(request, params, sep = '&') 82 | request.body = params.map {|k,v| 83 | if v.instance_of?(Array) 84 | v.map {|e| "#{urlencode(k.to_s)}=#{urlencode(e.to_s)}"}.join(sep) 85 | else 86 | "#{urlencode(k.to_s)}=#{urlencode(v.to_s)}" 87 | end 88 | }.join(sep) 89 | 90 | request.content_type = 'application/x-www-form-urlencoded' 91 | end 92 | 93 | def urlencode(str) 94 | CGI::escape(str) 95 | end 96 | 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /lib/detect_language/configuration.rb: -------------------------------------------------------------------------------- 1 | module DetectLanguage 2 | class Configuration 3 | # The API key for your project, found on your homepage after you login into detectlanguage.com website 4 | # Defaults to 'demo', which has a limited number of requests. 5 | attr_accessor :api_key 6 | 7 | # The API version you are using (defaults to 0.2). 8 | attr_accessor :api_version 9 | 10 | # HTTP request user agent (defaults to 'Detect Language API ruby gem'). 11 | attr_accessor :user_agent 12 | 13 | # The host to connect to (defaults to ws.detectlanguage.com). 14 | attr_accessor :host 15 | 16 | # The port on which your DetectLanguage server runs (defaults to 443 for secure 17 | # connections, 80 for insecure connections). 18 | attr_accessor :port 19 | 20 | # +true+ for https connections, +false+ for http connections. 21 | attr_accessor :secure 22 | 23 | # The HTTP open timeout in seconds. 24 | attr_accessor :http_open_timeout 25 | 26 | # The HTTP read timeout in seconds. 27 | attr_accessor :http_read_timeout 28 | 29 | # The hostname of your proxy server (if using a proxy). 30 | attr_accessor :proxy_host 31 | 32 | # The port of your proxy server (if using a proxy). 33 | attr_accessor :proxy_port 34 | 35 | # The username to use when logging into your proxy server (if using a proxy). 36 | attr_accessor :proxy_user 37 | 38 | # The password to use when logging into your proxy server (if using a proxy). 39 | attr_accessor :proxy_pass 40 | 41 | alias_method :secure?, :secure 42 | 43 | def initialize 44 | @api_key = nil 45 | @api_version = "0.2" 46 | @host = "ws.detectlanguage.com" 47 | @user_agent = "detectlanguage-ruby/#{VERSION}" 48 | end 49 | 50 | def protocol 51 | if secure? 52 | 'https' 53 | else 54 | 'http' 55 | end 56 | end 57 | 58 | def port 59 | @port || default_port 60 | end 61 | 62 | # Allows config options to be read like a hash 63 | # 64 | # @param [Symbol] option Key for a given attribute 65 | def [](option) 66 | send(option) 67 | end 68 | 69 | private 70 | 71 | # Determines what port should we use for sending requests. 72 | # @return [Fixnum] Returns 443 if you've set secure to true in your 73 | # configuration, and 80 otherwise. 74 | def default_port 75 | if secure? 76 | 443 77 | else 78 | 80 79 | end 80 | end 81 | 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/detect_language/errors.rb: -------------------------------------------------------------------------------- 1 | module DetectLanguage 2 | class Error < StandardError; end 3 | 4 | # deprecated 5 | class Exception < Error; end 6 | end 7 | -------------------------------------------------------------------------------- /lib/detect_language/version.rb: -------------------------------------------------------------------------------- 1 | module DetectLanguage 2 | VERSION = '1.1.2' 3 | end 4 | -------------------------------------------------------------------------------- /spec/detect_language_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'spec_helper' 4 | 5 | describe DetectLanguage do 6 | 7 | let(:api_key) { ENV['DETECTLANGUAGE_API_KEY'] } 8 | 9 | before do 10 | DetectLanguage.configuration.api_key = api_key 11 | end 12 | 13 | context "configuration" do 14 | it "should have default configuration values" do 15 | subject.configuration.api_version.should == '0.2' 16 | subject.configuration.host.should == 'ws.detectlanguage.com' 17 | subject.configuration.user_agent.should == "detectlanguage-ruby/#{DetectLanguage::VERSION}" 18 | end 19 | end 20 | 21 | context 'invalid api key' do 22 | let(:api_key) {'invalid'} 23 | 24 | it "should raise exception for invalid key" do 25 | lambda { 26 | subject.detect("Hello world") 27 | }.should raise_error(DetectLanguage::Error) 28 | end 29 | end 30 | 31 | context "detection" do 32 | it "should detect languages" do 33 | result = subject.detect("Hello world") 34 | result[0]['language'].should == "en" 35 | 36 | result = subject.detect("Jau saulelė vėl atkopdama budino svietą") 37 | result[0]['language'].should == "lt" 38 | end 39 | 40 | it "should have simple way to detect a language" do 41 | subject.simple_detect("Hello world").should == "en" 42 | end 43 | 44 | it "should allow sending batch requests" do 45 | result = subject.detect(["Hello world", "Jau saulelė vėl atkopdama budino svietą"]) 46 | 47 | result[0][0]['language'].should == "en" 48 | result[1][0]['language'].should == "lt" 49 | end 50 | 51 | it "with empty text in the batch it detects correctly" do 52 | result = subject.detect(["", "Hello", "Jau saulelė vėl atkopdama budino svietą"]) 53 | 54 | result[0].should be_empty 55 | result[1][0]['language'].should == "en" 56 | result[2][0]['language'].should == "lt" 57 | end 58 | 59 | context 'secure mode' do 60 | before { DetectLanguage.configuration.secure = true } 61 | after { DetectLanguage.configuration.secure = false } 62 | 63 | it "detects language" do 64 | result = subject.detect("Hello world") 65 | result[0]['language'].should == "en" 66 | end 67 | end 68 | end 69 | 70 | describe '.user_status' do 71 | subject(:user_status) {DetectLanguage.user_status} 72 | 73 | it 'fetches user status' do 74 | expect(user_status['date']).to be_kind_of(String) 75 | expect(user_status['requests']).to be_kind_of(Integer) 76 | expect(user_status['bytes']).to be_kind_of(Integer) 77 | expect(user_status['plan']).to be_kind_of(String) 78 | expect(user_status['daily_requests_limit']).to be_kind_of(Integer) 79 | expect(user_status['daily_bytes_limit']).to be_kind_of(Integer) 80 | end 81 | end 82 | 83 | describe '.languages' do 84 | subject(:languages) {DetectLanguage.languages} 85 | 86 | it 'fetches list of detectable languages' do 87 | expect(languages).to include({ 'code' => 'en', 'name' => 'ENGLISH' }) 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | require 'detect_language' 4 | 5 | RSpec.configure do |config| 6 | 7 | end 8 | --------------------------------------------------------------------------------