Zend Framework

Zend_Form_Decorator_Label Attempts to Translate Labels Twice

Details

Description

There exists an issue with Zend_Form translating labels which becomes apparent when Zend_Translate logging is enabled.

When a form is rendered the form loops through the decorators running their render method. The following code is called as a result of rendering the label.

Zend_Form_Decorator_Label Line #253

$label = $element->getLabel();
        $label = trim($label);

        if (empty($label)) {
            return '';
        }

        if (null !== ($translator = $element->getTranslator())) {
            $label = $translator->translate($label);
        }

The above code retrieves the label from the element object and the runs validation methods and then proceeds to translate the message. Below is the code for the $element->getLabel() method.

Zend_Form_Element Line #606

public function getLabel()
    {
        $translator = $this->getTranslator();
        if (null !== $translator) {
            return $translator->translate($this->_label);
        }

        return $this->_label;
    }

As you can see this method ALSO translates the text before sending it back to the decorator. This means the Element object is returning translated text back to the decorator which then is attempting to translate already translated text. This causes the Zend_Translate class to log a notice in its log file notifying the user it is missing a translation.

The fix is an obvious one, simply removing the duplicate code from the Zend_Form_Decorator_Label dealing with translation will solve the problem as their corresponding elements should already be translating the content for them.

Please note this also is affecting the Submit button and I have not been able to trace which decorator is causing that problem, although I assume the problem is the same. You will probably want to check through all of the decorators to check if any others are doing the same.

Brad

Issue Links

Activity

Hide
purple ankh added a comment -

With reference to the final note about the Submit button, this has been reported as ZF-8764.

Show
purple ankh added a comment - With reference to the final note about the Submit button, this has been reported as ZF-8764.
Hide
Ivan Krechetov added a comment -

For us this issue is very important, as far as we have an interactive translation mode. It allows to change the site texts right where you see them in the graphical user interface. To do this we have to append stuff to translated strings on the runtime. Like this:

<?php

set_include_path(
    implode(
        PATH_SEPARATOR,
        array(dirname(__FILE__) . '/library', get_include_path())
    )
);

require_once 'Zend/Loader/Autoloader.php';

Zend_Loader_Autoloader::getInstance()->registerNamespace('Zend_');

class TrickyAdapter extends Zend_Translate_Adapter_Array {
    public function translate($messageId, $locale = null) {
        return parent::translate($messageId, $locale) . '[XY]';
    }
}

Zend_Registry::set(
    'Zend_Translate',
    new Zend_Translate('TrickyAdapter', array('en' => array()))
);

function simple_form() {
    return new Zend_Form(
        array(
            'method' => 'post',
            
            'elements' => array(
                'title' => array(
                    'type' => 'text',
                    
                    'options' => array(
                        'label' => 'Bug title',
                    )
                ),
                
                'submit' => array(
                    'type' => 'button',
                    'options' => array(
                        'label' => 'Send',
                        'type' => 'submit',
                    )
                ),
            )
        )
    );
}

echo "\n" . simple_form()->render(new Zend_View()) . "\n\n";

Under ZF 1.9.7 the code above outputs:

<form enctype="application/x-www-form-urlencoded" method="post" action=""><dl class="zend_form">
<dt id="title-label"><label for="title" class="optional">Bug title[XY]</label></dt>
<dd id="title-element">
<input type="text" name="title" id="title" value=""></dd>
<dt id="submit-label">&nbsp;</dt><dd id="submit-element">
<button name="submit" id="submit" type="submit">Send[XY]</button></dd></dl></form>

While under ZF 1.10.0 and 1.10.1 it's:

<form enctype="application/x-www-form-urlencoded" method="post" action=""><dl class="zend_form">
<dt id="title-label"><label for="title" class="optional">Bug title[XY][XY]</label></dt>
<dd id="title-element">
<input type="text" name="title" id="title" value=""></dd>
<dt id="submit-label">&nbsp;</dt><dd id="submit-element">
<button name="submit" id="submit" type="submit">Send[XY][XY]</button></dd></dl></form>
Show
Ivan Krechetov added a comment - For us this issue is very important, as far as we have an interactive translation mode. It allows to change the site texts right where you see them in the graphical user interface. To do this we have to append stuff to translated strings on the runtime. Like this:
<?php

set_include_path(
    implode(
        PATH_SEPARATOR,
        array(dirname(__FILE__) . '/library', get_include_path())
    )
);

