New non translatable field on translatable content throws error

Created on 10 January 2019, almost 6 years ago
Updated 18 September 2024, about 2 months ago

Problem/Motivation

Even when access is denied to a widget, the value submitted propagates to the entity built from the sum of widgets.

Steps to reproduce

  1. Enable at least content translation and content moderation modules and some entity providing module, node is typical.
  2. Set Hide non translatable fields on translation forms on the content translation admin form.
  3. Create an entity.
  4. Now add a nontranslatable field with a non-null default value.
  5. Try to add a non-default revision translation of the entity.
  6. Kaboom courtesy of EntityUntranslatableFieldsConstraint as the non-null value changes to the default. (error message "Non-translatable fields can only be changed when updating the original language.")

Proposed resolution

Don't let widgets pass their values when access is denied to them.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Original report by pavlosdan

We use *Paragraphs + Content Moderation + Translations*. We have a lot of content that is moderated and translated. We've added a new field in one of the paragraphs that did not need to be translatable (it's a checkbox that should be the same across translations) but we noticed that if a user attempts to edit existing published translated content holding said paragraph type prior to the original having a value for that field then the system throws a "Non translatable fields can only be changed when updating the current revision" error.

So far the only workarounds we could think of was to make the field translatable even though it didn't need to be.

Another possibility would be to remove the constraint as suggested here: https://www.drupal.org/project/drupal/issues/2955321#comment-12541730 🐛 Unable to change non-translatable field value on translatable content with content moderation enabled Needs work but we didn't test this.

Your thoughts on this would be greatly appreciated. :)

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Entity 

Last updated about 7 hours ago

Created by

🇨🇦Canada pavlosdan

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇨🇭Switzerland tcrawford

    I have applied patch #79 and tested. I am seeing warnings and errors though in core (and in paragraphs) when using the paragraphs module together with this patch.

    If I re-save the node in the original language before saving the translation, I see the following warning:

    ```
    Warning: Undefined array key "original_deltas" in Drupal\Core\Field\WidgetBase->flagErrors() (line 474 of core/lib/Drupal/Core/Field/WidgetBase.php).
    Drupal\Core\Field\WidgetBase->flagErrors(Object, Object, Array, Object) (Line: 2210)
    Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget->flagErrors(Object, Object, Array, Object) (Line: 270)
    Drupal\Core\Entity\Entity\EntityFormDisplay->flagWidgetsErrorsFromViolations(Object, Array, Object) (Line: 268)
    Drupal\Core\Entity\ContentEntityForm->flagViolations(Object, Array, Object) (Line: 214)
    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, 'node_article_form') (Line: 118)
    ```
    If I don't resave the node in the original language first, but add a translation, I get the following TypeError.
    ```
    The website encountered an unexpected error. Please try again later.
    TypeError: Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget::errorElement(): Argument #1 ($element) must be of type array, null given, called in /app/docroot/core/lib/Drupal/Core/Field/WidgetBase.php on line 478 in Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget->errorElement() (line 2217 of modules/contrib/paragraphs/src/Plugin/Field/FieldWidget/ParagraphsWidget.php).
    Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget->errorElement(NULL, Object, Array, Object) (Line: 478)
    Drupal\Core\Field\WidgetBase->flagErrors(Object, Object, Array, Object) (Line: 2210)
    Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget->flagErrors(Object, Object, Array, Object) (Line: 270)
    Drupal\Core\Entity\Entity\EntityFormDisplay->flagWidgetsErrorsFromViolations(Object, Array, Object) (Line: 268)
    Drupal\Core\Entity\ContentEntityForm->flagViolations(Object, Array, Object) (Line: 214)
    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, 'node_article_form') (Line: 118)
    Drupal\Core\Form\FormValidator->validateForm('node_article_form', Array, Object) (Line: 591)
    Drupal\Core\Form\FormBuilder->processForm('node_article_form', Array, Object) (Line: 323)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
    Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'default', Array) (Line: 394)
    Drupal\content_translation\Controller\ContentTranslationController->add(Object, Object, Object, 'node')
    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: 68)
    Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->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: 713)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

  • Status changed to Needs work over 1 year ago
  • 🇺🇸United States smustgrave

    Seems there was an error in #80, what steps did you follow?

    Testing on Drupal 10.1 with a standard install
    Added a date field to the basic page content type with a default value of current date.
    Installed content translation module
    Translating basic page but unchecking date field and checking hide non translatable fields
    Create a page leaving date as default
    Save
    Translate to another language
    Am able to save without failure

    Added a 2nd field to the basic page content type with a default value
    Still able to translate without issue

    Can someone provide new testing steps.

  • 🇩🇪Germany Anybody Porta Westfalica

    Closed 🐛 Message "Non-translatable fields can only be changed when updating the original language." without specifying the concerning fields Closed: duplicate as duplicate. I agree that at least naming the affected field in the error message would be helpful to find out, what's wrong.

  • 🇩🇪Germany Anybody Porta Westfalica
  • 🇺🇦Ukraine lobodacyril

    Comment #75 worked form me. Thank you.

  • 🇧🇪Belgium herved

    #32 indeed a new untranslatable boolean field with previously existing translations is enough to cause this.
    Upon saving one of the translations we get the error message.
    The EntityUntranslatableFieldsConstraintValidator can trigger for other reasons but this here is one of them and can happen with just nodes.

    Here are my steps:
    - Install standard drupal profile
    - At /admin/modules: Enable the content translation module
    - At /admin/config/regional/language: add a language
    - At /admin/config/regional/content-language: enable translation for Content > Article + check "Hide non translatable fields on translation forms"
    - At /node/add/article: add an article node (just the title is enough) + create a translation
    - At /admin/structure/types/manage/article/fields/add-field: create a new boolean field (leave it as untranslatable)
    - Go back to the node translation edit form, update the title and attempt to save > we get "Non-translatable fields can only be changed when updating the original language."

    EntityUntranslatableFieldsConstraintValidator will return TRUE for hasUntranslatableFieldsChanges because the boolean field items went from nothing to something (a BooleanItem with [value => FALSE]. It will then trigger the error if hasTranslationChanges returns TRUE, which it will if changes are detected on any translatable fields (e.g: title).
    Breakpoints here and there help.

    Patch #79 works for me, thanks.

  • 🇺🇸United States amaisano Boston

    I am experiencing this issue but with a slightly different context.

    None of the patches here worked.

    Similar to https://www.drupal.org/project/drupal/issues/3026055 (no solution), I have a taxonomy term in English that has a File (Image) field that has a value for it. In my content translation settings, I have the term's Image field marked as translatable because we need to alter the ALT text for it per language, but the "File" attribute is UNchecked, because we don't need a different image per language.

    On the French translation of this term, I cannot save any changes due to the "Non-translatable field elements can only be changed when updating the original language" error.

    If I go back to the English version and remove the image (and save the English version), then I can once again make changes to fields and save the French translation without problems.

  • It's work for me.

    I have had checkbox field and At first didn't work but when I remove field and add other type(date) starts work. :)

    Single on/off checkbox(Img1) must be Check boxes/radio buttons(img2) and all work.

    I don't know about taxonomy term but maybe it will work for term.

  • Or you can use patch this patch.

  • last update about 1 year ago
    Patch Failed to Apply
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MariaDB 10.3.22
    last update about 1 year ago
    30,343 pass
  • Status changed to Needs review about 1 year ago
  • last update about 1 year ago
    30,213 pass, 99 fail
  • 🇮🇳India _utsavsharma

    #88 failed to apply .

  • Status changed to Needs work about 1 year ago
  • 🇺🇸United States smustgrave

    Wasn’t able to replicate but maybe test coverage will show it better. That will be needed

  • Patches don't work correctly(drupal 9.5/10).

    Reproduce

    1. Site is multilingual (there are 3 languages)
    2. Create field in the Article CT which type is link(non translatable, unlimited)
    3. Need only URL (Allow link text is disabled )
    4. create new Article and set 3-4 ULRs(working great)
    5. Translate node and click save
    6. Throw errors (img)
    7. 2th time we can't translate the same translation.
  • 🇩🇪Germany stborchert

    Hey. We use the latest patch and it breaks creating content when using content moderation for content types.

    Steps to reproduce

    :

    • setup a default workflow for content moderation ("Draft", "Published")
    • set the initial state to "Draft"
    • select a content type (e.g. "Page") to use the workflow
    • go to node/add/page (or whatever your selected content type has been named)
    • do no update the workflow state (leave as "Draft")
    • save the node

    This will result in

    EntityStorageException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'status' cannot be null ... 
    

    This happens because the patch explicitly sets the value of field "status" to NULL:

    $items->setValue(NULL);
    

    This is wrong for fields that must not be null (based on their schema), e.g. for "status" null-values are not allowed.

  • 🇪🇸Spain akalam

    I can't reproduce the bug anymore following the steps from #46 on drupal 10.2

  • 🇺🇦Ukraine loon Lutsk

    Updated patch #79 with fix the issue described in #92

  • 🇺🇸United States mgaskey

    Anyone still experiencing this issue using D10.2+ and content moderation should note that the latest patch in #94 will fail as the code is already added to Core.

    We experienced the effects of the current issue after having added a boolean field to all content types, which all have translations enabled. We could not save a new translation without manually saving the base node first.

    The patch in https://www.drupal.org/project/drupal/issues/2955321 🐛 Unable to change non-translatable field value on translatable content with content moderation enabled Needs work (#77) fixes the issue for us.

  • 🇨🇦Canada joseph.olstad

    an easy workaround for this is to put a non-translatable field for each language in your paragraph.

    example:

    paragraph bundle:
    fields:
    field_example
    field_example_fr
    field_example_de

    field_example2
    field_example2_fr
    field_example2_de

    then preprocess the fields to display when desired.

  • Still happening 6 years later in in the latest D10. Is there a stock in drupal I can invest in?

  • 🇨🇦Canada joseph.olstad

    We've hit this on a project that uses D10.2.5 and the paragraphs module.

    The patch has tests.

    We're currently reviewing patch #94 which so far is helping.

  • Pipeline finished with Canceled
    2 months ago
    Total: 122s
    #274709
  • 🇨🇦Canada joseph.olstad

    Merged the latest 11.x into MR1105

    Pushed up the fix that was added in patch 94

  • Status changed to Needs review 2 months ago
  • Assigned to joseph.olstad
  • Status changed to Active 2 months ago
  • 🇨🇦Canada joseph.olstad

    MR 1105 , I am unable to correct the branch, it should be for an 11.x merge

    I'll create a new MR for 11.x

  • Pipeline finished with Failed
    2 months ago
    Total: 511s
    #274711
  • Pipeline finished with Failed
    2 months ago
    Total: 137s
    #274729
  • Pipeline finished with Failed
    2 months ago
    Total: 157s
    #274743
  • Issue was unassigned.
  • Status changed to Needs review 2 months ago
  • 🇨🇦Canada joseph.olstad

    The MR 9429 patch is a reroll of patch 94, almost identical except for some fuzz.

    MR9429 is targetting 11.x , the others were tainted/OR not targetting 11.x and tainted with unrelated commits and noise.

    MR9429 is clean and only includes the desired changes with the new test case.

  • 🇨🇦Canada joseph.olstad

    PHPUnit version 10 deprecations forced a couple changes to the test to the MR9429

  • Pipeline finished with Failed
    2 months ago
    Total: 166s
    #274755
  • Pipeline finished with Failed
    2 months ago
    Total: 161s
    #274770
  • Pipeline finished with Failed
    2 months ago
    Total: 159s
    #274801
  • 🇨🇦Canada joseph.olstad

    Pipeline seems to have gone bonkers.

    Undefined variable: $this

    Makes no sense.

  • 🇨🇭Switzerland berdir Switzerland

    You made the test method static. That's wrong.

  • Pipeline finished with Success
    2 months ago
    Total: 8574s
    #276042
  • 🇨🇦Canada joseph.olstad

    Pipeline for MR 9429 passed and is green (YAY!).

    https://git.drupalcode.org/issue/drupal-3025039/-/pipelines/276042

    Running the tests-only job now, normally expect it to fail.

  • Status changed to RTBC 2 months ago
  • 🇨🇦Canada joseph.olstad
    1. MR has tests
    2. MR pipeline passes tests
    3. MR pipeline tests-only test is failing as expected
    4. Patch is fixing this issue in the wild
  • 🇺🇦Ukraine Foxy-vikvik

    We need to add a condition if the <?PHP
    !empty($widget)
    ?>

  • 🇺🇦Ukraine Foxy-vikvik

    Patched based on the "patch for the comment #94": https://www.drupal.org/project/drupal/issues/3025039#comment-15576672 🐛 New non translatable field on translatable content throws error Needs work

    for Drupal 10.3

  • Status changed to Needs work 2 months ago
  • 🇳🇿New Zealand quietone

    @foxy-vikvik, can you provide the steps that caused the null value? That is needed to ensure the test is robust. Also, uploading screenshots of your IDE is not something we do in the Drupal core issue queue.

    I have only noticed the last two comments and am setting back to Needs Works so that get input from the people working on this issue.

    And as I skimmed through and read the MR I think the title here needs to change to describe the fix, which is about access.

  • 🇺🇦Ukraine Foxy-vikvik

    @quietone I did the same steps as on the description BUT
    We use paragraphs module in our project and some fields we don't translate that's why I found NULL in $widget
    I think it is related to the $field_state['array_parents']

  • 🇺🇦Ukraine Foxy-vikvik

    It happens only when translating the node with paragraphs

  • 🇺🇦Ukraine Foxy-vikvik

    I added the following conditions:

     if (empty($widget) && $subform_position = array_search('subform', $field_state['array_parents'])) {
            $widget = NestedArray::getValue($form, array_slice($field_state['array_parents'], 0, $subform_position));
          }
    
  • Status changed to RTBC 2 months ago
  • 🇨🇦Canada joseph.olstad

    The title accurately describes what leads us to this issue.

    Patch 112 is incorrect, it is missing a change.

    Here is a link to the MR patch https://git.drupalcode.org/project/drupal/-/merge_requests/9429.patch

  • Status changed to Needs work 2 months ago
  • 🇬🇧United Kingdom alexpott 🇪🇺🌍

    This bug sounds really tricky, however the fix concerns me because of the hardcoding of the status field. The points to the possibility of unintended impacts. Is there another way to fix this or not hardcode the status field?

  • 🇨🇦Canada joseph.olstad

    @alexpott ,

    On translations of an entity a core message advises us to edit the non-translateable fields on the source language. The test code included with this MR illustrates a lack of validation to this effect. Translation functionality for contrib entities such as "Paragraphs" is otherwise broken. While core node entities do not have this problem by themselves, when other entity types such as "Paragraphs" are used with nodes, this issue surfaces.

    Currently there is no other known solution.

    The tests-only fail illustrates where the failure occurs. All tests pass with the MR code in it's entirety.

  • 🇨🇦Canada joseph.olstad

    joseph.olstad changed the visibility of the branch 3025039-new-non-translatable to hidden.

  • Status changed to RTBC 2 months ago
  • Pipeline finished with Success
    2 months ago
    Total: 645s
    #283270
  • Status changed to Needs work about 2 months ago
  • 🇬🇧United Kingdom alexpott 🇪🇺🌍

    @joseph.olstad the concern is because we have singled out the status field in the if condition and there is no reasoning as to why it is singled out. It must be possible for another contrib or custom field to work the same way as the status field and need the special casing. If that it is the case then this fix is likely to cause other problems. We need to answer #121 before we continue here.

  • 🇮🇳India shobhit_juyal New Delhi

    If we can just add a check to see if we are not editing default translation otherwise proceed for to add violation rule. Does this break any check ?

  • 🇩🇪Germany tfranz

    I tested and use Patch #116 on one of our projects (Drupal 10.3.5) and it so far solved the problem, that we could not change and save older translated content with paragraphs.

  • 🇳🇱Netherlands timohuisman Leiden, Netherlands

    This patch contains a snapshot of the latest state of the MR 9429 so it can be safely used with composer-patches.

  • 🇺🇦Ukraine Foxy-vikvik

    The main issue in my case was that the boolean field in the paragraph entity by default has a NULL value (bizarre behaviour)
    So the patch from comment #126 🐛 New non translatable field on translatable content throws error Needs work solved the main issue and I fixed issue with the NULL value by myself

  • 🇷🇴Romania Kosa Ilma

    The patch from #128 worked for me, on core 10.3.6.

Production build 0.71.5 2024