Problem/Motivation

Even when access is denied (e.g. form API #access property evaluates to FALSE or \Drupal\Core\Access\AccessResultForbidden for the widget) to a widget, in some instances depending on the field type, a value set, via a default or other logic, propagates to the entity built from the sum of widgets during form processing. Boolean fields (field type boolean, with a Single on/off checkbox widget (field widget boolean_checkbox) have consistently proven problematic on a multilingual site with content translation enabled, where a new boolean field is added after content with translations exists on the site, and that content is attempted to be edited.

Steps to reproduce

Scenario 1: Post-content Boolean Field Addition
  • Install standard drupal profile (eg. drush si -y standard)
  • Navigate to /admin/modules. Enable the Content Translation module
  • Navigate to /admin/config/regional/language. Click Add language. Follow steps to add any additional language.
  • Navigate to /admin/config/regional/content-language. Under "Custom language settings" check "Content". Open the details element for "Content". Check "Article", and check "Hide non translatable fields on translation forms" for the Article content type.
  • Navigate to /node/add/article. Add an article node (just the title is enough)
  • Create a translation of the node created in the last step.
  • Navigate to /admin/structure/types/manage/article/fields/add-field. Create a new boolean field (leave it as untranslatable)
  • Navigate back to the node translation's edit form. Update the title and attempt to Save.

Expected result

The title on the translation is saved without error.

Actual result

The following error is reported, and the title change is not saved:

Non-translatable fields can only be changed when updating the original language.

Scenario 2: Moderation state widget affecting un-translatable status property
  • Install standard drupal profile (eg. drush si -y standard)
  • Navigate to /admin/modules. Enable the Content Translation and Content Moderation modules
  • Navigate to /admin/config/regional/language. Click Add language. Follow steps to add any additional language.
  • Navigate to /admin/config/regional/content-language. Under "Custom language settings" check "Content". Open the details element for "Content". Check "Article", and check "Hide non translatable fields on translation forms" for the Article content type. Also uncheck Published (status property)
  • Navigate to /admin/config/workflow/workflows/manage/editorial.
  • Under "This workflow applies to" > "Content types", click the "Select" button. Check "Article" and Save.
  • Navigate to /node/add/article. Add an article node (just the title is enough). Mark it as Published, and Save
  • Create a translation of the node created in the last step. Mark it as Draft, and Save

Expected results

Moderation state widget should not be accessible when status is marked as un-translatable.

Actual result

Moderation state widget is accessible. Producing the error on Save when non-default translation is out-of-sync with default for status:

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

Continued testing and review.

User interface changes

None.

API changes

None.

Data model changes

None.

Release notes snippet

TBD

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 but we didn't test this.

Your thoughts on this would be greatly appreciated. :)

CommentFileSizeAuthor
#171 3025039-171.patch2.37 KBandras_szilagyi
#141 3025039-141.patch6.99 KBlukasz.tyc
#133 New-non-translatable-field-on-translatable-content-throws-error.patch6.73 KBakhil babu
#128 3025039-128.patch13.31 KBtimohuisman
#126 Screenshot 2024-09-18 at 9.59.34 PM.png115.19 KBshobhit_juyal
#126 not-tranlatable-field-issue-3025039-126.patch1.11 KBshobhit_juyal
#116 not-tranlatable-field-issue-3025039-116.patch2.39 KBfoxy-vikvik
#115 Screenshot from 2024-09-11 14-10-17.png33.86 KBfoxy-vikvik
#112 not-tranlatable-field-issue-3025039-112.patch1.13 KBfoxy-vikvik
#111 Screenshot from 2024-09-10 14-36-41.png146.51 KBfoxy-vikvik
#94 3025039-94.patch6.68 KBloon
#91 Screenshot from 2023-11-28 10-00-10.png65.68 KBartyom hovasapyan
#89 3025039-89.patch2.06 KB_utsavsharma
#89 interdiff_88-89.txt2.06 KB_utsavsharma
#88 3025039-80-for-bool-type.patch2.05 KBartyom hovasapyan
#87 Screenshot from 2023-09-28 11-57-42.png30.41 KBartyom hovasapyan
#87 Screenshot from 2023-09-28 11-55-48.png29.04 KBartyom hovasapyan
#79 3025039-MR1105-79.patch6.62 KBrecrit
#69 3025039-68.patch7.01 KBanna d
#69 interdiff-65-68.txt759 bytesanna d
#67 3025039-67.patch6.98 KBanna d
#67 interdiff_65_67.txt730 bytesanna d
#65 3025039-65.patch6.9 KBranjith_kumar_k_u
#64 3025039-64.patch7.06 KBpere orga
#53 3025039-53.patch6.94 KBclayfreeman
#53 3025039-53.interdiff.txt824 bytesclayfreeman
#52 3025039-52.patch6.94 KBclayfreeman
#52 3025039-52.interdiff-42.txt2.17 KBclayfreeman
#45 interdiff_42-45.txt4.17 KBsiddhant.bhosale
#45 3025039-45.patch6.62 KBsiddhant.bhosale
#42 3025039_42.patch6.46 KBghost of drupal past
#41 3025039_41.patch6.24 KBghost of drupal past
#40 3025039_40.patch6.29 KBghost of drupal past
#39 3025039_interdiff_37_39.txt3.33 KBghost of drupal past
#39 3025039_39.patch6.32 KBghost of drupal past
#37 3025039_37.patch5.7 KBghost of drupal past
#36 3025039_36.patch4.05 KBghost of drupal past
#35 3025039_33.patch3.99 KBghost of drupal past
#34 3025039_34.patch5.64 KBghost of drupal past
#33 3025039_33.patch3.99 KBghost of drupal past
#16 3025039_16.patch1.65 KBghost of drupal past
#15 3025039_15.patch1.68 KBghost of drupal past
#13 3025039_13.patch1.24 KBghost of drupal past

Issue fork drupal-3025039

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

pavlosdan created an issue. See original summary.

pavlosdan’s picture

Project: Paragraphs » Drupal core
Version: 8.x-1.5 » 8.6.4
Component: Miscellaneous » content_moderation.module

Initially reported in Paragraphs, did some further testing and was able to replicate the issue with a field attached straight on a content type. Moving this to core.

pavlosdan’s picture

Title: New non translatable field on translatable paragraph throws error » New non translatable field on translatable content throws error
Issue summary: View changes
pavlosdan’s picture

mikemccaffrey’s picture

Status: Closed (duplicate) » Active

I'm reopening this ticket, since it seems slightly different than the linked issue that also involves the comment module, and this ticket hits on a point that none of the other "Non translatable fields" tickets seem to contain, namely that the error can be triggered by the addition of new non-translatable fields.

I was getting the "Non translatable fields can only be changed when updating the current revision" error when trying to save the spanish version of some nodes, despite the fact that no non-translatable fields were showing on the edit form, and no values were being changed.

In the end I tracked it down to some new fields that I had recently added to the content type. It turns out the problem was that I was trying to save the translated version of the node before the default translation was saved and given an initial value to compare the translation to.

We can get around this problem for the moment by making sure to edit and save the english version of nodes before attempting to change the translated versions, but this shouldn't be necessary. The system should be smart enough to realize that the translated value of the field is different because the default translation has no value at all for the field, and it should just make sure that the translation value is empty or such before letting the save proceed.

sam152’s picture

Component: content_moderation.module » entity system

I think this may actually fall under the entity system, since the constraint in question is in Drupal\Core\Entity and pending revisions and translations are API features of the entity system, it's only content moderation that exposes this bug, but I suspect workspaces might trigger something similar.

pavlosdan’s picture

@Sam152, got any idea of what kind of test we could write to prove this bug?

I tried writing a Kernel test as follows but it passes.

I also did some manual testing with and without content moderation and I only get the error when content moderation is added to the content type. I am attaching the code for the test just in case you can see any issues with the test.

EDIT: removed the test code as I was using the wrong APIs.

pavlosdan’s picture

Version: 8.6.4 » 8.7.x-dev

bumping this to 8.7 since I just tested against that.

antoniya’s picture

+1 This happens every time we add a new untranslatable field. The error persists even when editing the original node instead of its translations.

The only workaround for now is setting all new fields to translatable, which is fine in most cases, but boolean fields should ideally remain untranslatable..

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.9 was released on November 6 and is the final full bugfix release for the Drupal 8.7.x series. Drupal 8.7.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.8.0 on December 4, 2019. (Drupal 8.8.0-beta1 is available for testing.)

Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

yahyaalhamad’s picture

I think I got around this issue using the checkbox in content translations "Hide non-translatable fields" in Paragraph types.

matthewv789’s picture

Related issue in Error when save translation (2956311). That was for Paragraphs, but I think the issue stems from core.

The solution that seems to work for everyone is indeed as per YahyaAlHamad in #11, and zanvidmar #7 in the other issue: uncheck all instances of "Hide non translatable fields on translation forms". That flag seems to be a feature that does not actually work properly.

ghost of drupal past’s picture

Status: Active » Needs review
StatusFileSize
new1.24 KB

If for whatever reason the widget is set to #access FALSE, just do nothing. The user, by definition, couldn't have changed anything so doing nothing is just the thing to do.

