2

I'm searching for a simple way to edit translated fields within a symfony2 form. I'm using the doctrine knp translatable extentions for translation of the entity. The form mixes not translated with translated properties in a special order. The form should be displayed (end edit) only in the active language. For example:

 $builder
 ->add('key')
 ->add('translate1','text',array(
    'property_path' => 'translations[de].translate1',
 ))
 ->add('mynumber')
 ->add('translate2','text',array(
    'property_path' => 'translations[de].translate2',
))

If the language translations[de] does not exists i get an error: "Cannot read property "translate1" from an array... "

A2LiX Translation Form is not the solution, because it displays all translatabe fields in a single list.

Any ideas?

gp_sflover
  • 3,460
  • 5
  • 38
  • 48
Hauke
  • 257
  • 4
  • 12
  • A2LiX Translation Form "is" the solution (Is not so clear your specific use case) but you have to read the docs carefully to learn how to manipulate the translation fields and eventually apply a little workaround for your needs (and take a look at the source code to see how it works). – gp_sflover Apr 07 '15 at 12:41
  • No idea how this should work. Even if i change the fields list in A2LiX - there is just one "translations" key in the builder list. $formMapper->add('translations', 'a2lix_translations'); – Hauke Apr 07 '15 at 13:40

3 Answers3

2

If you need to display the form fields in a specific order (using A2lix) you can do it like in this example:

$builder
     ->add('key')
     ->add('mynumber')
     ->add('translations', 'a2lix_translations', [
         'required_locales' => ['de'], <-- your current locale
             'fields'           => [
                 'translate1' => [
                     # your field options
                 ],
                 'translate2' => [
                     # your field options
                 ],
    ))

Then in the view:

{% import "A2lixTranslationFormBundle::macros.html.twig" as a2lixTranslations %}

{{ form_errors(form_edit) }}
{{ form_start(form_edit) }}
{{ form_row(form_edit.key) }}    
{{ a2lixTranslations.partialTranslations(form_edit.translations, ['translate1']) }}
{{ form_row(form_edit.mynumber) }}
{{ a2lixTranslations.partialTranslations(form_edit.translations, ['translate2']) }}
{{ form_end(form_edit) }}
gp_sflover
  • 3,460
  • 5
  • 38
  • 48
  • Great - works like a charm! Never see _partialTranslations_ before. – Hauke Apr 09 '15 at 13:24
  • @Hauke Glad to be helpful :-) – gp_sflover Apr 09 '15 at 13:39
  • @gp_slover : It's work fine thanks. But is there a way to only have one tabmenu on top for all fields (translation and commun fields) ? Here is my post http://stackoverflow.com/questions/29621412/how-to-organise-translation-fields-and-commun-fields-using-symfony-a2lix-and-knp. Thank you – Benjamin Lucas Apr 14 '15 at 07:34
0

Actually i solved my problem with a custom from type with two event listeners for setting and getting translations values:

  /**
 * build fields
 * @param \Symfony\Component\Form\FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{

    /**
     * merge new translation
     */ 

    $builder->addEventListener(FormEvents::SUBMIT, function(FormEvent $event) use ($options) {

        //test
        $form = $event->getForm();//form
        $data = $event->getData();//products

        $newTranslation = $event->getData();

        $key=$options['translation_property'];

        $lang=$this->getLocale($options);

        $entity=$form->getParent()->getData();

        $setter='set'.strtoupper($key);
        $getter='get'.strtoupper($key);

        $entity->translate($lang)->$setter($newTranslation);
        $entity->mergeNewTranslations();
     });

    /**
     * Populate with data
     */ 
    $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) use ($options) {

        $data = $event->getData();//products
        $form = $event->getForm();//form

        $key=$options['translation_property'];
        $lang=$this->getLocale($options);

        $entity=$form->getParent()->getData();

        $setter='set'.strtoupper($key);
        $getter='get'.strtoupper($key);

        $oldValue=$entity->translate($lang,false)->$getter();//no fallback

        $event->setData($oldValue);

    });
}

The fields are not mapped. translation property name and language can be provided directly.

 /**
 * Defauls
 * @param \Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'translation_path'=>'translations',
        'translation_property' => null,
        'translation_lang'=>null,//getLocale or set in form type
        'mapped'=>false     
    ));
}

And type inherit form basic text.

public function getParent()
{
    return 'text';
}

After define it as a twig extension service (translation_text) you can use it quite easy:

 $builder
        ->add('name')           
        ->add('key')            
        ->add('translate1', 'translation_text',
            array(
                    'translation_property'=>'translate1',
                    'translation_lang'=>null
            ))  
Hauke
  • 257
  • 4
  • 12
0

If it possible in your case, move field in needed order. Like this:

class Foo {
    private $translate1;
    private $translate2;
}

Worked for me

Dr.X
  • 853
  • 9
  • 15