- Introduction
- Requirements
- Installation
- Usage
- Translating Localization Files
- On-the-Fly Translation Setup
- Helpers
- Additional Resources
- Testing
- Linting
- Changelog
- Contributing
- Security
- License
- Support the Developer
- About the Developer
Laravel Deepl is a Laravel package that serves as a wrapper for the official DeepL PHP client, enhancing it with additional features such as caching and chainable translation methods. This package leverages the robustness of the official client while providing a more Laravel-centric interface. For comprehensive details about the DeepL API, including available endpoints and parameters, please refer to the DeepL API Documentation.
Before installing and using this package, please ensure your environment meets the following minimum requirements:
- PHP 8.2 or higher
- Laravel 11.0 or higher
- GuzzleHTTP 7.0 or higher
These versions are required to ensure compatibility with the package and the features it provides. Make sure your project is running on these versions or higher before integrating this package.
You can install the package via Composer:
composer require pavelzanek/laravel-deeplTo publish the configuration file, run:
php artisan vendor:publish --tag=laravel-deepl-configThis will create a config/laravel-deepl.php file where you can set your DeepL API key and other configuration options.
The package includes a migration that creates the translations table used for caching translations (more info: Text Translation). To publish the migration files, run:
php artisan vendor:publish --tag=laravel-deepl-migrationsThis command will copy the migration files to your application’s database/migrations directory.
After publishing the migrations, you need to run them to create the necessary database tables:
php artisan migrateThis will execute the migration and create the translations table in your database, enabling the caching feature.
Add your DeepL API key to your .env file:
DEEPL_API_KEY=your-deepl-api-keyOther environment variables you might want to set:
DEEPL_DEFAULT_SOURCE_LANG=en
DEEPL_DEFAULT_TARGET_LANG=cs
DEEPL_RETRY_ON_FAILURES=3
DEEPL_TIMEOUT=30
DEEPL_ENABLE_TRANSLATION_CACHE=true
DEEPL_TRANSLATION_CACHE_TABLE=your_custom_table_name
DEEPL_ENABLE_ON_THE_FLY_TRANSLATION=true
DEEPL_ON_THE_FLY_OUTSIDE_LOCAL=false
DEEPL_ON_THE_FLY_SOURCE_LANG=en
DEEPL_ON_THE_FLY_USE_QUEUE_FOR_TRANSLATION=trueThe package offers two primary ways to interact with the DeepL API: using the Facade or directly using the DeeplClient class. Additionally, the translateText method now supports method chaining, allowing for more flexible and readable translation requests.
Using the Facade:
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedText = Deepl::translateText('Hello, world!', 'en', 'de');
echo $translatedText; // Outputs: Hallo, Welt!Using the DeeplClient:
use PavelZanek\LaravelDeepl\DeeplClient;
$client = app(DeeplClient::class);
$translatedText = $client->translateText('Hello, world!', 'en', 'de');
echo $translatedText; // Outputs: Hallo, Welt!Note: The result is returned as an object from the official DeepL API PHP package. For more details on the response structure, refer to the official documentation.
You can easily translate text using the provided client:
Example Using the Facade:
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedText = Deepl::translateText('Hello, world!', 'en', 'de');
echo $translatedText; // Outputs: Hallo, Welt!Example Using the DeeplClient:
Basic Usage Example of DeeplClient for Translating Text:
use PavelZanek\LaravelDeepl\DeeplClient;
$client = app(DeeplClient::class);
$translatedText = $client->translateText('Hello, world!', 'en', 'de');
echo $translatedText; // Outputs: Hallo, Welt!Integrating DeeplClient into a Laravel Controller for example:
<?php
namespace App\Http\Controllers;
use PavelZanek\LaravelDeepl\DeeplClient;
class TestController extends Controller
{
public function __construct(
protected readonly DeeplClient $deeplClient
) {}
public function translateText(): void
{
$translation = $this->deeplClient->translateText(
texts: 'Ahoj, jak se máš?',
sourceLang: 'cs',
targetLang: 'en-gb'
);
dd($translation);
// DeepL\TextResult {
// +text: "Hey, how are you?"
// +detectedSourceLang: "cs"
// +billedCharacters: 17
// }
$translation = $this->deeplClient->translateText(
texts: ['Ahoj, jak se máš?', 'Mám se dobře, jak se máš ty?'],
sourceLang: 'cs',
targetLang: 'en-gb'
);
dd($translation);
// array [
// 0 => DeepL\TextResult {
// +text: "Hey, how are you?"
// +detectedSourceLang: "cs"
// +billedCharacters: 17
// }
// 1 => DeepL\TextResult {
// +text: "I'm fine, how are you?"
// +detectedSourceLang: "cs"
// +billedCharacters: 28
// }
// ]
}
}When utilizing the chainable methods provided by the translateText function, do not pass the text as an argument. Instead, call translateText without any parameters to receive a builder instance that allows method chaining. Passing the text directly will bypass the builder and prevent the use of chainable methods.
The translateText method supports method chaining, allowing you to set additional options and parameters in a more readable and concise way:
Example Using the Facade:
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedText = Deepl::translateText()
->text('Hello, world!')
->sourceLang('en')
->targetLang('de')
->formality('less')
->preserveFormatting('enabled')
->splitSentences('1')
->glossary('example-glossary-id')
->withoutCache()
->translate();
echo $translatedText; // Outputs: Hallo, Welt!Example Using the DeeplClient:
use PavelZanek\LaravelDeepl\DeeplClient;
$client = app(DeeplClient::class);
$translatedText = $client->translateText()
->text('Hello, world!')
->sourceLang('en')
->targetLang('de')
->formality('less')
->preserveFormatting('enabled')
->splitSentences('1')
->glossary('example-glossary-id')
->withoutCache()
->translate();
echo $translatedText; // Outputs: Hallo, Welt!Available Chainable Methods
The translateText method returns a builder instance that allows you to chain the following methods:
text(string|array $texts): Sets the text(s) to translate.sourceLang(string $sourceLang): Sets the source language code.targetLang(string $targetLang): Sets the target language code.formality(string $formality): Sets the formality level of the translation.preserveFormatting(string $preserveFormatting): Controls whether to preserve the original formatting.splitSentences(string|bool $split): Configures how sentences should be split during translation.glossary(string $glossaryId): Sets the glossary ID to use for the translation.withoutCache(): Disables the use of the translation cache for this request.translate(): Executes the translation and returns the result.
The translateText method accepts an optional options array as its fourth argument, allowing you to specify additional translation settings. Alternatively, you can use chainable methods to set these options.
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedText = Deepl::translateText(
'Hello, world!',
'en',
'de',
[
'formality' => 'less',
'preserve_formatting' => 'enabled',
'split_sentences' => '1',
'glossary_id' => 'example-glossary-id',
],
)->translate();
echo $translatedText; // Outputs: Hallo, Welt!Using Chainable Methods
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedText = Deepl::translateText()
->text('Hello, world!')
->sourceLang('en')
->targetLang('de')
->options([
'formality' => 'less',
'preserve_formatting' => 'enabled',
'split_sentences' => '1',
'glossary_id' => 'example-glossary-id',
])
->translate();
echo $translatedText; // Outputs: Hallo, Welt!The package includes a caching mechanism that stores translations in the database to optimize performance and reduce the number of API calls to DeepL. This can be especially useful when translating the same text multiple times or when working with large volumes of text.
Before you can use the caching feature, you need to publish and run the migration that creates the translations table in your database:
php artisan vendor:publish --tag=laravel-deepl-migrations
php artisan migrateThis will create the necessary table where translations will be stored.
When you request a translation, the package checks if the translation already exists in the database before making an API call to DeepL. This is controlled by the useCache property.
- If the translation exists in the cache: The cached translation is returned, avoiding an API call.
- If the translation does not exist in the cache: An API call is made to DeepL, and the translation result is stored in the database for future requests.
Customizing Cache Behavior
The caching mechanism uses the TranslationCache model to store the translated texts. The cache table name can be customized via the DEEPL_TRANSLATION_CACHE_TABLE environment variable. By default, it is set to translations_cache.
DEEPL_ENABLE_TRANSLATION_CACHE=true
DEEPL_TRANSLATION_CACHE_TABLE=your_custom_table_nameThis option can also be set directly in the configuration file:
// config/laravel-deepl.php
return [
// ...
'enable_translation_cache' => env('DEEPL_ENABLE_TRANSLATION_CACHE', false),
'translation_cache_table' => env('DEEPL_TRANSLATION_CACHE_TABLE', 'translations_cache'),
// ...
];Disabling this option means that every translation request will result in an API call to DeepL, which could increase your API usage costs.
Benefits of Caching
- Performance: Reduces the load on the DeepL API by reusing translations.
- Cost Savings: Helps to minimize the number of API calls, reducing potential costs.
- Flexibility: Easily bypass or disable the cache when needed for fresh translations.
The caching feature is a powerful tool for optimizing your application’s localization workflow, ensuring that translations are both fast and cost-effective.
The translation cache is sensitive to the options used in the translation request. Any change in the options (such as formality, splitSentences, preserveFormatting, etc.) will lead to a different cache entry. Ensure that you consider this when working with translations that require specific options, as the cache will reflect these variations.
$translatedText = $client->translateText()
->text('Hello, world!')
->sourceLang('en')
->targetLang('de')
->translate();
$translatedText = $client->translateText()
->text('Hello, world!')
->sourceLang('en')
->targetLang('de')
->formality('less')
->translate();In the first case, the translation is performed with default settings. In the second case, the translation includes the formality option set to less. Even though both translations are for the same text and languages, they will produce different results and therefore be cached separately.
use PavelZanek\LaravelDeepl\DeeplClient;
$client = new DeeplClient();
$translatedText = $client->translateText()
->text('Hello, world!')
->sourceLang('en')
->targetLang('de')
->translate();
echo $translatedText; // Outputs: Hallo, Welt! (from cache or API)In this example, the translation of “Hello, world!” from English to German is either retrieved from the cache or, if not cached, obtained from DeepL and then stored in the cache for future use.
If you need to bypass the cache and always make a fresh API call, you can use the withoutCache method:
Using the useCache Parameter:
The translateText method includes a fifth parameter, useCache, which determines whether to utilize the translation caching mechanism. This parameter is optional and defaults to the value specified in your configuration (config('laravel-deepl.enable_translation_cache')).
- Type:
?bool(nullable boolean) - Default:
null(which means it will fallback to the configuration setting)
Using the useCache Parameter Directly:
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedText = Deepl::translateText(
'Hello, world!',
'en',
'de',
[], // No additional options
false // Disables cache usage for this request
)->translate();
// or if u prefer named parameters
$translatedText = Deepl::translateText(
text: 'Hello, world!',
sourceLang: 'en',
targetLang: 'de',
useCache: false // Disables cache usage for this request
)->translate();
echo $translatedText; // Always fetches from APIUsing Chainable Methods:
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedText = Deepl::translateText()
->text('Hello, world!')
->sourceLang('en')
->targetLang('de')
->withoutCache() // Disables cache usage for this request
->translate();
echo $translatedText; // Always fetches from APIThe TranslationBuilder provides two methods for setting the text to translate:
text(string $text): Sets a single text string for translation.texts(array|string $texts): Sets multiple text strings for translation.
Example Using text() for a Single Text:
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedText = Deepl::translateText()
->text('Hello, world!')
->sourceLang('en')
->targetLang('de')
->translate();
echo $translatedText; // Outputs: Hallo, Welt!Example Using texts() for Multiple Texts:
use PavelZanek\LaravelDeepl\Facades\Deepl;
$translatedTexts = Deepl::translateText()
->texts(['Hello, world!', 'Good morning!'])
->sourceLang('en')
->targetLang('de')
->translate();
foreach ($translatedTexts as $translatedText) {
echo $translatedText->text . "\n"; // Outputs: Hallo, Welt! and Guten Morgen!
}By utilizing the text() and texts() methods appropriately, you can efficiently handle both single and multiple translation requests within your application.
You can also translate documents using the provided client or facade.
Example Using the Facade:
use PavelZanek\LaravelDeepl\Facades\Deepl;
// Upload the document for translation
$uploadResponse = Deepl::uploadDocument('path/to/document.pdf', 'de');
// Check the status of the translation
$status = Deepl::getDocumentStatus($uploadResponse['document_id'], $uploadResponse['document_key']);
if ($status->status === \PavelZanek\LaravelDeepl\Enums\V2\DocumentStatus::DONE->value) {
// Download the translated document
$translatedDocument = Deepl::downloadDocument($uploadResponse['document_id'], $uploadResponse['document_key']);
file_put_contents('path/to/translated-document.pdf', $translatedDocument);
}Example Using the DeeplClient:
use PavelZanek\LaravelDeepl\DeeplClient;
$client = app(DeeplClient::class);
// Upload the document for translation
$uploadResponse = $client->uploadDocument('path/to/document.pdf', 'de');
// Check the status of the translation
$status = $client->getDocumentStatus($uploadResponse['document_id'], $uploadResponse['document_key']);
if ($status->status === \PavelZanek\LaravelDeepl\Enums\V2\DocumentStatus::DONE->value) {
// Download the translated document
$translatedDocument = $client->downloadDocument($uploadResponse['document_id'], $uploadResponse['document_key']);
file_put_contents('path/to/translated-document.pdf', $translatedDocument);
}With the introduction of the DocumentTranslationBuilder, you can now perform document translations using chainable methods, making your code more organized and readable. Do not pass the inputFile and outputFile directly as arguments when using chainable methods. Instead, use the builder to set these paths along with other optional parameters.
Example Using the Facade:
use PavelZanek\LaravelDeepl\Facades\Deepl;
// Perform a document translation with chainable methods
$status = Deepl::translateDocumentBuilder()
->inputFile('path/to/input.docx')
->outputFile('path/to/output.docx')
->sourceLang('en')
->targetLang('de')
->enableMinification()
->options([
'formality' => 'more',
// Add other options as needed
])
->translate();
echo $status->status; // Outputs: done, translating, etc.Example Using the DeeplClient:
use PavelZanek\LaravelDeepl\DeeplClient;
$client = app(DeeplClient::class);
// Perform a document translation with chainable methods
$status = $client->translateDocumentBuilder()
->inputFile('path/to/input.pdf')
->outputFile('path/to/output.pdf')
->sourceLang('en')
->targetLang('fr')
->translate();
echo $status->status; // Outputs: done, translating, etc.Available Chainable Methods for Document Translation:
The DocumentTranslationBuilder provides the following chainable methods:
inputFile(string $file): Sets the path to the input document.outputFile(string $file): Sets the path to save the translated document.sourceLang(string $lang): Sets the source language code.targetLang(string $lang): Sets the target language code.options(array $options): Adds additional options for the translation.enableMinification(bool $enable = true): Enables document minification.translate(): Executes the document translation and returns theDocumentStatus.
The underlying DeepL PHP API offers more advanced options for document translation, such as specifying translation formality, using glossaries, or enabling document minification for larger files (e.g., PowerPoint presentations with many images).
For example, you can use the translateDocument method to set formality or enable document minification:
$client->translateDocument(
'path/to/input.docx',
'path/to/output.docx',
'en',
'de',
[
'formality' => 'more',
\DeepL\TranslateDocumentOptions::ENABLE_DOCUMENT_MINIFICATION => true,
]
);Document minification helps to reduce the size of the document before translation by removing or compressing large media files, ensuring that the file meets the DeepL API size limits. For more details on supported file types, media formats, and additional options, please refer to the DeepL PHP API documentation.
You can create, retrieve, list, and delete glossaries using the provided client or facade. With the introduction of the CreateGlossaryBuilder, creating glossaries has become more flexible and streamlined through method chaining.
Example Using the Facade:
use PavelZanek\LaravelDeepl\Facades\Deepl;
// Create a glossary
$glossary = Deepl::createGlossary(
'My Glossary',
'en',
'de',
[
'hello' => 'hallo',
'world' => 'welt',
]
);
// Retrieve glossary details
$glossaryDetails = Deepl::getGlossary($glossary->glossaryId);
// Delete a glossary
Deepl::deleteGlossary($glossary->glossaryId);Example Using the DeeplClient:
use PavelZanek\LaravelDeepl\DeeplClient;
$client = app(DeeplClient::class);
// Create a glossary
$glossary = $client->createGlossary(
'My Glossary',
'en',
'de',
[
'hello' => 'hallo',
'world' => 'welt',
]
);
// Retrieve glossary details
$glossaryDetails = $client->getGlossary($glossary->glossaryId);
// Delete a glossary
$client->deleteGlossary($glossary->glossaryId);Example Using the Facade with CreateGlossaryBuilder:
use PavelZanek\LaravelDeepl\Facades\Deepl;
try {
$glossaryInfo = Deepl::createGlossaryBuilder()
->name('My Glossary')
->sourceLang('en')
->targetLang('de')
->addEntry('artist', 'Künstler')
->addEntry('prize', 'Preis')
->create();
echo "Created '{$glossaryInfo->name}' ({$glossaryInfo->glossaryId}) ";
echo "{$glossaryInfo->sourceLang} to {$glossaryInfo->targetLang} ";
echo "containing {$glossaryInfo->entryCount} entries\n";
} catch (\Exception $e) {
echo "Error creating glossary: " . $e->getMessage();
}Example Using the DeeplClient with CreateGlossaryBuilder:
use PavelZanek\LaravelDeepl\DeeplClient;
$client = app(DeeplClient::class);
try {
$glossaryInfo = $client->createGlossaryBuilder()
->name('My Glossary')
->sourceLang('en')
->targetLang('de')
->addEntry('artist', 'Künstler')
->addEntry('prize', 'Preis')
->create();
echo "Created '{$glossaryInfo->name}' ({$glossaryInfo->glossaryId}) ";
echo "{$glossaryInfo->sourceLang} to {$glossaryInfo->targetLang} ";
echo "containing {$glossaryInfo->entryCount} entries\n";
} catch (\Exception $e) {
echo "Error creating glossary: " . $e->getMessage();
}Adding Multiple Glossary Entries
You can add multiple glossary entries either by passing an associative array or by using a GlossaryEntries object.
Adding Entries Using an Associative Array:
use PavelZanek\LaravelDeepl\Facades\Deepl;
try {
$glossaryInfo = Deepl::createGlossaryBuilder()
->name('Extended Glossary')
->sourceLang('en')
->targetLang('de')
->addEntries([
'hello' => 'hallo',
'world' => 'welt',
'goodbye' => 'auf Wiedersehen',
])
->create();
echo "Created '{$glossaryInfo->name}' with ID {$glossaryInfo->glossaryId}";
} catch (\Exception $e) {
echo "Error creating glossary: " . $e->getMessage();
}Adding Entries Using a GlossaryEntries Object:
use PavelZanek\LaravelDeepl\Facades\Deepl;
use DeepL\GlossaryEntries;
$entries = GlossaryEntries::fromEntries([
'computer' => 'Computer',
'internet' => 'Internet',
]);
try {
$glossaryInfo = Deepl::createGlossaryBuilder()
->name('Tech Glossary')
->sourceLang('en')
->targetLang('de')
->addEntriesFromGlossaryEntries($entries)
->create();
echo "Created '{$glossaryInfo->name}' with ID {$glossaryInfo->glossaryId}";
} catch (\Exception $e) {
echo "Error creating glossary: " . $e->getMessage();
}Summary of Available Methods in CreateGlossaryBuilder
name(string $name): Sets the glossary name.sourceLang(string $lang): Sets the source language code.targetLang(string $lang): Sets the target language code.addEntry(string $source, string $target): Adds a single glossary entry.addEntries(array $entries): Adds multiple glossary entries from an associative array.addEntriesFromGlossaryEntries(GlossaryEntries $glossaryEntries): Adds multiple glossary entries from aGlossaryEntriesobject.create(): Executes the glossary creation and returns aGlossaryInfoobject.
The official DeepL API offers advanced functionality for glossary management, such as uploading glossaries from CSV files and listing glossary entries. You can also use stored glossaries for both text and document translation.
CSV Glossary Example:
$csvData = file_get_contents('/path/to/glossary_file.csv');
$myCsvGlossary = $client->createGlossaryFromCsv('CSV glossary', 'en', 'de', $csvData);To see all stored glossaries, retrieve glossary entries, or use glossaries in translations, refer to the DeepL PHP API documentation.
You can list all supported source and target languages, including details about which target languages support the formality option, and you can also retrieve supported glossary language pairs.
Example Using the Facade:
use PavelZanek\LaravelDeepl\Facades\Deepl;
// Get source languages
$sourceLanguages = Deepl::getSourceLanguages();
foreach ($sourceLanguages as $sourceLanguage) {
echo $sourceLanguage->name . ' (' . $sourceLanguage->code . ')';
// Example: 'English (en)'
}
// Get target languages
$targetLanguages = Deepl::getTargetLanguages();
foreach ($targetLanguages as $targetLanguage) {
$supportsFormality = $targetLanguage->supportsFormality ? 'supports formality' : 'does not support formality';
echo $targetLanguage->name . ' (' . $targetLanguage->code . ') ' . $supportsFormality;
// Example: 'German (de) supports formality'
}
// Get glossary-supported language pairs
$glossaryLanguages = Deepl::getGlossaryLanguages();
foreach ($glossaryLanguages as $glossaryLanguage) {
echo $glossaryLanguage->sourceLang . ' to ' . $glossaryLanguage->targetLang;
// Example: 'en to de'
}Example Using the DeeplClient:
use PavelZanek\LaravelDeepl\DeeplClient;
$client = app(DeeplClient::class);
// Get source languages
$sourceLanguages = $client->getSourceLanguages();
foreach ($sourceLanguages as $sourceLanguage) {
echo $sourceLanguage->name . ' (' . $sourceLanguage->code . ')';
// Example: 'English (en)'
}
// Get target languages
$targetLanguages = $client->getTargetLanguages();
foreach ($targetLanguages as $targetLanguage) {
$supportsFormality = $targetLanguage->supportsFormality ? 'supports formality' : 'does not support formality';
echo $targetLanguage->name . ' (' . $targetLanguage->code . ') ' . $supportsFormality;
// Example: 'German (de) supports formality'
}
// Get glossary-supported language pairs
$glossaryLanguages = $client->getGlossaryLanguages();
foreach ($glossaryLanguages as $glossaryLanguage) {
echo $glossaryLanguage->sourceLang . ' to ' . $glossaryLanguage->targetLang;
// Example: 'en to de'
}Leveraging the LanguageBuilder for a more fluent and flexible approach.
use PavelZanek\LaravelDeepl\Facades\Deepl;
$languages = Deepl::languageBuilder()
->source()
->target()
->glossary()
->get();
// Accessing Source Languages
foreach ($languages['source_languages'] as $sourceLanguage) {
echo $sourceLanguage->name . ' (' . $sourceLanguage->code . ")\n";
// Example: 'English (en)'
}
echo "\n";
// Accessing Target Languages
foreach ($languages['target_languages'] as $targetLanguage) {
$supportsFormality = $targetLanguage->supportsFormality ? 'supports formality' : 'does not support formality';
echo $targetLanguage->name . ' (' . $targetLanguage->code . ') ' . $supportsFormality . "\n";
// Example: 'German (de) supports formality'
}
echo "\n";
// Accessing Glossary-Supported Language Pairs
foreach ($languages['glossary_languages'] as $glossaryLanguage) {
echo $glossaryLanguage->sourceLang . ' to ' . $glossaryLanguage->targetLang . "\n";
// Example: 'en to de'
}Available Chainable Methods
The LanguageBuilder provides the following chainable methods:
source(): Sets the builder to retrieve source languages.target(): Sets the builder to retrieve target languages.glossary(): Sets the builder to retrieve glossary-supported languages.get(): Executes the language retrieval based on set flags and returns the results.
Monitoring your API usage is essential to ensure that you do not exceed your DeepL plan limits. The package provides mechanisms to retrieve and display usage information.
You can retrieve the current usage and quota information from the DeepL API to monitor your translation usage:
use PavelZanek\LaravelDeepl\Facades\Deepl;
$usage = Deepl::usage()->getUsage();This will return an object containing details about your API usage, including the number of characters translated and any other relevant quota limits.
The package provides an Artisan command to retrieve and display usage information directly from the command line.
Command Syntax:
php artisan deepl:usageExample Output:
+-----------------------+--------+---------+-----------+------------+
| Usage Type | Count | Limit | Remaining | Percentage |
+-----------------------+--------+---------+-----------+------------+
| Translated Characters | 14,464 | 500,000 | 485,536 | 2.89% |
| Total | 14,464 | 500,000 | 485,536 | 2.89% |
+-----------------------+--------+---------+-----------+------------+
The deepl:usage command retrieves usage information within the current billing period along with account limits. It displays the data in a formatted table, highlighting usage types that are approaching or have exceeded their limits.
The command can display various usage types, such as:
- Translated Characters
- Translated Documents
- Translated Team Documents
- Total
Each usage type includes the count, limit, remaining quota, and the percentage of the limit used.
Color-Coded Warnings
- Red: Indicates that the usage limit has been exceeded.
- Yellow: Indicates that the usage is approaching the limit (e.g., 90% or more of the limit).
The package includes a convenient Artisan command for translating Laravel localization files using the DeepL API. This allows you to quickly translate your application’s language files from one language to another. However, it’s always important to review the generated translations and verify their correctness. Human oversight is crucial to ensure that translations are accurate, appropriate, and contextually relevant for your application.
You can use the command as follows:
php artisan deepl:translate {file} --sourceLang=en --targetLang=cs [--with-pint]file: The path to the localization file you wish to translate--sourceLang: The source language code (default is en)--targetLang: The target language code (default is cs)--with-pint: (Optional) If provided, the command will run Pint (a code formatter) after translation, but only in the local environment.
To translate a file from English to Czech, you can run:
php artisan deepl:translate lang/en/messages.php --sourceLang=en --targetLang=csThis will create a translated file at lang/cs/messages.php, preserving the structure and formatting of the original file.
To translate all localization files within a folder (including subdirectories), use the following command:
php artisan deepl:translate-folder {folder} --sourceLang=en --targetLang=cs [--with-pint]folder: The path to the folder containing localization files to translate.--sourceLang: The source language code (default is en).--targetLang: The target language code (default is cs).--with-pint: (Optional) If provided, the command will run Pint (a code formatter) after translation, but only in the local environment.
To translate all files in the English localization folder to Czech, run:
php artisan deepl:translate-folder lang/en --sourceLang=en --targetLang=csThis command will recursively traverse all files and subdirectories within lang/en, translating each file and saving the translated versions in the corresponding target language directory (e.g., lang/cs).
Laravel 10 and Below Compatibility
In Laravel 10 and earlier versions, the localization files are stored in resources/lang. This package supports both Laravel 10 (or below) and Laravel 11. To ensure compatibility, use the appropriate folder path when running the commands:
- For Laravel 11 and higher, the localization files are located in the
lang/directory at the project root. - For Laravel 10 and below, the localization files are in the
resources/lang/directory.
Example
Laravel 11:
php artisan deepl:translate-folder lang/en --sourceLang=en --targetLang=csLaravel 10 and below:
php artisan deepl:translate-folder resources/lang/en --sourceLang=en --targetLang=csThis package will check both paths (lang/ and resources/lang/) and will prevent translating the root folder, ensuring only subdirectories (like lang/en or resources/lang/en) are translated.
When using the deepl:translate-folder command, the package automatically skips translating the root lang folder (or resources/lang in Laravel 10 and below). This is because translating the entire lang directory is not recommended. Instead, you should specify a subfolder, such as lang/en or resources/lang/en, to translate localization files for a specific language. If the root lang folder is provided, the command will skip it and display a warning without interrupting the process.
Both commands support both JSON and PHP localization files. They will automatically detect the file type based on the file extension and handle the translation appropriately.
- For JSON files: The translations are saved in JSON format, with keys and values preserved
- For PHP files: The translations are saved in PHP array syntax, with keys and values maintained
It’s important to note that examples like lang/en/messages.json used in this documentation are purely illustrative. While it’s technically possible to structure your localization files this way, the recommended approach, especially for JSON-based translations, follows a different convention. Laravel encourages storing language-specific JSON files directly in the root of the lang folder, such as lang/en.json, lang/cs.json, etc., where each file represents translations for a specific language. This method allows for easier management of translations across multiple languages, without needing separate subdirectories for each language. By adhering to this structure, Laravel can automatically detect the appropriate JSON file based on the language setting and ensure that the translations are loaded correctly. This best practice also streamlines the process of adding new languages, as you simply need to create a new JSON file for the target language, such as fr.json for French, and fill in the necessary translations.
Original File (lang/en/messages.json):
{
"welcome": "Welcome to our application!",
"user": {
"profile": "Your profile",
"settings": "Account settings"
},
"greeting": "Hello, :name!"
}Translated File (lang/cs/messages.json):
{
"welcome": "Vítejte v naší aplikaci!",
"user": {
"profile": "Váš profil",
"settings": "Nastavení účtu"
},
"greeting": "Ahoj, :name!"
}Original File (lang/en/messages.php):
<?php
return [
'welcome' => 'Welcome to our application!',
'user' => [
'profile' => 'Your profile',
'settings' => 'Account settings',
],
'greeting' => 'Hello, :name!',
];Translated File (lang/cs/messages.php):
<?php
return [
'welcome' => 'Vítejte v naší aplikaci!',
'user' => [
'profile' => 'Váš profil',
'settings' => 'Nastavení účtu',
],
'greeting' => 'Ahoj, :name!',
];When translating localization files, the commands are designed to be efficient and avoid overwriting existing translations. If a key already exists in the target localization file, the command will skip translating that key. This means that only keys that are not present in the target file will be translated and added.
This behavior is particularly useful when you have previously translated keys or when you want to update your localization files incrementally. By skipping existing keys, the command ensures that your existing translations remain untouched, and only new or missing keys are added.
Suppose you have a target localization file that already contains some translations.
Existing Target File (lang/cs/messages.php):
<?php
return [
'welcome' => 'Vítejte v naší aplikaci!',
// The 'user' key is missing
'greeting' => 'Ahoj, :name!',
];If you run the translation command:
php artisan deepl:translate lang/en/messages.php --sourceLang=en --targetLang=csThe command will detect that the keys welcome and greeting already exist in the target file and will skip translating them. It will only translate and add the missing user key.
Updated Target File (lang/cs/messages.php):
<?php
return [
'welcome' => 'Vítejte v naší aplikaci!',
'user' => [
'profile' => 'Váš profil',
'settings' => 'Nastavení účtu',
],
'greeting' => 'Ahoj, :name!',
];In this way, the command preserves your existing translations and focuses on filling in any gaps with new translations.
The command is smart enough to handle placeholders (e.g., :attribute) within your localization strings. It ensures that these placeholders remain unchanged during the translation process, preserving the integrity of your application.
If the target directory does not exist, the command will automatically create it, ensuring that the translated file is saved in the correct location.
Both commands (deepl:translate and deepl:translate-folder) support the --with-pint option, which allows you to run Pint (a PHP code formatter) after the translation is complete.
Pint will only run if your application is in the local environment. This prevents unintended code formatting changes in production or other environments.
Note: Before using the --with-pint option, make sure that you have Pint installed in your project. Pint is typically installed as a development dependency via Composer. You can install it using the following command:
composer require laravel/pint --devIf Pint is not installed, the command will fail when attempting to run Pint. Ensuring that Pint is installed will allow the code formatter to run successfully after translation.
To translate all files in the English localization folder to Czech and run Pint after translation, use:
php artisan deepl:translate-folder resources/lang/en --targetLang=cs --with-pintThe package provides an on-the-fly translation feature that dynamically translates missing keys at runtime using the DeepL API. This can be helpful when you want to automatically handle missing translations without pre-generating them.
To use the on-the-fly translation feature, you need to register a custom translator in your application's AppServiceProvider. This custom translator will replace Laravel's default translation service with one that integrates with this package.
You can add the following code to your AppServiceProvider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Translation\Loader as LoaderContract;
use Illuminate\Translation\FileLoader;
use Illuminate\Filesystem\Filesystem;
use PavelZanek\LaravelDeepl\Services\TranslationService;
use PavelZanek\LaravelDeepl\Services\TranslatorService;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
// Register this only if you intend to utilize the queue for handling translations
$this->app->singleton(LoaderContract::class, function ($app) {
return new FileLoader(new Filesystem(), lang_path());
});
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
$this->app->extend('translator', function ($translator, $app) {
$loader = $app['translation.loader'];
$translationService = $app->make(TranslationService::class);
return new TranslatorService($loader, $app, $translationService);
});
}
}If you want the missing translation keys to be processed in the background using Laravel’s queue system, include the register method code snippet in your AppServiceProvider. This will dispatch the translation jobs to the queue, avoiding any delays during runtime.
Without this, the translations will be processed immediately when they are requested, which may cause a delay if there is a high number of missing translations.
Ensure that the following configuration settings in config/laravel-deepl.php are enabled or adjusted based on your needs:
Enable On-The-Fly Translation:
'enable_on_the_fly_translation' => env('DEEPL_ENABLE_ON_THE_FLY_TRANSLATION', true),Translate Outside Local Environment:
'on_the_fly_outside_local' => env('DEEPL_ON_THE_FLY_OUTSIDE_LOCAL', false),On-The-Fly Source Language:
'on_the_fly_source_lang' => env('DEEPL_ON_THE_FLY_SOURCE_LANG', 'en'),Use Queue for Translation:
'on_the_fly_use_queue_for_translation' => env('DEEPL_ON_THE_FLY_USE_QUEUE_FOR_TRANSLATION', true),These settings allow you to control how on-the-fly translations are handled, including whether they are processed immediately or dispatched to a queue for asynchronous processing.
This package provides a set of enumerations (enums) to simplify and standardize the use of certain options and parameters when interacting with the DeepL API. These enums help ensure that your code remains consistent and less prone to errors.
Here are some of the enums included in the package:
-
DocumentStatus: Represents the status of a document translation.
DocumentStatus::DONEDocumentStatus::TRANSLATING
-
Formality: Allows you to control the formality level of the translated text.
Formality::DEFAULTFormality::MOREFormality::LESSFormality::PREFER_MOREFormality::PREFER_LESS
-
PreserveFormatting: Controls whether the original formatting is preserved in the translation.
PreserveFormatting::DISABLEDPreserveFormatting::ENABLED
-
SourceLanguage: Lists the available source languages.
- Includes languages such as
SourceLanguage::ENGLISH,SourceLanguage::GERMAN,SourceLanguage::FRENCH, etc. - Special value:
SourceLanguage::AUTOMATICto let DeepL detect the source language automatically.
- Includes languages such as
-
SplitSentences: Configures how sentences should be split during translation.
SplitSentences::NONESplitSentences::DEFAULTSplitSentences::NO_NEWLINES
-
TargetLanguage: Lists the available target languages.
- Includes languages such as
TargetLanguage::ENGLISH_BRITISH,TargetLanguage::GERMAN,TargetLanguage::SPANISH, etc.
- Includes languages such as
You can use these enums to improve code readability and reduce the chance of errors:
use PavelZanek\LaravelDeepl\Facades\Deepl;
use PavelZanek\LaravelDeepl\Enums\V2\Formality;
use PavelZanek\LaravelDeepl\Enums\V2\SourceLanguage;
use PavelZanek\LaravelDeepl\Enums\V2\TargetLanguage;
$translatedText = Deepl::translateText()
->text('How are you today?')
->sourceLang(SourceLanguage::ENGLISH->value)
->targetLang(TargetLanguage::GERMAN->value)
->formality(Formality::PREFER_LESS->value)
->translate();
echo $translatedText; // Outputs: Wie geht es dir heute?
For more in-depth information about the DeepL API, including advanced features and detailed parameter descriptions, please refer to the official DeepL API Documentation.
- Official DeepL PHP Client: GitHub Repository
- DeepL API Reference: DeepL API Docs
- Deepl API Postman Collection: Postman Collection
To run the tests, use:
composer testThe test suite covers various aspects, including:
- Translation caching and retrieval.
- Translation using both the Facade and the DeeplClient.
- Translation of JSON and PHP language files.
- Handling of edge cases and error scenarios.
- Document translation processes.
- Glossary management.
- Usage command functionality.
You can run PHPStan to ensure code quality:
composer lintPlease see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
If you discover any security-related issues, please email zanek.pavel@gmail.com instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.
If you find this package helpful and would like to support its ongoing development, consider leaving a tip. Your support is greatly appreciated!
Thank you for your generosity!
This package is developed and maintained by Pavel Zaněk, a passionate developer with extensive experience in Laravel and PHP development.