PHPackages                             webfactory/polyglot-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. webfactory/polyglot-bundle

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

webfactory/polyglot-bundle
==========================

Symfony Bundle simplifying translations of values stored in Doctrine ORM entities

4.5.1(1mo ago)324.7k↑50%2[4 issues](https://github.com/webfactory/WebfactoryPolyglotBundle/issues)[3 PRs](https://github.com/webfactory/WebfactoryPolyglotBundle/pulls)MITPHPPHP &gt;= 8.1CI passing

Since Sep 9Pushed 1mo ago8 watchersCompare

[ Source](https://github.com/webfactory/WebfactoryPolyglotBundle)[ Packagist](https://packagist.org/packages/webfactory/polyglot-bundle)[ RSS](/packages/webfactory-polyglot-bundle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (32)Versions (37)Used By (0)

[![webfactory Logo](https://camo.githubusercontent.com/94fcecf25c8bf567abd94885268fdd037985a53fc8cbb13bda9c9a43f70f08da/68747470733a2f2f7777772e776562666163746f72792e64652f62756e646c65732f776562666163746f7279747769676c61796f75742f696d672f6c6f676f2e706e67)](https://camo.githubusercontent.com/94fcecf25c8bf567abd94885268fdd037985a53fc8cbb13bda9c9a43f70f08da/68747470733a2f2f7777772e776562666163746f72792e64652f62756e646c65732f776562666163746f7279747769676c61796f75742f696d672f6c6f676f2e706e67) WebfactoryPolyglotBundle
=====================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

[](#-webfactorypolyglotbundle)

[![Tests](https://github.com/webfactory/WebfactoryPolyglotBundle/workflows/Tests/badge.svg)](https://github.com/webfactory/WebfactoryPolyglotBundle/workflows/Tests/badge.svg)[![Dependencies](https://github.com/webfactory/WebfactoryPolyglotBundle/workflows/Dependencies/badge.svg)](https://github.com/webfactory/WebfactoryPolyglotBundle/workflows/Dependencies/badge.svg)

A bundle to simplify translations for Doctrine entities.

Its main advantages over similar bundles are:

- Transparency: Add translations to existing entities without any API changes.
- Fast: Entity translations are loaded eagerly from separate translation tables.
- Polyglot: Easy access to all available translations of an entity without additional database requests.

[We](https://www.webfactory.de/) use it to create multilingual navigation menus and links like "view this article in German", where the linked URL has a locale specific slug.

Installation
------------

[](#installation)

Just like any other Symfony bundle, and no additional configuration is required (wheeho!).

Underlying Data Model and How It Works
--------------------------------------

[](#underlying-data-model-and-how-it-works)

The assumption is that you already have a "main" Doctrine entity class with some fields that you now need to make locale-specific.

To do so, we'll add a new *translation entity class* that contains these fields plus a field for the locale. The main entity and the translation entity class will be connected with a `OneToMany` association.

So, for one single *main* entity instance, there are zero to many *translation entity* instances – one for every locale that you have a translation for.

This approach reflects our experience that almost always the relevant content (field values) are maintained for a "primary" locale. This is the "authoritative" version of your content/data. Then, this content is translated for one or several "secondary" locales. The *translation entity class* is concerned with holding this translated data only.

Technically, this bundle sets up a Doctrine event handler (`\Webfactory\Bundle\PolyglotBundle\Doctrine\PolyglotListener`) to be notified whenever a Doctrine entity is hydrated, that is, re-created as a PHP object based on database values.

This listener finds all fields in the entity that are marked as being locale-specific and replaces their value with a value holder object. These value holders are instances of `\Webfactory\Bundle\PolyglotBundle\TranslatableInterface`. To learn more about the Value Holder pattern, see [Lazy Load in PoEAA](https://martinfowler.com/eaaCatalog/lazyLoad.html).

You can then use this interface's `translate()` method to obtain the field value for a locale of your choice: The value holder will take care of returning either the original value present in your *main* entity or finding the right *translation* entity instance (for the matching locale) and take the field value from there, depending on whether you requested the *primary* or one of the *additional* locales. If no matching translation is found, the primary locale's data will be used.

While this approach should work for any type of data, including objects, in your locale-dependent fields, it works particularly well for strings: The value holder features a `__toString()` method that will return the value for the currently active locale whenever the value holder object is used in a string context.

Yet, it is worth noting that you're now dealing with the value holders in places where you previously had "your" data or objects. They are *not* "almost" transparent proxies as those used by Doctrine because they do not provide the same interface as the original values. Only for strings, the difference is sufficiently small.

The good news for Twig users is that `__toString()` support in Twig is good enough so that you need not care about the distinction of strings and translation value holders. So, Twig constructs like `{{ someObject.field }}` or `{% if someObject.field is not empty %}...` will work the same regardless of your `getField()` method returns a string value or the translation value holder.

You think an example could help clearing up the confusion? Read on!

Usage Example
-------------

[](#usage-example)

Let's say you have an existing Doctrine entity `Document` that looks like this:

```
