diff --git a/paragraphs.module b/paragraphs.module
index e5af4a6..8545404 100644
--- a/paragraphs.module
+++ b/paragraphs.module
@@ -242,6 +242,17 @@ function paragraphs_form_language_content_settings_form_alter(&$form, \Drupal\Co
}
}
}
+
+ // Update the description on the hide untranslatable fields checkbox.
+ if (isset($form['settings']['paragraph'])) {
+ $paragraph_untranslatable_hide_description = t('Paragraph types that are used in moderated content requires non-translatable fields to be edited in the original language form and this must be checked.');
+ foreach (Element::children($form['settings']['paragraph']) as $bundle) {
+ if (!empty($form['settings']['paragraph'][$bundle]['settings']['content_translation']['untranslatable_fields_hide'])) {
+ $form['settings']['paragraph'][$bundle]['settings']['content_translation']['untranslatable_fields_hide']['#description'] = $paragraph_untranslatable_hide_description;
+ }
+ }
+ }
+
$form['settings']['paragraphs_message'] = array(
'#type' => 'container',
'#markup' => $message_text,
diff --git a/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php b/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
index 681182f..8ffb05f 100644
--- a/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
+++ b/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
@@ -230,6 +230,7 @@ class InlineParagraphsWidget extends WidgetBase {
$parents = $element['#field_parents'];
$info = [];
+ /** @var \Drupal\paragraphs\ParagraphInterface $paragraphs_entity */
$paragraphs_entity = NULL;
$host = $items->getEntity();
$widget_state = static::getWidgetState($parents, $field_name, $form_state);
@@ -654,14 +655,38 @@ class InlineParagraphsWidget extends WidgetBase {
if ($item_mode == 'edit') {
$display->buildForm($paragraphs_entity, $element['subform'], $form_state);
+ $hide_untranslatable_fields = $paragraphs_entity->isDefaultTranslationAffectedOnly();
foreach (Element::children($element['subform']) as $field) {
if ($paragraphs_entity->hasField($field)) {
+ $field_definition = $paragraphs_entity->getFieldDefinition($field);
$translatable = $paragraphs_entity->{$field}->getFieldDefinition()->isTranslatable();
- if ($translatable) {
- $element['subform'][$field]['widget']['#after_build'][] = [
- static::class,
- 'removeTranslatabilityClue'
- ];
+
+ // Do a check if we have to add a class to the form element. We need
+ // those classes (paragraphs-content and paragraphs-behavior) to show
+ // and hide elements, depending of the active perspective.
+ // We need them to filter out entity reference revisions fields that
+ // reference paragraphs, cause otherwise we have problems with showing
+ // and hiding the right fields in nested paragraphs.
+ $is_paragraph_field = FALSE;
+ if ($field_definition->getType() == 'entity_reference_revisions') {
+ // Check if we are referencing paragraphs.
+ if ($field_definition->getSetting('target_type') == 'paragraph') {
+ $is_paragraph_field = TRUE;
+ }
+ }
+
+ // Hide untranslatable fields when configured to do so except
+ // paragraph fields.
+ if (!$translatable && $this->isTranslating && !$is_paragraph_field) {
+ if ($hide_untranslatable_fields) {
+ $element['subform'][$field]['#access'] = FALSE;
+ }
+ else {
+ $element['subform'][$field]['widget']['#after_build'][] = [
+ static::class,
+ 'addTranslatabilityClue'
+ ];
+ }
}
}
}
@@ -906,6 +931,11 @@ class InlineParagraphsWidget extends WidgetBase {
$elements['#attached']['library'][] = 'paragraphs/drupal.paragraphs.admin';
+ // Signal to content_translation that this field should be treated as
+ // multilingual and not be hidden, see
+ // \Drupal\content_translation\ContentTranslationHandler::entityFormSharedElements().
+ $elements['#multilingual'] = TRUE;
+
return $elements;
}
@@ -1349,38 +1379,46 @@ class InlineParagraphsWidget extends WidgetBase {
}
/**
- * After-build callback for removing the translatability clue from the widget.
+ * After-build callback for adding the translatability clue from the widget.
*
- * If the fields on the paragraph type are translatable,
- * ContentTranslationHandler::addTranslatabilityClue()adds an
- * "(all languages)" suffix to the widget title. That suffix is incorrect and
- * is being removed by this method using a #after_build on the field widget.
+ * ContentTranslationHandler::addTranslatabilityClue() adds an
+ * "(all languages)" suffix to the widget title, replicate that here.
*
* @param array $element
* @param \Drupal\Core\Form\FormStateInterface $form_state
*
* @return array
*/
- public static function removeTranslatabilityClue(array $element, FormStateInterface $form_state) {
+ public static function addTranslatabilityClue(array $element, FormStateInterface $form_state) {
+ static $suffix, $fapi_title_elements;
+
// Widgets could have multiple elements with their own titles, so remove the
// suffix if it exists, do not recurse lower than this to avoid going into
// nested paragraphs or similar nested field types.
- $suffix = ' (' . t('all languages') . ')';
- if (isset($element['#title']) && strpos($element['#title'], $suffix)) {
- $element['#title'] = str_replace($suffix, '', $element['#title']);
+ // Elements which can have a #title attribute according to FAPI Reference.
+ if (!isset($suffix)) {
+ $suffix = ' (' . t('all languages') . ')';
+ $fapi_title_elements = array_flip(['checkbox', 'checkboxes', 'date', 'details', 'fieldset', 'file', 'item', 'password', 'password_confirm', 'radio', 'radios', 'select', 'textarea', 'textfield', 'weight']);
}
- // Loop over all widget deltas.
- foreach (Element::children($element) as $delta) {
- if (isset($element[$delta]['#title']) && strpos($element[$delta]['#title'], $suffix)) {
- $element[$delta]['#title'] = str_replace($suffix, '', $element[$delta]['#title']);
- }
- // Loop over all form elements within the current delta.
- foreach (Element::children($element[$delta]) as $field) {
- if (isset($element[$delta][$field]['#title']) && strpos($element[$delta][$field]['#title'], $suffix)) {
- $element[$delta][$field]['#title'] = str_replace($suffix, '', $element[$delta][$field]['#title']);
- }
+
+ // Update #title attribute for all elements that are allowed to have a
+ // #title attribute according to the Form API Reference. The reason for this
+ // check is because some elements have a #title attribute even though it is
+ // not rendered; for instance, field containers.
+ if (isset($element['#type']) && isset($fapi_title_elements[$element['#type']]) && isset($element['#title'])) {
+ $element['#title'] .= $suffix;
+ }
+ // If the current element does not have a (valid) title, try child elements.
+ elseif ($children = Element::children($element)) {
+ foreach ($children as $delta) {
+ $element[$delta] = static::addTranslatabilityClue($element[$delta], $form_state);
}
}
+ // If there are no children, fall back to the current #title attribute if it
+ // exists.
+ elseif (isset($element['#title'])) {
+ $element['#title'] .= $suffix;
+ }
return $element;
}
diff --git a/src/Plugin/Field/FieldWidget/ParagraphsWidget.php b/src/Plugin/Field/FieldWidget/ParagraphsWidget.php
index 82b9872..e89b40e 100644
--- a/src/Plugin/Field/FieldWidget/ParagraphsWidget.php
+++ b/src/Plugin/Field/FieldWidget/ParagraphsWidget.php
@@ -715,16 +715,18 @@ class ParagraphsWidget extends WidgetBase {
$element['subform'][$field]['#attributes']['class'][] = 'paragraphs-content';
}
$translatable = $field_definition->isTranslatable();
- if ($translatable) {
- $element['subform'][$field]['widget']['#after_build'][] = [
- static::class,
- 'removeTranslatabilityClue',
- ];
- }
// Hide untranslatable fields when configured to do so except
// paragraph fields.
- elseif ($hide_untranslatable_fields && $this->isTranslating && !$is_paragraph_field) {
- $element['subform'][$field]['#access'] = FALSE;
+ if (!$translatable && $this->isTranslating && !$is_paragraph_field) {
+ if ($hide_untranslatable_fields) {
+ $element['subform'][$field]['#access'] = FALSE;
+ }
+ else {
+ $element['subform'][$field]['widget']['#after_build'][] = [
+ static::class,
+ 'addTranslatabilityClue'
+ ];
+ }
}
}
}
@@ -2229,38 +2231,46 @@ class ParagraphsWidget extends WidgetBase {
}
/**
- * After-build callback for removing the translatability clue from the widget.
+ * After-build callback for adding the translatability clue from the widget.
*
- * If the fields on the paragraph type are translatable,
- * ContentTranslationHandler::addTranslatabilityClue()adds an
- * "(all languages)" suffix to the widget title. That suffix is incorrect and
- * is being removed by this method using a #after_build on the field widget.
+ * ContentTranslationHandler::addTranslatabilityClue() adds an
+ * "(all languages)" suffix to the widget title, replicate that here.
*
* @param array $element
* @param \Drupal\Core\Form\FormStateInterface $form_state
*
* @return array
*/
- public static function removeTranslatabilityClue(array $element, FormStateInterface $form_state) {
+ public static function addTranslatabilityClue(array $element, FormStateInterface $form_state) {
+ static $suffix, $fapi_title_elements;
+
// Widgets could have multiple elements with their own titles, so remove the
// suffix if it exists, do not recurse lower than this to avoid going into
// nested paragraphs or similar nested field types.
- $suffix = ' (' . t('all languages') . ')';
- if (isset($element['#title']) && strpos($element['#title'], $suffix)) {
- $element['#title'] = str_replace($suffix, '', $element['#title']);
+ // Elements which can have a #title attribute according to FAPI Reference.
+ if (!isset($suffix)) {
+ $suffix = ' (' . t('all languages') . ')';
+ $fapi_title_elements = array_flip(['checkbox', 'checkboxes', 'date', 'details', 'fieldset', 'file', 'item', 'password', 'password_confirm', 'radio', 'radios', 'select', 'textarea', 'textfield', 'weight']);
}
- // Loop over all widget deltas.
- foreach (Element::children($element) as $delta) {
- if (isset($element[$delta]['#title']) && strpos($element[$delta]['#title'], $suffix)) {
- $element[$delta]['#title'] = str_replace($suffix, '', $element[$delta]['#title']);
- }
- // Loop over all form elements within the current delta.
- foreach (Element::children($element[$delta]) as $field) {
- if (isset($element[$delta][$field]['#title']) && strpos($element[$delta][$field]['#title'], $suffix)) {
- $element[$delta][$field]['#title'] = str_replace($suffix, '', $element[$delta][$field]['#title']);
- }
+
+ // Update #title attribute for all elements that are allowed to have a
+ // #title attribute according to the Form API Reference. The reason for this
+ // check is because some elements have a #title attribute even though it is
+ // not rendered; for instance, field containers.
+ if (isset($element['#type']) && isset($fapi_title_elements[$element['#type']]) && isset($element['#title'])) {
+ $element['#title'] .= $suffix;
+ }
+ // If the current element does not have a (valid) title, try child elements.
+ elseif ($children = Element::children($element)) {
+ foreach ($children as $delta) {
+ $element[$delta] = static::addTranslatabilityClue($element[$delta], $form_state);
}
}
+ // If there are no children, fall back to the current #title attribute if it
+ // exists.
+ elseif (isset($element['#title'])) {
+ $element['#title'] .= $suffix;
+ }
return $element;
}
diff --git a/tests/src/Functional/ParagraphsContentModerationTranslationsTest.php b/tests/src/Functional/ParagraphsContentModerationTranslationsTest.php
index 7894d1e..2c4a1c6 100644
--- a/tests/src/Functional/ParagraphsContentModerationTranslationsTest.php
+++ b/tests/src/Functional/ParagraphsContentModerationTranslationsTest.php
@@ -108,6 +108,8 @@ class ParagraphsContentModerationTranslationsTest extends BrowserTestBase {
$this->addParagraphsField('container', 'field_paragraphs', 'paragraph');
+ $this->drupalGet('admin/config/regional/content-language');
+ $this->assertSession()->pageTextContains('Paragraph types that are used in moderated content requires non-translatable fields to be edited in the original language form and this must be checked.');
$edit = [
'entity_types[paragraph]' => TRUE,
'entity_types[node]' => TRUE,
@@ -118,14 +120,13 @@ class ParagraphsContentModerationTranslationsTest extends BrowserTestBase {
'settings[paragraph][container][translatable]' => TRUE,
// Because the paragraph entity itself is not directly enabled in the
// workflow, these options must be enabled manually.
- // @todo Improve this.
'settings[paragraph][text][settings][content_translation][untranslatable_fields_hide]' => TRUE,
'settings[paragraph][container][settings][content_translation][untranslatable_fields_hide]' => TRUE,
'settings[paragraph][text][fields][field_text]' => TRUE,
'settings[paragraph][text][fields][field_untranslatable]' => FALSE,
'settings[paragraph][container][fields][field_paragraphs]' => FALSE,
];
- $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
+ $this->drupalPostForm(NULL, $edit, t('Save configuration'));
}
/**