2

I've created a multi-lingual custom content entity using Drupal Console. The basic stuff with editing/viewing works fine, also multi-lingual. But for some reason, I can't hide the "Translation" details form element (the one with the translation meta data) in the entity's edit form.

Screenshot of form display settings: Settings in form display

Screenshot of edit form: Translation details still visible in edit form

In the config export core.entity_form_display.chunk.weather_daswetter.default.yml the translation also is listed correctly in the hidden section:

id: chunk.weather_daswetter.default
targetEntityType: chunk
bundle: weather_daswetter
mode: default
third_party_settings:
  stuff_from_field_group_module_here: nothing_with_translation
content:
  all_visible_fields_listed_correctly
hidden:
  changed: true
  created: true
  langcode: true
  translation: true
  uid: true

Into the blue I've tried relisting the fields from core's ContentTranslationHandler in my own src/Entity/Chunk.php->baseFieldDefinitions() and explicitly set them configurable, but this did not help either:

/**
 * @ContentEntityType(
 *   id = "chunk",
 *    ...
 *   translatable = TRUE,
 *   ...
 * )
 */
class Chunk extends ContentEntityBase implements ChunkInterface {
  use EntityOwnerTrait;
  use EntityChangedTrait;
  use EntityPublishedTrait;

  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);
    $fields += static::ownerBaseFieldDefinitions($entity_type);
    $fields += static::publishedBaseFieldDefinitions($entity_type);

    // tried adding this, did not help
    if ($fields['content_translation_status']) {
      $fields['content_translation_status']->setDisplayConfigurable('form', TRUE);
    }

    if ($fields['content_translation_outdated']) {
      $fields['content_translation_outdated']->setDisplayConfigurable('form', TRUE);
    }

    if ($fields['content_translation_uid']) {
      $fields['content_translation_uid']->setDisplayConfigurable('form', TRUE);
    }

    if ($fields['content_translation_created']) {
      $fields['content_translation_created']->setDisplayConfigurable('form', TRUE);
    }
  }
}

Why doesn't the form display mode control for "Translation" work?

I really want to keep this visible and configurable in the UI and therefore want to avoid using hook_form_alter.

UPDATE:
I've tried using hook_form_alter, but this doesn't work either:


function wt_chunks_form_alter(&$form, $form_state, $form_id) {
  if ($form['#entity_type'] == 'chunk') {
    /** @var $formMode \Drupal\Core\Entity\Entity\EntityFormDisplay */
    $formMode = $form_state->getStorage()['form_display'];
    $hiddenFields = $formMode->get('hidden');
    if (in_array('translation', $hiddenFields)) {
      //code goes into here, but the key 'content_translation' 
      //does not exist in the $form array
      $form['content_translation']['#access'] = FALSE;
    }
  }
}
2

The translation field that you try to disable is not the one containing the metadata.

The translation metadata is generated in Drupal\content_translation\ContentTranslationHandler and is automatically applied if following access check is true:

'#access' => $this->getTranslationAccess($entity, $new_translation ? 'create' : 'update')->isAllowed(),

To solve this problem you can add a checkbox to your entity settings form that allows you to disable the translation.

You will also need to create a custom TranslationHandler for you entity.

In the annotations of your entity add this under handlers:

"translation" = "Drupal\MY_MODULE\MyEntityTranslationHandler",

Your custom translation handler can then be something like this:

namespace Drupal\MY_MODULE;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;

class MyEntityTranslationHandler extends ContentTranslationHandler {

  public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
    $form = parent::entityFormAlter($form, $form_state, $entity);
    if (// Some condition...) {
      $form['content_translation']['#access'] = FALSE;
    }
  }

}

Hope it makes sense.

5
  • OK, got this. But what is the point of the "Translation" field in the form display? Instead of creating a new, quite dislocated setting somewhere else, I'd rather use the form display config for the existing Translation field in the if-clause of hook_form_alter. Is this a safe approach or has the existing Translation field some other unknown purpose?
    – Hudri
    Dec 17 '19 at 11:11
  • Sadly this doesn't work. When I use hook_form_alter(&$form) in my custom module, the key content_translation does not yet exist in the $form array. Somehow the translation handler seems to run after my hook?
    – Hudri
    Dec 17 '19 at 11:49
  • @Hudri I have updated my answer :)
    – user72672
    Dec 17 '19 at 12:47
  • Thanks, this works. A stub translation handler was already created and set by Drupal console's boilerplate code. Just needed to move my code from .module to the handler class.
    – Hudri
    Dec 17 '19 at 13:48
  • Cool, I'm glad it works :)
    – user72672
    Dec 17 '19 at 13:49
1

Just for completeness, here is the working code I acutally use to make the hiding via form display mode functional:

(My custom entity's name is chunk)

file src/Entity/Chunk.php

namespace Drupal\MY_MODULE\Entity;

use ...

/**
 * Defines the Chunk entity.
 *
 * @ContentEntityType(
 *   id = "chunk",
 *   label = @Translation("Chunk"),
 *   ...
 *   handlers = {
 *     ...
 *     "translation" = "Drupal\MY_MODULE\ChunkTranslationHandler",
 *     ...
 *   },
 *   translatable = TRUE,
 *   ...
 * )
 */
class Chunk extends ContentEntityBase implements ChunkInterface {
  ...
  // no special code required here, just notice the translation handler annotation above
  ...

file src/ChunkTranslationHandler.php

namespace Drupal\MY_MODULE;

use Drupal\content_translation\ContentTranslationHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Defines the translation handler for chunk.
 */
class ChunkTranslationHandler extends ContentTranslationHandler {

  public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
    parent::entityFormAlter($form, $form_state, $entity);
    /** @var $formMode \Drupal\Core\Entity\Entity\EntityFormDisplay */
    $formMode = $form_state->getStorage()['form_display'];
    $hiddenFields = $formMode->get('hidden');
    if (in_array('translation', $hiddenFields) && array_key_exists('content_translation', $form)) {
      $form['content_translation']['#access'] = FALSE;
    }
  }
}

This is the same @JDrupal's solution above, but actually uses the form display config of the Translation field (i.e. if you move it to the disabled section in the UI, all translation meta data fields are hidden).

If you use Drupal console's drupal generate:entity:content you just need to write the custom entityFormAlter() function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.