Translate your Eloquent models automatically, using AI or translation services.
This package makes running a multi-lingual Laravel app as easy as running a single-language website. More exactly, it adds AI-powered translation capabilities for projects that use Laravel and spatie/laravel-translatable
:
created
/updated
, the system can automatically translate that entry;Put these features together and what you get is:
That's right, this package solves all the remaining difficulties of running a multi-language web app. Big words - we know. But try it out. And best of all? We've made this is a general-purpose Laravel package - it does not depend on Backpack at all. So you can install it on any Laravel 12+ project, and it will just work.
https://github.com/user-attachments/assets/513101da-4048-4b4f-9156-6a78a3d9be30
composer require backpack/auto-translate
# optional - you can publis the config file, if you want to make changes:
php artisan vendor:publish --tag=config --provider="Backpack\AutoTranslate\AddonServiceProvider"
This will publish the configuration file to config/backpack/auto-translate.php
.
This package supports multiple translation providers. You need to choose one and install its dependencies:
| Driver | Providers | Best For | Cost | |--------|----------|----------|------| | DeepL Driver | DeepL API | Large content (eg. HTML) | High-cost | | OpenAI Driver | OpenAI GPT Models | Small & medium content | Low-cost | | Prism Driver | OpenAI, Anthropic, Ollama, Mistral, DeepSeek, Groq, xAI, custom LLMs | Trying different LLMs for your content | Low-cost | | Custom Driver | Your own implementation | Specific requirements, custom APIs | Varies |
Need another driver? You can create your own custom driver or send us an email - we will consider adding support for AWS Translate, Azure Translate, Google Cloud Translation, ModernMT etc - if people actually need them.
To verify your driver installation:
php artisan auto-translate:drivers
Add these variables to your .env
file:
# Auto Translation Settings
AUTO_TRANSLATE_ENABLED=true
AUTO_TRANSLATE_DRIVER=openai # or deepl, or prism
# AUTO_TRANSLATE_QUEUE=translations # in production, it's highly recommended to run the translations on a separate queue
Double-check you have the .ENV variables for your driver (see driver documentation for details):
# Example for OpenAI:
OPENAI_API_KEY=your_openai_api_key_here
OPENAI_TRANSLATE_MODEL=gpt-4o-mini
Make sure your queue is configured and working:
php artisan queue:work --queue=translations
In production, it's highly recommended to use a different queue for the translations than the one for the rest of the application. That way, one big translation taking 2min will not hold up any other jobs.
Important Prerequisites:
spatie/laravel-translatable
)spatie/laravel-translatable
properly configured in your projectMethod 1: Using the Trait (Recommended)
Add the HasAutoTranslations
trait to your models that you will want translated:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
use Backpack\AutoTranslate\Traits\HasAutoTranslations;
class Event extends Model
{
use HasTranslations, HasAutoTranslations;
public array $translatable = ['name', 'description'];
protected $fillable = ['name', 'description', 'date'];
}
Method 2: Using the Configuration File
Alternatively, you can specify which models should be auto-translated in the config file:
// config/backpack/auto-translate.php
'models' => [
App\Models\Event::class,
App\Models\Article::class,
App\Models\Product::class,
],
Verify Your Setup:
Make sure your translatable columns are JSON columns in your database:
// Example migration
Schema::table('events', function (Blueprint $table) {
$table->json('name')->nullable();
$table->json('description')->nullable();
});
There are four ways in which you can auto-translate your Eloquent entries using this package:
Use Artisan commands to translate existing database entries, check translation status, and manage bulk operations:
# Check translation status
php artisan auto-translate:status
# Translate all existing entries
php artisan auto-translate:run
# Translate one particular entry
php artisan auto-translate:entry
Perfect for: Migrating existing content, bulk operations, scheduled tasks, one-time translations.
Set up your models to automatically translate an entry when it's created
or updated
. Just add a trait to your model and translations happen in the background:
class Event extends Model
{
use HasTranslations, HasAutoTranslations;
public array $translatable = ['name', 'description'];
}
// In config: 'enabled_events' => ['created', 'updated']
Perfect for: Hands-off translation management, new projects where you want everything translated automatically.
If your entries are added by an admin (not the end-user), we found it's best to just add a checkbox at the end of the Create/Update form, that allows the admin to choose whether the AI should auto-translate. That gives them the power to translate when they want... or skip if they don't.
For example, here's how you can achieve that in Backpack:
// remember to use the Facade:
// use Backpack\AutoTranslate\Facades\AutoTranslate;
// then:
CRUD::field('_auto_translate')
->type('checkbox')
->label('After save, use AI to auto-translate to the other languages')
->default(true)
->fake(true)
->on('saved', function ($entry) {
if (request()->input('_auto_translate')) {
$success = AutoTranslate::translate(
model: $entry,
overwrite: true,
immediate: false
);
if ($success) {
\Prologue\Alerts\Facades\Alert::add('info', 'Auto-translation in progress. It could take a few seconds or minutes, depending on the amount of text to translate.')->flash();
} else {
\Prologue\Alerts\Facades\Alert::add('warning', 'Auto-translation job failed.')->flash();
}
}
});
Perfect for: Most use cases where you want admin flexibility and control over the translation process.
Use the AutoTranslate Facade directly in your PHP code for complete programmatic control:
use Backpack\AutoTranslate\Facades\AutoTranslate;
// Auto-detects source language (recommended)
AutoTranslate::translate($model);
// Or specify explicit source language
AutoTranslate::translate($model, sourceLocale: 'en');
// Translate in background (queued)
AutoTranslate::translate($model, queue: true);
// Translate specific attributes only
AutoTranslate::translate($model, attributes: ['name', 'description']);
// Translate to specific locales
AutoTranslate::translate($model, locales: ['es', 'fr']);
// Check if service is ready
if (AutoTranslate::isReady()) {
AutoTranslate::translate($model);
}
Perfect for: Custom workflows, API integrations, conditional translation logic, advanced use cases.
For detailed API documentation, examples, and advanced usage patterns, see Manual Usage Documentation.
Automatically translate related models when a parent model is translated.
// When Event is translated, automatically translate its SeatingCategories
AutoTranslate::translate($event, cascade: ['seatingCategories']);
// Or define in your model
class Event extends Model {
public array $autoTranslateRelationships = ['seatingCategories'];
}
// Command usage
php artisan auto-translate:entry "App\Models\Event" 123 --cascade=seatingCategories
The configuration file config/backpack/auto-translate.php
provides extensive customization options:
You can control which model events trigger automatic translation:
// config/backpack/auto-translate.php
'enabled_events' => [], // Default: manual control only
// Examples:
'enabled_events' => ['created'], // Only on model creation
'enabled_events' => ['updated'], // Only on model updates
'enabled_events' => ['created', 'updated'], // Automatic on both create and update
Default Behavior: By default, enabled_events
is set to an empty array []
, which means automatic translation is disabled. This gives you complete control over when translations happen - perfect for use with the checkbox field approach above.
return [
// Enable/disable auto-translation
'enabled' => env('AUTO_TRANSLATE_ENABLED', true),
// Translation driver (openai, deepl, etc.)
'driver' => env('AUTO_TRANSLATE_DRIVER', 'openai'),
// Supported locales
'supported_locales' => explode(',', env('APP_SUPPORTED_LOCALES', 'en,ro,es,bg')),
// Source locale (defaults to 'auto' for automatic detection)
'source_locale' => env('AUTO_TRANSLATE_SOURCE_LOCALE', 'auto'),
// Queue configuration
'queue' => env('AUTO_TRANSLATE_QUEUE', 'auto-translations'),
// Cache TTL (30 days default)
'cache_ttl' => env('AUTO_TRANSLATE_CACHE_TTL', 2592000),
// Driver configurations
'drivers' => [
'openai' => [
'api_key' => env('OPENAI_API_KEY'),
'model' => env('OPENAI_TRANSLATE_MODEL', 'gpt-4o-mini'),
'temperature' => 0.2,
'max_tokens' => 2000,
],
],
// Translation constraints
'constraints' => [
'preserve_html_tags' => ['a', 'strong', 'em', 'code', 'ul', 'ol', 'li', 'br', 'p'],
'preserve_placeholders' => ['{{.*?}}', '%s', '{0}', '[:slug:]'],
'dont_translate_terms' => ['Backpack', 'Laravel', 'SENZORIAL'],
'style' => 'neutral, professional, concise',
],
];
The package includes an intelligent translation strategy system that automatically selects the optimal approach based on content size, ensuring reliable translations for both small and large content.
Small Content (< 5000 characters for OpenAI, < 10000 for DeepL):
Large Content (≥ threshold):
Oversized Content (> max limit):
You can customize the thresholds and limits in your configuration:
# OpenAI Settings
OPENAI_MAX_TOKENS=8000 # Token limit
OPENAI_PER_LANGUAGE_THRESHOLD=5000 # When to switch strategies
OPENAI_MAX_CONTENT_SIZE=50000 # Maximum content size
# DeepL Settings
DEEPL_PER_LANGUAGE_THRESHOLD=10000 # When to switch strategies
DEEPL_MAX_CONTENT_SIZE=120000 # Maximum content size (~120KB)
Or in your config file.
Cache keys follow this format:
auto_tr:{provider}:{model_hash}:{model_id}:{attribute}:{source_locale}:{content_hash}:{targets_hash}
Benefits:
$autoTranslateService = app(AutoTranslateService::class);
$stats = $autoTranslateService->getStats();
// Returns:
// [
// 'enabled' => true,
// 'driver' => 'openai',
// 'driver_configured' => true,
// 'cache_enabled' => true,
// 'supported_locales' => ['en', 'ro', 'es', 'bg'],
// 'source_locale' => 'en',
// 'overwrite_default' => false,
// ]
$autoTranslateService = app(AutoTranslateService::class);
$cleared = $autoTranslateService->clearModelCache($event);
echo "Cleared {$cleared} cache entries";
Monitor these log channels:
To add a new provider (e.g., DeepL):
AutoTranslatorDriverContract
Example:
use Backpack\AutoTranslate\Contracts\AutoTranslatorDriverContract;
use Backpack\AutoTranslate\DTOs\AutoTranslateRequest;
use Backpack\AutoTranslate\DTOs\AutoTranslateResult;
class DeepLAutoTranslator implements AutoTranslatorDriverContract
{
public function translate(AutoTranslateRequest $request): AutoTranslateResult
{
// DeepL API integration
}
public function getDriverName(): string
{
return 'deepl';
}
// ... other methods
}
HasTranslations
trait and has $translatable
arrayauto-translations
queueIf you discover any security related issues, please email [email protected] instead of using the issue tracker.
This software is proprietary & closed-source, released under the End-User License Agreement (EULA) for Private Backpack Addons. A copy of that license is also provided inside the source code - you can read that file by using the tabs at the beginning of this page.
You don't currently have access to this package. To gain access, go ahead and purchase it. You'll get: