Installation
composer require arsigor/i18n-doctrine-bundle
Ensure a2lix/translation-form-bundle is also installed (required dependency).
Enable the Bundle
Add to config/bundles.php:
return [
// ...
Arsigor\I18nDoctrineBundle\ArsigorI18nDoctrineBundle::class => ['all' => true],
A2lix\TranslationFormBundle\A2lixTranslationFormBundle::class => ['all' => true],
];
Configure Doctrine
Update config/packages/doctrine.yaml:
doctrine:
orm:
mappings:
App:
is_bundle: false
type: attribute
dir: "%kernel.project_dir%/src/Entity"
prefix: "App\Entity"
alias: App
First Use Case: Translatable Entity
Create a translatable entity (e.g., Product):
use Arsigor\I18nDoctrineBundle\Annotation as I18n;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[I18n\Translatable]
class Product
{
#[ORM\Id, ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[I18n\TranslationFields]
private array $translations = [];
// Getters/setters...
}
Generate Translations Run the bundle’s command to scaffold translation fields:
php bin/console arsigor:i18n:generate-translations App\Entity\Product
Define Translatable Fields Use annotations to mark fields for translation:
#[I18n\TranslationField("name")]
#[I18n\TranslationField("description")]
private array $translations = [];
Form Integration
Use A2lixTranslationFormBundle to handle translations in forms:
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use A2lix\TranslationFormBundle\Form\Type\TranslationsType;
$builder->add('translations', TranslationsType::class, [
'fields' => ['name', 'description'],
'locales' => ['en', 'fr'],
]);
Repository Patterns Query translations efficiently:
$product = $entityManager->getRepository(Product::class)
->findOneBy(['id' => 1], ['translations' => 'en']);
Validation Add constraints to translatable fields:
use Symfony\Component\Validator\Constraints as Assert;
#[I18n\TranslationField("name")]
#[Assert\NotBlank(groups: ['translation_validation'])]
private array $translations = [];
API Responses Normalize translations in serializers (e.g., API Platform):
use Arsigor\I18nDoctrineBundle\Serializer\Normalizer\TranslatableNormalizer;
#[Serializer\Normalizer\Context(['groups' => ['translations']])]
public function getTranslations(): array
{
return $this->translations;
}
Missing A2lixTranslationFormBundle
a2lix/translation-form-bundle is installed and configured.Locale Not Found
InvalidArgumentException when querying unsupported locales.config/packages/arsigor_i18n.yaml:
arsigor_i18n:
locales: ['en', 'fr', 'de']
Translation Field Overrides
getTranslations()/setTranslations() unless extending the bundle.Doctrine Migrations
php bin/console doctrine:migrations:generate
Check Generated SQL Enable Doctrine logging to verify queries:
doctrine:
dbal:
logging: true
profiling: true
Validate Annotations Use PHPStan or Psalm to catch annotation errors early.
Clear Cache After Changes
php bin/console cache:clear
Custom Translation Storage
Override the default TranslationStorage service to use a custom backend (e.g., Redis):
services:
Arsigor\I18nDoctrineBundle\Storage\TranslationStorage:
arguments:
$cache: '@redis.client'
Dynamic Locale Handling
Extend the TranslatableListener to add runtime locale logic:
use Arsigor\I18nDoctrineBundle\EventListener\TranslatableListener;
class CustomTranslatableListener extends TranslatableListener
{
public function onLoad(LoadClassMetadataEventArgs $event): void
{
// Custom logic here
parent::onLoad($event);
}
}
Fallback Locales
Configure fallback locales in arsigor_i18n.yaml:
arsigor_i18n:
fallback_locale: 'en'
How can I help you explore Laravel packages today?