PHPackages                             vkr/translation-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. vkr/translation-bundle

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

vkr/translation-bundle
======================

Translates texts from DB for non-annotation mappings, includes integration with Google Translate

1.1.2(9y ago)0533MITPHPPHP &gt;=5.6

Since Jan 23Pushed 9y ago2 watchersCompare

[ Source](https://github.com/wladislavk/TranslationBundle)[ Packagist](https://packagist.org/packages/vkr/translation-bundle)[ Docs](https://github.com/wladislavk/TranslationBundle)[ RSS](/packages/vkr-translation-bundle/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependencies (5)Versions (7)Used By (0)

Overview
========

[](#overview)

This bundle handles translations. Though there are several other Symfony bundles that do the same, this one is algorithm-agnostic and ORM-agnostic. Translations are stored in entities that might be the same as Doctrine entities, but technically any other ORM can be used as well as non-DB persistence solutions. Users can use default translation algorithms shipped with the bundle or create some on their own. An algorithm can use one or more drivers. Three drivers are shipped with this bundle - one uses Doctrine and and is written for situation where a translations table exists per every translatable entity, the second uses Google Translate, while the third allows to use another field of translated entity as a fallback.

Installation
============

[](#installation)

There are several steps that need to be done before using the bundle.

1. Create these entries in `config.yml`

```
vkr_translation:
    language_entity: "MyBundle:MyLanguageEntity"
    locale_retriever_service: "my.locale_retriever"

```

2. Create a locale retriever service. It must implement `LocaleRetrieverInterface`and define its two methods. Both methods can return ISO language codes in either short (as in 'en') or long (as in 'en\_US') forms.
3. Define a language entity. It must implement `LanguageEntityInterface`. The `getCode()`method should return a language code in the same form as returned by your locale retriever.
4. Define at least one pair of entities - see below.
5. (Optional) If you want to use Google Translations integration, set `vkr_translation.google_api_key` parameter in `parameters.yml`.

Defining entity pairs
=====================

[](#defining-entity-pairs)

This bundle is built around the idea of having a separate translation entity for every entity that needs to be translated. Therefore, two entities are needed - a **translatable entity** that is to be translated and a **translation entity** that contains translations.

The translatable entity must implement `TranslatableEntityInterface`, while its translation entity must implement `TranslationEntityInterface`. Also, there is a naming convention: the translation entity full class name must be the same as that of translatable entity (including namespace) with 'Translations' suffix.

It is recommended (though not necessary) to use provided traits for both interfaces: `TranslatableEntityTrait` and `TranslationEntityTrait`. The second one provides all needed methods for translation entity, but translatable entities requires one more method to be defined manually - `getTranslatableFields`, which should return an array of field names for every field of translation entity, excluding primary key and associations. For every field that is returned, a getter and a setter need to be defined manually on the translatable entity, their names should be identical to those on the translated entity. In other words, if you have a 'name' field on the translation entity, you need to write something like this on the translatable entity:

```
public function getTranslatableFields()
{
    return ['name'];
}

private $name;

public function setName($name)
{
    $this->name = $name;
    return $this;
}

public function getName()
{
    return $this->name;
}

```

If you are using Doctrine, YAML or XML mappings for both entities should contain these:

1. PK fields called "id".
2. One-to-many association to "translations" on translatable entity (eager loading highly recommended).
3. Many-to-one associations on translation entity to "language" and "entity" that point to language entity and translatable entity, respectfully.

Examples for YAML mappings of language, translatable and translation entities are provided in `Examples` folder.

Optional methods on translatable entity
=======================================

[](#optional-methods-on-translatable-entity)

A translatable entity may define two more methods.

`getTranslationFallback`. Under default algorithm, it allows to define a scalar value or another field on the translatable entity as a fallback in case no translations are found. It accepts one optional argument, `$field`, which can be used in case there is more than one translatable field. Under default algorithm, if `false` is returned, the bundle will revert to default behavior, that is, throw a `TranslationException`. If you do not want the exception to be thrown, but just return an empty string if translations are not found, just make `getTranslationFallback` return empty string.

This example will return slug instead of name and 'foo' instead of description:

```
public function getTranslationFallback($field = '')
{
    if ($field == 'name') {
        return $this->getSlug();
    }
    if ($field == 'description) {
        return 'foo';
    }
    return '';
}

```

If you want to use this method in your custom algorithm, you must include a dependency on `EntityTranslationDriver`.

`isGoogleTranslatable` method should return true if you want to enable Google Translations for the entity. If not present, Google Translations will be disabled under default algorithm.

If you want to use this method in your custom algorithm, you must include a dependency on `GoogleTranslationDriver`.

TranslationManager::translate() method
======================================

[](#translationmanagertranslate-method)

The most basic usage of this bundle is as follows:

```
$translationManager = $this->get('vkr_translation.translation_manager');
$translatedEntity = $translationManager->translate($entity);

```

It will return the first argument (the translatable entity), but the translatable fields will now be populated and accessible via getters. Note that cloning is not used, and the original `$entity` will be changed.

The first argument to `translate()` can be changed to an array of translatable entities, as returned by Doctrine's `findBy()` and `findAll()`. In this case, the same array of entities will be returned.

There are two more optional arguments.

The second argument is the locale string in the same format that is returned by language entity's `getCode()`. If not specified, the target language will be determined by `getCurrentLocale()` of your locale retriever service.

The third argument is the ordering column that should be the name of one of entity's translatable fields. If the first argument is an array, its elements will be reordered based on that field. Currently only ascending ordering is supported.

Because exceptions can be thrown, it is recommended to catch `TranslationException`on every call to `translate()`.

Algorithms and drivers
======================

[](#algorithms-and-drivers)

This bundle can work with multiple translation algorithms. By default, `DefaultAlgorithm` is used. You can swap algorithms by using this syntax:

```
$algorithm = $this->get('my.algorithm');
$translationManager->setAlgorithm($algorithm);

```

You can create your own algorithm by implementing `VKR\TranslationBundle\Interfaces\TranslationAlgorithmInterface`. It must contain `getTranslation()` method which must return a translation entity. While technically all external DB and API calls can be contained in the algorithm itself, it is recommended to decouple them into driver classes. A driver is a plain PHP class that handles external calls. Three drivers are shipped with the bundle: `VKR\TranslationBundle\Services\DoctrineTranslationDriver`, `VKR\TranslationBundle\Services\GoogleTranslationDriver` and `VKR\TranslationBundle\Services\EntityTranslationDriver`. The third one uses another field of a translated entity as a translation and was designed to be used as a fallback if no other translations are found. If you wish to extend the bundle, note that it is highly recommended that no classes except for algorithms depend on drivers.

Three algorithms are shipped with the bundle.

### DefaultAlgorithm

[](#defaultalgorithm)

1. The script into the DB looks for the translation into the specified locale.
2. If not found, the script looks for the translation into a locale specified by `getDefaultLocale()` method of your locale retriever.
3. If the translation into that default locale is found, and Google Translation is enabled, the script attempts to get translation into the specified locale from Google. If Google driver throws exception, translation from step 2 is returned.
4. If there is no translation neither to specified locale nor to default locale, the script attempts to retrieve just any other random translation from the DB.
5. Then, if successful, and if Google Translations is enabled, the script will try to translate that translation into the specified locale via Google. If Google driver throws exception, translation from step 4 is returned.
6. Finally, if no translations exist in the DB, the script will look for `getTranslationFallback()`method on the entity and return whatever value it returns, except for `false`.
7. If `getTranslationFallback()` does not exist or returns `false`, the script gives up and throws `TranslationException`.

### NoTranslationAlgorithm

[](#notranslationalgorithm)

This algorithm does not really translate anything, it just searches for any translation in the DB (returning the one with least PK value if there are many) and throws `TranslationException`if there are none. Second and third arguments to `TranslationManager::translate()` are not used.

### OnDemandAlgorithm

[](#ondemandalgorithm)

This algorithm behaves pretty close to `DefaultAlgorithm`, but is less persistent in trying to find a translation. It does not use third argument to `TranslationManager::translate()`.

1. The script looks into the DB for the translation into the specified locale.
2. If there is no translation to specified locale,the script attempts to retrieve just any other random translation from the DB.
3. Then, if successful, and if Google Translations is enabled, the script will try to translate that translation into the specified locale via Google. If Google driver throws exception, translation from step 2 is returned.
4. If step 2 is unsuccessful, the script gives up and throws `TranslationException`.

TranslationUpdater::updateTranslations() method
===============================================

[](#translationupdaterupdatetranslations-method)

This method provides simple interface for creating and updating translations. It has three mandatory arguments - the translatable entity, the locale, and the array of values. The basic usage example is as follows:

```
$translationUpdater = $this->get('vkr_translation.translation_updater');
$translationManager->translate($entity, 'fr', [
    'name' => 'French name',
    'description' => 'French description',
]);

```

The third argument must contain as many field-value pairs as there are translatable fields on the entity. The method searches for a translation to the given locale and updates the translatable fields, or creates a translation if it does not yet exist.

This method may also throw `TranslationException` if no getter and/or setter is found on the translation entity or if the translation entity cannot be initialized using `new`keyword.

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity10

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~11 days

Total

6

Last Release

3340d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/79f5fa971e7fda7a6180c1bdfca4f819a43b7681ec4e04c66b184a082fb5a20f?d=identicon)[wladislavk](/maintainers/wladislavk)

---

Top Contributors

[![wladislavk](https://avatars.githubusercontent.com/u/11371476?v=4)](https://github.com/wladislavk "wladislavk (11 commits)")

---

Tags

translationdoctrineSymfony2symfony3

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/vkr-translation-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/vkr-translation-bundle/health.svg)](https://phpackages.com/packages/vkr-translation-bundle)
```

###  Alternatives

[damienharper/auditor-bundle

Integrate auditor library in your Symfony projects.

4542.8M](/packages/damienharper-auditor-bundle)[data-dog/audit-bundle

Audit bundle for symfony2 and doctrine orm, logs any database change

141901.7k1](/packages/data-dog-audit-bundle)[webonaute/doctrine-fixtures-generator-bundle

Generate Fixture from your existing data in your database. You can specify the Entity name and the IDs you want to import in your fixture.

67184.1k](/packages/webonaute-doctrine-fixtures-generator-bundle)[petkopara/crud-generator-bundle

Symfony3 bundle for CRUD generation with pagination, filtering, sorting, page size, bulk delete and bootstrap3 markup. This Generator supports Doctrine association mapping.

7257.9k](/packages/petkopara-crud-generator-bundle)[damianociarla/dynamic-discriminator-map-bundle

DCSDynamicDiscriminatorMapBundle simplifies the use of Doctrine Single Table Inheritance mapping strategy in Symfony2.

1237.7k](/packages/damianociarla-dynamic-discriminator-map-bundle)[rcsofttech/audit-trail-bundle

Enterprise-grade, high-performance Symfony audit trail bundle. Automatically track Doctrine entity changes with split-phase architecture, multiple transports (HTTP, Queue, Doctrine), and sensitive data masking.

1022.4k](/packages/rcsofttech-audit-trail-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
