ZF-11831: Form's default translator incorrectly passed to subforms, causing override of subform elements' default translators

Description

If a form is validated, the translator of the form will be passed through all subforms. It's the same bug as ZF-9330 (for form elements) which was resolved long ago except that subforms were left out while fixing.

Only add "$this->hasTranslator()" in Form.php line 2261 (1.11.11) as it was done in line 2246 for elements

    foreach ($this->getSubForms() as $key => $form) {
        if (null !== $translator && $this->hasTranslator()
                && !$form->hasTranslator()) {

Comments

The Form/SubForm case is a special one. As a Form and an Element are completely separate entities, they can each have their own default translators (set via {{setDefaultTranslator}} method). However, SubForm is a sub-class of Form, and since the default translator is stored in a static class variable of {{Zend_Form}}, all forms and sub-forms share the same default translator. Determining an element's translator is a four step process:

If a validator was set with {{setValidator}}, return it.

If no validator was set, but a default validator was set with {{setDefaultValidator}}, return it.

If no default validator was set either, look up the key {{Zend_Validate}} in {{Zend_Registry}} and return it.

If no key {{Zend_Validate}} exists in {{Zend_Registry}}, return null

The only case where your suggested addition would make an impact is when {{$this->hasTranslator()}} is false while the two existing conditions are true. In this case, {{$translator}} contains the default translator instance, and that instance is passed down to all the sub-forms. Since all forms (both Form and SubForm) always have the same default translator definition, that's not a problem. I've attached a patch with a unit test showing this behaviour.

Unless you can provide a specific example where the existing behavior is a problem, I will recommend that this issue be closed as "Not an Issue".

Let me try to explain:

during initalisation I'm setting up two translation objects: "Zend_Registry::set('Zend_Translate', $translate)" [1] to my own Tramslate Object and setting a Default Translater for Validate: Zend_Validate_Abstract::setDefaultTranslator( $validateTranslation ); [2]

If a form exists with 2 elements and an additional subform with 2 elements (all 4 elements with a float validator for example) the error message of the elements of the form are translated by [2 - Default Translator of Zend_Validate] while the elements of the subform are translated by [1, cause the default Validation Translator is overwritten by the subform translator]

@Bjoern:

Aha! I figured I was missing the point, but I couldn't see where at the time. The attached test (ZF-11831_v2.patch) should reproduce the issue you are seeing. The result when I run it against trunk is:


There was 1 failure:

1) Zend_Form_FormTest::testElementsOfSubFormReceiveCorrectDefaultTranslator
SubForm element received wrong validator
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-Element
+Default

After adapting the fix applied in ZF-9364 for elements to this case:


Index: library/Zend/Form.php
===================================================================
--- library/Zend/Form.php       (revision 24514)
+++ library/Zend/Form.php       (working copy)
@@ -2254,7 +2254,8 @@
             }
         }
         foreach ($this->getSubForms() as $key => $form) {
-            if (null !== $translator && !$form->hasTranslator()) {
+            if (null !== $translator && $this->hasTranslator()
+                    && !$form->hasTranslator()) {
                 $form->setTranslator($translator);
             }
             if (isset($data[$key]) && !$form->isArray()) {

The failing test above passes, as does the entire {{Zend_Form}} suite.

Thanks for your help and patience in sorting this issue out!

Fixed in trunk r24515 Merged to release-1.11 in r24516 r24517.