Installation
composer require danilovl/translator-bundle
Ensure TranslatorBundle is enabled in config/bundles.php (auto-detected in Symfony 5.1+).
Configuration Publish the default config:
php bin/console translator:install
This creates:
translations)config/translations/)First Use Case Translate a string in a controller:
use TranslatorBundle\Service\TranslationService;
class MyController extends AbstractController {
public function index(TranslationService $translator): Response {
$translation = $translator->get('messages.welcome');
return $this->render('index.html.twig', ['message' => $translation]);
}
}
YAML-to-Database Sync
php bin/console translator:sync:yaml-to-db
Database-to-YAML Sync
php bin/console translator:sync:db-to-yaml
Cache Management
php bin/console translator:cache:generate
onAfterUpdate event.Twig Integration Extend the default translator service to work with Twig:
{{ app.translator.get('messages.welcome', { name: user.name }) }}
(Requires binding the service in services.yaml:
services:
App\Twig\TranslationExtension:
tags: ['twig.extension']
arguments: ['@translator']
EasyAdmin CRUD
Use the provided TranslationCrudController:
use TranslatorBundle\Controller\TranslationCrudController;
class TranslationController extends TranslationCrudController { ... }
/admin/translations.Dynamic Namespaces
Override the default namespace (messages) in config/packages/translator.yaml:
translator:
default_namespace: 'app'
yaml_directory: '%kernel.project_dir%/config/translations'
Namespace Collisions
messages.welcome in both messages.yml and auth.yml), the last synced file overwrites.Cache Staleness
sync:yaml-to-db or EasyAdmin).// src/EventListener/TranslationUpdateListener.php
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use TranslatorBundle\Service\TranslationService;
class TranslationUpdateListener {
public function __construct(private TranslationService $translator) {}
public function onPostUpdate(PostResponseEvent $event): void {
$this->translator->clearCache();
}
}
EasyAdmin Permissions
ROLE_ADMIN. Ensure your security.yaml includes:
access_control:
- { path: ^/admin/translations, roles: ROLE_ADMIN }
Check Sync Status
php bin/console translator:status
Log Translation Lookups
Enable debug mode in translator.yaml:
translator:
debug: true
var/log/dev.log.Custom Storage
Override the default TranslationStorage service to support JSON or XML:
# config/services.yaml
TranslatorBundle\Storage\TranslationStorage:
arguments:
$connection: '@doctrine.dbal.default_connection'
$table: 'custom_translations'
Pre-Translation Hooks Add a subscriber to validate translations before sync:
use TranslatorBundle\Event\TranslationEvent;
class TranslationValidatorSubscriber {
public function onPreSync(TranslationEvent $event): void {
$translations = $event->getTranslations();
// Validate $translations here (e.g., check for empty values).
}
}
Register in services.yaml:
services:
App\EventSubscriber\TranslationValidatorSubscriber:
tags: ['kernel.event_subscriber']
Multi-Database Support For multi-tenancy, extend the storage to use a tenant-aware connection:
class TenantTranslationStorage extends TranslationStorage {
public function __construct(private TenantConnection $connection) {}
public function findAll(): array {
return $this->connection->fetchAllAssociative('SELECT * FROM translations WHERE tenant_id = ?', [$this->tenantId]);
}
}
How can I help you explore Laravel packages today?