Problem/Motivation

Similar to #2345607: Translated taxonomy terms not rendered in the entity display language

To reproduce:

  1. Install Drupal 8 standard. Enable Language, Content translation modules.
  2. Add a language.
  3. Add an entity reference field to the article content type. (To the simple page type)
  4. Configure Articles to be translatable. But not the reference field.
  5. Configure the referenced entity (simple page) to be translatable.
  6. Create a content to be referenced.
  7. Add an article with a reference.
  8. Translate the referenced content.
  9. Translate the article.

Now regardless of which translation of the article you are viewing, the same original language is used to render the reference fields.

Proposed resolution

Make the reference fields show up in the rendering language of the entity.

For this a new method should be introduced in \Drupal\entity_reference\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase, which will provide the translated and accessible referenced entities for prepareView()

Remaining tasks

Discussion about these two unclear things (see comment #18):

  • New method vs. prepareView()
  • The default fallback behavior if the referenced entity has no translation

User interface changes

None.

API changes

A new method (see above).

CommentFileSizeAuthor
#42 2346315-42.patch19.27 KBamateescu
#40 2346315-entity_reference_translated_view-38.patch19.27 KBamateescu
#38 interdiff.txt2.47 KBamateescu
#38 2346315-entity_reference_translated_view-38.patch19.27 KBamateescu
#30 interdiff-23-30.txt748 bytesDésiré
#30 2346315-entity_reference_translated_view-30.patch19.44 KBDésiré
#23 interdiff.txt6.13 KBamateescu
#23 2346315-entity_reference_translated_view-23.patch19.43 KBamateescu
#22 interdiff-20-22.txt1.27 KBDésiré
#22 2346315-entity_reference_translated_view-22.patch20.37 KBDésiré
#20 2346315-entity_reference_translated_view-20.patch20.36 KBDésiré
#20 interdiff-18-20.txt7.84 KBDésiré
#18 interdiff-14-18.txt1.46 KBDésiré
#18 2346315-entity_reference_translated_view-18.patch18.94 KBDésiré
#14 interdiff-12-14.txt986 bytesDésiré
#14 2346315-entity_reference_translated_view-14.patch18.84 KBDésiré
#12 interdiff-10-12.txt3.05 KBDésiré
#12 2346315-entity_reference_translated_view-12.patch18.81 KBDésiré
#10 2346315-entity_reference_translated_view-10.patch18.06 KBDésiré
#10 interdiff-8-10.txt12.13 KBDésiré
#8 interdiff-5-8.txt2.32 KBDésiré
#8 2346315-entity_reference_translated_view-8.patch9.25 KBDésiré
#5 interdiff-3-5.txt1.65 KBDésiré
#5 2346315-entity_reference_translated_view-5.patch8.54 KBDésiré
#3 interdiff-1-3.txt781 bytesDésiré
#3 2346315-entity_reference_translated_view-test_only-3.patch6.89 KBDésiré
#1 2346315-entity_reference_translated_view-test_only-1.patch6.88 KBDésiré

Comments

Désiré’s picture

Status: Needs review » Needs work

The last submitted patch, 1: 2346315-entity_reference_translated_view-test_only-1.patch, failed testing.

Désiré’s picture

Status: Needs work » Needs review
StatusFileSize
new6.89 KB
new781 bytes

Patch updated fro the current HEAD.

Status: Needs review » Needs work

The last submitted patch, 3: 2346315-entity_reference_translated_view-test_only-3.patch, failed testing.

Désiré’s picture

StatusFileSize
new8.54 KB
new1.65 KB

The first fix is attached: it passes the test, it's very similar to taxonomy reference fields, but it's not deal yet with the auto create items.
I need some help about how can I test this with auto create items.

Désiré’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 5: 2346315-entity_reference_translated_view-5.patch, failed testing.

Désiré’s picture

Status: Needs work » Needs review
StatusFileSize
new9.25 KB
new2.32 KB

Well, the tests failed in #5 were passing on my environment, I don't see what is the problem...

Now I'm updated it:

  • Check also the auto_create items
  • Load translation only if the target is an instance of TranslatableInterface
  • Fallback to the original language if the translation isn't accessible

Next steps:
The current fix is implemented within the prepareView() method, and it rewrite the $item->entity property whit the translated entity. After some conversation this should be changed: A $node->field_something->entity() call will return an entity with it's original language regardless to the actual language of $node, while $item->entity is the translated entity, and this can be confusing.
So we need a new method which returns the accessible items with the correct translation, and use it everywhere instead of $items.

Status: Needs review » Needs work

The last submitted patch, 8: 2346315-entity_reference_translated_view-8.patch, failed testing.

Désiré’s picture

Status: Needs work » Needs review
StatusFileSize
new12.13 KB
new18.06 KB

The test still passes for me, I don't know what is the difference here.

Now the new getEntitiesToView() method is implemented, and used in all inherited class.

Status: Needs review » Needs work

The last submitted patch, 10: 2346315-entity_reference_translated_view-10.patch, failed testing.

Désiré’s picture

Status: Needs work » Needs review
StatusFileSize
new18.81 KB
new3.05 KB

\Drupal\entity_reference\Tests\EntityReferenceFieldViewTest still passing for me...

The other fails are fixed now.

Status: Needs review » Needs work

The last submitted patch, 12: 2346315-entity_reference_translated_view-12.patch, failed testing.

Désiré’s picture

Status: Needs work » Needs review
StatusFileSize
new18.84 KB
new986 bytes

OK, now it should pass.

The problem was that test bot installs Drupal in subdirectory, and $entity->url() returned the path with the prefix, also $this->drupalGet($path) added the prefix to the path before the request, so the real patch were double prefixed. I think it's some sort of bug in the test system.

amateescu’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests

Instead of all the changes done to EntityReferenceFormatterBase and its extending classes, couldn't we just write the logic of getAccessibleTranslatedEntity() in EntityReferenceFormatterBase::prepareView()? That's exactly the purpose of that method :)

