Problem/Motivation
In core/includes/theme.inc
, function template_preprocess_field_multiple_value_form()
:
$header = array(
array(
'data' => array(
'#prefix' => '<h4' . $header_attributes . '>',
'title' => array(
'#markup' => t($element['#title']),
),
'#suffix' => '</h4>',
...
But $element['#title']
is already translated either as TranslatableMarkup
when the field is a base field, either as translated string when the field is a config field. In the first case the page crashes with InvalidArgumentException
because t()
expects a string. In the second case it only translates an already translated string.
Proposed resolution
Remove the superfluous t()
. Remove also the un-needed nesting of #markup.
Remaining tasks
None.
User interface changes
None.
API changes
None.
Data model changes
None.
Original report, by @kevin.dutra
Not sure exactly where to slot this one, component-wise, but putting it under 'field system' for now.
Steps to reproduce
- Create an entity that has a base field that is multi-valued (e.g. CARDINALITY_UNLIMITED), like
$fields['multi_field'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Multi field label')) ->setDescription(t('Some description text.')) ->setSetting('target_type', 'user') ->setSetting('handler', 'default') ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setDisplayOptions('form', array( 'type' => 'entity_reference_autocomplete', 'weight' => 0, 'settings' => array( 'match_operator' => 'CONTAINS', 'size' => '60', 'placeholder' => '', ), )) ->setDisplayOptions('view', array( 'label' => 'above', 'type' => 'entity_reference_label', 'weight' => 0, ));
- Visit the add page
- Cry
More info
It looks like the underlying problem is that a call is made to t()
for the title in template_preprocess_field_multiple_value_form()
, but the title is a TranslatableMarkup object, not a string, so it barfs with the error:
InvalidArgumentException: $string ("Multi field label") must be a string. in Drupal\Core\StringTranslation\TranslatableMarkup->__construct() (line 83 of core/lib/Drupal/Core/StringTranslation/TranslatableMarkup.php).
Drupal\Core\StringTranslation\TranslationManager->translate(Object, Array, Array)
t(Object)
template_preprocess_field_multiple_value_form(Array, 'field_multiple_value_form', Array)
Drupal\Core\Theme\ThemeManager->render('field_multiple_value_form', Array)
Drupal\Core\Render\Renderer->doRender(Array)
Drupal\Core\Render\Renderer->doRender(Array)
Drupal\Core\Render\Renderer->doRender(Array, )
Drupal\Core\Render\Renderer->render(Array, )
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1)
Stack\StackedHttpKernel->handle(Object, 1, 1)
Drupal\Core\DrupalKernel->handle(Object)
It's probably worth noting that this doesn't happen for configured fields, just base fields.
You can sidestep the error by forcibly casting the label to a string when you're creating the base field definition, but that's a bit hokey since that translated string is then going to be translated again when it hits the preprocessor.
Also attaching a simple sample module to demonstrate. The listing page is at /admin/test.
Comment | File | Size | Author |
---|---|---|---|
#5 | 2585483-test-only.patch | 3.41 KB | claudiu.cristea |
#5 | 2585483-5.patch | 3.95 KB | claudiu.cristea |
Comments
Comment #2
kevin.dutra CreditAttribution: kevin.dutra at Workday, Inc. commentedComment #3
dawehnerSo
is certainly wrong ... can someone look which patch added it?
Comment #4
claudiu.cristea@dawehner, I tried with
$ git log --grep
against that file but I cannot find a point where this has been added.The bug affects both base and config fields but is crashing only on base fields because in that case the wrong placed t() take an object as argument, not a string
The fix is trivial. Should we add some tests?
Comment #5
claudiu.cristeaHere's a "test only" patch to prove the crash and the full patch.
I belive that this is Critical while breaks the entity add/edit form for multiple cardinality base fields.
Comment #6
claudiu.cristeaComment #9
star-szrHold on I think we have some duplication, let's combine forces: #2584837: Double translation in template_preprocess_field_multiple_value_form()
Comment #10
claudiu.cristeaMarking this as duplicate of #2584837: Double translation in template_preprocess_field_multiple_value_form().