Problem/Motivation

Layout Paragraphs Builder Experimental widget displays the original language (source) when editing a translation. This makes it impossible to translate or edit translated content from the frontend.

Steps to reproduce

- Install Drupal as multilingual system or use Umami
- Create a layout Paragraph type for layouts
- Create a paragraph type with a text field
- Configure the text field as translatable
- Create a new Content type with a Paragraph field and allow the use of the two Paragraph types created above
- Under Manage Display, use the Layout Paragraphs Builder Experimental widget
- Create a new content in any language
- Create a translation into another language and edit the paragraphs via frontend
- When editing, the original language is displayed

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

J-Lee created an issue. See original summary.

j-lee’s picture

I think that the problem was introduced with the release of v2.0. With beta9 the experimental widget still worked as expected.

j-lee’s picture

Issue summary: View changes

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

j-lee’s picture

Status: Active » Reviewed & tested by the community

Thank you for the merge request. Works well for us.

justin2pin’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests
Related issues: +#3275287: Add tests for layout paragraphs builder field formatter
Nowrie’s picture

Hi all,

I'm working on a project with Drupal 9.4 where I'm using layout paragraphs 2.0.1 with the experimental widget. As stated in this issue, whenever I translate an entity, the process is correct. However, editing the paragraphs on the translated entity also changes the values in the untranslated entity.

Not sure if this is because the rendered form is not the correct one, or because the paragraphs aren't being translated so it just renders always the untranslated ones.

Are there any temporary solutions until this patch is applied to the main version? I've tried recreating the code on the pull request but I failed in doing so.

Any help would be very much appreciated as I'm really stuck with this.

Kind regards,
Ismael.

j-lee’s picture

@Nowrie can you check it in conjunction with the patch from #3259729?

It can also be a problem with the multilingual setup.

finex’s picture

@j-lee: hi, I've tried to manually apply your patch to the current -dev version (without patch from #3259729).

The concept looks fine: now the experimental widget use the correct language. But the save/close/cancel buttons doesn't work anymore.

Did the buttons work on your branch?

Thank you very much!

j-lee’s picture

@FiNeX: Sorry for the late response. Yes, everything works with this MR in combination with #3259729 on our multilingual setup.

For the latest release we need a rebase for the current MR.
But I am very busy at the moment ...

socialnicheguru’s picture

patch no longer applies

cobadger’s picture

stmh’s picture

The patch from #14 works as advertised, but not 100% correct, at least for my scenario. Say I have 2 languages en and de. I create content in en and add a translation for de. Editing the translation works as expected, but the preview shows then the english page. Reloading the page shows then the updated content in the correct language.