amateescu’s picture

The problem was that test bot installs Drupal in subdirectory, and $entity->url() returned the path with the prefix, also $this->drupalGet($path) added the prefix to the path before the request, so the real patch were double prefixed. I think it's some sort of bug in the test system.

Please see https://www.drupal.org/project/testbot, the testbots are installing Drupal in a subdirectory by design.

pp’s picture

I tested the patch and it works fine for me.

I suggest rename EntityReferenceFieldViewTest to something clearer eg.: EntityReferenceFieldViewLanguageVariationsTest

When I translate a referred entity, and I not translate the "host" entity and I go to the "translated url" the host fallback English and refered entity also. If it is fine, I suggest write an another test for testing this usecase also. (If isn't, I suggest write a test for a good usecase and correct the patch.)

Désiré’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new18.94 KB
new1.46 KB

I suggest rename EntityReferenceFieldViewTest to something clearer

I agree, it's done.

When I translate a referred entity, and I not translate the "host" entity and I go to the "translated url" the host fallback English and refered entity also. If it is fine, I suggest write an another test for testing this usecase also. (If isn't, I suggest write a test for a good usecase and correct the patch.)

I'm also agree with this, but I don't know what should be the default fallback behavior, so I not changed anything about this.

Please see https://www.drupal.org/project/testbot, the testbots are installing Drupal in a subdirectory by design.

It's ok, I know it, my problem was that a test can behave differently on a subdirectory install that on a root dir install. But now I found, that $entity->getSystemPath() can be used for getting the unprefixed path. I'm also changed the test to use it.

Instead of all the changes done to EntityReferenceFormatterBase and its extending classes, couldn't we just write the logic of getAccessibleTranslatedEntity() in EntityReferenceFormatterBase::prepareView()?

Please see comment #8, there I explained why is the new method introduced, also the patch there is a working fix implemented in prepareView().

Maybe we should have more discussion about these two unclear things:

  • New method vs. prepareView()
  • The default fallback behavior if the referenced entity has no translation
Désiré’s picture

Issue summary: View changes
Désiré’s picture

After a consultation with webflow, I made some changes:

  1. If a referenced entity has no translation, we should fallback to the default language. So I added assertions to the test for this case.
  2. The translate and access check is more simplified. (We still have to usehasTranslation() becaulse getTranslation() will create it on the fly, but breaks the default language fallback)
schnitzel’s picture

The default fallback behavior if the referenced entity has no translation.

I could see some cases, where we would like to have more granular control over the fallback behavior (like fallback chains), but of all the experience with client websites, every website is different. And the default language is suitable for most of cases. So I +1 that.

New method vs. prepareView()

I agree with @amateescu that prepareView() sounds a lot like what we would like to use, but the case that is made in #8 makes a lot of sense.
So +1 for the new method.

+++ b/core/modules/entity_reference/src/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
@@ -15,6 +18,62 @@
+    $active_langcode = $parent_entity->language()->getId();

Discussed this with @Gabor and @Désiré.
Also here I could see the case that on some websites would like to use the negotiated content language, rather the language of the parent entity.
But when the case happens that the parent entity is not translated the whole page will show anyway a big language mix. If we wanna fix that fully properly we should have an additional Language Negotiation system: Referenced Content Language Negotiation. But this would confuse so many sitebuilders even more (it's now already crazy). So I think this is a case for a contrib module.

Maybe rename $active_langcode to $parent_entity_langcode?

Désiré’s picture

Variable name changed, as suggested.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new19.43 KB
new6.13 KB

Right, I think #8 makes sense as well. And further to #20, we can now simplify the code even more, something like the patch attached (note that the interdiff doesn't show it, but the patch includes the change from #22).

Désiré’s picture

I agree with the changes by @amateescu. Thank you.

The last submitted patch, 20: 2346315-entity_reference_translated_view-20.patch, failed testing.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 23: 2346315-entity_reference_translated_view-23.patch, failed testing.

The last submitted patch, 22: 2346315-entity_reference_translated_view-22.patch, failed testing.

The last submitted patch, 23: 2346315-entity_reference_translated_view-23.patch, failed testing.

Désiré’s picture

Status: Needs work » Needs review
StatusFileSize
new19.44 KB
new748 bytes

Well... The last few patches were failing, because they didn't respected if the $item->access was already TRUE, like before. Now I'm fixed this, the tests should pass.

         $entity = $item->originalEntity;
       }

-      if ($entity->access('view')) {
+      if ($item->access || $entity->access('view')) {
         $entities[$delta] = $entity;

         // Mark item as accessible.

But I think that this is not a good solution: now (I mean the current HEAD and also this last patch) makes it possible to display entities through entity reference fields even if the user have no access to the entity. But since it is the current behavior I think it should be an other issue.

If you agree with this we should go back to RTBC.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

I think that's mostly done for easy testing purposes and, since it's already the current HEAD behavior, this looks good to go now. Thanks Désiré!

schnitzel’s picture

Status: Reviewed & tested by the community » Needs work

can we get the changes from #22 back in there?

then I would also RTBC that :)

amateescu’s picture

Status: Needs work » Reviewed & tested by the community

It's there allright :P

schnitzel’s picture

Status: Reviewed & tested by the community » Needs work

oh damn, ignore #32, this is already in, looks like the interdiffs are strange.

but found

+++ b/core/modules/entity_reference/src/Plugin/Field/FieldFormatter/EntityReferenceIdFormatter.php
@@ -30,21 +30,15 @@ class EntityReferenceIdFormatter extends EntityReferenceFormatterBase {
-    foreach ($items as $delta => $item) {
-      if (!$item->access) {
-        // User doesn't have access to the referenced entity.
-        continue;
-      }
-      if (!empty($item->entity) && !empty($item->target_id)) {
-        /** @var $referenced_entity \Drupal\Core\Entity\EntityInterface */
-        $referenced_entity = $item->entity;
+    foreach ($this->getEntitiesToView($items) as $delta => $entity) {
+      if ($entity->id()) {
         $elements[$delta] = array(
-          '#markup' => String::checkPlain($item->target_id),
+          '#markup' => String::checkPlain($entity->id()),

we're removing the check for if (!empty($item->entity) && !empty($item->target_id)). it's also not in getEntitiesToView().
Not sure for what that exactly is, but maybe $item->target_id can be empty?
But there is a check for $entity->id() which probably is true every as getEntitiesToView() will return an entity?

+++ b/core/modules/entity_reference/src/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php
@@ -69,34 +69,30 @@ public function settingsSummary() {
-      if (!empty($item->target_id)) {
-        $elements[$delta] = entity_view($item->entity, $view_mode, $item->getLangcode());
+      if ($entity->id()) {
+        $elements[$delta] = entity_view($entity, $view_mode, $entity->language()->getId());

same here

Désiré’s picture

The entity should be auto created (with tag style fields), in this case the entity will have no id, $item->target_id will be empty, but $entity->id() will also return NULL, so the changed code should work the same way in these cases.

schnitzel’s picture

Status: Needs work » Reviewed & tested by the community

ok, cotcha. thanks for the explanation :)

back to RTBC

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/entity_reference/src/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php
    @@ -69,34 +69,30 @@ public function settingsSummary() {
    +        // @todo Find some better solution for fetch '_attributes'.
    

    Can we get an issue filed for this and referenced in the code. See https://twitter.com/xjmdrupal/status/497852222600790016

  2. +++ b/core/modules/entity_reference/src/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
    @@ -8,6 +8,9 @@
    +use Drupal\Core\Entity\EntityInterface;
    

    Not used.

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new19.27 KB
new2.47 KB

I'm not sure why that @todo was introduced in this patch, that is the only way to access _attributes :)

amateescu’s picture

Status: Reviewed & tested by the community » Needs review

Ok.. NR first.

amateescu’s picture

What a lazy bot! Re-uploading.

Désiré’s picture

@amateescu the todo was introduced here, and I'm also created a new issue. I'm also not sure if it makes any sense, so maybe it can just closed. #2350831: Find a better solution for fetch '_attributes' in entity reference fields

amateescu’s picture

StatusFileSize
new19.27 KB

Désiré, I just did that :P And I have no idea why the bot doesn't like that patch :/ Let's try with a different file name.

The last submitted patch, 38: 2346315-entity_reference_translated_view-38.patch, failed testing.

The last submitted patch, 40: 2346315-entity_reference_translated_view-38.patch, failed testing.

Désiré’s picture

Status: Needs review » Reviewed & tested by the community

Then I think it's RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed bf44ce4 and pushed to 8.0.x. Thanks!

  • alexpott committed bf44ce4 on
    Issue #2346315 by Désiré, amateescu: Fixed Translated entity references...

Status: Fixed » Closed (fixed)

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

yched’s picture

Related: #2405469: FileFormatterBase should extend EntityReferenceFormatterBase
Currently file/image formatters do not follow the correct translation behavior that was added for ER fields here.