diff --git a/core/modules/layout_builder/layout_builder.links.contextual.yml b/core/modules/layout_builder/layout_builder.links.contextual.yml index d27248f5bc..28f6c53412 100644 --- a/core/modules/layout_builder/layout_builder.links.contextual.yml +++ b/core/modules/layout_builder/layout_builder.links.contextual.yml @@ -38,3 +38,13 @@ layout_builder_block_translate: data-dialog-type: dialog data-dialog-renderer: off_canvas +layout_builder_inline_block_translate: + title: 'Translate block' + route_name: 'layout_builder.translate_inline_block' + group: 'layout_builder_inline_block_translation' + options: + attributes: + class: ['use-ajax'] + data-dialog-type: dialog + data-dialog-renderer: off_canvas + diff --git a/core/modules/layout_builder/layout_builder.module b/core/modules/layout_builder/layout_builder.module index 5aeedd5b1a..d51fe4ee03 100644 --- a/core/modules/layout_builder/layout_builder.module +++ b/core/modules/layout_builder/layout_builder.module @@ -17,6 +17,7 @@ use Drupal\field\FieldConfigInterface; use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay; use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplayStorage; +use Drupal\layout_builder\Form\BlockContentInlineBlockTranslateForm; use Drupal\layout_builder\Form\BlockPluginTranslationForm; use Drupal\layout_builder\Form\DefaultsEntityForm; use Drupal\layout_builder\Form\LayoutBuilderEntityViewDisplayForm; @@ -84,6 +85,10 @@ function layout_builder_entity_type_alter(array &$entity_types) { $entity_type->setFormClass('layout_builder', OverridesEntityForm::class); } } + + if (isset($entity_types['block_content'])) { + $entity_types['block_content']->setFormClass('layout_builder_translate', BlockContentInlineBlockTranslateForm::class); + } } /** diff --git a/core/modules/layout_builder/layout_builder.routing.yml b/core/modules/layout_builder/layout_builder.routing.yml index 6cb8a26f79..b987da9d3c 100644 --- a/core/modules/layout_builder/layout_builder.routing.yml +++ b/core/modules/layout_builder/layout_builder.routing.yml @@ -126,6 +126,21 @@ layout_builder.translate_block: section_storage: layout_builder_tempstore: TRUE +layout_builder.translate_inline_block: + path: '/layout_builder/translate/inline-block/{section_storage_type}/{section_storage}/{delta}/{region}/{uuid}' + defaults: + _entity_form: 'block_content.layout_builder_translate' + _title: 'Translate block' + requirements: + _permission: 'configure any layout' + _layout_builder_access: 'view' + _layout_builder_translation_access: 'translated' + options: + _admin_route: TRUE + parameters: + section_storage: + layout_builder_tempstore: TRUE + layout_builder.move_block_form: path: '/layout_builder/move/block/{section_storage_type}/{section_storage}/{delta}/{region}/{uuid}' defaults: diff --git a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php index 6ee51ad7dc..9307f8062e 100644 --- a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php +++ b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php @@ -2,7 +2,6 @@ namespace Drupal\layout_builder\Controller; -use Drupal\Core\Language\LanguageInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\layout_builder\SectionStorageInterface; @@ -38,11 +37,10 @@ public function title(SectionStorageInterface $section_storage) { * @return array * A render array. */ - public function layout(SectionStorageInterface $section_storage, LanguageInterface $language = NULL) { + public function layout(SectionStorageInterface $section_storage) { return [ '#type' => 'layout_builder', '#section_storage' => $section_storage, - '#langague' => $language, ]; } diff --git a/core/modules/layout_builder/src/Element/LayoutBuilder.php b/core/modules/layout_builder/src/Element/LayoutBuilder.php index 0f7514f802..9074167530 100644 --- a/core/modules/layout_builder/src/Element/LayoutBuilder.php +++ b/core/modules/layout_builder/src/Element/LayoutBuilder.php @@ -2,7 +2,9 @@ namespace Drupal\layout_builder\Element; +use Drupal\Component\Plugin\DerivativeInspectionInterface; use Drupal\Core\Ajax\AjaxHelperTrait; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\PluginFormInterface; @@ -45,6 +47,12 @@ class LayoutBuilder extends RenderElement implements ContainerFactoryPluginInter */ protected $messenger; + /** + * The entity type manager. + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + /** * Constructs a new LayoutBuilder. * @@ -58,11 +66,14 @@ class LayoutBuilder extends RenderElement implements ContainerFactoryPluginInter * The layout tempstore repository. * @param \Drupal\Core\Messenger\MessengerInterface $messenger * The messenger service. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger, EntityTypeManagerInterface $entity_type_manager) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->layoutTempstoreRepository = $layout_tempstore_repository; $this->messenger = $messenger; + $this->entityTypeManager = $entity_type_manager; } /** @@ -74,7 +85,8 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_id, $plugin_definition, $container->get('layout_builder.tempstore_repository'), - $container->get('messenger') + $container->get('messenger'), + $container->get('entity_type.manager') ); } @@ -300,10 +312,26 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s 'layout_builder_block' => $contextual_link_settings, ]; } - elseif ($is_translation && $section->getComponent($uuid)->hasTranslatableConfiguration()) { - $build[$region][$uuid]['#contextual_links'] = [ - 'layout_builder_block_translation' => $contextual_link_settings, - ]; + elseif ($is_translation) { + $component = $section->getComponent($uuid); + if ($component->hasTranslatableConfiguration()) { + /** @var \Drupal\layout_builder\Plugin\Block\InlineBlock $plugin */ + $plugin = $component->getPlugin(); + if ($plugin instanceof DerivativeInspectionInterface && $plugin->getBaseId() === 'inline_block') { + $configuration = $plugin->getConfiguration(); + /** @var \Drupal\block_content\Entity\BlockContent $block */ + $block = $this->entityTypeManager->getStorage('block_content')->loadRevision($configuration['block_revision_id']); + $build[$region][$uuid]['#contextual_links'] = [ + $block->isTranslatable() ? 'layout_builder_inline_block_translation' : 'layout_builder_block_translation' => $contextual_link_settings, + ]; + } + else { + $build[$region][$uuid]['#contextual_links'] = [ + 'layout_builder_block_translation' => $contextual_link_settings, + ]; + } + + } } } } diff --git a/core/modules/layout_builder/src/EventSubscriber/ComponentPluginTranslate.php b/core/modules/layout_builder/src/EventSubscriber/ComponentPluginTranslate.php index 8765fad4de..ec90cbf98d 100644 --- a/core/modules/layout_builder/src/EventSubscriber/ComponentPluginTranslate.php +++ b/core/modules/layout_builder/src/EventSubscriber/ComponentPluginTranslate.php @@ -3,13 +3,11 @@ namespace Drupal\layout_builder\EventSubscriber; use Drupal\Component\Plugin\ConfigurableInterface; -use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent; use Drupal\layout_builder\LayoutBuilderEvents; use Drupal\layout_builder\LayoutEntityHelperTrait; use Drupal\layout_builder\TranslatableSectionStorageInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -36,7 +34,6 @@ public function __construct(LanguageManagerInterface $language_manager) { $this->languageManager = $language_manager; } - /** * {@inheritdoc} */ @@ -72,4 +69,5 @@ public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) { } } } + } diff --git a/core/modules/layout_builder/src/Form/BlockContentInlineBlockTranslateForm.php b/core/modules/layout_builder/src/Form/BlockContentInlineBlockTranslateForm.php new file mode 100644 index 0000000000..6d3d3f0d99 --- /dev/null +++ b/core/modules/layout_builder/src/Form/BlockContentInlineBlockTranslateForm.php @@ -0,0 +1,148 @@ +routeMatch = $route_match; + $this->layoutTempstoreRepository = $tempstore; + $this->uuid = $route_match->getParameter('uuid'); + $this->delta = $route_match->getParameter('delta'); + $this->sectionStorage = $route_match->getParameter('section_storage'); + $this->languageManager = $language_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.repository'), + $container->get('entity_type.bundle.info'), + $container->get('datetime.time'), + $container->get('current_route_match'), + $container->get('layout_builder.tempstore_repository'), + $container->get('language_manager') + ); + } + + /** + * {@inheritdoc} + */ + public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) { + /** @var \Drupal\layout_builder\TranslatableSectionStorageInterface $section_storage */ + $translated_configuration = $this->sectionStorage->getTranslatedComponentConfiguration($this->uuid); + $current_langcode = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId(); + + if (!empty($translated_configuration)) { + if (!empty($translated_configuration['block_serialized'])) { + return unserialize($translated_configuration['block_serialized']); + } + elseif (!empty($translated_configuration['block_revision_id'])) { + /** @var \Drupal\block_content\BlockContentInterface $entity */ + $entity = $this->entityTypeManager->getStorage('block_content')->loadRevision($translated_configuration['block_revision_id']); + $entity = $this->entityRepository->getActive('block_content', $entity->id()); + if ($entity->hasTranslation($current_langcode)) { + return $entity->getTranslation($current_langcode); + } + } + } + $configuration = $this->sectionStorage->getSection($this->delta)->getComponent($this->uuid)->getPlugin()->getConfiguration(); + if (!empty($configuration['block_revision_id'])) { + /** @var \Drupal\block_content\BlockContentInterface $entity */ + $entity = $this->entityTypeManager->getStorage('block_content')->loadRevision($configuration['block_revision_id']); + $entity = $this->entityRepository->getActive('block_content', $entity->id()); + if ($entity->hasTranslation($current_langcode)) { + return $entity->getTranslation($current_langcode); + } + else { + $translation = $entity->addTranslation($current_langcode, $entity->toArray()); + if (!empty($translated_configuration['label'])) { + $translation->setInfo($translated_configuration['label']); + } + return $translation; + } + } + else { + throw new \LogicException("InlineBlockTranslationForm should never be invoked without an available block_content entity"); + } + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + $entity = $this->entity; + $translated_configuration = $this->sectionStorage->getTranslatedComponentConfiguration($this->uuid); + $translated_configuration['block_serialized'] = serialize($entity); + $translated_configuration['label'] = $entity->label(); + $this->sectionStorage->setTranslatedComponentConfiguration($this->uuid, $translated_configuration); + $this->layoutTempstoreRepository->set($this->sectionStorage); + } + + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state) { + $form = parent::form($form, $form_state); + $form['langcode']['#access'] = FALSE; + $form['revision_log']['#access'] = FALSE; + $form['revision']['#access'] = FALSE; + return $form; + } + +} diff --git a/core/modules/layout_builder/src/Form/BlockPluginTranslationForm.php b/core/modules/layout_builder/src/Form/BlockPluginTranslationForm.php index 422cf1fac6..cc20b9e6bc 100644 --- a/core/modules/layout_builder/src/Form/BlockPluginTranslationForm.php +++ b/core/modules/layout_builder/src/Form/BlockPluginTranslationForm.php @@ -5,6 +5,7 @@ use Drupal\Component\Plugin\ConfigurableInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait; use Drupal\Core\Plugin\PluginFormBase; use Drupal\Core\StringTranslation\StringTranslationTrait; @@ -48,7 +49,7 @@ public function __construct($current_langcode) { */ public static function create(ContainerInterface $container) { return new static( - $container->get('language_manager')->getCurrentLanguage()->getId() + $container->get('language_manager')->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId() ); } diff --git a/core/modules/layout_builder/src/Form/InlineBlockTranslationForm.php b/core/modules/layout_builder/src/Form/InlineBlockTranslationForm.php deleted file mode 100644 index 62b39dfc27..0000000000 --- a/core/modules/layout_builder/src/Form/InlineBlockTranslationForm.php +++ /dev/null @@ -1,192 +0,0 @@ -entityTypeManager = $entity_type_manager; - $this->entityRepository = $entity_repository; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('language_manager')->getCurrentLanguage()->getId(), - $container->get('entity_type.manager'), - $container->get('entity.repository') - ); - } - - /** - * {@inheritdoc} - */ - public function getEntity() { - if (!empty($this->translatedConfiguration)) { - if (!empty($this->translatedConfiguration['block_serialized'])) { - return unserialize($this->translatedConfiguration['block_serialized']); - } - elseif (!empty($this->translatedConfiguration['block_revision_id'])) { - /** @var \Drupal\block_content\BlockContentInterface $entity */ - $entity = $this->entityTypeManager->getStorage('block_content')->loadRevision($this->translatedConfiguration['block_revision_id']); - $entity = $this->entityRepository->getActive('block_content', $entity->id()); - if ($entity->hasTranslation($this->currentLangcode)) { - return $entity->getTranslation($this->currentLangcode); - } - } - } - $configuration = $this->plugin->getConfiguration(); - if (!empty($configuration['block_serialized'])) { - return unserialize($configuration['block_serialized']); - } - elseif (!empty($configuration['block_revision_id'])) { - /** @var \Drupal\block_content\BlockContentInterface $entity */ - $entity = $this->entityTypeManager->getStorage('block_content')->loadRevision($configuration['block_revision_id']); - $entity = $this->entityRepository->getActive('block_content', $entity->id()); - if ($entity->hasTranslation($this->currentLangcode)) { - return $entity->getTranslation($this->currentLangcode); - } - else { - return $entity->addTranslation($this->currentLangcode, $entity->toArray()); - } - } - else { - throw new \LogicException("InlineBlockTranslationForm should never be invoked without an available block_content entity"); - } - } - - /** - * {@inheritdoc} - */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $form = parent::buildConfigurationForm($form, $form_state); - $block = $this->getEntity(); - if ($block->isTranslatable()) { - // Add the entity form display in a process callback so that #parents can - // be successfully propagated to field widgets. - $form['block_form'] = [ - '#type' => 'container', - '#process' => [[static::class, 'processBlockForm']], - '#block' => $block, - ]; - } - return $form; - } - - /** - * Process callback to insert a Custom Block form. - * - * @param array $element - * The containing element. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The form state. - * - * @return array - * The containing element, with the Custom Block form inserted. - */ - public static function processBlockForm(array $element, FormStateInterface $form_state) { - /** @var \Drupal\block_content\BlockContentInterface $block */ - $block = $element['#block']; - $element += \Drupal::service('entity.form_builder')->getForm($block, 'edit'); - unset($element['form_token']); - //$element['actions']['#access'] = FALSE; - //$element['content_translation']['#access'] = FALSE; - //$element['revision']['#access'] = FALSE; - $element['revision_log']['#access'] = FALSE; - $element['info']['#access'] = FALSE; - $element['langcode']['#access'] = FALSE; - return $element; - } - - /** - * {@inheritdoc} - */ - public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { - parent::validateConfigurationForm($form, $form_state); - if (!empty($form['block_form'])) { - $block_form = $form['block_form']; - /** @var \Drupal\block_content\BlockContentInterface $block */ - $block = $block_form['#block']; - $form_display = EntityFormDisplay::collectRenderDisplay($block, 'edit'); - $complete_form_state = $form_state instanceof SubformStateInterface ? $form_state->getCompleteFormState() : $form_state; - $form_display->extractFormValues($block, $block_form, $complete_form_state); - $form_display->validateFormValues($block, $block_form, $complete_form_state); - // @todo Remove when https://www.drupal.org/project/drupal/issues/2948549 is closed. - $form_state->setTemporaryValue('block_form_parents', $block_form['#parents']); - } - - } - - /** - * {@inheritdoc} - */ - public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - parent::submitConfigurationForm($form, $form_state); - - if (!empty($form['settings']['block_form'])) { - // @todo Remove when https://www.drupal.org/project/drupal/issues/2948549 is closed. - $block_form = NestedArray::getValue($form, $form_state->getTemporaryValue('block_form_parents')); - /** @var \Drupal\block_content\BlockContentInterface $block */ - $block = $block_form['#block']; - $form_display = EntityFormDisplay::collectRenderDisplay($block, 'edit'); - $complete_form_state = $form_state instanceof SubformStateInterface ? $form_state->getCompleteFormState() : $form_state; - $form_display->extractFormValues($block, $block_form, $complete_form_state); - - $form_state->setValue('block_serialized', serialize($block)); - $form_state->unsetValue('block_form'); - } - } - -} diff --git a/core/modules/layout_builder/src/Form/OverridesEntityForm.php b/core/modules/layout_builder/src/Form/OverridesEntityForm.php index f94083d602..68e727cee5 100644 --- a/core/modules/layout_builder/src/Form/OverridesEntityForm.php +++ b/core/modules/layout_builder/src/Form/OverridesEntityForm.php @@ -208,14 +208,16 @@ protected function actions(array $form, FormStateInterface $form_state) { '#submit' => ['::redirectOnSubmit'], '#redirect' => 'discard_changes', ]; - // @todo This button should be conditionally displayed, see - // https://www.drupal.org/node/2917777. - $actions['revert'] = [ - '#type' => 'submit', - '#value' => $this->t('Revert to defaults'), - '#submit' => ['::redirectOnSubmit'], - '#redirect' => 'revert', - ]; + if (!$this->sectionStorage instanceof TranslatableSectionStorageInterface || $this->sectionStorage->isDefaultTranslation()) { + // @todo This button should be conditionally displayed, see + // https://www.drupal.org/node/2917777. + $actions['revert'] = [ + '#type' => 'submit', + '#value' => $this->t('Revert to defaults'), + '#submit' => ['::redirectOnSubmit'], + '#redirect' => 'revert', + ]; + } $actions['preview_toggle'] = $this->buildContentPreviewToggle(); return $actions; } diff --git a/core/modules/layout_builder/src/Form/TranslateBlockForm.php b/core/modules/layout_builder/src/Form/TranslateBlockForm.php index 86bfebfd70..b3898a66ea 100644 --- a/core/modules/layout_builder/src/Form/TranslateBlockForm.php +++ b/core/modules/layout_builder/src/Form/TranslateBlockForm.php @@ -63,7 +63,6 @@ protected function getPluginForm(BlockPluginInterface $block) { $plugin_form->setTranslatedConfiguration($this->sectionStorage->getTranslatedComponentConfiguration($this->uuid)); } return $plugin_form; - } return $block; } @@ -85,14 +84,4 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl()); } - /** - * Return the entity used in the form. - * - * @return \Drupal\Core\Entity\EntityInterface - * The entity - */ - public function getEntity() { - return $this->getPluginForm($this->block)->getEntity(); - } - } diff --git a/core/modules/layout_builder/src/LayoutBuilderTranslatablePluginInterface.php b/core/modules/layout_builder/src/LayoutBuilderTranslatablePluginInterface.php index d4181ce6d1..6a4b00d36e 100644 --- a/core/modules/layout_builder/src/LayoutBuilderTranslatablePluginInterface.php +++ b/core/modules/layout_builder/src/LayoutBuilderTranslatablePluginInterface.php @@ -4,8 +4,6 @@ /** * Provides an interface for plugins with Layout Builder translatable settings. - * - * @package Drupal\layout_builder */ interface LayoutBuilderTranslatablePluginInterface { diff --git a/core/modules/layout_builder/src/Plugin/Block/InlineBlock.php b/core/modules/layout_builder/src/Plugin/Block/InlineBlock.php index 08c300fe5f..169dd3e1d4 100644 --- a/core/modules/layout_builder/src/Plugin/Block/InlineBlock.php +++ b/core/modules/layout_builder/src/Plugin/Block/InlineBlock.php @@ -26,9 +26,6 @@ * admin_label = @Translation("Inline block"), * category = @Translation("Inline blocks"), * deriver = "Drupal\layout_builder\Plugin\Derivative\InlineBlockDeriver", - * forms = { - * "layout_builder_translation" = "\Drupal\layout_builder\Form\InlineBlockTranslationForm", - * }, * ) * * @internal @@ -195,7 +192,7 @@ public static function processBlockForm(array $element, FormStateInterface $form $element['revision_log']['#access'] = FALSE; $element['info']['#access'] = FALSE; if (isset($element['langcode'])) { - $element['langcode']['langcode'] = FALSE; + $element['langcode']['#access'] = FALSE; } return $element; } diff --git a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php index 7c1b734a8e..0d45047eee 100644 --- a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php +++ b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php @@ -2,7 +2,6 @@ namespace Drupal\layout_builder\Plugin\SectionStorage; -use Drupal\Component\Plugin\ConfigurableInterface; use Drupal\Core\Access\AccessResult; use Drupal\Core\Cache\RefinableCacheableDependencyInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; @@ -19,7 +18,6 @@ use Drupal\Core\Url; use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay; use Drupal\layout_builder\OverridesSectionStorageInterface; -use Drupal\layout_builder\Section; use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface; use Drupal\layout_builder\TranslatableSectionStorageInterface; use Symfony\Component\DependencyInjection\ContainerInterface; diff --git a/core/modules/layout_builder/src/SectionComponent.php b/core/modules/layout_builder/src/SectionComponent.php index f9c1ca9c06..5d9250ca31 100644 --- a/core/modules/layout_builder/src/SectionComponent.php +++ b/core/modules/layout_builder/src/SectionComponent.php @@ -331,8 +331,7 @@ public function hasTranslatableConfiguration() { } elseif ($plugin instanceof ConfigurableInterface) { // For all plugins that do not implement - // LayoutBuilderTranslatablePluginInterface only allow label - // translation. + // LayoutBuilderTranslatablePluginInterface only allow label translation. $configuration = $plugin->getConfiguration(); return !empty($configuration['label_display']) && !empty($configuration['label']); } diff --git a/core/modules/layout_builder/src/TranslatableSectionStorageInterface.php b/core/modules/layout_builder/src/TranslatableSectionStorageInterface.php index eaf3bae7b0..4226a126b9 100644 --- a/core/modules/layout_builder/src/TranslatableSectionStorageInterface.php +++ b/core/modules/layout_builder/src/TranslatableSectionStorageInterface.php @@ -4,13 +4,8 @@ /** * Defines an interface for translatable section overrides. - * - * @internal - * Layout Builder is currently experimental and should only be leveraged by - * experimental modules and development releases of contributed modules. - * See https://www.drupal.org/core/experimental for more information. */ -interface TranslatableSectionStorageInterface { +interface TranslatableSectionStorageInterface extends SectionStorageInterface { /** * Indicates if the layout is translatable. diff --git a/core/modules/layout_builder/tests/src/Functional/TranslationTestTrait.php b/core/modules/layout_builder/tests/src/Functional/TranslationTestTrait.php index 4fdbf46247..3efaee49f3 100644 --- a/core/modules/layout_builder/tests/src/Functional/TranslationTestTrait.php +++ b/core/modules/layout_builder/tests/src/Functional/TranslationTestTrait.php @@ -18,6 +18,7 @@ protected function assertNonTranslationActionsRemoved() { $assert_session->linkNotExists('Add block'); $assert_session->linkNotExists('Remove section'); $assert_session->elementNotExists('css', '[data-contextual-id^="layout_builder_block:"]'); + $assert_session->buttonNotExists('Revert to defaults'); } } diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTranslationTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTranslationTest.php index ad54019bfb..2717534c76 100644 --- a/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTranslationTest.php +++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTranslationTest.php @@ -215,17 +215,16 @@ protected function updateTranslatedBlock($existing_label, $existing_body, $new_l $assert_session = $this->assertSession(); $page = $this->getSession()->getPage(); $this->clickContextualLink(static::INLINE_BLOCK_LOCATOR, 'Translate block'); - //$assert_session->waitForElementVisible('css', '.go', 993939393939393983983983983983983983983983); $textarea = $assert_session->waitForElement('css', '[name="body[0][value]"]'); $this->assertNotEmpty($textarea); $this->assertEquals($existing_body, $textarea->getValue()); $textarea->setValue($new_body); - $label_input = $assert_session->elementExists('css', '#drupal-off-canvas [name="settings[label]"]'); + $label_input = $assert_session->elementExists('css', '#drupal-off-canvas [name="info[0][value]"]'); $this->assertNotEmpty($label_input); $this->assertEquals($existing_label, $label_input->getValue()); $label_input->setValue($new_label); - $page->pressButton('Translate'); + $page->pressButton('Save'); $this->assertNoElementAfterWait('#drupal-off-canvas'); $assert_session->assertWaitOnAjaxRequest(); diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/TranslationTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/TranslationTest.php index 8d416ed7cb..23b7046f5a 100644 --- a/core/modules/layout_builder/tests/src/FunctionalJavascript/TranslationTest.php +++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/TranslationTest.php @@ -81,7 +81,6 @@ protected function setUp() { 'body[0][value]' => 'The translated node body', ], 'Save'); - // Allow layout overrides. $this->drupalPostForm( static::FIELD_UI_PREFIX . '/display/default', @@ -93,7 +92,6 @@ protected function setUp() { ['layout[allow_custom]' => TRUE], 'Save' ); - } /** @@ -109,7 +107,7 @@ public function testLabelTranslation() { // @todo should you need this permission? You don't actually save the // entity translation because labels are stored with untranslated // layout. - //'translate bundle_with_section_field node', + // 'translate bundle_with_section_field node'. ])); // Add a new inline block to the original node. @@ -138,6 +136,7 @@ public function testLabelTranslation() { $page->pressButton('Save layout'); $assert_session->addressEquals('it/node/1'); $assert_session->pageTextContains('label in translation'); + $assert_session->pageTextNotContains('untranslated label'); // @todo this will fail until https://www.drupal.org/node/3039185 // $assert_session->pageTextContains('field label translated'); @@ -148,6 +147,20 @@ public function testLabelTranslation() { // @todo this will fail until https://www.drupal.org/node/3039185 // $assert_session->pageTextContains('field label translated'); // $assert_session->pageTextNotContains('field label untranslated'); + + // Update the translations block label. + $this->drupalGet('it/node/1/layout'); + $this->assertNonTranslationActionsRemoved(); + $this->updateBlockTranslation('.block-system-powered-by-block', 'label in translation', 'label updated in translation'); + // @todo this will fail until https://www.drupal.org/node/3039185 + // $this->updateBlockTranslation('.block-field-blocknodebundle-with-section-fieldbody', 'field label untranslated', 'field label translated'); + $assert_session->buttonExists('Save layout'); + $page->pressButton('Save layout'); + $assert_session->addressEquals('it/node/1'); + $assert_session->pageTextContains('label updated in translation'); + $assert_session->pageTextNotContains('label in translation'); + // @todo this will fail until https://www.drupal.org/node/3039185 + // $assert_session->pageTextContains('field label translated'); } }