adcog-cpi/translation-bundle
Symfony bundle providing translation-aware link helpers for controllers and Twig. Generates tags with translated name/title/description from route keys, optional route-to-class, underscore-to-dot mapping, prefixing, and active-route tracking via configurable defaults.
Installation
composer require adcog-cpi/translation-bundle
Add the bundle to AppKernel.php (or config/bundles.php for Symfony 4+):
new EB\TranslationBundle\TranslationBundle(),
Configure
Update config/packages/eb_translation.yaml (or app/config/config.yml for Symfony <4):
eb_translation:
domain: messages
locale: '%kernel.default_locale%'
use_route_as_class: false
replace_underscore: true
prefix: 'page.'
track_selected_links: 'active'
First Use Case
Define translations in translations/messages.fr.yml:
page:
home:
name: 'Accueil'
title: 'Page d''accueil'
Generate a link in a Twig template:
{{ translation.link('home') }}
Output:
<a href="/" title="Page d'accueil">Accueil</a>
Link Generation
{{ translation.link('route_name') }}
{{ translation.link('route_name', {'param': 'value'}) }}
{{ translation.link('route_name', {}, {'name': 'Custom Text', 'title': 'Custom Title'}) }}
Controller Integration Inject the service and use it programmatically:
public function index(Translation $translation) {
return $translation->link('home', ['page' => 1], ['class' => 'btn']);
}
Translation Structure
page:
admin:
users:
name: 'Users'
title: 'User Management'
Access via admin_users (if replace_underscore: true).Active Link Tracking
Automatically adds active class if track_selected_links is enabled:
{{ translation.link('current_route') }} <!-- Will include 'active' class -->
Custom Prefixes
Override the prefix to organize translations:
eb_translation:
prefix: 'custom.'
custom:
home:
name: 'Home'
Twig Extensions
Use the translation Twig function globally by adding to twig/config.yaml:
twig:
globals:
translation: '@eb_translation'
Dynamic Locale Switching Change locale dynamically in controllers:
$translation->setLocale('en');
Route Name Conversion
Leverage replace_underscore for cleaner YAML:
page:
home_index: # Maps to 'home.index' in translations
name: 'Home'
Custom Link Attributes Pass additional HTML attributes:
{{ translation.link('home', {}, {'class': 'btn-primary', 'data-toggle': 'modal'}) }}
Route Name Mismatches
replace_underscore: true, ensure route names in translations match the converted format (e.g., home_index → home.index).php bin/console debug:router and adjust translations accordingly.Missing Translations
$translation->link('missing_route', [], ['name' => 'Fallback Text']);
Locale Configuration
%locale% or %kernel.default_locale% must resolve correctly. Test with:
$this->getParameter('locale'); // Verify in a controller
Caching Issues
php bin/console cache:clear
Route Overrides
use_route_as_class: true to dynamically generate classes based on route names.Check Generated HTML
Temporarily add {{ dump(translation.link('route_name')) }} to inspect output.
Validate Route Names Use Symfony’s router to debug:
php bin/console debug:router | grep "route_name"
Translation Dumping Dump loaded translations for debugging:
$translator = $this->get('translator');
dump($translator->getCatalogue()->get('messages', 'fr')->all());
Override Default Behavior Extend the bundle’s service to customize logic:
# config/services.yaml
EB\TranslationBundle\Translation:
arguments:
$defaultOptions: ['custom_prefix' => 'app.']
Custom Link Builders
Extend the Translation service to add methods like:
public function buttonLink(string $route, array $params = [], array $options = []): string
{
$options['class'] = 'btn ' . ($options['class'] ?? '');
return $this->link($route, $params, $options);
}
Dynamic Prefixes
Override the prefix per request:
$translation->setPrefix('dynamic.');
Post-Process Link HTML
Subscribe to the eb_translation.link.html event to modify output:
$eventDispatcher->addListener('eb_translation.link.html', function (LinkEvent $event) {
$event->setHtml(str_replace('href', 'data-href', $event->getHtml()));
});
Fallback Translations Implement a fallback chain in the service:
public function getTranslation(string $key, string $locale): string
{
$translation = $this->translator->trans($key, [], null, $this->domain, $locale);
return $translation ?: $this->getFallbackTranslation($key, $locale);
}
How can I help you explore Laravel packages today?