Problem/Motivation
Unable to save a translation of a Message entity.
I was able to track this to ContentEntityForm::copyFormValuesToEntity()
where EntityFormDisplay::extractFormValues()
does not add 'langcode' to $extracted
. This means Message tries to set the langcode instead of skipping (a few lines down). This results in the following exception.
LogicException: The translation language cannot be changed (es). in Drupal\Core\Entity\ContentEntityBase->onChange() (line 822 of core/lib/Drupal/Core/Entity/ContentEntityBase.php).
Drupal\Core\Entity\Plugin\DataType\EntityAdapter->onChange('langcode') (Line: 80)
Drupal\Core\TypedData\Plugin\DataType\ItemList->setValue(Array, 1) (Line: 107)
Drupal\Core\Field\FieldItemList->setValue(Array, 1) (Line: 628)
Drupal\Core\Entity\ContentEntityBase->set('langcode', 'en') (Line: 341)
Drupal\Core\Entity\ContentEntityForm->copyFormValuesToEntity(Object, Array, Object) (Line: 293)
Drupal\Core\Entity\EntityForm->buildEntity(Array, Object) (Line: 155)
Drupal\Core\Entity\ContentEntityForm->buildEntity(Array, Object) (Line: 186)
Drupal\Core\Entity\ContentEntityForm->validateForm(Array, Object)
call_user_func_array(Array, Array) (Line: 82)
Drupal\Core\Form\FormValidator->executeValidateHandlers(Array, Object) (Line: 275)
Drupal\Core\Form\FormValidator->doValidateForm(Array, Object, 'message_in_platform_notification_add_form') (Line: 118)
Drupal\Core\Form\FormValidator->validateForm('message_in_platform_notification_add_form', Array, Object) (Line: 591)
Drupal\Core\Form\FormBuilder->processForm('message_in_platform_notification_add_form', Array, Object) (Line: 323)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'add', Array) (Line: 400)
Drupal\content_translation\Controller\ContentTranslationController->add(Object, Object, Object, 'message')
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 169)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 49)
Asm89\Stack\Cors->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 718)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)Drupal\Core\Entity\Plugin\DataType\EntityAdapter->onChange('langcode') (Line: 80)
Drupal\Core\TypedData\Plugin\DataType\ItemList->setValue(Array, 1) (Line: 107)
Drupal\Core\Field\FieldItemList->setValue(Array, 1) (Line: 628)
Drupal\Core\Entity\ContentEntityBase->set('langcode', 'en') (Line: 341)
Drupal\Core\Entity\ContentEntityForm->copyFormValuesToEntity(Object, Array, Object) (Line: 293)
Drupal\Core\Entity\EntityForm->buildEntity(Array, Object) (Line: 155)
Drupal\Core\Entity\ContentEntityForm->buildEntity(Array, Object) (Line: 186)
Drupal\Core\Entity\ContentEntityForm->validateForm(Array, Object)
call_user_func_array(Array, Array) (Line: 82)
Drupal\Core\Form\FormValidator->executeValidateHandlers(Array, Object) (Line: 275)
Drupal\Core\Form\FormValidator->doValidateForm(Array, Object, 'message_in_platform_notification_add_form') (Line: 118)
Drupal\Core\Form\FormValidator->validateForm('message_in_platform_notification_add_form', Array, Object) (Line: 591)
Drupal\Core\Form\FormBuilder->processForm('message_in_platform_notification_add_form', Array, Object) (Line: 323)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'add', Array) (Line: 400)
Drupal\content_translation\Controller\ContentTranslationController->add(Object, Object, Object, 'message')
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 169)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 49)
Asm89\Stack\Cors->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 718)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Steps to reproduce
- Create a message template.
- Add a field.
- Make it translatable.
- I set the message template's "message text" to a token representing this field, but I think that is optional to reproduce. (eg, [message:field_translatable_field]).
- Add a new message.
- Translate the message, and save.
Proposed resolution
Remove the 'langcode' form element. If we want to target a message to a particular language, we can add a field on the template and fill it out when saving the message. See patch.