EntityUntranslatableFieldsConstraint can cause translation issues when content is created with an earlier version of viewsreference

Created on 21 August 2025, 30 days ago

Problem/Motivation

If a content entity containing a viewsreference field has been created on v2.0-beta8 or earlier, trying to translate it on v2.0-beta9 or later will not work and produces the "Non-translatable fields can only be changed when updating the original language" error.

In my case, this happens with a translatable node containing an untranslatable reference to a translatable paragraph which has an untranslatable viewsreference field, but it seems likely this will also happen if the viewsreference field exists directly on a node.

Details

The viewsreference module uses a custom class (ViewsReferenceFieldItemList) for handling field item lists on forms. When updating an entity which contains a viewsreference field, the 'equals' method in that class is used to determine whether the field value has changed from the previous value. Even when a viewsreference field is marked untranslatable, that class is still comparing the field value of the source language entity to the field value in the translation being created.

In the case of viewreference, the compared values are objects containing the settings for the chosen view reference. The settings include a serialized field, 'data', which holds the "extra settings" which can be enabled in the field configuration:

  • Pagination
  • Argument
  • Limit results
  • Offset results
  • Hide header
  • Include View Title

When the entity has been created on beta8 or earlier, the serialized data in the source translation will not contain the 'header' key, as the "Hide header" option was added as a part of issue #3427005 Hide header option Active , released in beta9.

After upgrading to beta9 or later, the serialized data for the translation being created will contain the 'header' key, which leads to ViewsReferenceFieldItemList considering the source and translation fields unequal, which will cause EntityUntranslatableFieldsConstraint to kick in and prevent saving the entity.

Steps to reproduce

  1. Install 2.0-beta8
  2. In a translatable but untranslated node (the source language), add a translatable paragraph which contains an untranslatable viewsreference field
  3. Save the node
  4. Upgrade to 2.0-beta9 or 2.0-beta10
  5. Attempt to translate the node and observe that it's not possible

Workaround

Make some change in the source entity and save it (and undo your change and save it a second time).
This will re-create the serialized data stored in the field item.
After that, translation will work again.

Proposed resolution

The serialized data contains keys for all the extra settings even when no extra settings are enabled, which is probably how it needs to be: otherwise enabling a setting after content is already created would create this same issue.

One solution would be using module update hooks to recreate existing field item data whenever there is a change in the available settings.

Maybe a better one would be to change how ViewsReferenceFieldItemList::equals handles the comparison. It would need to disregard missing keys on either side of the comparison, but at the same time, enforce that keys found on both sides have the same values.

🐛 Bug report
Status

Needs work

Version

2.0

Component

Code

Created by

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

Merge Requests

Comments & Activities

  • Issue created by @marttir
  • Pipeline finished with Failed
    30 days ago
    Total: 208s
    #578469
  • Quick patch. Probably doesn't work right if items in a multi-value field are added/removed.

  • Pipeline finished with Canceled
    30 days ago
    Total: 88s
    #578479
  • Pipeline finished with Failed
    30 days ago
    Total: 302s
    #578480
  • Note: test failures are not related to the changes done here.

  • First commit to issue fork.
  • 🇬🇧United Kingdom scott_euser

    Thanks for the contribution! This sounds like it might be better as a update hook instead? Though I have not looked deeply at the cause.
    For now I rebased latest into your MR since tests past on latest at the moment

  • 🇬🇧United Kingdom scott_euser

    Will set to Needs Work per your comment in #3 in any case, but my guess is update hook is probably the way to go instead

  • Thinking about this further, I think the comparison does work for multi-value fields, since what's being compared is the entire field value at once, and not e.g. pairs of items. So e.g. adding new field items, removing some, or changing the order would still be detected as unequal even before the code hits the part where it checks the serialized data.

    There are some reasons to favor changing the comparison over adding an update hook:

    • An update hook needs to update field values on entity revisions – the comparison works on any revision
    • An update hook needs to look at nodes, paragraphs and possibly also other entities – paragraphs would need to be done conditionally, but is updating arbitrary entities feasible?
    • A separate update hook needs to be written every time a field setting is added/changed/removed
    • If there is a lot of content using viewreference, the update could take a long time

    So going the update hook route would increase the maintenance burden and potentially slow down deployments where the update runs. Also, there would still be the possibility of forgetting to create the hook and ending up in the same situation again.

Production build 0.71.5 2024