Problem/Motivation

When we have an entity that has the "fr" langcode on the server website and the "und" langcode on the client website, the sync fails with this error:

InvalidArgumentException : The entity cannot be translated since it is language neutral (und). dans Drupal\Core\Entity\ContentEntityBase->addTranslation()

This happens because ImportService::getProcessedEntity() sees that the entity does not already have a French translation so it calls addTranslation() on it, but this is not allowed for entities with a locked language.

Steps to reproduce

  1. Create a media with the "und" language and synchronize it to another website.
  2. Change the language to "fr" and synchronize it again.

Proposed resolution

ImportService::getProcessedEntity() should not add a translation when the existing entity has a locked language, it should instead change its language.

CommentFileSizeAuthor
#4 3277731-4.patch955 bytestaras.suliatitskiy
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

prudloff created an issue. See original summary.

prudloff’s picture

Status: Active » Needs review
taras.suliatitskiy’s picture

StatusFileSize
new955 bytes

Patch created.

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

grimreaper’s picture

Version: 8.x-3.0-beta4 » 8.x-3.x-dev
Assigned: Unassigned » grimreaper
grimreaper’s picture

Status: Needs review » Needs work

Hi,

Thanks I reproduce the problem. Having entities in a locked language is not something frequent.

So I made some test and ok, if an entity is in language und, it can't have translation so no risk to have imported it previously in another language.

The problem may also happen is the following scenario:

Site 1:
- Entity A und

Site 2:
import entity
- Entity A und

Site 1:
- change default language
- Entity A en
- add translation
- Entity A fr

Site 2:
- try to import Entity A fr (which is not the default language on Site 1)

In this case, with the currently proposed solution, this will change the default langcode of the imported entity to the langcode of the translation being imported which this may not be what we want.

In DefaultDataProcessor.php, the default_langcode attribute is removed, but I think we still have access to the content_translation_source attribute which value is und in the case of the default translation and the source translation code if not.

I will try to poc something around that.

grimreaper’s picture

I tried something like the following code.

And the problem is in the last else statement. So I guess that when having content switching from locked language to normal languages, this may not be a problem that the imported entity in language und, is overridden with new data set as default translation. In most cases I guess that the next import will be to update the default langcode.

      // If the existing entity is in an untranslatable language like 'und':
      // - if the imported translation is still the default language, update
      //   the entity default language.
      // - if the imported translation is for a different language than the
      //   new default language on the remote, detect remote new default
      //   language using content_translation_source attribute and set it. Then
      //   create a new translation has usual.
      if ($existing_entity->language()->isLocked()) {
        $content_translation_source_public_name = FALSE;
        if (isset($field_mappings[$entity_type_id][$entity_bundle]['content_translation_source'])) {
          $content_translation_source_public_name = $field_mappings[$entity_type_id][$entity_bundle]['content_translation_source'];
        }
        $content_translation_source = FALSE;
        if ($content_translation_source_public_name && !empty($entity_data['attributes'][$content_translation_source_public_name])) {
          $content_translation_source = $entity_data['attributes'][$content_translation_source_public_name];
        }

        // @todo Add check in Default data processor that content translation source is present.
        // We are still dealing with the default language.
        if ($content_translation_source == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
          $existing_entity->set('langcode', $data_langcode);
        }
        else {
          // The problem is that we would have to check that the content translation source
          // is referencing a language that exists on this website. And if not skip the entity and
          // log an error.
          $existing_entity->set('langcode', $content_translation_source);
        }
      }

So the issue "only" needs tests.

  • Grimreaper committed b4859113 on 8.x-3.x
    Issue #3277731 by Grimreaper: Can't add translation to locked language:...

  • Grimreaper committed b4fd3a95 on 8.x-3.x authored by prudloff
    Issue #3277731 by prudloff: Can't add translation to locked language
    
grimreaper’s picture

Assigned: grimreaper » Unassigned
Status: Needs work » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

lawxen’s picture

I still got error when syncing a node again
InvalidArgumentException: Invalid translation language (und) specified. in Drupal\Core\Entity\ContentEntityBase->addTranslation() (line 952 of /var/www/html/docroot/core/lib/Drupal/Core/Entity/ContentEntityBase.php) [d96fafe1-837e-42f9-ad09-cb688adda8fc].
Version : Drupal10 + entity_share 3.0

lawxen’s picture

Continue:
On ther sever side, I use jsonapi_extra hide the language field, then the client side will use the default languge to create the node, then sync again, error comes.