Skip to content

Commit c85bfe2

Browse files
authored
Move API key in request header and change body to json format (#89) (#90)
- also add examples for live testing and development scenarios
1 parent a90d66f commit c85bfe2

37 files changed

+820
-875
lines changed

example/retrieve_usage.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
require_once __DIR__ . '/../vendor/autoload.php';
6+
7+
use Scn\DeeplApiConnector\DeeplClientFactory;
8+
9+
$apiKey = 'your-api-key';
10+
11+
$usage = DeeplClientFactory::create($apiKey)
12+
->getUsage();
13+
14+
var_dump($usage);

example/translate_file.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
require_once __DIR__ . '/../vendor/autoload.php';
6+
7+
use Scn\DeeplApiConnector\DeeplClientFactory;
8+
use Scn\DeeplApiConnector\Model\FileSubmissionInterface;
9+
use Scn\DeeplApiConnector\Model\FileTranslationConfig;
10+
11+
$apiKey = 'your-api-key';
12+
13+
$deepl = DeeplClientFactory::create($apiKey);
14+
15+
$fileTranslationConfig = new FileTranslationConfig(
16+
'Das ist ein Test',
17+
'testfile.txt',
18+
'EN',
19+
'DE',
20+
);
21+
/**
22+
* 1. We request a new translation with an FileTranslationConfig
23+
*/
24+
/** @var FileSubmissionInterface $fileSubmission */
25+
$fileSubmission = $deepl->translateFile($fileTranslationConfig);
26+
27+
/**
28+
* Result look like a FileSubmission instance
29+
*
30+
* class Scn\DeeplApiConnector\Model\FileSubmission#22 (2) {
31+
* private string $documentId => "<DOCUMENT_ID>"
32+
* private string $documentKey => "<DOCUMENT_KEY>"
33+
* }
34+
*/
35+
var_dump($fileSubmission);
36+
37+
/**
38+
* We can simulate this by using our own instance with valid values:
39+
* $fileSubmission = (new FileSubmission())
40+
* ->setDocumentId('<DOCUMENT_ID>')
41+
* ->setDocumentKey('<DOCUMENT_KEY>');
42+
*/
43+
44+
45+
/** 2. We request in a queue logic the translation status with the Submission instance **/
46+
sleep(15);
47+
$translationStatus = $deepl->getFileTranslationStatus($fileSubmission);
48+
49+
/**
50+
* Result look like a FileTranslationStatus instance
51+
*
52+
* if the 'status' property value is 'done' we can get the fileTranslation
53+
*
54+
* class Scn\DeeplApiConnector\Model\FileTranslationStatus#43 (4) {
55+
* private string $documentId => "<DOCUMENT_ID>"
56+
* private string $status => "translating"
57+
* .....
58+
* }
59+
*/
60+
var_dump($translationStatus);
61+
62+
63+
/** 3. We request in a queue logic the translation status with the Submission instance **/
64+
$response = $deepl->getFileTranslation($fileSubmission);
65+
66+
/**
67+
* Result look like a FileTranslation instance
68+
*
69+
* class Scn\DeeplApiConnector\Model\FileTranslation#26 (1) {
70+
* private string $content => "This is a test"
71+
* }
72+
*/
73+
var_dump($response);

src/DeeplClient.php

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,30 @@
3333

3434
class DeeplClient implements DeeplClientInterface
3535
{
36+
private const DEEPL_PAID_BASE_URI = 'https://api.deepl.com';
37+
private const DEEPL_FREE_BASE_URI = 'https://api-free.deepl.com';
38+
39+
private string $apiKey;
3640
private DeeplRequestFactoryInterface $deeplRequestFactory;
3741

3842
private ClientInterface $httpClient;
3943

4044
private RequestFactoryInterface $requestFactory;
4145

4246
public function __construct(
47+
string $apiKey,
4348
DeeplRequestFactoryInterface $deeplRequestFactory,
4449
ClientInterface $httpClient,
45-
RequestFactoryInterface $requestFactory
50+
RequestFactoryInterface $requestFactory,
4651
) {
52+
$this->apiKey = $apiKey;
4753
$this->deeplRequestFactory = $deeplRequestFactory;
4854
$this->httpClient = $httpClient;
4955
$this->requestFactory = $requestFactory;
5056
}
5157

5258
/**
53-
* Return Usage of API- Key
59+
* Return Usage of API-Key
5460
* Possible Return:.
5561
*
5662
* Usage
@@ -62,7 +68,7 @@ public function __construct(
6268
public function getUsage(): ResponseModelInterface
6369
{
6470
return (new Usage())->hydrate(
65-
$this->executeRequest($this->deeplRequestFactory->createDeeplUsageRequestHandler())
71+
$this->executeRequest($this->deeplRequestFactory->createDeeplUsageRequestHandler()),
6672
);
6773
}
6874

@@ -79,7 +85,7 @@ public function getUsage(): ResponseModelInterface
7985
public function getTranslation(TranslationConfigInterface $translation): ResponseModelInterface
8086
{
8187
return (new Translation())->hydrate($this->executeRequest(
82-
$this->deeplRequestFactory->createDeeplTranslationRequestHandler($translation)
88+
$this->deeplRequestFactory->createDeeplTranslationRequestHandler($translation),
8389
));
8490
}
8591

@@ -98,38 +104,38 @@ public function translate(string $text, string $target_language): ResponseModelI
98104
public function translateFile(FileTranslationConfigInterface $fileTranslation): ResponseModelInterface
99105
{
100106
return (new FileSubmission())->hydrate($this->executeRequest(
101-
$this->deeplRequestFactory->createDeeplFileSubmissionRequestHandler($fileTranslation)
107+
$this->deeplRequestFactory->createDeeplFileSubmissionRequestHandler($fileTranslation),
102108
));
103109
}
104110

105111
public function translateBatch(array $text, string $targetLanguage): ResponseModelInterface
106112
{
107113
return (new BatchTranslation())->hydrate($this->executeRequest(
108114
$this->deeplRequestFactory->createDeeplBatchTranslationRequestHandler(
109-
new BatchTranslationConfig($text, $targetLanguage)
115+
new BatchTranslationConfig($text, $targetLanguage),
110116
)
111117
));
112118
}
113119

114120
public function getFileTranslationStatus(FileSubmissionInterface $fileSubmission): ResponseModelInterface
115121
{
116122
return (new FileTranslationStatus())->hydrate($this->executeRequest(
117-
$this->deeplRequestFactory->createDeeplFileTranslationStatusRequestHandler($fileSubmission)
123+
$this->deeplRequestFactory->createDeeplFileTranslationStatusRequestHandler($fileSubmission),
118124
));
119125
}
120126

121127
public function getFileTranslation(FileSubmissionInterface $fileSubmission): ResponseModelInterface
122128
{
123129
return (new FileTranslation())->hydrate($this->executeRequest(
124-
$this->deeplRequestFactory->createDeeplFileTranslationRequestHandler($fileSubmission)
130+
$this->deeplRequestFactory->createDeeplFileTranslationRequestHandler($fileSubmission),
125131
));
126132
}
127133

128134
public function getSupportedLanguages(): ResponseModelInterface
129135
{
130136
return (new SupportedLanguages())->hydrate(
131137
$this->executeRequest(
132-
$this->deeplRequestFactory->createDeeplSupportedLanguageRetrievalRequestHandler()
138+
$this->deeplRequestFactory->createDeeplSupportedLanguageRetrievalRequestHandler(),
133139
)
134140
);
135141
}
@@ -138,7 +144,7 @@ public function getGlossariesSupportedLanguagesPairs(): ResponseModelInterface
138144
{
139145
return (new GlossariesSupportedLanguagesPairs())->hydrate(
140146
$this->executeRequest(
141-
$this->deeplRequestFactory->createDeeplGlossariesSupportedLanguagesPairsRetrievalRequestHandler()
147+
$this->deeplRequestFactory->createDeeplGlossariesSupportedLanguagesPairsRetrievalRequestHandler(),
142148
)
143149
);
144150
}
@@ -147,7 +153,7 @@ public function getGlossariesList(): ResponseModelInterface
147153
{
148154
return (new Glossaries())->hydrate(
149155
$this->executeRequest(
150-
$this->deeplRequestFactory->createDeeplGlossariesListRetrievalRequestHandler()
156+
$this->deeplRequestFactory->createDeeplGlossariesListRetrievalRequestHandler(),
151157
)
152158
);
153159
}
@@ -194,20 +200,23 @@ private function executeRequest(DeeplRequestHandlerInterface $requestHandler): s
194200
$request = $this->requestFactory
195201
->createRequest(
196202
$requestHandler->getMethod(),
197-
sprintf('%s%s', $this->deeplRequestFactory->getDeeplBaseUri(), $requestHandler->getPath())
203+
sprintf('%s%s', $this->getDeeplBaseUri(), $requestHandler->getPath()),
204+
)
205+
->withHeader(
206+
'Authorization',
207+
$this->getAuthHeader(),
198208
)
199209
->withHeader(
200210
'Content-Type',
201-
$requestHandler->getContentType()
211+
$requestHandler->getContentType(),
202212
)
203-
->withBody($requestHandler->getBody());
204-
205-
if ($requestHandler->getAuthHeader() !== null) {
206-
$request = $request->withHeader('Authorization', $requestHandler->getAuthHeader());
207-
}
213+
->withBody(
214+
$requestHandler->getBody(),
215+
);
208216

209-
if ($requestHandler->getAcceptHeader() !== null) {
210-
$request = $request->withHeader('Accept', $requestHandler->getAcceptHeader());
217+
$acceptHeader = $requestHandler->getAcceptHeader();
218+
if ($acceptHeader !== null) {
219+
$request = $request->withHeader('Accept', $acceptHeader);
211220
}
212221

213222
try {
@@ -216,7 +225,7 @@ private function executeRequest(DeeplRequestHandlerInterface $requestHandler): s
216225
throw new RequestException(
217226
$exception->getMessage(),
218227
$exception->getCode(),
219-
$exception
228+
$exception,
220229
);
221230
}
222231

@@ -253,4 +262,18 @@ private function executeRequest(DeeplRequestHandlerInterface $requestHandler): s
253262
/** @var stdClass $result */
254263
return $result;
255264
}
265+
266+
private function getAuthHeader(): string
267+
{
268+
return sprintf('DeepL-Auth-Key %s', $this->apiKey);
269+
}
270+
271+
private function getDeeplBaseUri(): string
272+
{
273+
if (str_contains($this->apiKey, ':fx')) {
274+
return self::DEEPL_FREE_BASE_URI;
275+
}
276+
277+
return self::DEEPL_PAID_BASE_URI;
278+
}
256279
}

