deeplcom/deepl-php
Official PHP client for the DeepL API. Translate text and documents with simple methods like translateText(), using your DeepL authentication key. Composer install, supports PHP 7.3+ with ongoing updates as the API evolves.
Installation:
composer require deeplcom/deepl-php
Ensure PHP ≥8.1 (recommended) or ≥7.3.
Authentication:
.env):
DEEPL_API_KEY=f63c02c5-f056-...
First Translation:
use DeepL\DeepLClient;
$client = new DeepLClient(config('services.deepl.key'));
$result = $client->translateText('Hello, world!', null, 'fr');
echo $result->text; // "Bonjour, le monde !"
Configuration: Initialize the client with options (e.g., timeout, proxy):
$client = new DeepLClient(
$authKey,
['timeout' => 30, 'proxy' => 'http://proxy.example.com']
);
$results = $client->translateText(
['Text 1', 'Text 2'],
null, // Auto-detect source
'es'
);
$result = $client->translateText(
'The "user" clicked the button.',
null,
'de',
['context' => 'User interface terminology']
);
uploadDocument() + pollDocumentStatus() + downloadDocument() for granular control:
$handle = $client->uploadDocument('input.docx', 'en');
$client->pollDocumentStatus($handle->documentId);
$client->downloadDocument($handle->documentId, 'output.docx');
$result = $client->rephraseText(
'This is a draft.',
'en-US',
['writing_style' => 'business']
);
Laravel Service Provider: Bind the client to the container for dependency injection:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(DeepLClient::class, function ($app) {
return new DeepLClient(config('services.deepl.key'));
});
}
Queueable Jobs: Offload document translations to queues (avoid timeouts):
// app/Jobs/TranslateDocumentJob.php
public function handle()
{
$client = app(DeepLClient::class);
$client->translateDocument('input.docx', 'output.docx', 'en', 'fr');
}
Caching Responses: Cache translated text/document results (e.g., Redis) to avoid API calls for repeated requests:
$cacheKey = "deepl:translate:{$sourceLang}:{$targetLang}:{$text}";
$translation = cache()->remember($cacheKey, now()->addHours(1), function () use ($client, $text, $sourceLang, $targetLang) {
return $client->translateText($text, $sourceLang, $targetLang)->text;
});
Error Handling: Centralize exception handling (e.g., retry logic for rate limits):
try {
$result = $client->translateText($text, $source, $target);
} catch (\DeepL\DeepLException $e) {
if ($e->getCode() === 429) {
sleep(1); // Retry after rate limit
return $this->handle($request);
}
throw $e;
}
API Key Exposure:
.env or hardcoded keys to version control.env() helper or a dedicated config file:
config('services.deepl.key');
Character Billing:
billedCharacters in TextResult to estimate costs:
$chars = $result->billedCharacters; // e.g., 12 for "¿Cómo estás?"
Document Size Limits:
minification for PPTX:
$client->translateDocument(
'large.pptx', 'output.pptx',
'en', 'de',
['minification' => true]
);
Rate Limits:
429 Too Many Requests with exponential backoff.Language Pair Availability:
formality/custom_instructions. Test with:
$client->getUsage(); // Check available features
XML/HTML Tag Handling:
tag_handling: 'xml' requires valid XML. Use outline_detection: false for malformed markup:
$options = [
'tag_handling' => 'xml',
'outline_detection' => false,
];
Enable Logging: Configure the client to log API requests/responses:
$client = new DeepLClient($authKey, [
'logger' => new \Monolog\Logger('deepl'),
'logger_level' => \Monolog\Logger::DEBUG,
]);
Inspect Raw Responses:
Access the underlying Guzzle client for debugging:
$response = $client->getHttpClient()->getLastResponse();
$body = json_decode($response->getBody(), true);
Common Errors:
401 Unauthorized: Invalid API key.400 Bad Request: Invalid language codes (e.g., 'sp' instead of 'es').413 Payload Too Large: File exceeds 30MB. Use minification or split into chunks.Custom Middleware: Add request/response filters:
$client->getHttpClient()->getEmitter()->attach(
\GuzzleHttp\Middleware::tap(function ($request) {
// Modify request (e.g., add headers)
$request = $request->withHeader('X-Custom-Header', 'value');
return $request;
})
);
Model-Specific Logic:
Override default model selection (e.g., force latency_optimized):
$options = [
'model_type' => 'latency_optimized',
];
$client->translateText($text, $source, $target, $options);
Glossary Integration: Pre-load glossaries and reuse IDs:
$glossaryId = $client->createGlossary('my_glossary', ['term' => 'translation']);
$client->translateText($text, null, 'fr', ['glossary' => $glossaryId]);
Style Rules: Create reusable style rules via the API and reference them:
$styleId = $client->createStyleRule('business_style', ['formality' => 'more']);
$client->translateText($text, null, 'de', ['style_id' => $styleId]);
Batch Processing:
$client->translateText(['text1', 'text2'], null, 'fr');
Async Document Handling:
pollDocumentStatus() in a loop with delays:
while ($status = $client->pollDocumentStatus($docId)->status !== 'done') {
sleep(2); // Poll every 2 seconds
}
Memory Management:
$client->uploadDocument('large.docx', 'en', null, null, null, true); // Stream
How can I help you explore Laravel packages today?