alessandrolandim/translation-bundle
Installation
composer require alessandrolandim/translation-bundle
(Note: The package name in the composer.json differs from the GitHub repo. Use lexik/translation-bundle instead for compatibility with the documented version.)
Enable the Bundle
Add to config/bundles.php:
return [
// ...
Lexik\TranslationBundle\LexikTranslationBundle::class => ['all' => true],
];
Configure Database Storage
Update config/packages/lexik_translation.yaml (auto-generated):
lexik_translation:
driver: doctrine
doctrine:
entity_manager: default
class: App\Entity\Translation
Create Translation Entity Generate the entity (if not using auto-generation):
php bin/console make:entity Translation
(Follow documentation for fields: locale, domain, id, message, messageId.)
Import Initial Translations
php bin/console lexik:translation:import --format=yml --dir=%kernel.project_dir%/translations
Access the GUI
Visit /translation (or /admin/translation if using Symfony AdminBundle).
Edit a Translation
Navigate to the GUI, search for validation.required in the messages domain, and override the default YAML value (e.g., "This value should not be blank." → "Campo obrigatório.").
Verify in Code
$this->get('translator')->trans('validation.required', [], 'messages');
(Returns the overridden value.)
Development Phase
translations/messages.en.yml).php bin/console lexik:translation:import --format=yml --dir=translations
Production Phase
/translation).php bin/console lexik:translation:export --format=yml --dir=translations
Collaboration
ROLE_TRANSLATOR).Custom Domains
Extend the entity to support custom domains (e.g., email_templates):
// config/packages/lexik_translation.yaml
lexik_translation:
domains:
- messages
- email_templates
Validation Rules
Add constraints to the Translation entity:
use Symfony\Component\Validator\Constraints as Assert;
/**
* @Assert\NotBlank
* @Assert\Length(max=255)
*/
private $message;
Event Listeners Log translation changes:
// src/EventListener/TranslationListener.php
public function onTranslationUpdate(TranslationEvent $event) {
\Log::info('Translation updated', [
'locale' => $event->getTranslation()->getLocale(),
'domain' => $event->getTranslation()->getDomain(),
]);
}
Register in services.yaml:
services:
App\EventListener\TranslationListener:
tags:
- { name: kernel.event_listener, event: lexik.translation.pre_update }
API Access Expose translations via API (e.g., using API Platform):
# config/api_platform/resources.yaml
resources:
App\Entity\Translation:
collectionOperations:
get:
method: GET
path: /api/translations
normalization_context:
groups: ['translation:read']
Middleware for Locale Routing
// src/EventListener/LocaleListener.php
public function onKernelRequest(GetResponseEvent $event) {
$request = $event->getRequest();
$locale = $request->get('locale', 'en');
$event->getRequest()->setLocale($locale);
}
Register:
services:
App\EventListener\LocaleListener:
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Database-First Translations Override the translator to prioritize database entries:
# config/packages/translation.yaml
framework:
translator:
paths:
- '%kernel.project_dir%/translations'
defaults:
locale: '%locale%'
lexik_translation:
database_loader: true
Entity Mismatch
Translation entity with specific fields (locale, domain, messageId, message).php bin/console make:entity Translation --regenerate
CLI Import Failures
lexik:translation:import fails with "No translation files found."messages.en.yml) and the --dir path is absolute or relative to the project root.Caching Conflicts
php bin/console cache:clear
# config/packages/translation.yaml
framework:
translator:
caching: false
Locale-Specific Routes
/translation ignore the current locale.locale parameter:
/translation?locale=es
Check DatabaseLoader
Verify the DatabaseLoader is registered:
php bin/console debug:container lexik.translation.database_loader
(Should return Lexik\TranslationBundle\Loader\DatabaseLoader.)
SQL Queries Enable Doctrine debugging:
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
(Check var/log/dev.log for queries like SELECT message FROM translation WHERE messageId = ? AND locale = ?.)
Event Dispatching Debug events with:
php bin/console debug:event-dispatcher
(Look for lexik.translation.pre_update, lexik.translation.post_update.)
Custom Importers Extend the importer to support custom formats (e.g., CSV):
// src/Importer/CsvImporter.php
use Lexik\TranslationBundle\Importer\ImporterInterface;
class CsvImporter implements ImporterInterface {
public function import(string $file, string $locale, string $domain): void {
// Parse CSV and save to database
}
}
Register in services.yaml:
services:
App\Importer\CsvImporter:
tags:
- { name: lexik_translation.importer, format: csv }
GUI Customization Override the Twig templates:
mkdir -p templates/bundles/LexikTranslationBundle
cp vendor/lexik/translation-bundle/Resources/views/* templates/bundles/LexikTranslationBundle/
(Edit edit.html.twig to add custom fields or buttons.)
Translation Approval Workflow
Add a status field to the Translation entity and filter the GUI:
// src/Entity/Translation.php
private $status = 'draft'; // draft | reviewed | published
// Filter in the bundle's repository
public function findUnreviewed(string $locale) {
return $this->createQueryBuilder('t')
->where('t.locale = :locale')
->andWhere('t.status = :status')
->setParameter('locale', $locale)
->setParameter('status', 'draft')
->getQuery()
->getResult();
}
Lexik\TranslationBundle\Entity\Translation.How can I help you explore Laravel packages today?