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 newbooleanfield (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 (statusproperty) - 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. :)
| Comment | File | Size | Author |
|---|
Issue fork drupal-3025039
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
Comment #2
pavlosdanInitially 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.
Comment #3
pavlosdanComment #4
pavlosdanThis is a duplicate of #2959175: Non-translatable fields error when using: Content Moderation + Content Translation + Comments
Comment #5
mikemccaffreyI'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.
Comment #6
sam152 commentedI think this may actually fall under the entity system, since the constraint in question is in
Drupal\Core\Entityand 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.Comment #7
pavlosdan@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.
Comment #8
pavlosdanbumping this to 8.7 since I just tested against that.
Comment #9
antoniya commented+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..
Comment #11
yahyaalhamadI think I got around this issue using the checkbox in content translations "Hide non-translatable fields" in Paragraph types.
Comment #12
matthewv789 commentedRelated 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.
Comment #13
ghost of drupal pastIf 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.
Comment #14
berdiraccess could also be an access result object.. Maye we should have a helper method for that somewhere, not in scope..
Comment #15
ghost of drupal pastSure, we can do that.
Comment #16
ghost of drupal pastD'oh, only literal FALSE is access denied. Which means #13 was also slightly incorrect.
Comment #17
viappidu commentedI 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.
Comment #18
sanjayk commentedComment #19
sanjayk commentedUnable to reproduce please provide more information.
Comment #20
viappidu commented@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.
Comment #21
sanjayk commented@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".
Comment #22
yahyaalhamad@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.
Comment #23
viappidu commented@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
Comment #24
sanjayk commented@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. :)
Comment #25
viappidu commented@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 :)
Comment #26
clayfreemanForgive me if I'm missing something, but in trying to replicate the original issue (being that
EntityUntranslatableFieldsConstraint::$defaultRevisionMessageis violated), I noticed that#accessshould never be set toFALSE; 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::$defaultTranslationMessageviolation 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::$defaultRevisionMessageis 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 ofEntityUntranslatableFieldsConstraint::$defaultTranslationMessageinstead.Comment #27
dunebl#16 save my day!
Same as #26, I was facing 2 violations of the kind
EntityUntranslatableFieldsConstraint::$defaultTranslationMessageBut, it was **not** about paragraph fields, it was about a comment field and a stateItem field.
#16 solve it.
Thank you
Comment #28
anybodyJust 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!
Comment #29
mandclu commentedI 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.
Comment #30
alexpottThanks 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:
Comment #31
ghost of drupal pastI 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.
Comment #32
berdirI 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.
Comment #33
ghost of drupal pastThis is the failing test, I will post this + #16 next which passes.
Comment #34
ghost of drupal pastComment #35
ghost of drupal pastD'oh!
Comment #36
ghost of drupal pastAh. This is the failing version...
Comment #37
ghost of drupal past... and this is the passing one. I will stop posting duplicates once we have a fail-pass version verified by the testbot.
Comment #39
ghost of drupal pastI 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.
Comment #40
ghost of drupal pastI found a much cleaner way to do my asserts and fixed the code style issue found.
Comment #41
ghost of drupal pastSigh.
Comment #42
ghost of drupal pastI switched to entity constraint violations directly instead of form error messages because the comparison to
EntityUntranslatableFieldsConstraintcan 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.Comment #43
clayfreemanJust a nit... docblocks?
Should these instead be in
::setUp()?Then this wouldn't be necessary...
Comment #44
siddhant.bhosale commentedComment #45
siddhant.bhosale commentedI have made the changes from comment #43.
Please review.
Comment #46
ghost of drupal pastPlease 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:
To compare. #45 instead does
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.
Comment #47
andypostComment #48
clayfreeman@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...)Comment #49
ghost of drupal pastI 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.
Comment #50
clayfreemanIf we're trying to implement the steps to replicate, the issue summary explicitly calls for a non-NULL default:
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!
Comment #51
ghost of drupal pastI 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.
Comment #52
clayfreemanComment #53
clayfreemanRealized that I specified "non-null" - derp!
Comment #54
ghost of drupal pastThanks 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.Comment #56
ajitsConfirming that the patch from #53 works for me!
Comment #57
flyke commentedI 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
Comment #58
clayfreemanComment #60
clayfreemanRe: #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.Comment #61
pere orgaI haven't read the whole thread (nor https://www.drupal.org/project/paragraphs/issues/2956311), but I found that patch 64 of https://www.drupal.org/project/drupal/issues/3101344 fixes the problem this issue describes.
Comment #63
mikran commentedThis 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.
Comment #64
pere orgaAdding https://git.drupalcode.org/project/drupal/-/merge_requests/1105.diff as patch here, so it can be used in composer (no changes added)
Comment #65
ranjith_kumar_k_u commentedJust re-rolled for 9.4
Comment #66
ghost of drupal pastMaybe this should be using
Element::isVisibleElement?Comment #67
anna d commentedI 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.
Comment #69
anna d commentedComment #71
clayfreemanMade a revision per #66. Setting back to Needs Review.
If posting reference-only patches, please suffix the file name with
-do-not-testto 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.Comment #72
clayfreemanAfter 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.
Comment #73
anna d commentedHi @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
Comment #74
ghost of drupal pastI am sorry but I am still bothered by #54 could we try removing that setValue call from the test?
Comment #75
joseph.olstad***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 ***
Comment #76
clayfreeman@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.
Comment #77
ghost of drupal pastI 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.
Comment #78
aschiwi commentedThe 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.
Comment #79
recrit commentedAdding a static patch file for the latest MR that can be used for composer builds.
Comment #80
tcrawford commentedI 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)
Comment #81
smustgrave commentedSeems 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.
Comment #82
anybodyClosed #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.
Comment #83
anybodyComment #84
lobodakyrylo commentedComment #75 worked form me. Thank you.
Comment #85
herved commented#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
EntityUntranslatableFieldsConstraintValidatorcan 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."
EntityUntranslatableFieldsConstraintValidatorwill return TRUE forhasUntranslatableFieldsChangesbecause the boolean field items went from nothing to something (a BooleanItem with[value => FALSE]. It will then trigger the error ifhasTranslationChangesreturns 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?
Comment #86
amaisano commentedI 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
Comment #87
artyom hovasapyan commentedIt'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.
Comment #88
artyom hovasapyan commentedOr you can use this patch(update 79 patch).
Comment #89
_utsavsharma commented#88 failed to apply .
Comment #90
smustgrave commentedWasn’t able to replicate but maybe test coverage will show it better. That will be needed
Comment #91
artyom hovasapyan commentedPatches don't work correctly(drupal 9.5/10).
Reproduce
Comment #92
stborchertHey. We use the latest patch and it breaks creating content when using content moderation for content types.
Steps to reproduce
:
This will result in
This happens because the patch explicitly sets the value of field "status" to
NULL:This is wrong for fields that must not be null (based on their schema), e.g. for "status" null-values are not allowed.
Comment #93
akalam commentedI can't reproduce the bug anymore following the steps from #46 on drupal 10.2
Comment #94
loon commentedUpdated patch #79 with fix the issue described in #92
Comment #95
mgaskey commentedAnyone 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.
Comment #96
joseph.olstad***EDIT*** mistaken comment, removed to avoid confusion *** end EDIT ***
Comment #97
randy.houlahan@cbd.int commentedStill happening 6 years later in in the latest D10. Is there a stock in drupal I can invest in?
Comment #98
joseph.olstadWe'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.
Comment #99
joseph.olstadMerged the latest 11.x into MR1105
Pushed up the fix that was added in patch 94
Comment #100
joseph.olstadComment #101
joseph.olstadMR 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
Comment #105
joseph.olstadThe 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.
Comment #106
joseph.olstadPHPUnit version 10 deprecations forced a couple changes to the test to the MR9429
Comment #107
joseph.olstadPipeline seems to have gone bonkers.
Undefined variable: $thisMakes no sense.
Comment #108
berdirYou made the test method static. That's wrong.
Comment #109
joseph.olstadPipeline 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.
Comment #110
joseph.olstadComment #111
foxy-vikvik commentedWe need to add a condition if the <?PHP
!empty($widget)
?>
Comment #112
foxy-vikvik commentedPatched based on the patch from the comment #94 has issue too
Comment #113
quietone commented@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.
Comment #114
foxy-vikvik commented@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']
Comment #115
foxy-vikvik commentedIt happens only when translating the node with paragraphs
Comment #116
foxy-vikvik commentedI added the following conditions:
Comment #117
foxy-vikvik commentedComment #118
foxy-vikvik commentedComment #119
joseph.olstadThe 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
Comment #120
joseph.olstadComment #121
alexpottThis 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?
Comment #122
joseph.olstad@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.
Comment #124
joseph.olstadComment #125
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.
Comment #126
shobhit_juyal commentedIf 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 ?

Comment #127
tfranz commentedI 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 …
Comment #128
timohuismanThis patch contains a snapshot of the latest state of the MR 9429 so it can be safely used with composer-patches.
Comment #129
foxy-vikvik commentedThe 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
Comment #130
kosa ilma commentedThe patch from #128 worked for me, on core 10.3.6.
Comment #131
liquidcms commentedMy 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.
Comment #132
liquidcms commentedTo 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.
Comment #133
akhil babuUploading https://git.drupalcode.org/project/drupal/-/merge_requests/9429 as a patch to use in one of our projects, Thanks
Comment #134
achapThis 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
Comment #135
mohit.bansal623 commentedError 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.
Comment #136
ansergeyg commentedThe 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.
Comment #137
yfma commentedThe patch from #128 worked on 10.4.7, Thank you so much!
Comment #138
ansergeyg commentedGuys, 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.
Comment #139
andre.bononI 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.
Comment #140
andre.bononI 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.
Comment #141
lukasz.tyc commentedUpdated from #67 for Drupal 10.5.1 compatibility.
Comment #143
m4oliveiWe'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:
Comment #144
m4oliveiOK, I've also now run into the issue with the
statusfield, 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:drush si -y standard)/admin/modules. Enable the Content Translation and Content Moderation modules/admin/config/regional/language. Click Add language. Follow steps to add any additional language./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 (statusproperty)/admin/config/workflow/workflows/manage/editorial./node/add/article. Add an article node (just the title is enough). Mark it as Published, and SaveHere you again get the error message:
In this case, it's kind of expected behavior, because we marked the
statusfield 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.
Comment #145
m4oliveiComment #146
flyke commentedJust 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.
Comment #147
m4olivei@flyke absolutely! I've noted both scenarios in the issue summary.
Comment #148
økse commentedI 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:
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.
Comment #149
undersound3 commentedFWIW
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.
Comment #150
mandclu commentedI 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).
Comment #151
introfini commented#141 fixed the "Non-translatable fields can only be changed when updating the original language."
Thanks!
Comment #152
astonvictor commentedI 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.
Comment #153
astonvictor commentedI guess the reason for #152 and Scenario #1 is similar.
Comment #154
astonvictor commentedComment #155
oily commentedTest 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?
Comment #156
oily commentedComment #157
oily commentedHave left code review.
Comment #158
oily commentedComment #159
smustgrave commentedComment #161
rcodina@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?
Comment #162
rcodinaComment #163
oily commented@rcodina I have reviewed and approve your changes with my suggestions. I wanted to close the comments but do not have permission.
Comment #164
oily commentedSeems 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?
Comment #166
yaqbick commentedThis 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
Comment #167
andras_szilagyi commented@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).Comment #168
pavlosdan@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
Comment #169
herved commentedI'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:
Comment #171
andras_szilagyi commentedAlternate solution patch against D10.6.x
Just the solution not the tests in case anyone needs it in their D10 website.
Comment #173
claudiu.cristeaFor sure is Major if not Critical
Comment #174
smustgrave commentedThere are 3 MRs can those be cleaned up or hidden please.
Comment #175
anybodyI'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).