Problem/Motivation

This issue is not to be confused with general multilingual support:
#2414913: Support entity translation of paragraphs

Usually, the fields on the paragraphs itself are translated and all paragraphs from a node translation A are also present in node translation B.
Switching the entity reference revision field of the paragraph itself into multilingual mode causes a different effect and raises complexity significantly.

Suddenly there are paragraphs in lauguage A that are not to be displayed on language B.
In general, the question is if individual paragraphs are using entity / field translation at all or are just decoupled.

Proposed resolution

For now, define that we don't support this translate mode.

Remaining tasks

  • Write tests
  • ...

User interface changes

API changes

CommentFileSizeAuthor
#220 2461695-220.patch24.96 KBJo Fitzgerald
#218 meta_support-2461695-218.patch17.53 KBandreasderijcke
#213 paragraphs-8-1-DEV-d15b2e4----2461695-213.patch13.23 KBRajabNatshah
#212 meta_support-2461695-212.patch24.27 KBAndriy Khomych
#206 meta_support-2461695-206.patch24.61 KBjanchojnacki
#202 meta_support-2461695-202.patch24.6 KBdrupal_beast
#198 meta_support-2461695-198.patch46.5 KBvilepickle
#194 meta_support-2461695-194.patch46.35 KBJo Fitzgerald
#194 interdiff-184-194.txt585 bytesJo Fitzgerald
#189 meta_support-2461695-189.patch46.35 KBMarieKirya
#186 2461695--data-model--translatable-paragraph-err-fields.pdf768.2 KBndf
#184 meta_support-2461695-184.patch46.3 KBefpapado
#184 interdiff-2461695-179-184.txt10.83 KBefpapado
#181 interdiff-2461695-177-178.txt2.73 KBefpapado
#179 meta_support-2461695-178.patch39.7 KBefpapado
#177 meta_support-2461695-177.patch39.75 KBefpapado
#168 meta_support-2461695-168.patch29.4 KBJeroenT
#168 meta_support-2461695-168-test-only.patch5.06 KBJeroenT
#164 meta_support-2461695-164.patch24.34 KBjanchojnacki
#162 meta_support-2461695-162.patch24.03 KBJeroenT
#156 paragraph_show_edit_delete_buttons_while_translating.patch937 bytesflyke
#155 paragraph_show_edit_delete_buttons_while_translating.patch949 bytesflyke
#151 interdiff-2461695-142-143.txt1.67 KBjanchojnacki
#143 meta_support-2461695-143.patch22.05 KBjanchojnacki
#142 interdiff-2461695-139-142.txt3.39 KBJeroenT
#142 meta_support-2461695-142.patch20.87 KBJeroenT
#140 meta_support-2461695-139.patch17.34 KBJeroenT
#128 meta_support-2461695-against-dev-128.patch33.04 KBhoebekewim
#121 meta_support-2461695-against-dev-120.patch32.61 KBRene Bakx
#117 4_fr_translation.png42.42 KBscaldinglake
#117 3_en_content.png47.56 KBscaldinglake
#117 2_paragraph_typ.png40.48 KBscaldinglake
#117 1_content_type.png64.43 KBscaldinglake
#112 paragraph_translation_migration.tar_.gz1.58 KBbucefal91
#106 meta_support-2461695-106.patch17.81 KBweseze
#106 meta_support-2461695-106-stable8.1.0.patch17.11 KBweseze
#99 meta_support-2461695-99-stable8.1.0.patch17.04 KBweseze
#99 meta_support-2461695-99.patch18.76 KBweseze
#96 meta_support-2461695-96.patch16.39 KBbucefal91
#94 meta_support-2461695-94.patch16.32 KBJeroenT
#94 meta_support-2461695-94-test-only.patch4.65 KBJeroenT
#94 interdiff-2461695-93-94.txt4.52 KBJeroenT
#93 interdiff-2461695-82-93.txt968 bytesJeroenT
#93 meta_support-2461695-93.patch11.66 KBJeroenT
#88 paragraphs_multilingual-2461695-72.patch11.06 KBignat.volosky
#82 meta_support-2461695-82.patch12.42 KBJeroenT
#81 meta_support-2461695-81.patch32.95 KBJeroenT
#72 paragraphs_multilingual-2461695-72.patch12.24 KBSutharsan
#72 interdiff-2461695-65-72.txt7.64 KBSutharsan
#65 interdiff-2461695-44-65-do-not-test.diff7.5 KBFooZee
#65 paragraphs-recursive_cloning_localised_paragraphs_field_collections-2461695-65.patch7 KBFooZee
#59 recursive_cloning_localised_paragraphs_field_collections-2461695-59.patch6.1 KBFooZee
#44 paragraphs_localised-2461695.patch3.38 KBTom Robert
#34 paragraphs-meta_support-2461695-34.patch4.08 KBmikemiles86
#15 interdiff-2461695-11-15.txt1.19 KBkrlucas
#15 paragraphs_multilingual-2461695-15.patch3.92 KBkrlucas
#12 2461695-with-2631590-2597201-no-test-12.patch6.72 KBkillua99
#11 paragraphs_multilingual-2461695.patch3.84 KBTom Robert
#10 paragraphs_field-translation-2461695.patch4.05 KBTom Robert
Members fund testing for the Drupal project. Drupal Association Learn more

Comments

DamienMcKenna’s picture

miro_dietiker’s picture

Shouldn't this be dependent...

Not IMHO.

The first usecase i would target is, in case the reference is translatable, the target entities are considered single language entities at all. Adding a translation of a host then would all create new inline / composite entities. Semantically that's my understanding: You make the reference field translatable. So you want to point to different targets per host translation. No target language in the reference needed.

Since until now, we have never started talking about supporting cross language references, i don't see a requirement to add the language code to the reference target at all. I can't find a single usecase that needs it.

paulmckibben’s picture

I'm a little confused about what use cases are supported or not supported. Can you explain the best way to accomplish the following use case? My client has content (nodes) that can be translated, and these nodes have paragraph fields. Some translations will need more/fewer paragraph field instances than others, based on product availability in the target country.

Is this scenario supported for translation, or is it required that each translation have the same number of paragraph field instances as the source entity?

miro_dietiker’s picture

@paulmckibben what you describe is not considered translation of content. Translation means, the same meaning applies to all translations, in different languages. Thus it means that the paragraph items stay the same in amount and only the (translatable) content is translated.

With what you describe, the paragraphs of language A of entity E can be completely different to the paragraphs of language B of entity E. While this is a multilingual aspect, it does NOT need paragraph translation. Instead, the entity reference is set to multilingual and thus the paragraphs of language A are completely different to language B. The paragraphs on their own are no more set as translatable.

However, this case is not yet supported and that's the whole reason why this issue exists.
Adding support for this is feasible and much less work compared to introducing the original multilingual capability. However adding test coverage for this alternative multilingual setup is critical.

paulmckibben’s picture

@miro_dietiker, thank you. Your explanation clears up my misunderstanding. So it sounds like the outstanding issue is for Entity Reference Revisions to support different target ids across translations, is that correct? Does that have anything to do with #2491247: Point to a specific target language that @DamienMcKenna referenced?

What would be the best way for me to help with a path forward?

miro_dietiker’s picture

It has also nothing to do with pointing to a specific target language. :-)

If the entity reference of the host entity for german points to a paragraph item in german, the reference still only needs to point to the entity(type, id, revision). again if the italian version of the host entity points to a paragraph item, the item is not connected to the previous mentioned german one and the reference again only needs to refer to the item as entity(type, id, revision). No one needs to point to a specific target language. This is only needed if you start to mix languages such as force displaying a referred entity in spanish although the host entity is in english and even if the target entity has an english translation. An exotic thing.

So yeah, Entity Reference Revision needs to support translation. But i think technically it supports it because core does it right. Still this doesn't help too much to make the widget work in that situation. The paragraph widget / UX code needs to be made aware of this new use case. I would expect that the widget needs a bunch of adjustments to first avoid misbehavior and second to improve the user experience.

If you are interested in this problem, just configure it the way you need it and report here the things you configure and what bugs you identified when testing the whole UI processes.

Tom Robert’s picture

I have the same issue as above, a content type with unlimited paragraphs items.
In language A i added 3 paragraphs, translate to language B and there are the 3 paragraphs. I add more paragraphs in A and they don't appear in B and there are no add more buttons in B. This is not really usable for a multilingual setup.

When using a core field with unlimited delta. The fields in Language A are copied to B and then the can function individually. I can add extra delta's in language A. They don't appear in B but i can add new delta's there. Which is fine.

When looking in Drupal\paragraphs\Plugin\Field\FieldWidget\InlineParagraphsWidget.php