require_once 'Zend/Loader/Autoloader.php';

Zend_Loader_Autoloader::getInstance()->registerNamespace('Zend_');

class TrickyAdapter extends Zend_Translate_Adapter_Array {
    public function translate($messageId, $locale = null) {
        return parent::translate($messageId, $locale) . '[XY]';
    }
}

Zend_Registry::set(
    'Zend_Translate',
    new Zend_Translate('TrickyAdapter', array('en' => array()))
);

function simple_form() {
    return new Zend_Form(
        array(
            'method' => 'post',
            
            'elements' => array(
                'title' => array(
                    'type' => 'text',
                    
                    'options' => array(
                        'label' => 'Bug title',
                    )
                ),
                
                'submit' => array(
                    'type' => 'button',
                    'options' => array(
                        'label' => 'Send',
                        'type' => 'submit',
                    )
                ),
            )
        )
    );
}

echo "\n" . simple_form()->render(new Zend_View()) . "\n\n";
Under ZF 1.9.7 the code above outputs:
<form enctype="application/x-www-form-urlencoded" method="post" action=""><dl class="zend_form">
<dt id="title-label"><label for="title" class="optional">Bug title[XY]</label></dt>
<dd id="title-element">
<input type="text" name="title" id="title" value=""></dd>
<dt id="submit-label">&nbsp;</dt><dd id="submit-element">
<button name="submit" id="submit" type="submit">Send[XY]</button></dd></dl></form>
While under ZF 1.10.0 and 1.10.1 it's:
<form enctype="application/x-www-form-urlencoded" method="post" action=""><dl class="zend_form">
<dt id="title-label"><label for="title" class="optional">Bug title[XY][XY]</label></dt>
<dd id="title-element">
<input type="text" name="title" id="title" value=""></dd>
<dt id="submit-label">&nbsp;</dt><dd id="submit-element">
<button name="submit" id="submit" type="submit">Send[XY][XY]</button></dd></dl></form>
Hide
Joakim Nygård added a comment -

The question is whether the translation should be restricted to the element's or the Label decorator's getLabel() method. I think it makes the most sense to place the translation in the decorator - as close to the user as possible, but I am not sure if this change will break anything depending on the element doing the translation.

Show
Joakim Nygård added a comment - The question is whether the translation should be restricted to the element's or the Label decorator's getLabel() method. I think it makes the most sense to place the translation in the decorator - as close to the user as possible, but I am not sure if this change will break anything depending on the element doing the translation.
Hide
Tomáš Fejfar added a comment -

The only legitimate place to translate the value is where the value is received - i.e. in element's getLabel() method. Decorator's purpose is to receive some value and wrap it around the current content. Not tu modify it in any way.

Show
Tomáš Fejfar added a comment - The only legitimate place to translate the value is where the value is received - i.e. in element's getLabel() method. Decorator's purpose is to receive some value and wrap it around the current content. Not tu modify it in any way.
Hide
Nicolae Dima added a comment -

This can be fixed fast, by commenting these lines

  • Zend_Form_Element_Submit - Line 80 to 83 <-- These most be also commented since you already call the parent method get label, which will result in a double translation from Zend_Form_Element
  • Zend_Form_Decorator_Label - Line 260 to 263 <-- Decorator should not be used for translation, it is out of purpose
Show
Nicolae Dima added a comment - This can be fixed fast, by commenting these lines
  • Zend_Form_Element_Submit - Line 80 to 83 <-- These most be also commented since you already call the parent method get label, which will result in a double translation from Zend_Form_Element
  • Zend_Form_Decorator_Label - Line 260 to 263 <-- Decorator should not be used for translation, it is out of purpose
Hide
Holger Schletz added a comment -

OK, it's bug hunt days again. Time to bump this issue. Any chance to see it fixed this time? It's been around for ages, as well as the proposed simple fix, like in the previous comment.

BTW, the issue with Zend_Form_Element_Submit has been silently fixed in the meantime, but it still occurs with Zend_Form_Decorator_Label.

Show
Holger Schletz added a comment - OK, it's bug hunt days again. Time to bump this issue. Any chance to see it fixed this time? It's been around for ages, as well as the proposed simple fix, like in the previous comment. BTW, the issue with Zend_Form_Element_Submit has been silently fixed in the meantime, but it still occurs with Zend_Form_Decorator_Label.
Hide
Kim Blomqvist added a comment -