berdir’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -388,13 +388,16 @@ public function extractFormValues(FieldItemListInterface $items, array $form, Fo
+      if ($widget['#access'] ?? TRUE) {

access could also be an access result object.. Maye we should have a helper method for that somewhere, not in scope..

ghost of drupal past’s picture

Version: 8.8.x-dev » 8.9.x-dev
Status: Needs work » Needs review
StatusFileSize
new1.68 KB

Sure, we can do that.

ghost of drupal past’s picture

StatusFileSize
new1.65 KB

D'oh, only literal FALSE is access denied. Which means #13 was also slightly incorrect.

viappidu’s picture

I don't use content moderation or paragraph but I have found an extremely simple temporary solution here #3117100: Non-translatable fields can only be changed when updating the current revision.. Not sure it can help.
Seems quite an old problem though, found also #3015480: Allow skipping translation check at field level for non-translatable fields and #2959175: Non-translatable fields error when using: Content Moderation + Content Translation + Comments which seems all related.

sanjayk’s picture

Assigned: Unassigned » sanjayk
sanjayk’s picture

Assigned: sanjayk » Unassigned

Unable to reproduce please provide more information.

viappidu’s picture

@sanjayk very simple, with any of the above modules (or in my case just memcache) installed you'll get an error making impossible to translate the node. If you look at my last post there are plenty of related issues explaining the problem.

sanjayk’s picture

@viappidu thanks for update.
I have test many time and follow your steps and got the message "Non-translatable fields can only be changed when updating the original language." again and again and never got "Non translatable fields can only be changed when updating the current revision".

yahyaalhamad’s picture

@sanjayk, yeah, it is kind of hard to replicate, that's why this issue is still here. It seems that there are specific variables that have to be met. I believe one of them is related to the Paragraphs module, and possibly with Content Moderation.

Edit: I remember that it happened to old content that had paragraphs and content moderation before enabling translation. Maybe this will help.

viappidu’s picture

@sanjayk, might be due to the 'Create new revision' being off in your content type? I think I should have paid more attention myself to the error message. That I believe was the error I was getting, having myself revisioning off for the particular content. I solved unchecking the 'Hide non translatable fields on translation forms' in content translation. I'm the only one working on my site so that works for me. I didn't check the created entity translation for 'funny' fields/values though watchdog doesn't show any error of sort.

The only thing I can add is that the only module enabled, of those mentioned in this post, is memcache. Also content moderation is off for me. Drupal 8.9, PHP 7.4, MySQL 8

sanjayk’s picture

@viappidu @YahyaAlHamad let me explain what steps I am following

I have installed modules (*Paragraphs + Content Moderation + Translations*) as mentioned in description and followed the steps.

I have created article content with Spanish content and also added a field in paragraph and as description edit translated content.
You can see in screenshot in the bottom have a field with name checkbox(field type paragraph), have a drop down of content moderation and revision also enabled.

Here https://ibb.co/Fn4Q6Sn https://ibb.co/5vhyRv7 screenshot please check and let me know if I am doing anything wrong. If you required more information or anything else let me know. :)

viappidu’s picture

@sanjayk, I'm not following you.
What exactly do you need?
If you wanted to reproduce the error, well, you achieved it.
If you want to solve
1. try the patch at #16
OR
2. Try the method I explained at #17 or #23
OR
3. Make a patch :)

clayfreeman’s picture

Forgive me if I'm missing something, but in trying to replicate the original issue (being that EntityUntranslatableFieldsConstraint::$defaultRevisionMessage is violated), I noticed that #access should never be set to FALSE; this specific violation requires that "Hide non translatable fields on translation forms" be unchecked and that you're modifying the value of a non translatable field on a pending revision.

I don't believe the patch in #16 actually solves the original issue.

I will note, however, that the patch in #16 may be useful (and necessary) to solve an issue with Paragraph reference fields that aren't translatable (regardless of any translation capabilities of fields on the Paragraph entity itself). My team experienced a EntityUntranslatableFieldsConstraint::$defaultTranslationMessage violation after hiding a non translatable Paragraph reference field on a content type without any value changes; applying the patch in #16 seemed to resolve the issue, although a patch to Paragraphs was also necessary. I've yet to make a contrib issue for this yet because further investigation is required.

All that being said, if the original issue is that EntityUntranslatableFieldsConstraint::$defaultRevisionMessage is violated, then the patch from #16 has no relevance for this issue and another solution is needed. Otherwise, the original issue should be updated to reflect a violation of EntityUntranslatableFieldsConstraint::$defaultTranslationMessage instead.

dunebl’s picture

#16 save my day!
Same as #26, I was facing 2 violations of the kind EntityUntranslatableFieldsConstraint::$defaultTranslationMessage
But, it was **not** about paragraph fields, it was about a comment field and a stateItem field.

#16 solve it.

Thank you

anybody’s picture

Just ran into the same issue with a translated Core Media Entity. The workaround from https://www.drupal.org/project/paragraphs/issues/2956311#comment-13854241 helped and also the patch from #16 did! Thank you!

mandclu’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +ContributionWeekend2021

I had a similar issue, with a Smart Date field. The patch from #16 resolved the problem without any other code changes required. Though it seems that some other modules require additional fixes, it would be great if this core fix could be committed. Moving to RTBC based on my own testing as well as that in previous comments.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

Thanks for filing this bug report and for fixing the issue. Bug fixing is very valuable. In order to commit a bug fix, we need an automated test to prove that we've fixed the bug and ensure that we don't break it again in the future. For more information about writing tests in Drupal, see the following links:

  1. https://www.drupal.org/docs/testing/phpunit-in-drupal/phpunit-javascript...
  2. https://api.drupal.org/api/drupal/core%21core.api.php/group/testing/9.1.x
ghost of drupal past’s picture

I emailed DuneBL and Anybody because #27 / #28 both mention they were able to reproduce this with just core modules -- more details or perhaps even config export would allow me to write a test.

berdir’s picture

I believe just adding a new boolean field to a node type with existing content (not 100% sure if it needs an existing translation, but not even that should be necessary) might be sufficient to trigger this, AFAIK it doesn't have to be on a paragraph. Then just go to the add/edit translation form and try to save.

ghost of drupal past’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new3.99 KB

This is the failing test, I will post this + #16 next which passes.

ghost of drupal past’s picture

StatusFileSize
new5.64 KB
ghost of drupal past’s picture

Version: 8.9.x-dev » 9.2.x-dev
StatusFileSize
new3.99 KB

D'oh!

ghost of drupal past’s picture

StatusFileSize
new4.05 KB

Ah. This is the failing version...

ghost of drupal past’s picture

StatusFileSize
new5.7 KB

... and this is the passing one. I will stop posting duplicates once we have a fail-pass version verified by the testbot.

The last submitted patch, 36: 3025039_36.patch, failed testing. View results

ghost of drupal past’s picture

StatusFileSize
new6.32 KB
new3.33 KB

I have added comments, use the error message from the constraint directly and most importantly, added a dataProvider to actually show that if #access is TRUE then the error is expected. There is no point in uploading a failing test for this -- that already demonstrated there is a bug and this fixes it and the new test added with #access TRUE is not relevant to that.

ghost of drupal past’s picture

StatusFileSize
new6.29 KB

I found a much cleaner way to do my asserts and fixed the code style issue found.

ghost of drupal past’s picture

StatusFileSize
new6.24 KB

Sigh.

ghost of drupal past’s picture

Issue summary: View changes
StatusFileSize
new6.46 KB

I switched to entity constraint violations directly instead of form error messages because the comparison to EntityUntranslatableFieldsConstraint can be directly done this way instead of comparing messages. EntityFormDisplay creation is also more direct now. It becomes more and more different from FieldWidgetConstraintValidatorTest at every iteration. I added even more comments. I updated the issue summary.

clayfreeman’s picture

Status: Needs review » Needs work
  1. +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityUntranslatableFieldsConstraintTest.php
    @@ -0,0 +1,128 @@
    +  protected function setUp(): void {
    ...
    +  public function accessValues() {
    

    Just a nit... docblocks?

  2. +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityUntranslatableFieldsConstraintTest.php
    @@ -0,0 +1,128 @@
    +    $field_name = strtolower($this->randomMachineName());
    +    $field_storage = FieldStorageConfig::create([
    +      'field_name' => $field_name,
    +      'entity_type' => self::ENTITY_TYPE,
    +      'type' => 'boolean',
    +      'translatable' => FALSE,
    +    ]);
    +    $field_storage->save();
    +    FieldConfig::create([
    +      'field_storage' => $field_storage,
    +      'bundle' => self::ENTITY_TYPE,
    +    ])->save();
    ...
    +    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $display */
    +    // The entity form should only contain the field under testing.
    +    $display = EntityFormDisplay::create([
    +      'targetEntityType' => self::ENTITY_TYPE,
    +      'bundle' => self::ENTITY_TYPE,
    +    ])->setComponent($field_name, [
    +      'type' => 'options_buttons',
    +    ]);
    

    Should these instead be in ::setUp()?

  3. +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityUntranslatableFieldsConstraintTest.php
    @@ -0,0 +1,128 @@
    +    // Necessary for picking up the new field.
    

    Then this wouldn't be necessary...

siddhant.bhosale’s picture

Assigned: Unassigned » siddhant.bhosale
siddhant.bhosale’s picture

Assigned: siddhant.bhosale » Unassigned
Status: Needs work » Needs review
StatusFileSize
new6.62 KB
new4.17 KB

I have made the changes from comment #43.
Please review.

ghost of drupal past’s picture

Status: Needs review » Needs work

Please read the steps to reproduce in the issue summary (maybe it's not clear enough? should I write more?) and observe the following, necessary steps, in this very specific order:

  1. Create an entity
  2. add a field
  3. Add a translation to a non-default revision of the entity

To compare. #45 instead does

  1. add a field
  2. Create an entity

You could try to post the test from #45 without the patch into a testing issue to see it passes as it doesn't test the issue at hand.

We could move creating an entity into setup for sure but in my opinion, setup should, as the name suggests, create the environment where the bug is reproducible and the actual reproduction steps should live in the test method.

Setting it to CNW because #42 indeed missed some docblocks.

andypost’s picture

clayfreeman’s picture

@Charlie ChX Negyesi, ah, you may be right; what about explicitly setting the field to NULL for the default translation? If we do it the way you recommend in #42, we'll also need to delete the field on each run of the test, no?

After re-reading the issue summary, we also need to set a default value for the field (which isn't being done in either #42 or #45).

Also, would it be safer to use a text field for testing instead? (Otherwise we may be flirting with a scenario where empty() causes discrepancies in testing...)

ghost of drupal past’s picture

I am not quite sure what you are asking. The field is created in a test method and every test method runs in its own Drupal installation with a completely fresh database. I am equally not sure what do you mean by setting a default value -- the test merely relies on changing the value and BooleanItem does not have a default of 1. There's no empty() involved in the test as far as I can tell.

We still need to fix the doxygen in #42.

clayfreeman’s picture

If we're trying to implement the steps to replicate, the issue summary explicitly calls for a non-NULL default:

[...] Now add a nontranslatable field with a non-null default value. [...]

We should update the IS if this is incorrect.

As far as my initial review is concerned, I agree that the only thing that applies is the docblock stuff at this point. Revisions should be on #42 since the patch in #45 doesn't match the replication criteria in the IS - sorry for the confusion!

ghost of drupal past’s picture

I guess you are right in that one and while for the bug it doesn't matter whether the change occurs because of the default value is set or because an explicit set, certainly for user expierence it does because the the error says something changed but they didn't change from the default value... So please update that in the patch.

clayfreeman’s picture

Status: Needs work » Needs review
StatusFileSize
new2.17 KB
new6.94 KB
clayfreeman’s picture

StatusFileSize
new824 bytes
new6.94 KB

Realized that I specified "non-null" - derp!

ghost of drupal past’s picture

Thanks for rolling this version, I posted it to https://www.drupal.org/project/drupal/issues/3196235#comment-14043183 to see it fails without the fix and it still does which is great but then I re-read the patch and it still has $form_state->setValueForElement($form[$field_name]['widget'], [['value' => 1]]); and I thought the reason to give the new field a default was to remove this very line and let the default provide the change. However, when I do so I get an error and I am right now out of time so I can just leave this comment here.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

ajits’s picture

Confirming that the patch from #53 works for me!

flyke’s picture

I have this error on a clients site from time to time, with translations and paragraphs enabled.
We dont use workbench or content moderation.

When it happens the fastest fix is:
- go to /admin/config/regional/content-language
- uncheck 'Hide non translatable fields on translation forms'
- edit the translation of the node again, no need to change anything and save. This will work now. Great magic.
- now again go to /admin/config/regional/content-language
- you can re-activate 'Hide non translatable fields on translation forms' now
- this time you or the client can edit the translation without error

clayfreeman’s picture

Issue summary: View changes

clayfreeman’s picture

Re: #54

Since the value is being fed to the form state, it will be ignored by time it hits the change in WidgetBase. In theory, this should be fine for testing purposes, as it accurately captures what happens when the form is submitted anyway.

pere orga’s picture

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mikran’s picture

Issue summary: View changes

This issue was originally reported for *Paragraphs + Content Moderation + Translations*. The proposed fix does not fix that combination with paragraphs but it works for steps given in the updated issue summary so I've now filed the paragraph bug as #3262149: New non-translatable field on translatable paragraph throws error. Steps to reproduce are almost same, but paragraph bug does not require content moderation.

pere orga’s picture

StatusFileSize
new7.06 KB

Adding https://git.drupalcode.org/project/drupal/-/merge_requests/1105.diff as patch here, so it can be used in composer (no changes added)

ranjith_kumar_k_u’s picture

StatusFileSize
new6.9 KB

Just re-rolled for 9.4

ghost of drupal past’s picture

      $access = $widget['#access'] ?? TRUE;
      if (($access instanceof AccessResultInterface && $access->isAllowed()) || $access === TRUE) {

Maybe this should be using Element::isVisibleElement?

anna d’s picture

StatusFileSize
new730 bytes
new6.98 KB

I faced with issue with paragraphs: https://www.drupal.org/project/paragraphs/issues/3262149
In this case #65 patch didn't solve the error, because $widget returns null for all fields in paragraph. I took the №65 patch as a base, this solution works locally for me.

Status: Needs review » Needs work

The last submitted patch, 67: 3025039-67.patch, failed testing. View results

anna d’s picture

StatusFileSize
new759 bytes
new7.01 KB

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

clayfreeman’s picture

Status: Needs work » Needs review

Made a revision per #66. Setting back to Needs Review.

If posting reference-only patches, please suffix the file name with -do-not-test to avoid ruining the state of the issue. Actual development on the issue should occur in the MR so that maintainers only have to review one set of code.

clayfreeman’s picture

Version: 9.5.x-dev » 10.0.x-dev

After further consideration, I think it makes more sense to base this patch on 10.0.x.

@Anna D can you provide replication criteria for the problem you're experiencing? I'd like to try to confirm if changes to this core patch are needed or if it would be better to address it in the Paragraphs module, especially since the additional change is causing test failures.

anna d’s picture

Hi @clayfreeman
There is a related issue https://www.drupal.org/project/paragraphs/issues/3262149
mikran created test that failed with #65 patch, but passed with my small changes https://git.drupalcode.org/project/drupal/-/merge_requests/1105/diffs?co...

So you can try to run test for yourself

ghost of drupal past’s picture

I am sorry but I am still bothered by #54 could we try removing that setValue call from the test?

joseph.olstad’s picture

***EDIT***
It would be nice if the error mentioned which field was the problem, at least to focus the issue on something.
***EDIT***

*** Final update ***

For our environment we had forgot to enable translation on the 'published' option
this can be found in /admin/config/regional/content-language
seems our use case was different than the one explained above.

We did not need, nor did we use a patch for what appeared to be a similar problem.
*** end final update ***

clayfreeman’s picture

@Anna D:

I think this line may be at fault in the Paragraphs module. I recommend patching Paragraphs to remove it, or to at least make it conditional on the form element's visibility.

@Charlie ChX Negyesi:

Perhaps we should be writing a functional test instead? I think it would more closely approximate the replication criteria in the issue summary.

ghost of drupal past’s picture

I personally avoid functional tests whenever possible. They tend to be hard to debug, slow and somewhat harder to reason about.

But that's just me. I can see how in this case that might work.

aschiwi’s picture

The patch from https://git.drupalcode.org/project/drupal/-/merge_requests/1105 works for us.

Our problem was a non-translatable taxonomy reference field that was set to be hidden on translation forms.

recrit’s picture

StatusFileSize
new6.62 KB

Adding a static patch file for the latest MR that can be used for composer builds.

tcrawford’s picture

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)

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative

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.

anybody’s picture

Version: 10.0.x-dev » 11.x-dev

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

lobodakyrylo’s picture

Comment #75 worked form me. Thank you.

herved’s picture

#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.
PS: It would be nice indeed if it could report the problematic field but perhaps this belongs to a separate issue?

amaisano’s picture

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.

For the Taxonomy Term, I have the "Hide untranslatable fields" checked, but the Image field still appears with the "Remove" button and the Image thumbnail, even though it shouldn't be there.

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.

EDIT: This is directly related to a known issue with Image fields. See https://www.drupal.org/project/drupal/issues/3218426#comment-15173943

artyom hovasapyan’s picture

It's work for me.

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

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

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

artyom hovasapyan’s picture

StatusFileSize
new2.05 KB

Or you can use this patch(update 79 patch).

_utsavsharma’s picture

Status: Needs work » Needs review
StatusFileSize
new2.06 KB
new2.06 KB

#88 failed to apply .

smustgrave’s picture

Status: Needs review » Needs work

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

artyom hovasapyan’s picture

StatusFileSize
new65.68 KB

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.
stborchert’s picture

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.

akalam’s picture

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

loon’s picture

StatusFileSize
new6.68 KB

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

mgaskey’s picture

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 (#77) fixes the issue for us.

joseph.olstad’s picture

***EDIT*** mistaken comment, removed to avoid confusion *** end EDIT ***

randy.houlahan@cbd.int’s picture

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

joseph.olstad’s picture

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.

joseph.olstad’s picture

Merged the latest 11.x into MR1105

Pushed up the fix that was added in patch 94

joseph.olstad’s picture

Status: Needs work » Needs review
joseph.olstad’s picture

Assigned: Unassigned » joseph.olstad
Status: Needs review » Active

MR 1105 , I lack permissions to correct the merge request, it should target an 11.x merge not 10.0.x

I'll create a new MR for 11.x

joseph.olstad’s picture

Assigned: joseph.olstad » Unassigned
Status: Active » Needs review

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.

joseph.olstad’s picture

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

joseph.olstad’s picture

Pipeline seems to have gone bonkers.

Undefined variable: $this

Makes no sense.

berdir’s picture

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

joseph.olstad’s picture

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.

joseph.olstad’s picture

Status: Needs review » Reviewed & tested by the community
  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
  5. All rolled up against the latest 11.x
foxy-vikvik’s picture

StatusFileSize
new146.51 KB

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

picture with issue

foxy-vikvik’s picture

quietone’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs title update

@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.

foxy-vikvik’s picture

@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']

foxy-vikvik’s picture

StatusFileSize
new33.86 KB

It happens only when translating the node with paragraphs

foxy-vikvik’s picture

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));
      }
foxy-vikvik’s picture

foxy-vikvik’s picture

joseph.olstad’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs title update

The title accurately describes what leads us to this issue.

Patch 116 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

joseph.olstad’s picture

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

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?

joseph.olstad’s picture

@alexpott ,

On translations of an entity a core message advises us to edit the non-translateable fields on the source language version. 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 /referenced from core entity types and translation is enabled 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.

With that said, I'd be very pleased if someone finds a contrib solution to this. Meanwhile we'll keep using this fix.

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

joseph.olstad’s picture

Status: Needs work » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Needs work

@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.

shobhit_juyal’s picture

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 ?
patch screenshot

tfranz’s picture

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

timohuisman’s picture

StatusFileSize
new13.31 KB

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

foxy-vikvik’s picture

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 solved the main issue and I fixed issue with the NULL value by myself

kosa ilma’s picture

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

liquidcms’s picture

My edge case:
- i have a paragraph with both translatable and non-translatable fields
- i have a date range field with TZ enabled on the paragraph (non translatable)

I have tried a few of the patches here and currently using #128.

Regardless if "Hide non translatable fields on translation forms" is selected or not, i get "Non-translatable fields can only be changed when updating the original language.". Debugging the code and it appears a lot like the issue discussed here: #3194515: Smart Date Recurring doesn't work in non translatable field. Basically the date field is compared to check if it has changed. For the translated value that is checked it doesnt consider TZ plus the array values of value, end_value and tz are not in the same order. This causes the check to fail (regardless if TZ is enabled or not due to ordering within the array).

I think, But not 100% sure, that the point of this fix is if fields are hidden, then they aren't checked. I have other date range fields which are not in paragraphs, and they work correctly here. So i suspect these are checked as the paragraph still has translatable fields.. and is therefore checking ALL fields within the paragraph.

As a side note, if i make the date field translatable, i am able to save my translated node.

liquidcms’s picture

To close the loop a bit on this, i did test a different bundle with a date range field not in a paragraph. Without any patch from here it fails (sadly with no suggestion as to which field is the issue). Debugging shows it is the same issues for the date field - TZ not applied and order of date array is different (this sounds like a core bug in how original values are determined). With at least the patch from #94 (and likely other versions of patch), this field is not checked and therefore this bug messing up date fields does not impact outcome.

So i stand by my comment above; the fields are not checked recursively as would need to be done for paragraphs.

akhil babu’s picture

Uploading https://git.drupalcode.org/project/drupal/-/merge_requests/9429 as a patch to use in one of our projects, Thanks

achap’s picture

This issue can also occur when you programmatically create taxonomy terms and then translate them programmatically too, because the content_translation_uid field is NULL in the database by default. When you go to re-save the previously created translation in the UI you get the above error message because it defaults to the anonymous user (0) when assigning a value via the form.

Different cause and fix to this issue. See: https://www.drupal.org/project/drupal/issues/3338036

mohit.bansal623’s picture

Error message appears "Non-translatable fields can only be changed when updating the original language. The /en string has been updated and successfully saved. The issue presents when trying to update strings for non /en Menu link titles. Any work around this?

I am currently using Drupal version 10.4.5. Any guidance will be helpful. Thanks in advance.

ansergeyg’s picture

The issue can be more complicated:

Imagine the situation:

We have a node with content moderation. The node was saved and the moderation state is now "Published".

Now you want to edit that node.

If you have a hook that alters node-edit form to hide the moderation_state widget setting '#access' to false, then when the node is saved in a draft state (can be default state, but remember: the '#access' is false) and it is supposed to redirect to the "view draft" page with the moderation state change form instead it redirects to the "view published" page, because when the code in the WidgetBase class with the patch runs it checks the visibility of the widget and because the '#access' is false it skips the moderation_state field and the node state is still "Published".

The issue here is what is the definition of the "#access" attribute? Is it to hide some components? Or is it to suppress the access to change some values? Because nowhere in the render-array design the actual values are protected from accessing if the "#access" attribute is set to false.

yfma’s picture

The patch from #128 worked on 10.4.7, Thank you so much!

ansergeyg’s picture

Guys, all these patches only work if you don't manually hide (or manipulate in some other way) some fields like moderation state through node edit form hook. Which is allowed by design. If you do have such customization then moderation state change form is no longer available for you after you save a node in draft mode. It will always be published. Because the patches operate on a widget level they should also consider all the widget derived functionality.

For further detail, please check my comment above.

andre.bonon’s picture

I have the Simplenews module installed and the issue field added to an Article CT, and also set to non-translatable.
The error message "Non-translatable fields can only be changed when updating the original language" is shown when saving a new translation for the Article.
The #128 worked for me on 10.4.3.

andre.bonon’s picture

I was able to reproduce what was described in #136 in a custom form that has a field of the type language_select with #access set to false.

lukasz.tyc’s picture

StatusFileSize
new6.99 KB

Updated from #67 for Drupal 10.5.1 compatibility.

m4olivei made their first commit to this issue’s fork.

m4olivei’s picture

Issue summary: View changes

We've run into this issue as well. I've been through the issue and all comments here. I think part of why this issue hasn't been moving forward is that the issue summary is not clear wrt minimal steps to reproduce the issue. From folks who have chimed in, it would seem that when this issue arises, it's happening on sites that are complex by nature (multilingual, workflow, paragraphs, etc.), so each experience is slightly different. It will be useful to express a minimal test case. To that end, I have:

  • Updated the issue summary. Here I've found that #85 from @herved is the most minimal reproducible example. I independently came up with steps like this and then discovered his post.
  • Merged the lastest 11.x to the branch here. Small change to the test to add return types to appease the phpstan job.
m4olivei’s picture

Issue summary: View changes
Issue tags: +Needs tests

OK, I've also now run into the issue with the status field, which means you can run into this problem without runing into the scenario where a field is created for a content type after content already exists. Here are the steps to repro:

  • Install standard drupal profile (eg. drush si -y standard)
  • Navigate to /admin/modules. Enable the Content Translation and Content Moderation modules
  • Navigate to /admin/config/regional/language. Click Add language. Follow steps to add any additional language.
  • Navigate to /admin/config/regional/content-language. Under "Custom language settings" check "Content". Open the details element for "Content". Check "Article", and check "Hide non translatable fields on translation forms" for the Article content type. Also uncheck Published (status property)
  • Navigate to /admin/config/workflow/workflows/manage/editorial.
  • Under "This workflow applies to" > "Content types", click the "Select" button. Check "Article" and Save.
  • Navigate to /node/add/article. Add an article node (just the title is enough). Mark it as Published, and Save
  • Create a translation of the node created in the last step. Mark it as Draft, and Save

Here you again get the error message:

Non-translatable fields can only be changed when updating the original language.

In this case, it's kind of expected behavior, because we marked the status field as untranslatable, but here we're setting a different value on the translation. The problem is more that the Moderation state widget is exposed in a way that can end up changing a non-translatable field (status). It feels like the solution here would be to mark the Moderation state widget as `#access' => FALSE.

I've updated the issue summary to reflect this other scenario. This resolves some of the mystery around why Content Moderation seems to trigger this issue.

The existing test covers the first scenario, we need a Test for this second scenario. Especially since the existing patch does not seem to resolve this second scenario.

m4olivei’s picture

Issue summary: View changes
flyke’s picture

Just want to note that we had this issue on projects that do not use workflow / content moderation.
Just in case someone reads the reproduction steps above and draws the conclusion that this is specifically workflow related: that is not the case. You can have this issue without workflow / content moderation.

m4olivei’s picture

@flyke absolutely! I've noted both scenarios in the issue summary.

økse’s picture

I had exactly this issue as described in #144 (workflow)

What helped for me is to uncheck the content type, save, check it again and save again.

Now, I can add translations while before I always got the error message on certain content types:

Non-translatable fields can only be changed when updating the original language.

Weirdly enough, I don't see any config changes so not sure what actually changed.

Finally, I have to add that I only had this problem on certain environments (staging vs production) so it might just have been a database issue in my case.

undersound3’s picture

FWIW

I received the following messages when trying to save a paragraph which has translated and non translated (all languages) fields on it:

Error message
Warning: Undefined array key "width" in Drupal\content_translation\Plugin\Validation\Constraint\ContentTranslationSynchronizedFieldsConstraintValidator->hasSynchronizedPropertyChanges() (line 153 of core/modules/content_translation/src/Plugin/Validation/Constraint/ContentTranslationSynchronizedFieldsConstraintValidator.php).

Non-translatable field elements can only be changed when updating the original language.

While searching for "Warning: Undefined array key "width" in " i stumbled upon this issue https://www.drupal.org/project/drupal/issues/3218426 and
used the patch https://www.drupal.org/files/issues/2025-08-28/3218426-90-10.3.x.patch and now I can save my node.

Worth mentioning perhaps is that before this I could not open the paragraph when trying to edit it and received the error in the console. After disabling the devel module I was able to at least open the paragaph and edit it.

Applying the patch also allowed having the devel module enabled again.

mandclu’s picture

I have run into this error many times and have had to patch many sites with the solutions kindly provided here. It would be amazing to see a fix for this in Drupal 11.3. Santa? I promise I've been a good Drupalist all year.

I will point out that #148 suggests that a "fix" is to uncheck your content type in the content translation interface, save, and then check it again and save. While this does indeed allow translations to be saved, effectively this resets the field translatability, making all fields translatable. IMHO this doesn't make sense, especially for things like entity reference fields (where it often makes more sense to translate the referenced entity instead).

introfini’s picture

#141 fixed the "Non-translatable fields can only be changed when updating the original language."

Thanks!

astonvictor’s picture

I also had a similar issue with migration.

Steps to reproduce:
1. Add a non-translatable Boolean field to a content type.
2. Create a new migration that doesn't migrate the field from #1.
3. Ran migration.
4. Try to translate the migrated content.

As a result, the editor has Non-translatable fields can only be changed when updating the original language. error.
After some debugging, I found that the original node has [field_name] => [], but when we try to translate the form, we submit the value as [field_name] => [0 => ['value' => 0]]. So, values are different.

p.s. in my case, as a hotfix, I updated the migration plugin by adding a default value to the field.

astonvictor’s picture

Issue summary: View changes

I guess the reason for #152 and Scenario #1 is similar.

astonvictor’s picture

Issue summary: View changes
oily’s picture

Test coverage is now in place so removing 'Needs tests' tag.

The test-only test fails as it should:
https://git.drupalcode.org/issue/drupal-3025039/-/jobs/6753022

The pipeline is green. Setting to 'Needs review'.

What is missing? I notice that the issue affects migrations. Do we need migrations test coverage, also?

oily’s picture

Status: Needs work » Needs review
oily’s picture

Have left code review.

oily’s picture

Issue tags: -Needs tests
smustgrave’s picture

Status: Needs review » Needs work

rcodina made their first commit to this issue’s fork.

rcodina’s picture

@oily @smustgrave I've made changes based on the suggestions in all threads, but I don't have permission to close them. Could someone review them?

rcodina’s picture

Status: Needs work » Needs review
oily’s picture

@rcodina I have reviewed and approve your changes with my suggestions. I wanted to close the comments but do not have permission.

oily’s picture

Seems the MR was created by @joseph.olstad. @rcodina Not sure if it is necessary to create a new MR? Unless @joseph.olstad can resolve the comments?

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

yaqbick’s picture

This patch caused some additional issues in my project.

I changed this line

if (Element::isVisibleElement($widget) || $items->getFieldDefinition()->getName() == 'status')

To

if (Element::isVisibleElement($widget) || $items->getFieldDefinition()->getName() == 'status' || $items->getFieldDefinition()->getName() == 'field_state')

Now it is working

andras_szilagyi’s picture

@pavlosdan even if I set status to untranslatable (with or without content moderation), it seems Drupal will ignore that.

If Drupal is designed like that maybe its rather a content moderation issue?
(I found also https://www.drupal.org/project/drupal/issues/3088793#comment-15460204)

If I test this patch (with only if (Element::isVisibleElement($widget))) without content moderation, it solves the boolean field issue (scenario 1), also I have publication status untranslatable and there are no issues with it (no error is thrown).

pavlosdan’s picture

@andras_szilagyi This was initially reported on the content moderation issue queue, but later got moved to the entity system by the system's maintainers: https://www.drupal.org/project/drupal/issues/3025039#comment-12962139

herved’s picture

I'll try to sum up my understanding of this issue.
I've encountered scenario 1 (post-content boolean field addition) and I can confirm the patch solves it (see #85).

What seems to be holding this issue back is the exception done for the status field (#121, #125), which I agree doesn't seem right.
This was introduced in #94 and described in #144 and specifically relates to content_moderation.
I think this should be addressed separately in content_moderation.
What I don't understand is why are you marking the status field as untranslatable in the first place? because content_moderation currently forces different moderation_state per translation and the moderation_state field controls the status field (in \Drupal\content_moderation\Entity\Handler\ModerationHandler::onPresave).
So marking the status field as untranslatable simply does not work and achieves nothing (besides triggering the constraint).
I'm not saying it's not an issue, it is at least from a UI perspective, but I just want to mention that this seems to be caused by a wrong configuration: if you are using content_moderation, the status field should be marked as translatable.

I think we should remove that status condition and do something like this in content_moderation:

#[Hook('entity_bundle_field_info_alter')]
public function entityBundleFieldInfoAlter(&$fields, EntityTypeInterface $entity_type, $bundle): void {
  /** @var \Drupal\content_moderation\ModerationInformationInterface $moderation_info */
  $moderation_info = \Drupal::service('content_moderation.moderation_information');
  if ($moderation_info->shouldModerateEntitiesOfBundle($entity_type, $bundle)) {
    // Force the published field to be translatable since moderation_state is always translatable and controls it.
    $published_field = $entity_type->getKey('published');
    if ($published_field && isset($fields[$published_field])) {
      $fields[$published_field]->setTranslatable(TRUE);
    }
  }
}

andras_szilagyi’s picture

StatusFileSize
new2.37 KB

Alternate solution patch against D10.6.x

Just the solution not the tests in case anyone needs it in their D10 website.

claudiu.cristea’s picture

Priority: Normal » Major

For sure is Major if not Critical

smustgrave’s picture

Status: Needs review » Needs work

There are 3 MRs can those be cleaned up or hidden please.

anybody’s picture

I've run into this on a quite basic taxonomy term now. Confirming Major or even Critical.

In addition to the proposed fixes I'd vote to add the name of the affected field(s) to the message for easier debugging. So if anyone runs into this in the future, we'll at least know which field caused the issue (and its details).