5

UPDATE: This bug was just fixed in Issue 2174633 and Drupal v8.7.9 will no longer have this problem.

For some of my entity reference fields I'm using "Views: Filter by an entity reference views" as reference method. I've configured those views to use the current interface language for rendering (with fallback to default lang).

enter image description here

The interface language selection basically works (in other view blocks, or when previewing in /admin/structure/views), but it does not work when used as source for an entity reference field:

  • In my admin interface I'm using I've got a paragraph with an ER field using such a view as source. The paragraph always shows the title in default lang
  • On the frontend I've got a webform select field using the same view as source. The select options are always rendering in default lang.
  • When using the default reference method I do get translated titles in both use cases.
  • As stated above, the correct language is used in preview on /admin/structure/views

How can I select the correct language for my view-filtered ER fields?

(Please note that I can not use the interface language as filter criteria, because this would disable the language fallback.)

3
  • Under filter criteria section, remove "Content: Default translation" and add " Content: Translation language (= Interface text language selected for page)"
    – lamp5
    Dec 12, 2018 at 15:33
  • This would disable the fallback functionality to default language if the entity is not translated into the current interface language.
    – Hudri
    Dec 12, 2018 at 15:58
  • Facing the same problem. I'm using the view for getting the list of ER. And inside the view titles are translated. But when I'm using the view from webform module for selecting the options I'm always getting content titles in default language. @Hudri, did you find solution for this?
    – MilanG
    Aug 21, 2019 at 8:57

3 Answers 3

1

I have created a patch for @4k4's answer that also uses dependency injection.

To apply this patch:

Take the code snippet below and paste it into a new file e.g test.patch.

Then run git apply /path-to-file/test.patch.

For a UI only solution, see my other answer.

diff --git a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
index 79707af..e092ba9 100644
--- a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
+++ b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
@@ -4,6 +4,7 @@

 use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
 use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginBase;
+use Drupal\Core\Entity\EntityRepositoryInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormStateInterface;
@@ -59,6 +60,13 @@ class ViewsSelection extends SelectionPluginBase implements ContainerFactoryPlug
    */
   protected $currentUser;

+  /**
+   * The entity repository.
+   *
+   * @var EntityRepositoryInterface
+   */
+  protected $entityRepository;
+
   /**
    * Constructs a new ViewsSelection object.
    *
@@ -74,13 +82,16 @@ class ViewsSelection extends SelectionPluginBase implements ContainerFactoryPlug
    *   The module handler service.
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
+   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository
+   *   The entity repository.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user, EntityRepositoryInterface $entityRepository) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);

     $this->entityTypeManager = $entity_type_manager;
     $this->moduleHandler = $module_handler;
     $this->currentUser = $current_user;
+    $this->entityRepository = $entityRepository;
   }

   /**
@@ -93,7 +104,8 @@ public static function create(ContainerInterface $container, array $configuratio
       $plugin_definition,
       $container->get('entity_type.manager'),
       $container->get('module_handler'),
-      $container->get('current_user')
+      $container->get('current_user'),
+      $container->get('entity.repository')
     );
   }

@@ -231,6 +243,7 @@ public function getReferenceableEntities($match = NULL, $match_operator = 'CONTA
     if ($result) {
       foreach ($this->view->result as $row) {
         $entity = $row->_entity;
+        $entity = $this->entityRepository->getTranslationFromContext($entity);
         $return[$entity->bundle()][$entity->id()] = $entity->label();
       }
     }

2
  • I successfully applied this patch on Drupal v8.7.6 and it worked for me. Thanks!
    – Hudri
    Aug 27, 2019 at 15:06
  • So... why has this not being put into a bug ticket for Drupal?
    – Patrick
    Nov 20, 2019 at 21:30
4
+100

Comparing TermSelection::getReferenceableEntities and ViewsSelection::getReferenceableEntities it seems like the Views entity reference selection plugin doesn't translate the entity before returning the entity labels. It should work with a core patch adding one line:

/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php:

public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
  $display_name = $this->getConfiguration()['view']['display_name'];
  $arguments = $this->getConfiguration()['view']['arguments'];
  $result = [];
  if ($this->initializeView($match, $match_operator, $limit)) {
    // Get the results.
    $result = $this->view->executeDisplay($display_name, $arguments);
  }

  $return = [];
  if ($result) {
    foreach ($this->view->result as $row) {
      $entity = $row->_entity;
      // add this line to translate the entity
      $entity = \Drupal::service('entity.repository')->getTranslationFromContext($entity);
      $return[$entity->bundle()][$entity->id()] = $entity->label();
    }
  }
  return $return;
}

Edit:

This won't be necessary anymore, when https://www.drupal.org/project/drupal/issues/2174633 is fixed, then resolving the underlying problem, that the selection plugin ignores the views output.

5
  • Will this work if the entity doesn't have a translation?
    – user72672
    Aug 21, 2019 at 18:30
  • 2
    @JDrupal, this code means that the rendered output you configure in UI and you see in the preview doesn't matter. The selection plugin uses the configured display only for the SQL query to get the filtered entities. So the only thing matters is the filter for the default translation to avoid duplicates. The added getTranslationFromContext method gets the best translation candidate fitting the context, if there is no translation then the original entity is returned.
    – 4uk4
    Aug 21, 2019 at 19:31
  • This solution works fine for me.
    – MilanG
    Aug 22, 2019 at 8:23
  • This solution does work for me. One minor caveat though: After applying this patch, you no longer can force a foreign Rendering language (see middle column in Views UI), it will always use the translation context (e.g. you no longer can create a german page and force the view to display translated english node titles within the german page).
    – Hudri
    Aug 27, 2019 at 15:18
  • You could never do this as explained in the last comment, also the fields selected are ignored and it's always the title which is displayed. You have to wait until the the issue mentioned in the edit is fixed. Then you can configure the rendered result in UI, like select and format fields and choose the rendering language.
    – 4uk4
    Aug 27, 2019 at 15:33
1

Here's a UI solution if you don't want to apple a core patch.

You'll need to use the translation_views module.

Here's a screenshot of the needed filter configuration:

enter image description here

The logic is simple, if the node has no translations then show the original language, otherwise show the translation language.

I use the translation_views module to get the Translation counter filter.

9
  • Interesting approach, I'm already using translation_views on my projects, but can't test it right now due workload. Why are you using Original language = Site default instead of Default translation = true in the first filter group? I think with default translation the fallback would work in both directions, while original language would only work one-way from default to other.
    – Hudri
    Aug 21, 2019 at 16:08
  • I think that was a mistake, updated the answer. Looking forward to hear from you when you have tested it :)
    – user72672
    Aug 21, 2019 at 16:22
  • I've tested this and it does not work for me, I still do get the default/original language. I think that the filter logic is correct, but I guess this solution is afftected by the same bug as described by @4k4's answer
    – Hudri
    Aug 27, 2019 at 14:45
  • Seems strange are you using the latest version of Drupal core, and have you remembered to use OR between the filter groups in views?
    – user72672
    Aug 27, 2019 at 14:47
  • No, not using dev, I'm running latest stable v8.7.6. This answer certainly is interesting for people without composer, but I'm using cweagans/composer-patches so core patches are no problem for me.
    – Hudri
    Aug 27, 2019 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.