Welcome to Abdul Malik Ikhsan's Blog

Zend Framework 2 : Translate ZF2 form label and value using translatorTextDomain

Posted in Tutorial PHP, Zend Framework 2 by samsonasik on September 22, 2014

zf2-zendframework2When you work with ZF2 Form, you can translate the form element label and element value by specify translatorTextDomain. It can be applied globally on Module class so all form will be applied with its translation.
For example, We have structure of our translation like this :
zf2-form-label-translation

We can create a translation file then

<?php

return array(
    'Address' => 'Alamat', // for label "Address"
    'Create'  => 'Buat',   // for Submit value "Create" 
);

Now, let’s configure the translator in the module.config.php

return array(
    // .. other array config here

    'translator' => array(
        'locale' => 'id',
        'translation_file_patterns' => array(
            array(
                'type' => 'phpArray',
                'base_dir' => 'vendor/zendframework/zendframework/resources/languages',
                'pattern' => '%s/Zend_Captcha.php',
                'text_domain' => 'formvalidation',
            ),
            array(
                'type' => 'phpArray',
                'base_dir' => 'vendor/zendframework/zendframework/resources/languages',
                'pattern' => '%s/Zend_Validate.php',
                'text_domain' => 'formvalidation',
            ),
            
            // for label and value that we define ourself ...
            array(
                'type'     => 'phpArray',
                'base_dir' => __DIR__ . '/../translation',
                'pattern' => '%s/site.php',
                'text_domain' => 'myformlabelandvalue',
            ), 
        ),
    ),
    
    // ...
);

Ok, so, we then can create a form for that demo :

namespace TranslationSample\Form;

use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;

class SampleForm extends Form implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('sampleform');
    }
    
    public function init()
    {
        $this->add(array(
            'name' => 'address',
            'type' => 'Textarea',
            'options' => array(
                'label' => 'Address',
            ),
        ));
        
        $this->add(array(
            'type' => 'Submit',
            'name' => 'create',
            'attributes' => array(
                'value'    => 'Create',
                'class'    => 'btn btn-success',
            ),
        ));
    }
    
    public function getInputFilterSpecification()
    {
        return array(
            array(
                'name' => 'address',
                'required' => true,
                'validators' => array(

                    array(
                        'name'    => 'StringLength',
                        'options' => array(
                            'min'      => 6,
                            'max'      => 200,
                        ),
                    ),
                    
                ),
            ),
        );
    }
}

The above setup need to be fired at Module::onBootstrap :

namespace TranslationSample;

use Zend\Mvc\MvcEvent;
use Zend\Validator\AbstractValidator;

class Module
{
    public function onBootstrap(MvcEvent $event)
    {
        $application    = $event->getApplication();
        $serviceManager = $application->getServiceManager();
        $translator     = $serviceManager->get('translator');
        // for validation
        AbstractValidator::setDefaultTranslator($translator, 'formvalidation'); 
        // for form element label and value
        $serviceManager->get('ViewHelperManager')
                       ->get('formcollection')
                       ->setTranslatorTextDomain('myformlabelandvalue');
    }

    // ...
}

So, when $this->formCollection($form); is called :

$form = $this->form;
$form->prepare();

echo $this->form()->openTag($form);
echo $this->formCollection($form);
echo $this->form()->closeTag();

then the label and value will use the translatortextdomain registered like this :

formcollection-zf2-translate

If you use formLabel or formRow individually, you can apply the translatorTextDomain into it.

I uploaded the full code at my github account : https://github.com/samsonasik/TranslationSample .

NOTE : based on feedback by Manuel Stosic, we can do this for specific resource in view like :

$this->formLabel()->setTranslatorTextDomain('myformlabelandvalue');
$this->formInput()->setTranslatorTextDomain('myformlabelandvalue');
$this->formButton()->setTranslatorTextDomain('myformlabelandvalue');

References :
1. https://gist.github.com/stefanotorresi/13da4d2c8e486927a2f8
2. https://github.com/zendframework/zf2/issues/5826