As you know there is no built-in feature in
Doctrine2 for translating entities. If you need entities translation you can choose one of several already existing bundles or create the new one. As there is no “the right” way of working with
Doctrine2 translations I just want to share my experience.
I don’t really like Doctrine2 Translatable extension as:
- the idea of storing each translatable property as different record in
DBis not a good solution to me;
- quite complex logic when we want to display form to edit translations for all languages that we support in application;
- changing default locale causes
- maybe this is only my opinion by this is not really intuitive for me.
I’ve used this solution only in one project and it’s not something that I remember well.
You can try it but I’m not recommending it. Official documentation can be found here.
This is my favorite entities translation implementation for
Doctrine2 – I couldn’t find better solution so far. Even for project that I was migrating schema from old
symfony 1.0 where there were used
Propel translations with Active Record models like
CategoryI18n – almost everything can be configured and even if there is something that can’t be configured we can just override it.
Note: KNPLabs translatable behaviour is using PHP traits. If you don’t know it already please read the documentation.
In this example I will create simple
Post entity for storing translations in three languages (you can use as many languages as you need). I’m also using Symfony3 framework with its installer to setup new project. We will also need DB connection (
sqlite or any other you like).
KnpLabsBehaviors bundle and configure it according to documentation.
Next step is to generate our
PostTranslation entities for storing translations.
Post will be our main entity and
PostTranslation will be used for storing translations:
php bin/console doctrine:generate:entity
Post entity with properties:
PostTranslation entity with properties:
Note: if you want to generate
PostTranslation entity using
Doctrine2 commmand you would have to remove
PostTranslation->id property after generation as
Knp is adding it automatically generating also proper relations for translations.
When entities are ready we should add new methods to be able to work with translations. We don’t have to that manually, just to import and use proper traits from
- to translated entity add import of:
- to entity which will be storing translation we should add:
Then we need to update
php bin/console doctrine:schema:update --force
and we can start working with translations:
$post = new \AppBundle\Entity\Post();
// In order to persist new translations, call mergeNewTranslations method, before flush
Translation interface is simple and intuitive. In similar scenario we would have to add proper relation and persist translation entity. Thanks to
Knp this is handled by calling
For me it is also very useful to be able to call direct method on translated entity based on current locale:
// in Post entity class
public function __call($method, $arguments)
return $this->proxyCurrentLocaleTranslation($method, $arguments);
Thanks to this method we can simply call:
// will return string: "programowanie" as my default locale is 'pl'
// now will return string: "programming"
Knp is shipped with
TranslatableSubscriber which is also responsible for setting current locale on translated entities. We can change that locale by calling
setCurrentLocale on translated entity (
Post in our case).
Note: if you need
Doctrine2 entities translations to be managed from
Symfony forms, this implementation works great with A2lix\TranslationFormBundle bundle. I described this integration in dedicated blog post.