Index: src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php (revision edf36e039c3b243be03b22d400a7b1cc0aae59eb) +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php (revision ) @@ -4,7 +4,6 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\Html; -use Drupal\Core\Entity\Entity; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\RevisionableInterface; @@ -14,6 +13,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Render\Element; +use Drupal\field\Entity\FieldConfig; use Drupal\paragraphs; use Symfony\Component\Validator\ConstraintViolationInterface; @@ -232,6 +232,26 @@ } } } + + /** + * Localised Paragraphs. + * + * If the parent field is marked as translatable, assume paragraphs + * to be localized (host entity expects different paragraphs for + * different languages) + */ + else if ($items->getFieldDefinition()->isTranslatable()) { + $paragraphs_entity = $this->cloneReferencedEntity($paragraphs_entity, $entity_manager, $target_type, $langcode); + } + + /** + * Translated Paragraphs + * + * If the parent field is not translatable, assume the paragraph + * entity itself (rather the fields within it) are marked as + * translatable. (host entity expects same paragraphs in different + * languages). + */ else { // Add translation if missing for the target language. if (!$paragraphs_entity->hasTranslation($langcode)) { @@ -332,7 +352,7 @@ } // Hide the button when translating. - $button_access = $paragraphs_entity->access('delete') && !$this->isTranslating; + $button_access = $paragraphs_entity->access('delete') && (!$this->isTranslating || $items->getFieldDefinition()->isTranslatable()); $links['remove_button'] = array( '#type' => 'submit', '#value' => $this->t('Remove'), @@ -733,7 +753,7 @@ foreach ($bundles as $machine_name => $bundle) { if ($dragdrop_settings || (!count($this->getSelectionHandlerSetting('target_bundles')) - || in_array($machine_name, $this->getSelectionHandlerSetting('target_bundles')))) { + || in_array($machine_name, $this->getSelectionHandlerSetting('target_bundles')))) { $options[$machine_name] = $bundle['label']; if ($access_control_handler->createAccess($machine_name)) { @@ -794,7 +814,7 @@ $elements['add_more'] = array( '#type' => 'container', '#theme_wrappers' => array('paragraphs_dropbutton_wrapper'), - '#access' => !$this->isTranslating, + '#access' => (!$this->isTranslating || $items->getFieldDefinition()->isTranslatable()), ); if (count($access_options)) { @@ -830,7 +850,7 @@ ); if ($drop_button) { $elements['add_more']['add_more_button_' . $machine_name]['#prefix'] = '
  • '; - $elements['add_more']['add_more_button_' . $machine_name]['#suffix'] = '
  • '; + $elements['add_more']['add_more_button_' . $machine_name]['#suffix'] = '
  • '; } } } @@ -1082,9 +1102,8 @@ /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $display */ $display = $widget_state['paragraphs'][$item['_original_delta']]['display']; - if ($widget_state['paragraphs'][$delta]['mode'] == 'edit') { - $display->extractFormValues($paragraphs_entity, $element[$item['_original_delta']]['subform'], $form_state); + $display->extractFormValues($paragraphs_entity, $element[$item['_original_delta']]['subform'], $form_state); - } + $paragraphs_entity->setNewRevision($new_revision); // A content entity form saves without any rebuild. It needs to set the // language to update it in case of language change. @@ -1188,5 +1207,50 @@ } } return $element; + } + + /** + * Clones Paragraphs (and field_collections) recursively, preparing them to be + * passed to the translated paragraph widget. + * + * @param $entity_to_clone + * @param $entity_manager + * @param $target_type + * @param $langcode + * @return array + */ + protected function cloneReferencedEntity($entity_to_clone, $entity_manager, $target_type, $langcode) { + // Get the paragraph item as an array of values. + $paragraph_array = $entity_to_clone->toArray(); + $entity_type = $entity_manager->getDefinition($target_type); + $bundle_key = $entity_type->getKey('bundle'); + + // Create a new entity for this language. + $new_entity = array( + $bundle_key => $entity_to_clone->bundle(), + 'langcode' => $langcode + ); + + // Loop through all fields in the paragraph and add to new entity. + foreach ($entity_to_clone->getFieldDefinitions() as $key => $field) { + // Check that the value is a field config and not empty. + if ($field instanceof FieldConfig && !empty($paragraph_array[$key])) { + if(in_array($field->getSetting('target_type'), ['field_collection_item', 'paragraph'])){ + // we need to get the actual field object from the original entity being cloned. + $entities = $entity_to_clone->get($key)->referencedEntities(); + $cloned_entites = []; + foreach ($entities as $entity){ + /** @var EntityInterface $entity */ + $cloned_entites_target_type = $entity->getEntityTypeId(); + $cloned_entites[] = $this->cloneReferencedEntity($entity, $entity_manager, $cloned_entites_target_type, $langcode); + } + $new_entity[$key] = $cloned_entites; + } + else{ + $new_entity[$key] = $paragraph_array[$key]; + } + } + } + return $entity_manager->getStorage($target_type)->create($new_entity); } }