php - Translate custom form type in symfony2

27

I'm trying to create a custom form type in Symfony (2.7), in order to add an help_block (Boostrap 3 style) to some of my forms fields.

I followed this page instructions : http://symfony.com/doc/current/cookbook/form/create_form_type_extension.html

Displaying is OK, help_block works fine, but it is not translatable, (dev bar not showing any missing translation). So there is my question : How can I make a custom form type translatable, like the label option, and if possible, in the same translation_domain than the form?

Here is the extension code:

<?php

namespace WIC\MasterBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * Add a BootStrap Help block to any form field
 */
class HelpTextExtension extends AbstractTypeExtension
{

    /**
     * Returns the name of the type being extended.
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType() {
        return 'form';
    }

    /**
     * Add the help_text option
     *
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefined(array('help_text'));
        $resolver->setDefault('help', null);
    }

    /**
     * Pass the Help Text to the view
     *
     * @param FormView $view
     * @param FormInterface $form
     * @param array $options
     */
    public function buildView(FormView $view, FormInterface $form, array $options) {
        $view->vars['help_text'] = $form->getConfig()->getAttribute('help_text');
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
        if (array_key_exists('help_text', $options)) {
            $builder->setAttribute('help_text', $options['help_text']);
        }
    }

}

And my template override:

{% extends 'bootstrap_3_horizontal_layout.html.twig' %}

{% block form_row -%}
  {% spaceless %}
    <div >
      {{ form_label(form) }}
      <div >
        {{ form_widget(form) }}
        {{ form_errors(form) }}
        {% if help_text is not null %}
          <span >{{ help_text }}</span>
        {% endif %}
      </div>
    </div>
  {% endspaceless %}
{%- endblock form_row %}

Thanks in advance for any help,

Best regards

776

Answer

Solution:

You can add translations like in other places, just fill the label.

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('title', 'text', [
            'label' => 'rpr.page.title', // <- any string can be there
        ]);
}

The default translation domain is 'messages', to change add 'translation_domain' to you configureOptions

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
       'data_class'         => 'Acme\Entity\DemoEntity',
       'translation_domain' => 'forms'
    ]);
}

Of course you then need to create the translation files in the right place:AcmeBundle\Resources\translations

Important things to note: - when you create new translation files in yourAcmeBundle\Resources\translations like forms.de.yml you need to clear the cache even in development.

docs here: http://symfony.com/doc/current/reference/forms/types/form.html#translation-domain

532

Answer

Solution:

a) set locale parameter and enable translation in config.yml

parameters:
    locale: en

framework:
    #esi:             ~
    translator:      { fallbacks: ["%locale%"] }

b) create custom form type. I created the GenderType from the docs.

c) extend the custom form type with a constructor to get access to the translator and use the translater where you want to:

namespace AppBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Translation\Translator;

class GenderType extends AbstractType
{
    private $translator;

    public function __construct(Translator $translator)
    {
        $this->translator = $translator;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'choices' => array(
                'm' => $this->translator->trans('user.male'),
                'f' => $this->translator->trans('user.female'),
            )
        ));
    }

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

    public function getName()
    {
        return 'gender';
    }
}

d) Create your Field Type as a Service

// app/config/services.yml
services:
    app.form.type.gender:
        class: AppBundle\Form\Type\GenderType
        arguments:
            - @translator.default
        tags:
            - { name: form.type, alias: gender }

e) Create a translationfile:

// src/AppBundle/Resources/translations/user.en.yml
user:
    creation: Create User
    gender: Gender
    male: Male
    female: Female

f) Extend your formType (e.g. UserType). Make sure that you pass the fieldtype by the 'gender' service-alias that you created at step d. Also set the label and the translation_domain options for each field.

// src/AppBundle/Form/UserType.php
namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use AppBundle\Form\Type\GenderType;

class UserType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('gender', 'gender', array('label' => 'user.gender', 'translation_domain' => 'user'))
            // and more fields
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'appbundle_user';
    }
}

g) add trans_default_domain to your twig templates and translate whatever you want to translate. Example:

{% extends '::base.html.twig' %}

{% trans_default_domain 'user' %}

{% block body -%}
    <h1>{{ 'user.creation'|trans }}</h1>

    {{ form(form) }}

{% endblock %}

People are also looking for solutions to the problem: php - Make field required only if other field is filled out

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.