299 // Hide the button when translating.
          $button_access = $paragraphs_entity->access('delete') && $paragraphs_entity->language()->getId() == $paragraphs_entity->getUntranslated()->language()->getId();
          $links['remove_button'] = array(
            '#type' => 'submit',
            '#value' => t('Remove'),
            '#name' => strtr($id_prefix, '-', '_') . '_remove',
...

735   // Hide the button when translating.
      $add_more_access = $this->getCurrentLangcode($form_state, $items) == $items->getEntity()->getUntranslated()->language()->getId();
      $elements['add_more'] = array(
        '#type' => 'container',
        '#theme_wrappers' => array('paragraphs_dropbutton_wrapper'),
        '#access' => $add_more_access,
      );

If i allow the buttons to be shown on the translations. It reacts like core. Copy and manage individually. So is there a reason/problem/issue i 'm not seeing when enabling the add more and remove buttons on translations?

There is an other issue with the revision id for the original language paragraph. But i don't think this is related to the add buttons for translations.

When a field is saved. The revisions are updated but not the field. For example my field is field_paragraphs, translation is enabled for field_paragraphs. The paragraph as a field "field_body". On saving the node the information in paragraphs_revision__field_body is updated. But information in paragraphs__field_body remains unchanged. Not sure if this is paragraphs or entity_reference_revision.

miro_dietiker’s picture

Tom Robert: You found the right issue.

Until now, no one was able to describe us a real use case where a translatable paragraph should have totally different paragraph items. All our cases were finally clearly asking for translated paragraph items - thus the paragraph entity + fields being translatable, not the entity referencen revisions field.
Can you please explain your use case to allow us to understand it?

Tom Robert’s picture

The site is 2 languages (A and B).
We provided paragraphs as building blocks for a page. For example 3 paragraph types. Intro, text and quote.

Paragraph Intro = field_intro -> textarea with wysiwyg
Paragraph text = field_text -> textrarea with wysiwyg
Paragraph quote = field_quote_text -> textarea with wysiwg
field_quote_author -> textfield

Basic page has field_paragraphs with delta unlimited and can contain te above paragraphs in a random order.

What would be ideal:
A page is build language A, with paragraph intro and text. We want to translate the page to language B. Al the information of A is provided so we can translate the existing paragraphs. In language B I have extra information and would like to add a quote paragraph and move it to the top between intro and text. After that i create a new paragraph item image that i can add in Language A and B.

I tested this with a core textarea with unlimited delta. This works as described above. Initial copy after that they work independently in both languages.

At this moment we made all the pages without paragraphs in Language A. To create a site/menu structure. We added paragraphs in A. But we can't add paragraphs in B anymore, so no real cms functionality here.

And if we do as suggested in the readme. So field_paragraphs is not translatable and the fields for the paragraphs are translatable. Here it would be impossible to obtain a different order per language.

Hope this clarifies our usecase.

Tom Robert’s picture

I worked out a solution for my use case. And the most simple solution is don't translate the paragraph entities.
Wat i want is that the field of the host handles the translations and not the paragraph entities. When translating the host entity the paragraph entities are duplicated with the values of the original language instead of translated.

 // If there is no paragraph entity in this language create one and duplicate the fields.
      $target_langcode = $this->getCurrentLangcode($form_state, $items);
      if ($paragraphs_entity->language()->getId() != $target_langcode) {
        $values = $paragraphs_entity->toArray();
        $entity_type = $entity_manager->getDefinition($target_type);
        $bundle_key = $entity_type->getKey('bundle');
        $new_values = array(
          $bundle_key => $paragraphs_entity->bundle(),
          'langcode' => $target_langcode,
        );

        foreach ($paragraphs_entity->getFieldDefinitions() as $key => $value) {
          if (get_class($value) == 'Drupal\field\Entity\FieldConfig') {
            $new_values[$key] = $values[$key][0];
          }
        }
        $paragraphs_entity = $entity_manager->getStorage($target_type)->create($new_values);
       }

vs

    // If target translation is not yet available, populate it with data from the original paragraph.
      $target_langcode = $this->getCurrentLangcode($form_state, $items);
      if ($paragraphs_entity->language()->getId() != $target_langcode && !$paragraphs_entity->hasTranslation($target_langcode)) {
        $paragraphs_entity->addTranslation($target_langcode, $paragraphs_entity->toArray());
      }

      // Initiate the paragraph with the correct translation.
      if ($paragraphs_entity->hasTranslation($this->getCurrentLangcode($form_state, $items))) {
        $paragraphs_entity = $paragraphs_entity->getTranslation($this->getCurrentLangcode($form_state, $items));
      } else {
        $paragraphs_entity = $paragraphs_entity->addTranslation($this->getCurrentLangcode($form_state, $items));
      }

In this case the the paragraphs items can co-exist without conflicts. I don't there should be an obvious link between the two items. It is provided by the host field. In this way we can add delete and modify paragraph entities without it having an effect on the translation. If the host translation is deleted the paragraph items are deleted as wel. This is not the case with the translations in the current version.

The patch attached will implement this method of translation. But it destroys the other method when you want the host field same for all languages and translate the paragraph fields instead. I think we need check the language settings for the host-field. If it is set to be translated. Create different entities. If not provide an option if the paragraph fields should be translated.

Tom Robert’s picture

killua99’s picture

This patch if for those that need it and are using others patch already.

In specific:

#2631590: After previewing an entity with nested paragraphs, EntityChangedConstraintValidator sometimes leaves a node entity un-saveable:
https://www.drupal.org/files/issues/paragraphs-EntityChangedConstraintVa...
#2597201: Translation source language is not set:
https://www.drupal.org/files/issues/2597201-11--vs-2631590-16--do-not-te...

Applied on that order.

Is not aim to make noise, just help for who is building a website that need solution asap with hope to be patched in the future.

Off-topic: That file doesn't pass any Drupal Standard. I don't mind to solve those problem in order to continue coding for it.

Kionn’s picture

After applying patch #11, which appears to work well, if one of the paragraph fields in the original language is empty, you get the following error on translation.
Notice: Undefined offset: 0 in Drupal\paragraphs\Plugin\Field\FieldWidget\InlineParagraphsWidget->formElement() (line 224 of modules/paragraphs/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php).

In this case $values[$key] is an empty array, so $values[$key][0] is undefined.

miro_dietiker’s picture

We have spent quite some time there and are extending test coverage to commit a multilingual fix and cleanly deal with the situation, at least for nodes.
#2698239: Multilingual workflow bugs

Please check there and help us extend it.
As a follow-up, we should check non-node cases, add test coverage and check if generalisation is needed.

Also, i want to check if we can / should move some of the code to ERR, in case a tool like IEF and other things are built on top of it.

krlucas’s picture

Attached is a re-roll of the patch from #11 which fixes the issue described in #13. It also copies all values for multi-valued nested paragraph fields, instead of just the first item.

I agree that the ideal solution to this translation strategy ("translate the primary host ERR field; never translate fields on paragraph entities") is to extend the InlineParagraphsWidget...once the work in #268239 is stable and committed.

therealssj’s picture

Status: Active » Needs review

The last submitted patch, 11: paragraphs_multilingual-2461695.patch, failed testing.

The last submitted patch, 11: paragraphs_multilingual-2461695.patch, failed testing.

The last submitted patch, 11: paragraphs_multilingual-2461695.patch, failed testing.

himanshugautam’s picture

from comment #15
the latest patch doesn't applies.

killua99’s picture

With the latest paragraphs it doesn't

miro_dietiker’s picture

Status: Needs review » Needs work

Then back to work.

miro_dietiker’s picture

Note that this issue will not only need a patch provided. We will only take time to review it if extensive test coverage is provided.

miro_dietiker’s picture

From our Paragraphs workshop:

Multiple participants already ran into a requirement where a paragraph was only needed in a specific language, thus no 1:1 translation applies.

There are two types of adding this:

1) Simplified, we can add translatable ERR field that then just allows add/remove action in translate display.
Still the user need to understand that paragraphs are totally disconnected!
I propose to just empty out the translatable paragraphs field as a first step.
If it is prefilled, the widget needs to make sure the paragraphs are cloned on save. The UI should also indicate that the paragraphs are disconnected!
Lukas prefers to still have the paragraphs prefilled when adding a translation.

For past accidentally temporarily working scenarios (that have led to shared translated paragraphs in this setup), we will NOT write a migration!

2) A mixed scenario is confusing and adding complexity.
I highly recommend to first care about #1 and limit complexity to then think about how the UI needs to evolve to allow a user deal with a mixed scenario.
This will need detailed mockups, definitions, and thoughts in deep detail.

Zerdiox’s picture

A translatable ERR field seems to be the best option in my mind. In most multilingual setups we have encountered the customer fills in a lot of content in one language and then just a little bit in a different, non-primary one.
I also don't think a regular customer would think that the paragraphs are connected so pre-filling them with the original message shouldn't be an issue. In fact it makes it easier if they do need to recycle styling and images, it avoids filling in the same data twice.

As a quick fix I removed the isTranslating check for the add/remove buttons and enabled them permanently. Along with that I turned off translation on any paragraph and turned on translation on the host-field. This seems to work in that content is now pre-filled in the translation but I can change it independently from the translation and add paragraphs or remove them.
The downside to this is that it does muddy up the revisions because for each change a new revision is created and linked to the current-node translation.

yongt9412’s picture

Please note that the current code has been tested exhaustively and isTranslating is function that is not related with supporting translation to the ERR fields but Hiding the buttons since we know that translations for the field are not supported and can create mismatches in the DB.

We are always happy to know about more people collaborating, and we can commit a working patch as soon as it has a proper test coverage and doesn't break the existing ones. :)

charginghawk’s picture

Jumping in on nomenclature, I think a good way to describe the current system is "symmetric translation", and the strategy this issue's trying to support would be "asymmetric translation".

killua99’s picture

The related link for the ERR issue the last comment said: "As long as there is no real use case identified, we can not promote an issue to major nor can we consider it for a release"

Plus is one year old that comment.

Are we missing a issue on ERR that cover "the real use case" that users (editors) need to have an "asymmetric translation" were paragraphs is enable to add / remove paragraph in the translations entities? This need to work for all entities.

Zerdiox’s picture

@yongt9412 I am well aware that this isn't intended to be used this way. But it's the only option we have at this point for asymmetric translations.

@killua99: If you want I can provide you with dozens of examples of so called asymmetric translations. Most sites we develop have multiple languages and most of those have a primary language that gets filled in with more info.

I don't think it's an ERR issue though. If we want asymmetric translation that translation needs to be available as a different entity all together, not as a different revision. Unless the revision points to a different entity to reference, but that doesn't seem like such a great idea. What would be great is translated entity-references.

miro_dietiker’s picture

Title: Support translatable paragraph entity reference revision field » [META] Support translatable paragraph entity reference revision field

@Zerdiox "What would be great is translated entity-references."

- thus the origin of supporting this case is ERR. However, i guess most of the work will be done in the Paragraphs widget.

@killua99 "Are we missing an issue..."

Until now the only issue i know of that describes a use case is Comment #9 in this issue.
Right, after spending many many month of work in Paragraphs area and talking to many stakeholders, almost no one found the energy to outline this use case in written detail. It's a complex use case and the requirements of everyone vary.

@killua99 "If you want I can provide you with dozens of examples of so called asymmetric translations."

Please do so. As i explained, without someone that spends time writing these use cases cleanly down, no progress or collaboration is possible.
Dunno what format is best, you might want to start with a collaborative google doc. And we need to order the cases to create specific issues.
As a next step, someone could then convert these use cases into (failing) tests. That will allow other developers to start making it work.

I'm switching this issue here to a meta issue. If we want to work on this, we need specific issues that are addressing specific aspects of the whole complexity. Let's start with something simple: No mixed mode. If the field is marked translatable, when adding a translation, do not add any paragraph at all. Thus new paragraphs added in a translation are saved as new ones. No connection between the paragraphs. If someone want to start on this topic, please create a separate issue and link it.

If you want to work on this, join DDD Milano. There is a paragraphs sprint and i'll also be there.

mErilainen’s picture

So there is no way to have asymmetric "translations" of content when using Paragraphs? Only way I guess is to just create two different content entities and place them in the same location in the menu to fool the user that these are translations of each other.

I'm disappointed, I think they just got this working in field_collection for Drupal7 after 4,5 years of work and 540+ comments at #1344672: Field Collection: Field translation (entity_translation) support..

I think the symmetric translation approach works well for legal and official documents, where translations must be 1:1. Pretty much everything else is asymmetric in real life.

So in short Paragraphs implements i18n but not l10n https://en.wikipedia.org/wiki/Internationalization_and_localization
(BTW wikipedia is a perfect example where Paragraphs would not work really at all, you'll find plenty of examples there to convince whoever needs convincing.)

charginghawk’s picture

Per #30, I've created a wiki page in the i18n group for collecting asymmetric translation use cases. See:

https://groups.drupal.org/node/512157

I've add Tom Robert's use case to start with. If you have a use case, please add it, and feel free to edit the page if you want to add additional information regarding how and why you want to use asymmetric translations in your projects.

miro_dietiker’s picture

@charginghawk Thank you for starting the page.

We should be careful with mixing translation here with localisation, or if this is what your goals is, name it explicitly.
Please consider the terminology:
https://en.wikipedia.org/wiki/Translation
IMHO the term translation should correctly only be used for symmetric translation.

When you use the term "assymetric translation", you mean much more language localisation.
https://en.wikipedia.org/wiki/Language_localisation
Product localisation to that extent often leads to region specific product definition and needs an extra layer of management that can not be substituted by paragraphs.
We sometimes use the term "regionalisation" for this layer.

"Pretty much everything else is asymmetric in real life."
Disagree. Paragraphs made many users happy and almost all great cases i know of are not legal.

But finally again, I agree, paragraphs is about less code and more power to the editor. Thus it makes sense that a user can break the symmetry if he has good reasons.
Please mind that we are talking about a new feature. While a first simplified version could be possible after a few days, a full clean UI that avoids user confusion will require many weeks of work. We are still looking for people who are willing to work on this issue.

mikemiles86’s picture

@miro_dietiker

I agree with you that what is being discussed is two different things, translation and localization. To your point we should be careful with how we mix those two.
Like others in this thread I have run into both of these situations with clients. Some would like purely translated content (same content different language) and others want localized content (different content for different languages). Each has a content structure that would greatly benefit from using paragraphs.

Thanks in part to the way you have structured the module, I think the Paragraphs logic could be augmented to support localization in addition to translation with little need of altering the UI or worry about confusing the user. The following is my theory (as well as my patch) for how to simplistically support both use cases.

Scenario 1: Translated Paragraphs ( currently implemented)

In this Scenario the user does not translated the host (entity_reference) field, but instead translates the fields in the Paragraph Entity. For the host entity this is a 1:1 translation. When the user creates a translation of the Entity, the paragraphs are translated as well. The user cannot alter the paragraphs in the translated Entity without altering them for all Entity translations (as in adding or reorganizing the paragraphs).

Scenario 2: Localized Paragraphs

In this Scenario the user does not translate the fields in the Paragraph Entity, instead they translate the host entity field (entity_reference field). When the user creates/edits a translation of an Entity, each paragraph is duplicated as a new paragraph entity in the translated language. The user then has the ability to change the value in the entity Reference field (add, remove, edit, re-order the paragraphs) without effecting the other translations. Allowing them to 'localize' their paragraphs.

----

Setting up Paragraphs to work in this method requires no need for additional UI work as it allows paragraphs to follow the expected workflow when marking a field as translatable. If a field is marked as translatable you expect to be able to change the field value per translation. If a field is not translatable you expect it to contain the same value for all translations.

My attached patch add this intrinsic functionality. When translating a paragraph entity, then host field is checked. If the host field is marked as translatable the logic then assumes the user is looking to localize the paragraphs and creates new paragraph entities in that language and assigns their value to the field. When editing a translated entity the logic also checks if the host field is translatable, and if so (since it is assume the content is 'localized') enables access to manipulate and add more paragraphs for that translation.

This patch was very much influenced by the patch provided by @krlucas in comment #15, is almost basically a re-roll with some additional logic added.

Hope this adds positively to this feature and discussion.

yongt9412’s picture

Status: Needs work » Needs review

Let's see if this break tests. It shouldn't.

SaytO’s picture

Works for me, thanks.
I can now add paragraphs with multilanguage option activated.

mashermike’s picture

This is exactly what I was looking for. Great Job!

yongt9412’s picture

Status: Needs review » Needs work

Before committing we for sure need test coverage otherwise we cannot ensure that there won't be db problems. :)

The last submitted patch, 34: paragraphs-meta_support-2461695-34.patch, failed testing.

The last submitted patch, 34: paragraphs-meta_support-2461695-34.patch, failed testing.

The last submitted patch, 34: paragraphs-meta_support-2461695-34.patch, failed testing.

martinpe’s picture

The patch from Comment #34 goes into the right direction.

We too have a problem, that we need to have that translation mechanism in which the English needs to be completely autonomous from its Source Version, which is in German. At least when it comes to Paragraphs

We cannot expect our customer to be forced to use rigid structure as described in https://www.drupal.org/node/2735121.

Example: If the customer has a video/image which in German but no French version, we cannot force him to upload one anyway, just because Paragraphs dictates it.

So that use case NEEDS to be implemented and I am glad it's in the making.

miro_dietiker’s picture

Issue tags: +Needs tests
Tom Robert’s picture

efpapado’s picture

Patch #44 seems to work.

yongt9412’s picture

We still need test coverage. :)

borisson_’s picture

Status: Needs review » Needs work

The last submitted patch, 44: paragraphs_localised-2461695.patch, failed testing.