src/DeeplClientFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public static function create(
2323
StreamFactoryInterface $streamFactory = null
2424
): DeeplClientInterface {
2525
return new DeeplClient(
26+
$authKey,
2627
new DeeplRequestFactory(
27-
$authKey,
2828
$streamFactory ?? Psr17FactoryDiscovery::findStreamFactory()
2929
),
3030
$httpClient ?? Psr18ClientDiscovery::find(),

src/Handler/AbstractDeeplHandler.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66

77
abstract class AbstractDeeplHandler implements DeeplRequestHandlerInterface
88
{
9-
public function getAuthHeader(): ?string
9+
public function getAcceptHeader(): ?string
1010
{
1111
return null;
1212
}
1313

14-
public function getAcceptHeader(): ?string
14+
public function getContentType(): string
1515
{
16-
return null;
16+
return 'application/json';
1717
}
1818
}

src/Handler/DeeplBatchTranslationRequestHandler.php

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,14 @@ final class DeeplBatchTranslationRequestHandler extends AbstractDeeplHandler
1616
private const SEPARATOR = ',';
1717
public const API_ENDPOINT = '/v2/translate';
1818

19-
private string $authKey;
20-
2119
private StreamFactoryInterface $streamFactory;
2220

2321
private BatchTranslationConfigInterface $translation;
2422

2523
public function __construct(
26-
string $authKey,
2724
StreamFactoryInterface $streamFactory,
28-
BatchTranslationConfigInterface $translation
25+
BatchTranslationConfigInterface $translation,
2926
) {
30-
$this->authKey = $authKey;
3127
$this->streamFactory = $streamFactory;
3228
$this->translation = $translation;
3329
}
@@ -44,37 +40,28 @@ public function getPath(): string
4440

4541
public function getBody(): StreamInterface
4642
{
47-
$query = http_build_query(
48-
array_filter(
49-
[
50-
'target_lang' => $this->translation->getTargetLang(),
51-
'tag_handling' => implode(
52-
self::SEPARATOR,
53-
$this->translation->getTagHandling()
54-
),
55-
'non_splitting_tags' => implode(
56-
self::SEPARATOR,
57-
$this->translation->getNonSplittingTags()
58-
),
59-
'ignore_tags' => implode(self::SEPARATOR, $this->translation->getIgnoreTags()),
60-
'split_sentences' => $this->translation->getSplitSentences(),
61-
'preserve_formatting' => $this->translation->getPreserveFormatting(),
62-
'glossary_id' => $this->translation->getGlossaryId(),
63-
'auth_key' => $this->authKey,
64-
]
65-
)
66-
);
43+
$body = array_filter([
44+
'target_lang' => $this->translation->getTargetLang(),
45+
'tag_handling' => implode(
46+
self::SEPARATOR,
47+
$this->translation->getTagHandling(),
48+
),
49+
'non_splitting_tags' => implode(
50+
self::SEPARATOR,
51+
$this->translation->getNonSplittingTags(),
52+
),
53+
'ignore_tags' => implode(self::SEPARATOR, $this->translation->getIgnoreTags()),
54+
'split_sentences' => $this->translation->getSplitSentences(),
55+
'preserve_formatting' => $this->translation->getPreserveFormatting(),
56+
'glossary_id' => $this->translation->getGlossaryId(),
57+
'text' => [],
58+
]);
6759

6860
// add the text parameters separately as http_build_query would create `text[]` params
6961
foreach ($this->translation->getText() as $text) {
70-
$query .= '&text=' . $text;
62+
$body['text'][] = $text;
7163
}
7264

73-
return $this->streamFactory->createStream($query);
74-
}
75-
76-
public function getContentType(): string
77-
{
78-
return 'application/x-www-form-urlencoded';
65+
return $this->streamFactory->createStream(json_encode($body, JSON_THROW_ON_ERROR));
7966
}
8067
}

0 commit comments

Comments
 (0)