Skip to content

Commit 8c7edf9

Browse files
authored
Add DeepL driver (#3)
* Bump minimum to Laravel 9.12 to have preventStrayRequests
1 parent faa98f6 commit 8c7edf9

File tree

8 files changed

+166
-4
lines changed

8 files changed

+166
-4
lines changed

.github/workflows/run-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
matrix:
1515
os: [ubuntu-latest]
1616
php: [8.1, 8.2]
17-
laravel: ['^9.0', '^10.0']
17+
laravel: ['^9.12', '^10.0']
1818
stability: [prefer-lowest, prefer-stable]
1919

2020
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}

composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
],
1818
"require": {
1919
"php": "^8.0",
20-
"illuminate/contracts": "^9.0|^10.0",
21-
"illuminate/support": "^9.0|^10.0",
22-
"illuminate/http": "^9.0|^10.0",
20+
"illuminate/contracts": "^9.12|^10.0",
21+
"illuminate/support": "^9.12|^10.0",
22+
"illuminate/http": "^9.12|^10.0",
2323
"symfony/process": "^6.0"
2424
},
2525
"require-dev": {

config/language-recognizer.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,10 @@
2020
// 'exclude' => ['cat','sot','kat','bcl','glg','lao','lit','umb','tsn','vec','nso','ban','bug','knc','kng','ibb','lug','ace','bam','tzm','ydd','kmb','lun','shn','war','dyu','wol','nds','mkd','vmw','zgh','ewe','khk','slv','ayr','bem','emk','bci','bum','epo','pam','tiv','tpi','ven','ssw','nyn','kbd','iii','yao','lav','quz','src','rup','sco','tso','rmy','men','fon','nhn','dip','kde','snn','kbp','tem','toi','est','snk','cjk','ada','aii','quy','rmn','bin','gaa','ndo'],
2121
],
2222

23+
'deepl' => [
24+
'host' => env('LANGUAGE_RECOGNIZER_DEEPL_HOST', 'https://api-free.deepl.com'),
25+
'key' => env('LANGUAGE_RECOGNIZER_DEEPL_KEY', null),
26+
],
27+
2328
]
2429
];

src/Commands/InstallLocalRecognizerCommand.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ protected function getOs()
6565

6666
protected function getDownloadPath()
6767
{
68+
/**
69+
* @var string
70+
*/
6871
$pathOption = $this->option('path');
6972

7073
if ($pathOption) {
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace Oneofftech\LaravelLanguageRecognizer\Drivers;
4+
5+
use Exception;
6+
use Illuminate\Support\Facades\Http;
7+
use InvalidArgumentException;
8+
use Oneofftech\LaravelLanguageRecognizer\Contracts\LanguageRecognizer;
9+
10+
class DeeplLanguageRecognizerDriver implements LanguageRecognizer
11+
{
12+
protected string $host;
13+
14+
protected string $token;
15+
16+
public function __construct($config)
17+
{
18+
if (empty($config['host'] ?? null)) {
19+
throw new InvalidArgumentException("Invalid host");
20+
}
21+
22+
if (empty($config['key'] ?? null)) {
23+
throw new InvalidArgumentException("Invalid authentication key");
24+
}
25+
26+
if (empty(trim($config['host']))) {
27+
throw new InvalidArgumentException("Invalid host");
28+
}
29+
30+
if (empty(trim($config['key']))) {
31+
throw new InvalidArgumentException("Invalid authentication key");
32+
}
33+
34+
$this->host = rtrim($config['host'], '/');
35+
$this->token = $config['key'];
36+
}
37+
38+
/**
39+
* @inherit
40+
*/
41+
public function recognize($text, $limit = 2): array
42+
{
43+
$response = Http::acceptJson()
44+
->asForm()
45+
->withToken($this->token, 'DeepL-Auth-Key')
46+
->post("{$this->host}/v2/translate", [
47+
'text' => $text,
48+
'target_lang' => 'EN-US',
49+
])
50+
->throw();
51+
52+
$json = $response->json();
53+
54+
$detectedLanguage = $json['translations'][0]['detected_source_language'] ?? null;
55+
56+
if (is_null($detectedLanguage)) {
57+
throw new Exception('Failed to obtain detected language from DeepL API');
58+
}
59+
60+
if (in_array($detectedLanguage, ['EN-US', 'EN-GB'])) {
61+
$detectedLanguage = 'EN';
62+
}
63+
64+
return [
65+
$detectedLanguage => 1.0,
66+
];
67+
}
68+
}

src/LaravelLanguageRecognizer.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Oneofftech\LaravelLanguageRecognizer;
44

55
use Illuminate\Support\Manager;
6+
use Oneofftech\LaravelLanguageRecognizer\Drivers\DeeplLanguageRecognizerDriver;
67
use Oneofftech\LaravelLanguageRecognizer\Drivers\LocalLanguageRecognizerDriver;
78

89
/**
@@ -36,6 +37,16 @@ protected function createLocalDriver()
3637
return new LocalLanguageRecognizerDriver($this->container['config']['language-recognizer.drivers.local']);
3738
}
3839

40+
/**
41+
* @return \Oneofftech\LaravelLanguageRecognizer\Drivers\DeeplLanguageRecognizerDriver
42+
*
43+
* @psalm-suppress UndefinedInterfaceMethod
44+
*/
45+
protected function createDeeplDriver()
46+
{
47+
return new DeeplLanguageRecognizerDriver($this->container['config']['language-recognizer.drivers.deepl']);
48+
}
49+
3950
/**
4051
* Get the default driver name.
4152
*
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace Oneofftech\LaravelLanguageRecognizer\Tests\Unit;
4+
5+
use Illuminate\Http\Client\Request;
6+
use Illuminate\Support\Facades\Http;
7+
use InvalidArgumentException;
8+
use Oneofftech\LaravelLanguageRecognizer\Drivers\DeeplLanguageRecognizerDriver;
9+
use Oneofftech\LaravelLanguageRecognizer\Tests\Integration\TestCase;
10+
11+
class DeeplLanguageRecognizerTest extends TestCase
12+
{
13+
/** @test */
14+
public function throws_if_host_empty()
15+
{
16+
$this->expectException(InvalidArgumentException::class);
17+
18+
new DeeplLanguageRecognizerDriver([
19+
'host' => ' ',
20+
'key' => 'a-value',
21+
]);
22+
}
23+
24+
/** @test */
25+
public function throws_if_key_empty()
26+
{
27+
$this->expectException(InvalidArgumentException::class);
28+
29+
new DeeplLanguageRecognizerDriver([
30+
'key' => ' ',
31+
'host' => 'https://a-domain',
32+
]);
33+
}
34+
35+
/** @test */
36+
public function it_can_recognize_a_string()
37+
{
38+
Http::preventStrayRequests();
39+
40+
Http::fake([
41+
'https://api-free.deepl.com/*' => Http::response('{"translations": [{"detected_source_language": "EN","text": "This should be an english string"}]}', 200),
42+
]);
43+
44+
45+
$driver = new DeeplLanguageRecognizerDriver([
46+
'key' => 'a-value',
47+
'host' => 'https://api-free.deepl.com',
48+
]);
49+
50+
$languages = $driver->recognize('This should be an english string');
51+
52+
$this->assertEquals([
53+
"EN" => 1.0,
54+
], $languages);
55+
56+
Http::assertSent(function (Request $request) {
57+
return $request->url() == 'https://api-free.deepl.com/v2/translate' &&
58+
$request['text'] == 'This should be an english string' &&
59+
$request['target_lang'] === 'EN-US';
60+
});
61+
}
62+
}

tests/Integration/LaravelLanguageRecognizerFacadeTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Oneofftech\LaravelLanguageRecognizer\Tests\Integration;
44

5+
use Oneofftech\LaravelLanguageRecognizer\Drivers\DeeplLanguageRecognizerDriver;
56
use Oneofftech\LaravelLanguageRecognizer\Drivers\LocalLanguageRecognizerDriver;
67
use Oneofftech\LaravelLanguageRecognizer\Support\Facades\LanguageRecognizer;
78

@@ -18,6 +19,18 @@ public function default_local_driver_can_be_obtained()
1819
$this->assertInstanceOf(LocalLanguageRecognizerDriver::class, $service);
1920
}
2021

22+
/** @test */
23+
public function deepl_driver_can_be_obtained()
24+
{
25+
$this->app['config']->set('language-recognizer.default', 'deepl');
26+
$this->app['config']->set('language-recognizer.drivers.deepl.host', 'https://api-free.deepl.com');
27+
$this->app['config']->set('language-recognizer.drivers.deepl.key', 'a-key');
28+
29+
$service = LanguageRecognizer::driver('deepl');
30+
31+
$this->assertInstanceOf(DeeplLanguageRecognizerDriver::class, $service);
32+
}
33+
2134
/** @test */
2235
public function recognition_can_be_done_from_facade()
2336
{

0 commit comments

Comments
 (0)