Developed with love by KnpLabs Hire us for your project!
42

TranslationFormBundle

by a2lix

Translation field to facilitate the use of the Translatable Doctrine extension

TranslationFormBundle

What does this bundle?

Offers the possibility to easily manage the translatable fields of your entity with a new form type: 'a2lix_translations'.

This repository contains a screenshot and example code.

Requirements

Installation & Configuration

Add the repository to your composer.json

"a2lix/translation-form-bundle": "dev-master"

Run Composer to install the bundle

php composer.phar update a2lix/translation-form-bundle

Enable the bundle in AppKernel.php

new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),    // Check its existing or add
new A2lix\TranslationFormBundle\A2lixTranslationFormBundle(),

Configure the bundle in config.yml

# Check its existing or add
stof_doctrine_extensions:
    default_locale: %locale%
    orm:
        default:
            translatable: true

a2lix_translation_form:
    locales: [fr, es, de]       # [optional] Array of the translation locales (The default locale have to be excluded). Can also be specified in the form builder.
    default_required: false     # [optional] Defaults to false. In this case, translation fields are not mark as required with HTML5.
    use_aop: true               # [optional] Defaults to false.

# Template
twig:
    form:
        resources:
            - 'A2lixTranslationFormBundle::form.html.twig'

Example

Entity (example)

<?php

namespace Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Entity\Product.php
 *
 * @ORM\Table()
 * @Gedmo\TranslationEntity(class="Translation\ProductTranslation")
 */
class Product
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string $title
     *
     * @ORM\Column(name="title", type="string", length=255)
     * @Gedmo\Translatable
     */
    private $title;

    /**
     * @var string $description
     *
     * @ORM\Column(name="description", type="text")
     * @Gedmo\Translatable
     */
    private $description;

    /**
     * @ORM\OneToMany(
     *     targetEntity="Translation\ProductTranslation",
     *  mappedBy="object",
     *  cascade={"persist", "remove"}
     * )
     * @Assert\Valid(deep = true)
     */
    private $translations;

    public function __construct()
    {
        $this->translations = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     * @return Product
     */
    public function setTitle($title)
    {
        $this->title = $title;
        return $this;
    }

    /**
     * Get title
     *
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set description
     *
     * @param string $description
     * @return Product
     */
    public function setDescription($description)
    {
        $this->description = $description;
        return $this;
    }

    /**
     * Get description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Set translations
     *
     * @param ArrayCollection $translations
     * @return Product
     */
    public function setTranslations($translations)
    {
        foreach ($translations as $translation) {
            $translation->setObject($this);
        }

        $this->translations = $translations;
        return $this;
    }

    /**
     * Get translations
     *
     * @return ArrayCollection
     */
    public function getTranslations()
    {
        return $this->translations;
    }


}

Personal Translation Entity (example)

<?php

namespace Entity\Translation;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation;

/**
 * Entity\Translation\ProductTranslation.php

 * @ORM\Entity
 * @ORM\Table(name="product_translations",
 *   uniqueConstraints={@ORM\UniqueConstraint(name="lookup_unique_idx", columns={
 *     "locale", "object_id", "field"
 *   })}
 * )
 */
class ProductTranslation extends AbstractPersonalTranslation
{
    /**
     * @ORM\ManyToOne(targetEntity="Entity\Product", inversedBy="translations")
     * @ORM\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $object;
}

Form

Minimal form example:

$builder
    ->add('title')
    ->add('description')
    ->add('translations', 'a2lix_translations')
;

Advanced form example:

$builder
    ->add('translations', 'a2lix_translations', array(
        'locales' => array('fr', 'es', 'de'),   // [optional|required - depends on the presence in config.yml] See above
        'required' => true,                     // [optional] Overrides default_required if need
        'fields' => array(                      // [optional] Manual configuration of fields to display and options. If not specified, all translatable fields will be display, and options will be auto-detected
            'title' => array(
                'label' => 'name',              // [optional] Custom label. Ucfirst, otherwise
                'type' => 'textarea',           // [optional] Custom type
                **OTHER_OPTIONS**               // [optional] max_length, required, trim, read_only, constraints, ...
            ),
            'description' => array(
                'label' => 'Desc.'              // [optional]
                'locale_options' => array(              // [optional] Manual configuration of field for a dedicated locale -- Higher priority
                    'es' => array(
                        'label' => 'descripción'        // [optional] Higher priority
                        **OTHER_OPTIONS**               // [optional] Same possibilities as above
                    ),
                    'fr' => array(
                        'display' => false              // [optional] Prevent display of the field for this locale
                    )
                )
            ),
        );
    ))
;

Template

Separate the render of the default locale away from tabs of locales translation.

{{ form_widget(form.title) }}
{{ form_widget(form.description) }}

{{ form_widget(form.translations) }}

or group all locales (default and translations) in a tabs way:

{{ form_widget(form.translations, {'fields': [form.title, form.description]}) }}

More help

You can find a common use case in this repository. With translations for your collections as bonus.

There is also an article with an example on how to manage translations with SonataAdminBundle available on Elao's blog.

Thanks to

a2lix_translation_form:
locales: []
default_required: false
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Merge pull request #20 from mablae/patch-1
    By webda2l, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Update Resources/public/js/a2lix_translation.js
    By mablae, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago
  • Merge pull request #17 from Videl/patch-1
    By webda2l, 3 months ago