Patch attached. Holger - where did you check that the issue with Zend_Form_Element_Submit has been already fixed. It wasn't in my trunk.

Show
Kim Blomqvist added a comment - Patch attached. Holger - where did you check that the issue with Zend_Form_Element_Submit has been already fixed. It wasn't in my trunk.
Hide
Holger Schletz added a comment -

It has not been fixed in Zend_Form_Element_Submit itself - in fact, removing the translate() call there would result in an untranslated label. Something else in the code path has changed so that now only Zend_Form_Decorator_Label is still affected.

I don't know where this change has been made and whether the new behavior is intentional or just happened to stop the bug from occurring. The facts are: with the current implementation, the label gets translated once for Zend_Form_Element_Submit::getLabel() (correct) and twice for Zend_Form_Decorator_Label::getLabel() (incorrect). This might need more investigation, but removing the translate() call from Zend_Form_Decorator_Label::getLabel() would at least be an interim solution that actually works. It could easily be reverted if it turns out to be the wrong place for the fix.

The fix has been proposed and known to work flawlessly by several users for a long time, so I think it would be safe to provide it as a working solution. There are already discussions about restructuring and where translations should actually be done, but that's more of a long term goal.

Show
Holger Schletz added a comment - It has not been fixed in Zend_Form_Element_Submit itself - in fact, removing the translate() call there would result in an untranslated label. Something else in the code path has changed so that now only Zend_Form_Decorator_Label is still affected. I don't know where this change has been made and whether the new behavior is intentional or just happened to stop the bug from occurring. The facts are: with the current implementation, the label gets translated once for Zend_Form_Element_Submit::getLabel() (correct) and twice for Zend_Form_Decorator_Label::getLabel() (incorrect). This might need more investigation, but removing the translate() call from Zend_Form_Decorator_Label::getLabel() would at least be an interim solution that actually works. It could easily be reverted if it turns out to be the wrong place for the fix. The fix has been proposed and known to work flawlessly by several users for a long time, so I think it would be safe to provide it as a working solution. There are already discussions about restructuring and where translations should actually be done, but that's more of a long term goal.
Hide
Holger Schletz added a comment -

Somewhere between 1.11.7 and 1.11.10, a change to Zend_Form_Element_Submit was introduced. The label no longer gets translated if the patch to Zend_Form_Decorator_Label is applied. If that patch is reverted, the problem with the double-translated labels shows up again.

An updated patch that works for 1.11.10 is available at http://svn.savannah.nongnu.org/viewvc/*checkout*/trunk/development/Zend.diff?root=braintacle

Show
Holger Schletz added a comment - Somewhere between 1.11.7 and 1.11.10, a change to Zend_Form_Element_Submit was introduced. The label no longer gets translated if the patch to Zend_Form_Decorator_Label is applied. If that patch is reverted, the problem with the double-translated labels shows up again. An updated patch that works for 1.11.10 is available at http://svn.savannah.nongnu.org/viewvc/*checkout*/trunk/development/Zend.diff?root=braintacle
Hide
Sebastian added a comment -

The updated patch of Holger works also fine for me in v1.11.11. Thanks!

Show
Sebastian added a comment - The updated patch of Holger works also fine for me in v1.11.11. Thanks!
Hide
Michael Boke added a comment -

Got an entire day wasted figuring out why my label is translated into the wrong text.

For example we got a tag english "or"
Translated to dutch to "of"
Got translated again english "of" to "van"

Please fix this with the remove translate from the decorator label.
That seems to be the right solution.

btw the latest svn revision 24561 still has this problem

Show
Michael Boke added a comment - Got an entire day wasted figuring out why my label is translated into the wrong text. For example we got a tag english "or" Translated to dutch to "of" Got translated again english "of" to "van" Please fix this with the remove translate from the decorator label. That seems to be the right solution. btw the latest svn revision 24561 still has this problem
Hide
Rafael Tavares Amorim added a comment -

Removing the translate code block from:
Form/Decorator/Label.php
Form/Decorator/Description.php
Form/Element/Submit.php

Since translate happen in Form/Element.php, It works fine in my application and solve this issue in v1.11.11 i believe

Show
Rafael Tavares Amorim added a comment - Removing the translate code block from: Form/Decorator/Label.php Form/Decorator/Description.php Form/Element/Submit.php Since translate happen in Form/Element.php, It works fine in my application and solve this issue in v1.11.11 i believe

People

Vote (26)
Watch (19)

Dates

  • Created:
    Updated: