It seems that EntityEmbedDialog has no awareness of the parent entity's language, when used on an entity form.

UPDATE: The autocomplete during the selection stage does respect the parent language, but not the review stage.

I notice this working on #2924391: [media entities] Regardless of @EntityEmbedDisplay plugin, Media entities representing a `image/*` MIME type should be able to have a per-embed `alt` and `title`, where I'm trying to add alt and title to the dialog for images.

Without the EntityEmbedDialog knowing the language of the parent entity, we can't edit the correct alt and title text.

This also can be helpful for passing to entity browsers during the selection phase.

Proposed solution:

update js/plugins/drupalentity/plugin.js to pass in language of entity being edited.

Correct display should be the translated label, like this:
correct display, translated label

CommentFileSizeAuthor
#52 entity-embed-pass-langcode-3018485-52.patch46.87 KBoknate
#52 3018485--interdiff-50-52.txt714 bytesoknate
#50 entity-embed-pass-langcode-3018485-50.patch46.86 KBoknate
#50 3018485--interdiff-43-50.txt4.36 KBoknate
#44 3018485-43.patch44.27 KBWim Leers
#44 interdiff.txt2.52 KBWim Leers
#42 3018485-42.patch44.29 KBWim Leers
#42 interdiff.txt24.07 KBWim Leers
#41 entity-embed-pass-langcode-3018485-41.patch43.33 KBoknate
#41 3018485--interdiff-39-41.txt1.35 KBoknate
#39 entity-embed-pass-langcode-3018485-39.patch43.22 KBoknate
#39 3018485--interdiff-30-39.txt10.47 KBoknate
#31 entity-embed-editor-lang-3018485-30.patch42.79 KBoknate
#31 3018485--interdiff-29-30.txt1.49 KBoknate
#29 entity-embed-editor-lang-3018485-29.patch42.75 KBoknate
#29 3018485-interdiff--28-29.txt967 bytesoknate
#28 entity-embed-editor-lang-3018485-28.patch43 KBoknate
#28 3018485-interdiff--27-28.txt1.33 KBoknate
#27 entity-embed-editor-lang-3018485-27.patch43.02 KBoknate
#27 3018485-interdiff--26-27.txt7.28 KBoknate
#26 entity-embed-editor-lang-3018485-26.patch38.88 KBoknate
#26 3018485--interdiff-22-26.txt5.89 KBoknate
#22 entity-embed-editor-lang-3018485-22.patch39.85 KBoknate
#22 3018485-interdiff--21-22.txt20.66 KBoknate
#21 entity-embed-editor-lang-3018485-21.patch28.6 KBoknate
#21 3018485--interdiff-20-21.txt3.42 KBoknate
#19 entity-embed-editor-lang-3018485-20.patch28.63 KBoknate
#19 entity-embed-editor-lang-3018485-20--TEST-ONLY.patch22.7 KBoknate
#19 3018485--interdiff-19-20.txt528 bytesoknate
#18 entity-embed-editor-lang-3018485-18--TEST-ONLY.patch0 bytesoknate
#15 entity-embed-editor-lang-3018485-13.patch28.63 KBoknate
#15 entity-embed-editor-lang-3018485-13--TEST-ONLY.patch22.71 KBoknate
#15 3018485--interdiff-12-13.txt9.97 KBoknate
#14 entity-embed-editor-lang-3018485-12.patch23.13 KBoknate
#14 3018485--interdiff-11-12.txt2.78 KBoknate
#12 selected entity label.png227.85 KBoknate
#11 entity-embed-editor-lang-3018485-11.patch23.21 KBoknate
#5 entity-embed-editor-lang-3018485-5.patch5.93 KBoknate
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

oknate created an issue. See original summary.

oknate’s picture

Issue summary: View changes
Wim Leers’s picture

Category: Feature request » Bug report
Issue tags: +D8MI
Wim Leers’s picture

oknate’s picture

Here's a patch that adds the language pulled from the editor and saves it to private temp storage. Using private temp storage solved an issue I was having with the ckeditor editor information (as apposed to the drupal Editor.php editor) no longer being available after the entity browser selection. Using private temp storage solves this problem.

It's currently saved in tempStoreFactory->get('entity_embed_dialog')->get('editor_language')

It seems not quite right to use variable across all entity embed dialogs, but you really can only use one at a time, so that might be ok.

oknate’s picture

Status: Active » Needs review
Wim Leers’s picture

Issue tags: +Needs tests

Great work here!

We'll need test coverage for this though, to ensure this doesn't break in the future. Do you think you could do that?

Wim Leers’s picture

Status: Needs review » Needs work
oknate’s picture

Yes, I can add test coverage.

Wim Leers’s picture

🥳Awesome — thanks so much!

oknate’s picture

Getting started with test coverage. I want to add media test coverage with alt and title, and I want to add more end-to-end testing of embedding of nodes, but this gets it started.

This demonstrates the bug in this issue.

For now, I couldn't get the fix to work, so I put in a hack temporarily, as I need to go to bed and will continue on this later.

diff --git a/js/plugins/drupalentity/plugin.js b/js/plugins/drupalentity/plugin.js
index 27bbf56..5119845 100644
--- a/js/plugins/drupalentity/plugin.js
+++ b/js/plugins/drupalentity/plugin.js
@@ -37,7 +37,7 @@
           var existingElement = getSelectedEmbeddedEntity(editor);
 
           var existingValues = {
-            'data-editor-langcode' : editor.langCode
+            'data-editor-langcode' : drupalSettings.path.currentLanguage
           };
           if (existingElement && existingElement.$ && existingElement.$.firstChild) {
             var embedDOMElement = existingElement.$.firstChild;

I'm hoping that the original fix works and I just need to fix the test set up. The change would mean it's not pulling from the field's language but from the parent entity. If a field isn't translatable, it should use the original language. Back when I was working on this in December, the editor.langCode changed appropriately. I just need to keep working on the test, I think.

oknate’s picture

FileSize
227.85 KB
oknate’s picture

Issue summary: View changes
oknate’s picture

I was able to get editor.langCode to work correctly. Unfortunately, this requires the locale module to be enabled.

In /web/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php:

    if ($this->moduleHandler->moduleExists('locale')) {
      $ckeditor_langcodes = $this->getLangcodes();
      $language_interface = $this->languageManager->getCurrentLanguage();
      if (isset($ckeditor_langcodes[$language_interface->getId()])) {
        $display_langcode = $ckeditor_langcodes[$language_interface->getId()];
      }
    }

The odd thing is that the autocomplete in the selection phase of the dialog followed the parent without the locale module enabled, but then when you press "Next" and go to the review step, it would show the wrong language on the label of the embedded entity. So the locale requirement is inconsistent, the dialog is unaware of the correct language, but the autocomplete works properly: odd! So perhaps the patch should use whatever autocomplete is using to detect the language, or maybe it's better to fix the autocomplete to respect the editor language.

For now I'll proceed with the review stage using the editor language and enable locale for the test.

NOTE: I have a namespace error in the test class, it took me a minute to figure that out, so the test didn't run and I didn't realize this.

oknate’s picture

Remaining question: Should we have the functionality work without the locale module enabled. It seems to me that it should, but I'm not sure of the right approach to pull the language from the parent entity. It's in a lot of places, but the editor seems most appropriate. But that doesn't work without locale enabled.

NOTE: I have a namespace error in the test class, it took me a minute to figure that out, so the tests didn't run and I didn't realize this.

oknate’s picture

Issue summary: View changes
oknate’s picture

I have a namespace error in the test class, it took me a minute to figure that out.

oknate’s picture

oknate’s picture

Here we go, I realized what was confusing me. My test wasn't actually running.

It was ignoring the test on testbot because of an error in the namespace. I had a copy and paste error in my namespace.

-namespace Drupal\Tests\content_translation\FunctionalJavascript;
+namespace Drupal\Tests\entity_embed\FunctionalJavascript;

oknate’s picture

  • Removing the special characters because they look off in the patch, makes the patch easier to read.
  • Since I updated the embedded content titles, the "trap" parent name doesn't make sense, since I'm not using "mouse" for the embed. So changing that. It's just cosmetic and shouldn't affect the test.
oknate’s picture

This adds some changes outside the scope of the new test, but some good clean up.

  • Removes unused getTestFile method.
  • Moves set up in base class to EntityEmbedDialogTest.
  • Copies assignNameToCkeditorIframe method to base class, updates classes to extend base class.
  • Fixes another cut and paste error:
    - * @group content_translation
    + * @group entity_embed
    
  • Fixes deprecation of file_unmanaged_copy
  • removes screenshot I accidentally added to the module in a previous commit:
    $this->createScreenshot(\Drupal::root() . '/sites/default/files/simpletest/screen.png');
    
  • Fixes inconsistent naming of file:
         \Drupal::service('file_system')->copy(\Drupal::root() . '/core/misc/druplicon.png', 'public://Smeagol.jpg');
         /** @var \Drupal\file\FileInterface $file */
         $file = File::create([
    -      'uri' => 'public://example.jpg',
    +      'uri' => 'public://Smeagol.jpg',
    
  • I made the titles longer, so it's obvious what's French and what's English:
    -    $node_fr->title = 'Superman';
    +    $node_fr->title = 'Superhomme';
    

    and

    -      'name' => 'Smeagol',
    +      'name' => 'Smeagol likes cheese',
    

    and

    -    $media_fr->name = 'Gollum';
    -    $media_fr->field_media_image->alt = 'Gollum';
    -    $media_fr->field_media_image->title = 'Gollum';
    +    $media_fr->name = "Gollum n'aime que la bague";
    +    $media_fr->field_media_image->alt = "Gollum n'aime que la bague";
    +    $media_fr->field_media_image->title = "Gollum n'aime que la bague";
    
  • There were a few places the comments had the wrong language due to cutting and pasting:
    -    // Assert suggestions are in parent language (en).
    +    // Assert suggestions are in parent language (fr).
    
oknate’s picture

Because I keep stepping on my own toes, I'm creating a meta issue with some of my test updates:
#3055928: [META] 8.x-1.0-beta4 plan

oknate’s picture

Status: Needs review » Needs work

I think editor.langCode is the ckeditor language code, not the drupal code, so we need to rethink this.

It needs to get \Drupal::service('language_manager')->getCurrentLanguage() from the form holding the ckeditor.

oknate’s picture

This is easier than I thought, the language is available in the dialog from \Drupal::service('language_manager')->getCurrentLanguage()

the url changes for the dialog based on the parent form, notice the "/fr/" in the url:

https://my.site/fr/entity-embed/dialog/basic_html/media_entity_embed?_wr...

oknate’s picture

Updating the way we fetch the language. I still think we might need to pass it through the js. I'm thinking of stupid edge cases, where you have a form with an inline entity form with a wysiwyg with an entity embed button. It should pull the language from the entity being edited in the inline entity form. I'm not sure if it would or wouldn't. I'd have to investigate. Or a paragraph with a wysiwyg, that would probably work, but what about a paragraph on an entity within an inline entity form?

oknate’s picture

  • Removing dependency on locale: which is great.
  • Adding additional test coverage outside the scope of the bug, such as testing that translation appears correctly in preview and when the entity is saved, and that adding data-langcode will override the default behavior.
oknate’s picture

oknate’s picture

oknate’s picture

Next time I update this, I need to fix this comment:

+    // Assert suggestions do not contain translation.
+    $this->assertNotContains('Superhomme', $suggestions);

Text should read "Assert suggestions contain translation."

oknate’s picture

Replacing some code with a more verbose, but I think more elegant bit of code. The code is adding an attribute to a dom element, and I think DomDocument is a more elegant way of handing html in PHP than string manipulation with str_replace.

-    $new_value = str_replace('drupal-entity ', 'drupal-entity  data-langcode="en" ', $value);
-    $source->setValue($new_value);
+    $dom = Html::load($value);
+    $xpath = new \DOMXPath($dom);
+    $drupal_entity = $xpath->query('//drupal-entity')[0];
+    $drupal_entity->setAttribute("data-langcode", "en");
+    $source->setValue(Html::serialize($dom));
Wim Leers’s picture

Status: Needs review » Needs work

#11: interesting hack, using drupalSettings.path.currentLanguage :) Note that this represents the negotiated URL language (\Drupal\Core\Language\LanguageInterface::TYPE_URL), not the content language of the parent entity.


#14: Using editor.langCode is also wrong, this is using the negotiated interface language (\Drupal\Core\Language\LanguageInterface::TYPE_INTERFACE).

So the locale requirement is inconsistent, the dialog is unaware of the correct language, but the autocomplete works properly: odd!

Presumably this is because the autocomplete because it autocompletes content entities, which use the negotiated content language (\Drupal\Core\Language\LanguageInterface::TYPE_CONTENT).


#15:

Remaining question: Should we have the functionality work without the locale module enabled.

Yes, because this functionality is about content language, not about interface language. The locale module is about being able to use the Drupal user interface in multiple languages, and hence is solely about interface language.

, but I'm not sure of the right approach to pull the language from the parent entity.

You could alter the entity edit form, retrieve the entity ($entity = $form_state->getFormObject()->getEntity();) and then read its language ($langcode = $entity->language();).


#19: that happened more times to me than I'd like to admit 😂


#21: The special characters didn't bother me at all. I'm fine with it either way.


#22: 👍


#23: 🙏


#24 + #25 + #26: \Drupal\Core\Language\LanguageManager::getCurrentLanguage() returns the interface language by default. Which is going to be the same as the CKEditor language :)


#27: Why the sleep(1)?


Overall: once again, excellent work, thank you so much! 🥳

The remaining problem definitely is the use of the language manager: that results in the currently negotiated interface language being used, which is wrong. Even using the currently negotiated content language is wrong. It's possible I'm using the site in French but embedding an entity in a Spanish translation. That means the entity being edited has $entity->language() === 'es', and hence should result in Spanish content showing up in the dialog.

oknate’s picture

for #27, why "sleep(1)"? It's shorter than

$this->getSession()->wait(1000);

Ideally, if I knew what was causing the random failure, we could add a condition:

$this->getSession()->wait(1000, '$("#something-special").length == 1');

Then if the condition is met, it doesn't have to wait. The problem is I don't know what is causing the bug. When it happens, clicking the entity embed button doesn't open the dialog. But if I wait a little bit, such as adding sleep() command, it'll work. So some javascript library probably needs to initialize. If we can figure out how to detect when that's ready, we could add a condition.

oknate’s picture

Note, for this:

It's possible I'm using the site in French but embedding an entity in a Spanish translation.

I don't this is currently supported when adding an entity. There's no option to select what language you'd like to select during the selection phase. If you manually set the language, say using the source button in the wysiwyg and then add data-langcode to the embed code, then when you open the dialog it should use that language. That would be a pretty easy change to make to the last patch. The data-langcode should override the language manager negotiated language when editing an embed.

oknate’s picture

Title: EntityEmbedDialog should be aware of language of parent » Selected Entity should display in parent language in EntityEmbedDialog when data-langcode not set

Changing the title, as I'm realizing (based on #32) that when editing an embed with data-langcode explicitly set, it should override the parent language.

This also means, I should add to the test coverage: Add this action:

reopen the dialog after adding data-langcode manually by clicking the "source" button, check that the entity displays the label in English, despite the fact that the parent language is fr, when the embed's data-langcode is set to "en".

Wim Leers’s picture

Sorry, I should've been clearer.

Let's use your screenshot as a starting point:
correct display, translated label

This is editing the French translation. But the interface language is English. The interface language would have been French if the French translation was installed. Because you're accessing /fr/something, which negotiates both the interface language and content language to be French.

That screenshot looks like things are working correctly. And it is. I'm saying this is only in this particular set of circumstances that it's working correctly: it's only working correctly because /fr/… negotiates all language types (URL, interface, content, config) to be the same by default.

What I'm also saying, but expressing it poorly in It's possible I'm using the site in French but embedding an entity in a Spanish translation., is that it's possible for me to access the admin UI in French (for example by setting that as a user preference, so that I don't need to use /fr/…), go to /admin/content and start editing a Spanish node translation. At that point, both the negotiated interface language and the negotiated content language are French (which means \Drupal\Core\Language\LanguageManager::getCurrentLanguage() === \Drupal\Core\Language\LanguageManager::getCurrentLanguage(LanguageInterface::TYPE_INTERFACE) === \Drupal\Core\Language\LanguageManager::getCurrentLanguage(TYPE_CONTENT) === 'fr'), yet the language of the particular entity I'm looking at and editing may not match that. And like this issue title says: we want the embedded entity's language to match that of the parent entity (the host entity). So when the negotiated interface and content languages both are French but I'm editing a Spanish translation, I still need my entity embed dialog to show embed candidates in Spanish, not in French.

That's why I'm saying we need to use $form_state->getFormObject()->getEntity()->language() instead of \Drupal\Core\Language\LanguageManager::getCurrentLanguage($something).

Am I missing something? :)

oknate’s picture

No, you're not missing something. Interface language is irrelevant.

If the parent is a French node, and you open the embed dialog, the the autocomplete shows French translations (this works), and when you click the next button, it should show the french translation, if available. That was the original bug. It wasn't respecting that. It was showing the original label, even though there was a french translation.

So it's more than just display. It's that the embed button should embed the entity in the same language as the parent by default.

I think you're right that the fact that it works in my test is just luck, The negotiated language just happened to match the parent language. But if the parent was a spanish node within an inline entity form within a french node and one clicked the embed button, it would probably show the page's language, rather than the parent. So we should probably pass through the javascript the language of the parent entity to the form, and then it should be passed to the preview step. The preview step would only not show the parent language if you're editing an embed and it has data-langcode set to a different language, then it would use that language. And I suppose it should validate that a translation in that language exists, and if not, fall back to the parent language.

Ideally the test should also have an edge case where you have a nested entity with a wysiwyg that has a different language than the parent, such as in inline entity form. Or perhaps if we get a source that is rock solid in pulling from the parent then we don't need to worry about that.

Wim Leers’s picture

the autocomplete shows French translations (this works)

I'm saying it only works by accident, because you're using \Drupal\Core\Language\LanguageManager::getCurrentLanguage() instead of $form_state->getFormObject()->getEntity()->language(). But … based on the rest of your comment, seems we're on the same page :)

So we should probably pass through the javascript the language of the parent entity to the form

Right; we either need to have the server inform the client what the edited entity's language is and pass that back to the dialog, or we need to store that in TempStore somehow.

Ideally the test should also have an edge case where you have a nested entity

Nested entities don't exist in Drupal core, only in Paragraphs/Inline Entity Forms. I don't care about that right now; that's a concern for the future :)

Or perhaps if we get a source that is rock solid in pulling from the parent then we don't need to worry about that.

In principle $form_state->getFormObject()->getEntity()->language() should be just that!

oknate’s picture

I was able to pass the language using hook_field_widget_form_alter().

Since a field could be untranslated, if "Users may translate this field" is unchecked, it should pull from the field, when possible. I left the entity as a fallback. I'm not sure that fallback would ever be used in hook_field_widget_form_alter().

I checked, and if "Users may translate this field" is unchecked, the language returned from $context['items']->getLangcode() reverts to the original language.

So that's a better place to get it than from the parent entity.

+
+/**
+ * Implements hook_field_widget_form_alter().
+ */
+function entity_embed_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
+
+  // Add a langcode attribute so that entity embed javascript can pass it to
+  // EntityEmbedDialog.
+  if (!empty($element['#type']) && $element['#type'] == 'text_format') {
+    if (!empty($context['items']) && $context['items'] instanceof FieldItemListInterface) {
+      $element['#attributes']['data-langcode'] = $context['items']->getLangcode();
+    }
+    else {
+      $entity = $form_state->getFormObject()->getEntity();
+      if ($entity instanceof ContentEntityBase) {
+        $element['#attributes']['data-langcode'] = $entity->language()->getId();
+      }
+    }
+  }
+}

I also replaced the "sleep(1)" with a better way of waiting:

+    $this->getSession()->wait(5000, "(typeof CKEDITOR != 'undefined' && typeof CKEDITOR.instances['edit-body-0-value'] != 'undefined' && CKEDITOR.instances['edit-body-0-value'].instanceReady)");

It waits that long unless the condition is met. I'm pretty sure this is right, since the modal wasn't appearing when it failed, I think it was because the CKEditor instance wasn't ready yet.

Status: Needs review » Needs work

The last submitted patch, 39: entity-embed-pass-langcode-3018485-39.patch, failed testing. View results

oknate’s picture

I introduced a new bug that the tests caught! Here's a fix.

Wim Leers’s picture

  1. +++ b/entity_embed.module
    @@ -232,3 +234,23 @@ function entity_embed_filter_format_edit_form_validate($form, FormStateInterface
    +      $element['#attributes']['data-langcode'] = $context['items']->getLangcode();
    

    We shouldn't use data-langcode; that's too generic and could potentially result in collisions. We should make this entity_embed-specific.

    Also: bunch of nits here.

    Fixed all of that.

  2. +++ b/src/Form/EntityEmbedDialog.php
    @@ -168,7 +170,13 @@ class EntityEmbedDialog extends FormBase {
         $form_state->set('entity_element', $entity_element);
         $entity = $this->entityTypeManager->getStorage($entity_element['data-entity-type'])
           ->loadByProperties(['uuid' => $entity_element['data-entity-uuid']]);
    -    $form_state->set('entity', current($entity) ?: NULL);
    +    $entity = current($entity);
    +    if ($entity && $entity instanceof TranslatableInterface && !empty($entity_element['data-langcode'])) {
    +      if ($entity->hasTranslation($entity_element['data-langcode'])) {
    +        $entity = $entity->getTranslation($entity_element['data-langcode']);
    +      }
    +    }
    +    $form_state->set('entity', $entity ?: NULL);
    
    @@ -752,6 +772,13 @@ class EntityEmbedDialog extends FormBase {
         $entity = $this->entityTypeManager->getStorage($entity_element['data-entity-type'])
           ->loadByProperties(['uuid' => $entity_element['data-entity-uuid']]);
         $entity = current($entity);
    +
    +    $langcode = $entity_element['data-langcode'];
    +    if ($entity && $entity instanceof TranslatableInterface && !empty($langcode)) {
    +      if ($entity->hasTranslation($langcode)) {
    +        $entity = $entity->getTranslation($langcode);
    +      }
    +    }
         $plugin_id = $entity_element['data-entity-embed-display'];
    

    This is repetition. It already existed, but we just made it worse. Introduced a helper.

  3. +++ b/tests/src/FunctionalJavascript/ContentTranslationTest.php
    @@ -0,0 +1,402 @@
    +class ContentTranslationTest extends EntityEmbedTestBase {
    

    👏 Epic work. Thank you so much! 🙏

  4. Just a bunch of nits:
    +++ b/tests/src/FunctionalJavascript/ContentTranslationTest.php
    @@ -0,0 +1,402 @@
    +    // Assert suggestions contain the translated label.
    +    $this->assertNotContains('Superhomme', $suggestions);
    

    There are some problematic comments like this one, which says the opposite of what we're testing. Cleaned all that up.

    +++ b/tests/src/FunctionalJavascript/EntityEmbedTestBase.php
    @@ -29,102 +22,46 @@ abstract class EntityEmbedTestBase extends WebDriverTestBase {
    +  protected function waitFoEditor() {
    

    s/Fo/For/ :)

  5. +++ b/tests/src/FunctionalJavascript/ContentTranslationTest.php
    @@ -0,0 +1,402 @@
    +    $this->assertSession()
    +      ->fieldExists('entity_id')
    +      ->setValue('super');
    +
    +    $suggestions = $this->assertSession()
    +      ->waitForElementVisible('css', '#drupal-modal .ui-widget-content.ui-autocomplete')
    +      ->getText();
    +
    +    // Assert suggestions contain the translated label.
    +    $this->assertNotContains('Superhomme', $suggestions);
    

    This pattern is repeated many times. Created a helper for it :) Makes it much easier to follow along.

oknate’s picture

I love the helper method for autocomplete! Using getAutocompleteSuggestions() is much easier to read!

Oops!

-waitFoEditor()
+ waitForEditor()

That's funny. Nice catch.

Wim Leers’s picture

+++ b/tests/src/FunctionalJavascript/ContentTranslationTest.php
@@ -0,0 +1,338 @@
+    $parent = $this->createNode([
...
+      'title' => 'parent',
...
+    $parent_fr = $parent->addTranslation('fr');

We named this "host" everywhere else. Renaming it here too for consistency.

("parent" is also semantically inaccurate: there's no parent/child relationship here.)

Done.

Wim Leers’s picture

Status: Needs review » Needs work

#43: I'm glad you like it 😀

Here's the one remaining concern I have before I commit this:

+++ b/js/plugins/drupalentity/plugin.js
@@ -37,6 +37,13 @@
+            existingValues['data-langcode'] = hostEntityLangcode;

I have two remarks about this:

  1. Every other entity-related data- attribute uses the data-entity- prefix. I think this should too.

    Except that data-langcode has already been supported by the filter for a long time, so we can't easily change that now. Even if we change it, we'd have to continue to support the old pattern too.

    So, let's just leave that as-is for now.

  2. data-langcode is currently not being automatically added to the allowed_html filter setting. I think we should do what #3022768: Validate that `alt` and `title` are required attributes for `<drupal-entity>`, and ensure they're added by default did for alt and title. Could you expand it to do that too? 🙏
Wim Leers’s picture

Wim Leers’s picture

Priority: Normal » Major
oknate’s picture

The attribute data-langcode is also missing here:

 allowedContent: 'drupal-entity[data-embed-button,data-entity-type,data-entity-uuid,data-entity-embed-display,data-entity-embed-display-settings,data-align,data-caption]',

But attributes being stripped out doesn't seem to be a thing any more.

See #2917132: EntityEmbedBuilder removes data- attributes set by other text filter plugins.

See line 204 of EntityEmbedFilterTest.

 $content = '<drupal-entity data-foo="bar" foo="bar"

I can add it, but it just works already, FYI.

Wim Leers’s picture

Sorry, I should've been more clear. I mean that the data-langcode attribute gets stripped by CKEditor, not by EntityEmbedBuilder. That's not happening in the test coverage because it doesn't use the filter_html filter.

oknate’s picture

Sure enough. And I failed to cover that in the test. Updated so that the test uses the 'filter_html' filter. I ran it without updating the allowed html, and the test failed:

There was 1 failure:

1) Drupal\Tests\entity_embed\FunctionalJavascript\ContentTranslationTest::testDialogLanguage
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'Smeagol likes cheese alt'
+'Gollum n'aime que la bague alt'

Then added 'data-langcode alt title' and it passed.

oknate’s picture

Also, now I think we should rename the test function 'testDialogLanguage()'. Since the dialog language would be the interface language, and the test was expanded to cover more than that. I'll change it to 'testHostEntityLangcode()'.

oknate’s picture

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

Perfect! :)

Wim Leers’s picture

Title: Selected Entity should display in parent language in EntityEmbedDialog when data-langcode not set » Selected Entity should display in host entity's language in EntityEmbedDialog when data-langcode not set

  • Wim Leers committed ed9ec7d on 8.x-1.x authored by oknate
    Issue #3018485 by oknate, Wim Leers: Selected Entity should display in...
Wim Leers’s picture

Status: Reviewed & tested by the community » Fixed

🚢🥳👏

oknate’s picture

Awesome! Thanks for getting this committed. I'm happy that we have this test coverage running now. Between CKEditorIntegrationTest and ContentTranslationTest we have pretty good test coverage of the usual use cases I think.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

maximpodorov’s picture

ShawnRong’s picture

If user select a different language admin interface in the admin panel, the "data-entity_embed-host-entity-langcode" is not correct. It will retrieve the wrong langcode which user configured in personal profile.

Dave Reid’s picture

Reading back on when this was added, I'm trying to understand why we have these two if conditions, based on the hook, the first one should always be run and the second one is never hit? What condition would be where $context['items'] isn't a FieldItemListInterface?

    if (!empty($context['items']) && $context['items'] instanceof FieldItemListInterface) {
      $element['#attributes']['data-entity_embed-host-entity-langcode'] = $context['items']->getLangcode();
    }
    else {
      $entity = $form_state->getFormObject()->getEntity();
      if ($entity instanceof ContentEntityInterface) {
        $element['#attributes']['data-entity_embed-host-entity-langcode'] = $entity->language()->getId();
      }
    }