joachim’s picture

  1. +++ b/src/Form/LayoutParagraphsBuilderForm.php
    @@ -93,7 +93,8 @@ class LayoutParagraphsBuilderForm extends FormBase {
    -    string $view_mode = NULL) {
    +    string $view_mode = NULL
    +  ) {
    

    Unrelated change.

  2. +++ b/src/Form/LayoutParagraphsBuilderForm.php
    @@ -225,8 +245,7 @@ class LayoutParagraphsBuilderForm extends FormBase {
    -    }
    -    else {
    +    } else {
    

    Unrelated, and incorrect change - elses should not be coddled.

joachim’s picture

joachim’s picture

Surprisingly, the MR's branch (which is currently hidden) *doesn't* have the problem described in #15, the incorrect return to the default language when working with a translation.

However, that currently conflicts with the 2.0.x branch and needs a rebase.

(BTW it gets confusing when an issue has BOTH a MR and patches!)

joachim’s picture

Assigned: Unassigned » joachim

Trying to rebase the branch...

j-lee’s picture

I think justin2pin closed the MR because of the many changes since the MR was created. That is why the MR is out of date.

The patch from #14 changes the field values to the translated values. But the field with the source language is inserted into the LayoutParagraphsLayout (Line 129 in patched Drupal\layout_paragraphs\Form\LayoutParagraphsBuilderForm) which is used to create the tempstore key. If the field language is changed, the correct language will be displayed in the UI after saving the changes.

      if ($entity->hasField($default_langcode_key)) {
        $entity = $entity->getTranslation($langcode);
+      $entity->$field_name->setLangcode($langcode);
        foreach ($entity->$field_name as $delta => $item) {
joachim’s picture

Does anyone know why the MR removes this code from LayoutParagraphsBuilderForm::submitForm():

    // The entity may have been altered by another process, and needs to be
    // loaded from storage to ensure edits to other fields are not overwritten.
    // @see https://www.drupal.org/project/layout_paragraphs/issues/3275179
    $entity_id = $this->layoutParagraphsLayout->getEntity()->id();
    $entity_type = $this->layoutParagraphsLayout->getEntity()->getEntityTypeId();
    $entity = $this->entityTypeManager->getStorage($entity_type)->load($entity_id);
    $field_name = $this->layoutParagraphsLayout->getFieldName();
    $entity->$field_name = $this->layoutParagraphsLayout->getParagraphsReferenceField();
j-lee’s picture

Maybe because the entity is cloned at buildEntity()?

joachim’s picture

Filed #3352152: Get the request time to set on the updated entity in LayoutParagraphsBuilderForm for the use of the time service which is in the MR here, and unrelated to this issue.

joachim’s picture

This code (and related changes) probably also needs moving to a separate issue:

+  /**
+   * Should new revisions created on default.
+   *
+   * @return bool
+   *   New revision on default.
+   */
+  protected function getNewRevisionDefault($entity) {
+    $new_revision_default = FALSE;
+    $bundle_entity = $this->getBundleEntity($entity);
+    if ($bundle_entity instanceof RevisionableEntityBundleInterface) {
+      // Always use the default revision setting.
+      $new_revision_default = $bundle_entity->shouldCreateNewRevision();
+    }
+    return $new_revision_default;
+  }

EDIT On second thoughts, I don't know -- nothing in the MR call this method!!! And I don't understand whether the intention is that a new revision is created for the parent entity or the paragraph!

joachim’s picture

Thanks for the feedback @J-Lee.

You're right, the MR is really out of date.

Also, it's trying to fix the problem by removing the use of the custom form element, which surely isn't right:

    $form['layout_paragraphs_builder_ui'] = [
      '#type' => 'layout_paragraphs_builder',
      '#layout_paragraphs_layout' => $this->layoutParagraphsLayout,
    ];

If the custom form element is showing the wrong language, it needs to be fixed, not bypassed!

Things in the patch don't look right either though:

      // Load the correct translation for the layout paragraphs layout field.
      $default_langcode_key = $entity->getEntityType()->getKey('default_langcode');
      $langcode_key = $entity->getEntityType()->getKey('langcode');
      $langcode = $entity->get($langcode_key)->value;
      if ($entity->hasField($default_langcode_key)) {
        $entity = $entity->getTranslation($langcode);

$entity is already in the correct language at this point, because it's loaded by the routing system which takes into account the current language.

          $entity->$field_name[$delta]->entity = $paragraph;

Setting the paragraph BACK into the entity looks really wrong!!!

I've tried your suggested fix for the patch:

+      $entity->$field_name->setLangcode($langcode);

It doesn't work - when I click the Save button, I see the original language for the paragraph and not the translation.

I'm not sure about doing that to the $field anyway -- it's an entity reference field, so it won't be set to translatable.

joachim’s picture

I think we need to add the $entity as a constructor parameter to LayoutParagraphsLayout:

$this->layoutParagraphsLayout = new LayoutParagraphsLayout($field, $layout_paragraphs_settings);

I don't think we can get the right language from what it currently receives.

We get $entity->activeLangcode set to the translation language, but $entity->FIELD->parent->entity->activeLangcode is set to the **default language**. So we can't get hold of the correct language to use.

j-lee’s picture

@joachim You are right. It doesn't seem to be possible to get the currently used language from the field.
Either the entity must be specified or the language, which in turn would have to be taken into account in LayoutParagraphsLayout.

j-lee’s picture

In the LayoutParagraphsLayout class, there is a getEntity() method that gets the entity from the entity reference field, but there is also a setEntity() method that sets the entity dynamically and is not used. This looks a bit strange. Maybe this is the point where you could start.

/**
   * Returns the layout's parent entity with updated paragraphs reference field.
   *
   * @return \Drupal\Core\Entity\EntityInterface
   *   The entity.
   */
  public function getEntity() {
    $entity = $this->paragraphsReferenceField->getEntity();
    return $entity;
  }

  /**
   * Set the entity that this layout is attached to.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity to set.
   *
   * @return $this
   */
  public function setEntity(EntityInterface $entity) {
    $this->entity = $entity;
    return $this;
  }

joachim’s picture

Status: Needs work » Needs review

I've got this working!

Thanks for your help @J-Lee!

Work is on a new branch '3305070-set-language-on-layout' with a new MR.

j-lee’s picture

Status: Needs review » Reviewed & tested by the community

Looks good. Thank you.

j-lee’s picture

Status: Reviewed & tested by the community » Needs work

Ah, there are still the tests missing ... back to needs work.

grumpydev74’s picture

@joachim, @J-Lee thank you guys, you are life savers on that issue !

The patch works !

Hope the MR will be approved and released in the next module's version.

Edited :

Actually there is still an issue dealing with multi languages using the experimental widget :

1- use the widget to add a paragraph on the main site's language
2- save the page
3- got to another language version of the page
4- click the "Edit components" button
5- you will receive the following error:

"InvalidArgumentException: Invalid translation language (en) specified. in Drupal\Core\Entity\ContentEntityBase->getTranslation() (line 874 of /app/web/core/lib/Drupal/Core/Entity/ContentEntityBase.php)."
j-lee’s picture

I can confirm the problem and have left a comment at the appropriate place in MR. With $entity->hasTranslation($this->langcode) and $entity->addTranslation($this->langcode) we can solve this.

grumpydev74’s picture

Thank you again @J-Lee.

Another issue remains however. When clicking the "Save button" at the bottom of the layout paragraph builder interface (to save paragraphs items order) the page is reloaded and paragraphs are displayed using the default language like described in the comment #15. Then if you click the "Close button", the paragraphs are back in the correct language. I don't know if it is linked with your proposed solution in the MR, but it would avoid confusion for editors and need to be fixed too.

cobadger’s picture

@jleehr thanks so much for the suggested changes to MR122. I included them in a patch file and tested locally.

My experience was that the error that @grumpy74 described did not appear, so that's great.

However, in my testing the new paragraph that I added on the site's main language did not show up when I edited the page in an alternate language.

I'd be curious to hear whether others experience the same thing using patch 36.

grumpydev74’s picture

@COBadger thank you for the provided patch. I tested it and it seems to fix the issue with the language code I was pointed out.

However. There is still another problem remaining.

Reproduce the steps described in my comment #33.

Then, when you have a node with paragraphs created and you have already the translated node created afterward, the paragraphs exist on the translated node too. But as soon as you re-edit the default language node paragraphs to add new one for example, here comes the issue.

Basicaly at that point the default language has a new paragraph added to the items list, but the translated node do not have that reference yet. So if you go to the translated node front page you see the newly added paragraph in the widget preview (which is correct), but as soon as you click "Edit components", the display switch to the edit display and the paragraph disappears (because actually the paragraph translation do not exists). I think when the widget switch to edit mode, the same kind of test on the paragraph translation existence must be done. Like if the paragraph do not exists for the translation language, in edit mode, we must create a new paragraph translation when clicking "edit" icon to be able to add the translation instance of the paragraph to the translated node.

On the other hand (and it is not part of that specific issue), the widget should not propose the controls "add", "duplicate" or "delete" on a non default language entity, as this is forbidden by design by the paragraphs principles (paragraphs are ISO between languages).

I hope my description is clear enough for the context overall understanding.

On my side for instance, I took the decision to write custom code to force node translation creation and paragraphs translation creation on node post save to avoid that issue (which is not ideal, but it fits my needs so far), but it should be handle by the widget IMHO.

Hope this will help resolving the issue. I'm sorry to not contribute actively on the code part of this, but I can help by testing patches.

joachim’s picture

I'm not managing to reproduce the error described in #33.

I tried both with a node that didn't have a translation, and one which did.

Please could we stick to the MR and not also make patches? It's going to get really confusing if we have both MRs and patches floating around.

j-lee’s picture

We have tested it again. Now we could not reproduce the problem from #33.
We only used the changes from MR, not the patch from #36 with my previously suggested changes.

We should definitely have tests for that.

I agree, we should use the MR. I think COBadger makes the patch just to test my suggestions.

j-lee’s picture

Just as a note, we also tested the MR in conjunction with #3259729: Fatal error saving translation when content moderation is enabled in a development environment. Maybe this fixes some of the other translation issues as well?

joachim’s picture

I'm working on tests :)

joachim’s picture

Assigned: joachim » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs tests

Added test.

cobadger’s picture

Status: Needs review » Needs work

Changing status back to "Needs work".

In my test of the merge request I took the following steps:

  1. Created a new paragraph in the original language of a node
  2. Navigated to a translation of the node
  3. Opened the layout editor
  4. Observed that the new paragraph from Step 1 above did not render in the layout editor as expected

With the logic from my comment on the merge request when I performed the above steps I did see the new paragraph in the layout editor, and it saved as expected.

joachim’s picture

> 4. Observed that the new paragraph from Step 1 above did not render in the layout editor as expected

Do you mean that the new paragraph *should* appear there?

j-lee’s picture

Strange that sometimes my suggestion is needed and sometimes not. Maybe it is due to different language settings?
To make the codebase more robust, I would suggest to apply the check to the language/translation.

cobadger’s picture

Status: Needs work » Reviewed & tested by the community

As the tests have passed I'm marking this RBTC.

joachim’s picture

Status: Reviewed & tested by the community » Needs review

Thanks for the fix.

However, people who've worked on the MR shouldn't set it to RTBC - that should be done by reviewers.

j-lee’s picture

Status: Needs review » Reviewed & tested by the community

The nit-pick could be done on commit.

Thank you all for the work.

justin2pin’s picture

Status: Reviewed & tested by the community » Needs work

Thanks for all the work on this. Unfortunately, I think this needs a little more work. I don't think we want to add translation functionality directly into the LayoutParagraphsLayout class, as it assumes a little too much about possible use cases. Specifically, I'm concerned that this does not accommodate asymmetric paragraph translations.

So... I think we need to keep functionality specific to translations in the widget / formatter, and not in the underlying API classes. It might be worth abstracting the translation functionality into either a service or trait that both the widget and formatter can use, or refactoring the formatter so it just invokes the widget -- rather than directly using the layout paragraphs builder render element.

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

I made sure the original (source) content is shown when creating new translations, as it was only showing new empty paragraphs, which were difficult to edit (lbp controls where not clickable in the experimental widget on node-view) and the context was missing for translating.

Also needing this for symmetric translations .. is there another pathway to get translations (a/symmetric) working???

Are asymmetric translations working? If so, then we should be able to opt this in via settings IMO.

prompt-h’s picture

We're currently sticking with version 2.0.0-beta9 for this module due to its compatibility with multi-language websites. Newer versions of the module aren't suitable for such websites. Any help would be appreciated.

ytsurk’s picture

I'm using the module's version 2.0.4 with this MR's patch (https://git.drupalcode.org/project/layout_paragraphs/-/merge_requests/12...) for symmetric paragraph translation.

This module forces you to use go with asymmetric translation, which is not official supported (nor recommended) by the paragraphs module itself.

If you can explain the incompatibility issues you have, we can try to guide you?

prompt-h’s picture

We were able to update to 2.0.4 on several multi-language websites and use async translation successfully with the provided patch. Thank you!!

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

j-lee’s picture

Version: 2.0.x-dev » 2.1.x-dev

j-lee’s picture

Opened MR 191 which has the same status as MR 122, but has been rebased to version 2.1.x.

j-lee’s picture

j-lee’s picture

And a patch file for 2.1.x

kristiaanvandeneynde’s picture

Trying to combine this MR with the one from #3269138: Support revisions and content moderation with the Layout Paragraphs Builder Field Formatter as both deal with the same part of the widget that needs some love. I noticed a discrepancy in how one method has a fail-safe for missing translations and the other does not. Will fix in the combined patch that I'm working on to see if it holds up.

spfaffly’s picture

Re-rolled patch for 2.2.x

kanchamk’s picture

I am facing the same issue and tested all the patches provided in this issue, but none of them resolved my problem.

Environment:

  • Drupal core: 10.6.2
  • layout_paragraphs: 2.1.1
  • Languages: EN (default) and DE

Steps to reproduce:

  • Create a content type with a Paragraph field (entity_reference_revisions), including nested paragraphs and media fields, make nested paragraph fields as translatable
  • Create a node in EN.
  • Add a DE translation and verify on the frontend — it works correctly.
  • Go back to the EN version and edit some fields inside paragraphs and nested paragraphs.
  • Save the EN node.
  • Open the DE view page.

Actual result:

The DE translation content is overwritten with the updated EN paragraph values.

Expected result:

Saving or updating the default language (EN) should not override paragraph or nested paragraph content in other translations. Each translation should retain its own independent paragraph field values.

Edited:

Ignore it, it is working fine after some configuration changes.

kanchamk’s picture

Priority: Normal » Major
kanchamk’s picture

Priority: Major » Normal

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