penyaskito’s picture

Commented on https://www.drupal.org/node/2735121 with a link to this issue.
If right now it's not supported, I'm wondering if we should avoid that the checkbox in the content translation settings can be checked.

miro_dietiker’s picture

@penyaskito In some processes such as enabling translation for a content type, core enables translation for fields. It doesn't check fields and there is limited pluggability. It's a core limitation. IMHO we should not force disable it, but indicate that its a wrong choice.
And core should offer a way so we can force the default.

BTW: People are asking that this mode is also supported. Even once this case is supported, we want to make sure it's not offered as the default. And we will want to display a warning that this is not a common recommended configuration.

IMHO the top prio should be to get rid of the core limitation.

penyaskito’s picture

Thanks Miro! Are there issues created for improving the situation in core? I may be interested on allowing paragraph localization.

miro_dietiker’s picture

We are not yet aware of any issue covering the topic.

Martijn Houtman’s picture

Is there a reason to exclude support for patch #44 for a field of type 'entiry_reference' ? Currently it only supports 'entity_reference_revisions' fields, bit I just tested the patch and added support for an 'entity_reference' field, and all seems to be working fine.

Martijn Houtman’s picture

Scratch that, the Paragraphs widget does not properly update non-revision fields, so this combination does not work. I have just confirmed path #44 does work as expected with 'entity reference revisions' fields.

mErilainen’s picture

So what is the current stake on this feature? I can see "(* unsupported) Paragraphs fields do not support translation." messages with the latest dev-version of Paragraphs when adding a paragraph field to content type. With the patch translating the paragraphs seems to work fine, so we could get rid of those messages. Is there other UI work to be done before the patch can be committed? Unfortunately I have zero experience working on tests, which are required I assume.

yongt9412’s picture

I don't think more UI changes are needed. This cannot be committed without having first extensive test coverage. :)

Martijn Houtman’s picture

I agree with @mErilainen: the message becomes obsolete if this patch actually works. Creating unit tests makes sense indeed.

What I would like to know is: should I now always use entity_reference_revisions (contrib) field types, rather than entity_reference (core) fields?

yongt9412’s picture

Currently Paragraphs doesn't support being referenced by a Entity Reference field.

FooZee’s picture

This patch is based on #44 with the addition that it goes into the paragraphs being cloned and clones any paragraphs or field collections in them. I don't really like that we had to hard-code the entities we support for cloning although the code doing the cloning itself is pretty generic (but I had to do so, because it's very often not very desirable to clone other entity types referenced in the paragraph --e.g. users, taxonomy terms and probably nodes-- ) ...

In fact, whether an entity should be cloned or just referenced (when we are speaking about asymmetric translation) largely depends on whether the widget shown on that form allows the entity to be edited (but that's not a very practical condition, because a site builder can always change the widget of such an entity back and forth, which would leave the DB totally inconsistent) thoughts specifically about this are highly appreciated :)

yongt9412’s picture

Status: Needs work » Needs review

Let's see with test bot :)

Status: Needs review » Needs work

Sutharsan’s picture

FooZee, Thanks for your patch. Some code style nits:

  1. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -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()) {
    

    Code style: use slashes for inline comments: https://www.drupal.org/docs/develop/coding-standards/api-documentation-a...

    Lines containing comments (including docblocks) must wrap as close to 80 characters as possible without going over, ...

  2. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -232,6 +232,26 @@
    +      else if ($items->getFieldDefinition()->isTranslatable()) {
    +        $paragraphs_entity = $this->cloneReferencedEntity($paragraphs_entity, $entity_manager, $target_type, $langcode);
    +      }
    +
    

    Use 'elseif' instead of 'else if'

  3. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -733,7 +753,7 @@
           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'];
     
    

    Indent of 2 spaces is good here. IDE settings?

  4. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -1188,5 +1207,50 @@
    +        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.
    

    Spacing: if..., ...{

Sutharsan’s picture

  1. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -232,6 +232,26 @@
    +       *  If the parent field is marked as translatable, assume paragraphs
    +       *  to be localized (host entity expects different paragraphs for
    +       *  different languages)
    

    Is it important that paragraphs are to be localized? What if the parent is translatable and the paragraph is not? Perhaps the paragraph does not need to be translatable (= localized). Different paragraph entities does not need to be translatable, as far as I can see.

  2. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -1188,5 +1207,50 @@
    +   * @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);
    

    It's unusual to pass the entity (type?) manager to the method. Does it change from one call to another?

  3. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -1188,5 +1207,50 @@
    +    // 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])) {
    

    Comments that describe why something is done ar more valuable that comments that describe what is done.
    It is important to describe the recursive nature of the cloning.

  4. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -1188,5 +1207,50 @@
    +        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.
    

    Abstract this out to a method (e.g. cloneableEntities), to make it extensible in the future.

  5. +++ src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php	(revision )
    @@ -1188,5 +1207,50 @@
    +            $cloned_entites[] = $this->cloneReferencedEntity($entity, $entity_manager, $cloned_entites_target_type, $langcode);
    

    Is Drupal's entity reference protected against circular referencing? Otherwise we may need to check for this. (follow-up issue)

FooZee’s picture

Okay, I recreated the patch with all the code style stuff and some extra syntactical enhancements :)

Is it important that paragraphs are to be localized? What if the parent is translatable and the paragraph is not? Perhaps the paragraph does not need to be translatable (= localized). Different paragraph entities does not need to be translatable, as far as I can see.

yes, if a paragraphs (entity revision) field is marked as translatable, this means that in different languages it will (be able to) reference different paragraph entities ... what that really means is: it doesn't really matter whether the paragraph itself is translatable or not, we'll always pre-populate the widget and make it ready to create a new paragraph entity that will be only referenced from this host translation (even if it has the exact same content). I prefer doing it like this because it's much easier to understand from an editor perspective (it's more confusing as a content editor to have some paragraphs that I can change per translation and some that would change everywhere if changed in one translation)

It's unusual to pass the entity (type?) manager to the method. Does it change from one call to another?

The entity_manager is being passed just because it was already instantiated in a pervious point in the code before actually calling this function, it doesn't change, it comes from the IDE refactoring, I've moved this to a property on the widget object to be shareable between methods.

Is Drupal's entity reference protected against circular referencing? Otherwise we may need to check for this. (follow-up issue)

I think it's not, although I believe it's not exactly possible from the admin UI, yet I don't think it's impossible to create a circular reference programmatically, which really makes this issue interesting to investigate.

jmuzz’s picture

some paragraphs that I can change per translation and some that would change everywhere if changed in one translation

It really works on a per subfield basis currently, not per paragraph. Personally, I find this better aligned with the general use case where two translations of an entity will contain the same data but in different languages. Take for example a photo gallery where each paragraph is a photo and a description. It doesn't make sense to "translate" the photos. The same pictures will be in every language. Just the descriptions need to be translated.

IMO this patch should include some updates to the UI. It's not clear at all from the information on the screen what the difference is between activating translation on the paragraph's fields or in the host. For example, if you were to activate both of them, the subfield settings would be ignored completely because every host translation would be a separate entity. That's not intuitive and could even be considered a bug.

FooZee’s picture

Take for example a photo gallery where each paragraph is a photo and a description. It doesn't make sense to "translate" the photos.

unless the photo itself has some text? or the site supports two languages once of which happens to be rtl ... by the way the core image module allows you to "translate" the images (and the alt and title fields as well)

IMO this patch should include some updates to the UI

Totally agree, the warning on the UI of entity revision reference fields should be updated with one that explains the difference between symmetric translations (like for legal documents where they have exact one to one mapping) and asymmetric translation (localization) (which is a pretty common use case, please read the full thread if you haven't already, for more details on that.)

miro_dietiker’s picture

About recursion:
We are talking about a composite relationship. Every child is owned by its parent. Semantically, this makes recursion impossible and Paragraphs UI itself is also not protecting agains illegal data. We are simply expecting that the data is valid and whoever uses the API needs to follow our integrity definitions. Adding more recursion checks could artificially drive complexity that is not needed.

Sutharsan’s picture

@jmuzz I agree that the user interface should be updated to match the new situation this patch creates. But let's create a new issue for that and keep this issue for the core of the technical implementation. I've created the issue: #2820318: Update user interface for translatable paragraph

Sutharsan’s picture

The code that prepares the paragraph entity as part of InlineParagraphsWidget::formElement has grown in this patch. I think it is good to break this out into its own ::prepareEntity() method.

Status: Needs review » Needs work

The last submitted patch, 72: paragraphs_multilingual-2461695-72.patch, failed testing.

The last submitted patch, 72: paragraphs_multilingual-2461695-72.patch, failed testing.

Sutharsan’s picture

This is the part that breaks the tests:

-        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);
johndevman’s picture

For those using patch #44 be aware that you cannot use configuration management to update database configuration for Paragraphs localisation. When configuring it crashes, and gives you an error:

It includes these files:

core.base_field_override.paragraph.paragraph_name.changed.yml
language.content_settings.paragraph.paragraph_name.yml

The error:

Argument 2 passed to Drupal\Core\Entity\ContentEntityStorageBase::onFieldDefinitionUpdate() must implement interface Drupal\Core\Field\FieldDefinitionInterface, null [error]
given, called in core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php on line 192 and defined ContentEntityStorageBase.php:164
E_RECOVERABLE_ERROR encountered; aborting. To ignore recoverable errors, run again with --no-halt-on-error [error]
Drush command terminated abnormally due to an unrecoverable error.

JeroenT’s picture

The code gives the following error:

exception: [Recoverable fatal error] Line 457 of core/lib/Drupal/Core/Field/WidgetBase.php:
Argument 4 passed to Drupal\Core\Field\WidgetBase::setWidgetState() must be of the type array, null given, called in /var/www/html/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php on line 166 and defined

In inline_entity_form, the following code is called:

    // Put delta mapping in $form_state, so that flagErrors() can use it.
    $field_name = $this->fieldDefinition->getName();
    $field_state = WidgetBase::getWidgetState($form['#parents'], $field_name, $form_state);
    foreach ($items as $delta => $item) {
      $field_state['original_deltas'][$delta] = isset($item->_original_delta) ? $item->_original_delta : $delta;
      unset($item->_original_delta, $item->_weight);
    }

    WidgetBase::setWidgetState($form['#parents'], $field_name, $form_state, $field_state);

WidgetBase::getWidgetState() executes the following code:

  /**
   * {@inheritdoc}
   */
  public static function getWidgetState(array $parents, $field_name, FormStateInterface $form_state) {
    return NestedArray::getValue($form_state->getStorage(), static::getWidgetStateParents($parents, $field_name));
  }

It's possible that the static function NestedArray::getValue returns NULL, as stated in the comment:

   * @return mixed
   *   The requested nested value. Possibly NULL if the value is NULL or not all
   *   nested parent keys exist. $key_exists is altered by reference and is a
   *   Boolean that indicates whether all nested parent keys exist (TRUE) or not
   *   (FALSE). This allows to distinguish between the two possibilities when
   *   NULL is returned.

i'm not sure, but isn't this problem in inline_entity_form then?

johndevman’s picture

Regarding #76. This seems to be fixed when updating Drupal Core to at least 8.2.

system module :
8200 - Fix configuration overrides to not override non existing keys.

Sutharsan’s picture

@JeroenT, When does this occur? pls describe the steps to reproduce the error.

JeroenT’s picture

JeroenT’s picture

Patch no longer applied. Created re-roll.

JeroenT’s picture

The last submitted patch, 81: meta_support-2461695-81.patch, failed testing.

The last submitted patch, 81: meta_support-2461695-81.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 82: meta_support-2461695-82.patch, failed testing.

The last submitted patch, 82: meta_support-2461695-82.patch, failed testing.

mogio_hh’s picture

Hi there.

Does this patch fix also the issue with the newest dev in latest core 8.2.2 where the translation checkbox of an field which was created within a paragraph entity is not clickable anylonger?

EDIT: PROBLEM SOLVED - HAD TO RE-SETUP DRUPALS CORE.

ignat.volosky’s picture

I little changed path from #72 - just deleted lines which already exists.

JeroenT’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 88: paragraphs_multilingual-2461695-72.patch, failed testing.

The last submitted patch, 88: paragraphs_multilingual-2461695-72.patch, failed testing.

JeroenT’s picture

So I was able to reproduce the errors I mentioned in #77.

  1. Enable inline_entity_form module.
  2. Create a paragraph type with an entity reference field.
  3. Create a content type with a paragraph field on it.
  4. In the form display of the content type, set the edit mode of the paragraph to preview.
  5. In the form display of the form, change the widget to Inline Entity Form - Simple
  6. Add a new node and add a paragraph and save it.
  7. Go back to the node and try to edit the paragraph.

I currently don't have any time left anymore, but I don't have a clue what's going wrong here.

JeroenT’s picture

I was debugging this issue and re-reading this thread again.

As mentioned in #75, that piece of code is indeed the problem.

-        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);

I re-added the if, and now the tests pass locally. I also did some manual testing and translating the paragraphs still work.

Anyone a clue why this if was removed?

Maesteri’s picture

Applying patch #94 allows our projects to use Paragraphs the way we want (to make it possible to use separate paragraphs per translation, if necessary). I believe this functionality is crucial in multilingual environments. Hopefully we can complete this issue so we can start working on the following issue: #2820318: Update user interface for translatable paragraph.

bucefal91’s picture

There have been some commits into dev of Paragraphs since #94. I am attaching re-rolled patch against latest (today) dev.

mogio_hh’s picture

Any idea when this patch will end up in DEV Version of paragraphs?

JurgenR’s picture

Patch #96 fails on latest dev version.

error: patch failed: src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php:343
error: src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php: patch does not apply

weseze’s picture

Attached a working patch against latest dev with the following extra's:

I've also attached a patch against the latest stable release: meta_support-2461695-99-stable8.1.0.patch. (We prefer patches against stables) It contains the exact same functionality except #2778409: Incorrect closing <li> tag on paragraph add buttons because that was not released in 8.1.0.

Status: Needs review » Needs work

The last submitted patch, 99: meta_support-2461695-99-stable8.1.0.patch, failed testing.

The last submitted patch, 99: meta_support-2461695-99-stable8.1.0.patch, failed testing.

JeroenT’s picture

Status: Needs work » Needs review
mErilainen’s picture

I tested the patch against latest stable and it works very well. I applied it on to a site I'm working on which has plenty of different paragraph types already and nothing broke. This will make Paragraphs even more useful for different sites.

We have also a group paragraph type which has paragraphs inside it and it seems to work fine. The group paragraph itself is not translatable, so I couldn't make the paragraph reference fields translatable either, but it's enough that the top-level paragraph reference in the entity where paragraphs are added in the first place is translatable. Awesome.

I will leave the code review for someone else who knows more about the module.

miro_dietiker’s picture

Heads up, we have found issues that lead to data integrity / loss troublel if this setup is chosen.
As long as this is not fixed, make sure you're never deleting translations.

The journey into this direction will only start with a very well defined scenario and its painstaking test coverage (create, update, without AND with revisions), deep paragraph nesting, including multiple variations, edge cases that could happen, and considering also deletions (revision, translation, entity).

Grayle’s picture

Hey guys, maybe wrap the cloning of the paragraph for translatable parent entities in this:

if (!empty($form_state->get('content_translation'))) {

So it only clones everything when you add a new translation, and not also every time you edit a translation. Got no time for patch-writing at the moment, but I figured I'd let you know. It can bloat your database real fast real quick.

weseze’s picture

Attached are 2 new patches (against dev and stable) implementing the comment from @Grayle. The cloning now only happens when initially translating, not when editing.

@miro_dietiker: #2832592: Deleting Translation deletes content Seems to be a non issue when field translations are enabled (what this patch allows us to do). I have manually tested this and there is no use case where content is lost. We will need to revisit/retest this after the issue has a fix.

I agree test coverage is needed. I think we will most likely need to do the same kind of tests for field translations as the current tests?

The last submitted patch, 106: meta_support-2461695-106-stable8.1.0.patch, failed testing.

The last submitted patch, 106: meta_support-2461695-106-stable8.1.0.patch, failed testing.

miro_dietiker’s picture

@weseze i have committed the fix for the related issue, see updates and commit #2832592: Deleting Translation deletes content
The remaining step there is just about paragraphs specific test coverage.

Berdir’s picture

Yes, but we "fixed" it by not deleting anything anymore now for translatable fields, we still need to figure out how to delete the paragraphs and avoid a lot of cruft in the database.

megadesk3000’s picture

I experience some strange behavior when attaching patch #106 and enabling translation for a paragraph field.

We have a page with already translated nodes. As it was not possible before, only the fields inside the paragraph itself were translatable and that worked as expected.
After i applied #106 and enabled translation for the ERR field, which references the paragraphs, the field shows empty in the non default language. When i reset the field to not translatable the content appears again, so there is no data loss, but it is not displayed in both the node edit and the node view mode.

When i create a new translation of a node, everything works fine, so the problem seems to be with existing, translated nodes.

bucefal91’s picture

@megadesk3000 Feel free to try the tiny module I attach. I've written this module to migrate the existing paragraph translations onto this new scheme.

Use at your own risks :) for me it worked out, but probably you'll have to poke it at least a little bit before it functions for you too. All it does is the following: for each entity type that has paragraph field attached to it, do: take the translation per old logic and save it per new logic.

The steps are the following:

  1. Download and install this custom module
  2. Enable translation on paragraph fields (do not yet disable the translation on the host entity)
  3. Apply a patch from this issue
  4. drush cr
  5. Navigate to /admin/paragraph-translation-migration and run the migration
  6. Disable the translation on the host entity
  7. Double check that your content has successfully migrated
  8. Uninstall this custom module and you should be set at this stage (you've migrated your old translations and now run on the new "asymmetric" logic of translation.

I was able to migrate about 5 content types and 5 different paragraph types via this custom module. It's been about a week since I've migrated and nobody reported issues since then (probably we were at the magnitude of hundreds of migrated entity translations).

killua99’s picture

I'm trying to test this patch but I don't see any change.

I'm trying to localize my paragraph as the description #34 does, but I'm not able to add / remove paragraph on my translation version.

How the Host (Node Content Type field) should be set and how the Paragraphs Entities should be set ? (may be a few screenshots ? )

JeroenT’s picture

Issue tags: +Needs reroll
scaldinglake’s picture

I'm in the same boat as killua99/#113, I've applied the patch from #106 and I can't seem to see any differences. I still cannot add new paragraph instances to an translation.

Example: I created a new content type called Content and I have one field called Field A with a single paragraph type allowed and unlimited cardinality. Created a new node in English and adding 1 paragraph to Field A, save. Create French Translation, modify the title and the text inside the paragraph in Field A. Go back to English, add a new paragraph to Field A, save. Go to edit page for French translation and there is no second paragraph or 'add paragraph' button inside Field A, forever stuck with 1 paragraph.

Am I doing something wrong? Or am I misunderstanding the purpose of this issue?

Thanks

weseze’s picture

@scaldinglake: The patch allows you to do exactly what you want. I'm guessing you are missing configuration or permission... Or maybe something has changed in the dev version of paragraphs...
Are you using the dev release or stable release? Did you enable the translation for the field that contains the paragraphs?

scaldinglake’s picture

@weseze thanks for the reply. I did enable translations for the content type and the paragraph field. I've checked the permissions, also I am logged in as user 1. If it matters, this from updating paragraphs, not a fresh install.

I've attached 4 screenshots to show what I'm looking at that might give some hints as to what's going on. They are the content type's translation settings, the paragraph type's translation settings, the english edit page and the corresponding french translation's edit page. You'll see the english allows the user to add more paragraphs, but not the french.

weseze’s picture

@scaldinglake:: your paragraph entity should not be translatable (screenshot 2), there is no need for that. I guessing that will fix your issue.
Also note that switching the translation settings, does not update existing nodes and paragraphs. So you should always start clean. Or you can try and use the module provided here: https://www.drupal.org/files/issues/paragraph_translation_migration.tar_.gz (thanks to @bucefal91)

scaldinglake’s picture

@weseze thanks again for following up.

I disabled translations for the paragraph type and created a new node, but the issue persists. Is there anything I can pull to help track this down?

scaldinglake’s picture

Okay, so I rolled back to the most recent stable and the patch for that and it works (hooray!). I'm hoping I can come back to this later this week when I'm a little less swamped and start investigating what changed in dev that may have caused it to stopped working, at least in my case. Again, thanks @weseze for your help.

Rene Bakx’s picture

I was researching the localized options for Paragraphs, mostly for the reasons like explained above. Our current project requires that the editor should be able to add/remove a paragraph per translated node.

Tried to roll the #106 patch against the current dev version, but that failed so I rolled the failed parts of the patch by hand. Hope I got them all. (long live pull requests instead of patches)

See

Anyhow, attached you that patch, hopefully it works. And for what it is worth, hopes this will be the defacto behaviour for Paragraphs or else at least will continues to live as a separate community project as a separate widget because most of the 'magic' happens in there. The form overrides could be de-overridden in a .module.

Status: Needs review » Needs work

The last submitted patch, 121: meta_support-2461695-against-dev-120.patch, failed testing.

andypost’s picture

Issue tags: -Needs reroll

Patch contains a lot of changes that unrelated to the issue (mostly code style clean-up) that I'd prefer to see extracted to separate issue

main changes are
- removal of notice about ability to translate fields
- added cloning of paragraphs from original language

Still needs tests but the approach looks right

@Rene Bakx Here's docs for rerolls https://www.drupal.org/patch/reroll

Rene Bakx’s picture

I forked the patched widget into a separate module. We need this async (Scenario 2: Localized Paragraphs) behaviour in our current project but patching paragraphs every .dev release is too much hassle on our already heavy deadlined project. Actually we need both widgets, translations of paragraphs should be fixed to that node (scenario 1) but the nested paragraphs on the paragraph should be localized.

We ran into a issue with deleting a paragraph resulting in all paragraphs being to deleted, but are going to figure that during this project.

When done with the project, or when I find some spare time, I will create a sandbox project for our forked widget module, that maybe later could be merged back into paragraphs by the maintainers as a third option, next to the 'experimental' widget. (or just continue to live as a full project)

yongt9412’s picture

As long as this change has extensive test coverage and it doesn't break existing tests, I think it can be included in Paragraphs.

We cannot ensure a proper stability and reliability of the code without tests. ;).

Rene Bakx’s picture

It's a different widget, so it should not break existing tests on widget level However on storage level it will break tests (if that is tested), because of the way language attribute is stored (UND vs EN).

stella’s picture

I couldn't get patch in #120 above to work (it applied but didn't do what was expected), while the patch against dev for #106 also didn't apply cleanly. The #106 patch against the release applied cleanly and worked.

However the stable #106 patch and the #120 patch are both missing the if (!empty($form_state->get('content_translation'))) { check for Localised Paragraphs to handle the scenario mentioned by Grayle in comment #105.

hoebekewim’s picture

I've re-rolled the patch id 120 from comment #121 since it failed on the DEV version. Further I've implemented the following fixes:

  • In the scenario where you create a node in language 1 and then translate it, it is not possible to add more paragraphs into the translation. This is because the add buttons are not shown when translating a node. I've created an exception to check if the field is set as "translatable" before showing the add buttons. This way the add buttons won't show up on a paragraphs field that is not set as translatable.
  • The comment from #127 referencing to #105 has also been applied. I don't know what this does, can someone check if this does not break anything in nested paragraphs ?
hoebekewim’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 128: meta_support-2461695-against-dev-128.patch, failed testing.

killua99’s picture

Why does the patch #120 works against stable version and doesn't for dev.

Why you have to create that exception about it.

This is a META issue, we shouldn't break this issue in minor issues to work on this ? This patch is quite big, and might cause problem if we just applied without any test coverage.

btw, good work on the reroll patch.

miro_dietiker’s picture

Yeah, do NOT mix codestyle fixes with functional changes. It makes review of the diff hard.

So yeah, a third widget might be the easiest approach. But i don't want to start maintain too many widgets...

Rene Bakx’s picture

@Miro, that is why I proposed to make the widget a separate project. Most people are okay with the default paragraphs behaviour (relation has no language, target entity inherits from parent). Some case, like ours, needs the actual relation have a language so the selected paragraphs can be altered per language instead of defined by the originating one.

And I agree, this issue is getting a bit messy now, will open the sandbox when I have a proper version of 'our' version of that widget, mostly based upon the patch in #120 and #128 with some cleaning up.

miro_dietiker’s picture

@Rene If you want to release it as a sub project, that's fine. But that doesn't make a difference to me. Here my last (TM) few cents:
- The limitation in Paragraphs itself would still present..
- The project that fixes it should try to be minimum invasive - thus if cloned code, just adapt what is needed, to easily track the applied changes. I would recommend not to apply code style fixes, if you ever intend to bring the matured functionality back to Paragraphs.
- A different approach would be intentionally a rewrite, but that's what we try to do with our experimental widget. So i wouldn't recommend.
- Extensive test coverage is still the main subject. You should focus on carefully outlining the user stories you want to support and check storage integrity in complex cases. The knowledge about the implementation is only around while you do the implementation. We already have 120 comments and previous versions to check, to understand the pitfalls and problems that should be test covered now in order to do proper quality assurance. The complexity this issue adds is likely about the same complexity that (synchronous) translation added to Paragraphs. So expect many follow-up issues that identify edge cases that need quality assured fixing.

That said, i am very happy if you take the lead in maintaining a solution to this problem.

miro_dietiker’s picture

At the recent Paragraphs Sprint, we created a new plugin to control per-language visibility of a Paragraph:
#2846682: New Plugin: Visibility per language
This is a completely different approach and possibly fits better if per-language variants are rare. Also we create fully transparent user awareness.

Sure, if you really need different structure / representation and many variants / languages, it will create UI clutter.

tomasnagy’s picture

@miro_dietiker Since the whole point of this patch is to have a lot of per-language variants the plugin is not a viable solution to this issue.
Current patch works perfectly for localizing paragraphs thus negating the need for a plugin (since now it follows the general Drupal workflow).
This also doesn't break anything when combining localized & translated paragraphs.

Apart from the failing tests & limited test coverage, what is holding this patch back from being integrated?

miro_dietiker’s picture

@tomasnagy I don't know what is holding us back, because missing tests is EVERYTHING. I promised to look into this issue and provide feedback once the beneficiary parties described their requirements in tests as an easily readable MVP describing step by step user stories and expectations. Before reaching that level of QA and reproducible expectations, i will not invest time to review the code, sorry.

stella’s picture

I completely understand that tests are required, +1 to that. Just to add though, the approach in this patch works well for our "localisation" / "variants" use case too.

JeroenT’s picture

Status: Needs work » Needs review

Created a reroll. I started from patch #106 because the other patches contained a lot of unrelated changes.

JeroenT’s picture

Status: Needs review » Needs work

The last submitted patch, 140: meta_support-2461695-139.patch, failed testing.

JeroenT’s picture

janchojnacki’s picture

Made a small changes to #142
- Added if (!empty($form_state->get('content_translation'))) {
- Allowed add/remove buttons

Status: Needs review » Needs work

The last submitted patch, 143: meta_support-2461695-143.patch, failed testing.

janchojnacki’s picture

Status: Needs work » Needs review
vilepickle’s picture

Status: Needs review » Needs work

In using the patch at #143, I'm noticing an inconsistency when editing a multilingual piece of content but viewing it in a different interface language. It is assumed that you have "Customize Content language detection to differ from Interface text language detection settings" selected at `admin/config/regional/language/detection` and "Content language" bumped to top priority.

If I am editing in interface: ENGLISH, but the content is FRENCH, when I first create the translation my paragraphs can be edited to show French fields. When I come BACK to the piece of content with a URL such as `/en-us/node/3820/edit?language_content_entity=fr-ca`, it shows the ENGLISH field values inside the paragraphs. Since the language_content flag is set to French, I should be seeing those French values in the paragraph fields. It is using the interface language and not the content language.

vilepickle’s picture

I will note that everything seems to work if my interface was in French editing the new French translation for the paragraph fields.

janchojnacki’s picture

@vilepickle Thank you for checking that.

I could not reproduce this issue. I have "Content language" language detection method enabled.
Tried those use cases:
1. Create Swedish node (source) from English interface
2. Create English translation from Swedish interface

1. Create Swedish node (source) from Swedish interface
2. Create English translation from Swedish interface

When I edit translation, paragraph fields (and other as well) are displayed according to "language_content_entity" parameter if it's present, but not interface language.

JeroenT’s picture

@janchojnacki, can you please upload an interdiff?

vilepickle’s picture

@janchojnacki Perhaps it is our other language detection settings affecting it?

This always seems to be a tricky point in debugging the admin stuff with language...

Interface priority:

  1. Browser
  2. URL
  3. Selected language
  4. All others disabled

Content language detection: enabled
Content priority:

  1. Content language
  2. Browser
  3. URL
  4. All others disabled

I could maybe assume that the browser is taking hold of the Paragraph field reference somehow and showing the English version since we prioritize browser highly. I am browsing as an English user with the content flag set to another language.

janchojnacki’s picture

janchojnacki’s picture

@vilepickle Yeah, you have not the most common language detection settings. But even with those it works for me. Are you sure that you have ERR field set as translatable? Also it probably wont work with existing content. Could you try to debug it by yourself?

vilepickle’s picture

@janchojnacki Yes the main field is set to translatable. However The way it's set up is...

field_layout - TRANSLATABLE
This links to a few layout-type paragraphs: for example 30/70 Layout, 70/30 Layout, etc.
Within Our 30/70 paragraph type, we have more paragraph references: Aside and Main
I don't believe aside or main are set to be translatable. Could this be the issue?

flyke’s picture

I am probably missing something here, because this is such a long issue for something that for me seems already working out of the box minus 1 small adjustment.

The described functionality works, even on the latest stable version 8.x-1.0, if you only patch paragraphs to NOT hide the edit/delete buttons while translating with the correct settings.

What you want to achieve:
- Create a node in language A with paragraph X and paragraph Y
- Translate the node to language B, where you for example edit paragraph X, delete paragraph Y and add paragraph Z just for that translation. Deleting paragraph Y on node B should not delete it on node A and adding paragraph Z should not add it on node A.

How to achieve this:
- Go to the admin/config/regional/content-language page
- Do almost the exact opposite as the paragraphs module recommends:
-- "Custom language settings": check the box to make Paragraphs translatable
-- "Content": check the box for each paragraph field you have to make it translatable
-- "Paragraph": uncheck all the fields, so none is translatable. Set Default language to 'Interface text language selected for page'

Now the only thing you need to do is patch paragraphs so the edit/delete buttons do show when translating.
I added a patch (paragraph_show_edit_delete_buttons_while_translating.patch) that does this

This works for me as described in the what we want to achieve part.
If someone could point out how or why this is a wrong approach, that would be very insightful for me.

flyke’s picture

I had 1 typo in the patch, fixed it. So using this patch and the settings mentioned above, you can translate paragraph fields on nodes and have a different number of paragraphs between the translations.

yongt9412’s picture

@flyke there is no way to ensure that the languages of each paragraph are properly updated with the last approach you are trying to achieve, please note that we need tests.
As you said, with your changes, we can have different number of paragraph in each translation of a node, but did you check the language of each? They might need to be updated and that's why we need to do some more stuff as the previous patches.
Settings to "Needs Review" for triggering test bot.

yongt9412’s picture

Status: Needs work » Needs review

The last submitted patch, 155: paragraph_show_edit_delete_buttons_while_translating.patch, failed testing.

The last submitted patch, 155: paragraph_show_edit_delete_buttons_while_translating.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 156: paragraph_show_edit_delete_buttons_while_translating.patch, failed testing.

JeroenT’s picture

flyke’s picture

@yongt9412 Thank you for your explanation, I now understand better what problems are tackled in this issue.
@JeroenT I just tested your latest patch, #162, on latest dev version and it applied clean. I did some testing with creating pages with paragraphs and translating them and it is all working well.

janchojnacki’s picture

Patches #142 and #162 failed to apply towards the latest dev version.
Created a new one.

LaravZ’s picture

Status: Needs review » Needs work

Patch #164 leads to the following error in the latest develop: fatal: corrupt patch at line 7. Two of the patched files (InlineParagraphsWidget and ParagraphsConfigTest) have been changed since this patch.

JeroenT’s picture

Issue summary: View changes
Issue tags: +Needs reroll
gnuschichten’s picture

Patch #164 applied on latest dev and it works without errors.

JeroenT’s picture

Another attempt to write a test for this issue.

The last submitted patch, 168: meta_support-2461695-168-test-only.patch, failed testing.

The last submitted patch, 168: meta_support-2461695-168-test-only.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 168: meta_support-2461695-168.patch, failed testing.

JeroenT’s picture

Status: Needs work » Needs review
flyke’s picture

I can confirm latest patch meta_support-2461695-168.patch applies clean on latest dev (8.x-1.x-dev) and is working as expected for me.

mike.stijlloos’s picture

I can also confirm that patch meta_support-2461695-168.patch works as expected.

efpapado’s picture

I tested on D8.2.7 with the latest dev of Paragraphs and ERR, and it seems to work.

borisson_’s picture

@miro_dietiker: we're using this patch on a couple of different projects, are there any tests we can write to help get this in?

efpapado’s picture

I have merged the patches from #168 to a single patch, and I have also written some more tests myself:

  1. Translate node and confirm different paragraphs.
  2. Update the paragraphs on each translation.
  3. Add different number of paragraphs on each translation.
  4. Remove paragraphs from each translation.
  5. Reorder the paragraphs on each translation.

I tested in a clean installation of:

  • D8.2.7
  • Paragraphs: latest dev (ae21d1a)
  • ERR: latest dev (5e30fd0)

All tests seem to pass, and the new feature seems to work fine.

Status: Needs review » Needs work

The last submitted patch, 177: meta_support-2461695-177.patch, failed testing.

efpapado’s picture

efpapado’s picture

Sorry, my bad. Attaching interdiff 177 - 178

efpapado’s picture

Please note: The failing D8.2 tests have nothing to do with this patch. If you apply the paragraphs latest dev's tests (without the patch) on a clean D8.2.7, they will also fail.

badrange’s picture

The use cases of the tests in the latest patch look good! And I think it would be good to have tests that include nested paragraphs as well, with either translatable and/or untranslatable parents/children.

In addition to having fields in the paragraphs that reference translatable/untranslatable content. The references to the translatable content may or may not be translated, and there may or may not be language fallback set up to decide what to show.

Pretty technically challenging and interesting issue, this one!

efpapado’s picture

I submit a new patch that:

  • Adds a test for nested paragraphs (one level of nesting)
  • Adds a test for deleting a translated node
  • Removes some trailing spaces that were introduced by my previous patch (this can be seen at the interdiff)

Please note that an important change was implemented, in order to test for nested paragraphs: The paragraph entity, and it's paragraph reference field had to be set as translatable. I left the previous configuration (that was setting them as non-translatable) commented on purpose.

ndf’s picture

@efpapado Thanks for adding the tests; great work!

Can we improve the issue-summary on top of this issue?

What I would like to see are 2 things:
1. A list of tests (so that anyone can judge them on relevance) that are implemented or missing.
2. A description of the data-model / field configuration regarding translation settings.

ndf’s picture

Regarding #185-2

To me it is unclear (especially with the change in #184) if there will be a standard configuration regarding translation settings.
What I understand till now is that the 'top-level node' and the 'entity reference revision field' are both translatable.
And that this should lead to a situation that different languages will have a different list/tree(nested) with paragraphs.
Each paragraph is unique and is not a translation of another paragraph.
Each translated node can have a totally different set of paragraphs attached. For example: In English we start with Body-text and in Spanish we start with a Accordion.

This sounds good to me and I tried to catch this in the attached diagram.
Note: the entity-ids are different on purpose.
Is this correct? Needs review :)

On the UX part I see a couple of issues that might arise:
- Should we enforce a specific translation-configuration for the nodes/err-fields/paragraphs?
- What is the effect when you 'start' translating in the 'not-default' language?
- How impossible is it to get 'stale' paragraphs?
- Should we add an option 'replace translation with original' or 'replace translation with XX language' so that you can start over again with the translation when the original has been changed a lot?

miro_dietiker’s picture

Here some general maintenance feedback.

So this issue should be un-metaized. Instead we need a new parent meta.
And the child issues here need to be unchilded and put to the new meta parent. We can't commit this issue with unresolved childs. The issue summary needs update.

And we need more issue work with creating other follow-ups identified.

I'm missing a clear statement about the status of mixed mode (combining translatable paragraphs with separated paragraphs per language).

Every scenario identifieds in this issue comment tree needs to be test covered. Someone needs to work through every comment and partial Patch submissions.

And finally everything related to UX is ignored here. No screenshots, no changes(?), no mock-ups, no process visualization. We need to define how we make the user aware of the situation.

MarieKirya’s picture

I tried #184 and it mostly worked aside from requiring

$entity = $entity->getTranslation($langcode);

in function prepareEntity() after checking if it needs cloning into the langcode. This got my editing interface working in the right language.

MarieKirya’s picture

Adding a patch with my last comment and explaining my problem a little better.

I had the parent field already set to translated unknowing to the limitations, content for the site was created and translated and worked. Each paragraph set had it's own group of entities, I just couldn't alter them. When the patch was applied, the ability to do so was added but my editor did not display the correct copy of the paragraphs entity. But content display did. So I needed to set the active language on the paragraph to get this working.

Status: Needs review » Needs work

The last submitted patch, 189: meta_support-2461695-189.patch, failed testing.

efpapado’s picture

Could you attach also an interdiff?

sgurlt’s picture

I applied Patch #184 and was hoping that this would fix the translation issue with panelizer: https://www.drupal.org/node/2838638#comment-12075513
But sadly without any luck.
Node Paragraph field set to not translatable.
Paragraph field itself set to translatable.

Patch #189 could not be applied on the latest dev on my side.

Martijn Houtman’s picture

Initial testing of patch #184 works perfectly for our site, we can now add new paragraphs on a translated node, and paragraphs are nicely cloned on initial translation creation. Patch #189 does not apply for me, it gives an error of malformed input.

Jo Fitzgerald’s picture

Having reviewed the patch in #189 I believe this is what @pavelkiryanov was hoping to contribute.

Jo Fitzgerald’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 194: meta_support-2461695-194.patch, failed testing.

vilepickle’s picture

@Jo Fitzgerald, is there anything you can do to make those tests pass?

vilepickle’s picture

So I took the patch in #194 and fixed it to apply on the latest dev. It wasn't applying properly. Expecting tests to still fail (maybe?) but at least we can look at it now.

geertvd’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 198: meta_support-2461695-198.patch, failed testing. View results

Regnoy’s picture

After apply patch i have error with language because is not check if hasTranslation
Check the translation in line

//line 1314
// Localised Paragraphs.
    //  If the parent field is marked as translatable, assume paragraphs
    //  to be localized (host entity expects different paragraphs for
    //  different languages)
    elseif ($items->getFieldDefinition()->isTranslatable()) {
      if (!empty($form_state->get('content_translation'))) {
        $entity = $this->cloneReferencedEntity($entity, $langcode);
      }
      if ($entity->hasTranslation($langcode)) { << Added by me
        $entity = $entity->getTranslation($langcode);
      }
    }
drupal_beast’s picture

Status: Needs work » Needs review
FileSize
24.6 KB

I took patch #198 and add Regnoy’s fix. This solution works for me.

yongt9412’s picture

Status: Needs review » Needs work

Tests are still missing. :(

rcodina’s picture

Patch on #202 works for me. Thanks @drupal_beast!!!

cutesquirrel’s picture

I'm using the 1.x-dev version on drupal 8.3, composer seems to download the #c14d496 commit.
This is the right last dev commit on the 8.x-1.x branch on the paragraphs project (git.drupal.org)
But the installed files aren't the corresponding ones : paragraphs.module is really different than in the #c14d496 commit !
Even if I explicitly use this command : composer require drupal/paragraphs:dev-1.x#c14d496

 - Installing drupal/paragraphs (dev-1.x c14d496): Cloning c14d496 from cache
  - Applying patches for drupal/paragraphs
    https://www.drupal.org/files/issues/meta_support-2461695-202.patch ([META] Support translatable paragraph entity reference revision field (https://www.drupal.org/node/2461695))
   Could not apply patch! Skipping. The error was: Cannot apply patch https://www.drupal.org/files/issues/meta_support-2461695-202.patch

Could it be something with a cache in the drupal composer repo (https://packages.drupal.org/8) ?

Many thanks

janchojnacki’s picture

Confirm that patch #202 does not apply towards the latest dev version.
Created a new one.

Andriy Khomych’s picture

@yongt9412, about tests, will be enough to fix and rewrite testContentTranslationForm, testAvoidUsingParagraphsWithWrongEntity, testContentTranslationForm and testAvoidUsingParagraphsWithWrongEntity?

cutesquirrel’s picture

@janchojnacki it worked like a charm

RajabNatshah’s picture

#206 @janchojnacki It's working

JeroenT’s picture

Patch #198 already contains a lot of tests. We should add those back in the patch.

nicrodgers’s picture

Also need to address #187 (which was updated 18 hours ago but you'll need to scroll quite a bit up)

Andriy Khomych’s picture

So, after all, I need a patch also for a stable version now as a quick solution, so here it is:

RajabNatshah’s picture

Updated the patch to work with
drupal/paragraphs: 1.x-dev#d15b2e44281e5d85f9dfde164df61ccc8a764e9a

RajabNatshah’s picture

Status: Needs work » Needs review
miro_dietiker’s picture

I would be very interested in what happens with this patch, if you later disable translatability of the Paragraphs field.
See #2902171: Accidentally marking paragraph field translatable creates big mess

So for shared Paragraphs across multiple languages, we need to make sure, all languages still write to the same paragraph revision. So the host entity in its default revision would use the default revision of these multilingual Paragraphs (that are shared across multiple languages). This would then also allow us to disable field translatability with minimum data loss. If things fall apart, we make the entity subsystem very unhappy.

weseze’s picture

@RajabNatshah: does your patch include all functionality that was in patch #212?

Seems to me (if your patch #213 is indeed fully functional) that all we need to do is delete a bunch of stuff from the current dev version from paragraphs.
Wouldn't it make more sense then to not delete those pieces of code and instead include a setting to turn on/off these pieces of code? We might call it an experimental feature of paragraphs then and warn users of the possible consequences.

RajabNatshah’s picture

@weseze You are right, the patch is messing some parts.
After more aggregation tests, seems that It's not working.

[Sat Aug 19 17:20:22.311565 2017] [:error] [pid 8697] [client ::1:43382] PHP Fatal error:  Call to undefined method Drupal\\paragraphs\\Plugin\\Field\\FieldWidget\\ParagraphsWidget::getModalAddDialogTemplate() in /var/www/html/test/varbase4c/docroot/modules/contrib/paragraphs/src/Plugin/Field/FieldWidget/ParagraphsWidget.php 

Trying to have a better patch

andreasderijcke’s picture

Updated patch from #212 so it works on current head (1.x-dev#a0aa28bcfc0529e2b7a333009a214f30995a3208)

Status: Needs review » Needs work

The last submitted patch, 218: meta_support-2461695-218.patch, failed testing. View results

Jo Fitzgerald’s picture

Status: Needs work » Needs review
FileSize
24.96 KB

Re-rolled patch from #212 against current head (1.x-dev#a0aa28bcfc0529e2b7a333009a214f30995a3208).