Install the Bundle
composer require atoolo/translator-bundle
Enable in config/bundles.php:
return [
// ...
Atoolo\TranslatorBundle\AtooloTranslatorBundle::class => ['all' => true],
];
Configure the Service
Edit config/packages/atoolo_translator.yaml:
atoolo_translator:
api_key: '%env(ATOOLO_API_KEY)%' # Replace with your DeepL/API key
service: 'deepl' # Supported: 'deepl', 'custom'
cache:
enabled: true
pool: 'cache.app' # Symfony cache pool
default_locale: 'en'
target_locales: ['de', 'fr'] # Add your target locales
First Translation Inject the translator service in a controller or command:
use Atoolo\TranslatorBundle\Service\TranslatorService;
public function __construct(private TranslatorService $translator) {}
public function translateText(): string
{
$text = 'Hello, world!';
$translation = $this->translator->translate($text, 'de');
return $translation; // Returns cached or freshly translated text
}
Translate a dynamic string (e.g., user-generated content) in a Symfony controller:
$translated = $this->translator->translate($userInput, $targetLocale);
$this->renderTemplate('page.html.twig', ['translatedText' => $translated]);
Translation Request
Use the TranslatorService to fetch translations:
$translator->translate('Source text', 'de'); // Returns cached or fresh translation
Batch Processing For bulk translations (e.g., CMS content):
$batch = [
['text' => 'Home', 'locale' => 'de'],
['text' => 'About', 'locale' => 'fr'],
];
$results = $translator->translateBatch($batch);
Integration with Symfony Forms
Add a TranslationType to forms for dynamic field labels:
use Atoolo\TranslatorBundle\Form\Type\TranslationType;
$builder->add('title', TranslationType::class, [
'source' => 'default_title',
'locales' => ['de', 'fr'],
]);
Custom Services
Extend Atoolo\TranslatorBundle\Service\AbstractTranslator for non-DeepL providers (e.g., Google Translate):
class GoogleTranslator extends AbstractTranslator {
public function translate(string $text, string $targetLocale): string {
// Custom logic
}
}
Register in config/services.yaml:
services:
App\Service\GoogleTranslator:
tags: ['atoolo_translator.provider']
Cache Invalidation Clear translations manually (e.g., after content updates):
$this->translator->invalidateCache('de'); // Invalidate for a locale
$this->translator->invalidateCacheAll(); // Clear all caches
Event Listeners Hook into translation events (e.g., log failed translations):
use Atoolo\TranslatorBundle\Event\TranslationFailedEvent;
$eventDispatcher->addListener(TranslationFailedEvent::class, function (TranslationFailedEvent $event) {
// Log or retry logic
});
API Key Leaks
api_key in config exposes credentials.%env() and validate in .env:
ATOOLO_API_KEY=%env(ATOOLO_API_KEY)% # Never commit .env
symfony/dotenv to load keys from .env.local.Cache Staleness
TTL (Time-To-Live) in cache config:
cache:
enabled: true
pool: 'cache.app'
ttl: 3600 # 1 hour (default: 86400)
invalidateCache() after bulk updates.Locale Mismatches
'xx').target_locales: ['de', 'fr'] # Explicitly list supported locales
LocaleValidator service to reject invalid locales early.Rate Limiting
$client->setOptions(['delay' => 1000]); // 1-second delay between requests
Enable Verbose Logging
Configure Monolog in config/packages/monolog.yaml:
handlers:
translator:
type: stream
path: "%kernel.logs_dir%/translator.log"
level: debug
Log translation events via the TranslationEvent class.
Test Cache Behavior
Use Symfony’s CacheClearer to simulate cache misses:
php bin/console cache:clear
Or manually clear the pool:
$cachePool = $this->container->get('cache.app');
$cachePool->clear();
Custom Providers
Atoolo\TranslatorBundle\Service\TranslatorInterface for new services (e.g., Azure Translator).services.yaml:
tags: ['atoolo_translator.provider']
Pre/Post-Translation Hooks
Extend AbstractTranslator to modify text before/after translation:
class CustomTranslator extends AbstractTranslator {
protected function preTranslate(string $text): string {
return strtoupper($text); // Example: Force uppercase
}
}
Fallback Logic
Configure fallback locales in config/packages/atoolo_translator.yaml:
fallback_locale: 'en' # Fallback if target locale fails
Override the TranslatorService to handle fallbacks:
public function translate(string $text, string $targetLocale): string {
try {
return parent::translate($text, $targetLocale);
} catch (TranslationException $e) {
return $this->translate($text, $this->config['fallback_locale']);
}
}
Cache Pool Selection
cache.app for short-lived translations (e.g., user input).cache.system for long-lived translations (e.g., static content).cache.doctrine (ORM-specific).Batch Size Limits
$translator->translateChunked($longText, 'de', 4000); // Custom method
Parallel Requests
config/packages/atoolo_translator.yaml if the API blocks IPs:
parallel_requests: false
How can I help you explore Laravel packages today?