Views entity reference relationships must join on langcode for translatable entities

Created on 31 May 2016, over 8 years ago
Updated 10 September 2024, 3 months ago

Problem/Motivation

(Why the issue was filed, steps to reproduce the problem, etc.)

Steps to reproduce

1) Create new node type (for example: referenced_page)
2) Navigate to admin/config/regional/content-language and set that node type to translatable
3) Create a piece of content of that node type (for example: This is the default language version of the referenced page)
4) Create another node type (for example: referencing_page)
5) Add an entity reference field to that node type that allows it to point to the referenced_page node type
6) Do NOT set that node type to be translatable (It doesn't actually matter if you do. You'll still run into the same problem. I'm just specifically addressing the point about having a non-translatable entity referencing a translatable entity. The heart of the issue is that the referenced entity is translatable).
7) Create a piece of content of the referencing page (for example: This is the default language of the referencing page)
8) Reference the first node type (for example, pointing to "This is the default language version of the referenced page.")
9) Create a block that uses: a contextual filter with a default argument of Content ID from URL; a relationship of "Content using {your_entity_reference_field}" and require the relationship; Title field (use the relationship) of referencing pages pointing to this referenced page.
10) Place the block in a region
11) Visit the "This is the default language version of the referenced page" node
12) Observe that there is only one title in the block
13) Add a translation "This is another language version of the referenced page"
14) Observe that the block now contains two titles.
15) Add another language to the site
16) Add a translation "This is a third language version of the referenced page"
17) Observe that there are now three titles in the block

Note: One workaround for the duplication is to use aggregation (for example Group column Entity ID or Language), although that's just masking the symptom and may have other undesirable side effects.

Proposed resolution

The primary key of an entity's data table is id, langcode. When joining on entity data tables as part of a Views relationship for an entity reference, Views only joins on the ID, however, not on the ID+langcode combination. This leads to duplicate results in case the respective entities are translated.

Remaining tasks

Modify the entity views data for all entity reference relationships to include an extra entry that additionally joins on the langcode. When joining from a non-translatable entity, to a translatable one, ideally there would need to be some way to select the language. Not sure about that, though. But we can definitely fix the case of joining two translatable entities as we can just make sure the langcodes match. (I guess that makes sense, but again, not really sure.)

User interface changes

?

API changes

?

Data model changes

?

πŸ› Bug report
Status

RTBC

Version

11.0 πŸ”₯

Component
ViewsΒ  β†’

Last updated about 2 hours ago

Created by

πŸ‡©πŸ‡ͺGermany tstoeckler Essen, Germany

Live updates comments and jobs are added and updated live.
  • D8MI

    (Drupal 8 Multilingual Initiative) is the tag used by the multilingual initiative to mark core issues (and some contributed module issues). For versions other than Drupal 8, use the i18n (Internationalization) tag on issues which involve or affect multilingual / multinational support. That is preferred over Translation.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡¬πŸ‡·Greece perarg

    Hi,
    I tried the last patch #34 but it has no impact with tables commerce_product_field_data and commerce_product_variation_field data. The join query has only the product_id but no langcode is present

  • πŸ‡¬πŸ‡·Greece perarg

    This doesn't work, at least with commerce.

    I found out that due to this issue https://www.drupal.org/project/drupal/issues/2930736 πŸ› EntityViewsData assumes BaseFieldDefinitions where it should use FieldDefinitionInterface Needs work if change the variable $field_definition --> $field_storage_definition, it works.

  • Status changed to Needs work almost 2 years ago
  • πŸ‡³πŸ‡±Netherlands Lendude Amsterdam

    Moving back to Needs work for automated test coverage.

  • πŸ‡ͺπŸ‡ΈSpain rcodina Barcelona

    Patch on #34 works for me on Drupal 9.5.2. Thanks @Piotr Pakulski!

  • πŸ‡§πŸ‡ͺBelgium bernardopaulino Brussels

    I could not reproduce this issue on my D10.1.1 installation.

  • πŸ‡§πŸ‡ͺBelgium bernardopaulino Brussels

    My last comment #39 is false. I tested again and I have duplicated values.

  • πŸ‡§πŸ‡ͺBelgium bernardopaulino Brussels

    Re-roll for drupal 10.1.1

  • last update over 1 year ago
    29,457 pass
  • #34 works perfectly, what a relief. This was causing so many issues in our project. Thanks!

  • πŸ‡¨πŸ‡¦Canada Shiraz Dindar Sooke, BC

    This is a very real issue and the patch in #41 solved my problem.

  • Hi, at the patch #41 the part:

    +++ b/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php
    @@ -513,6 +513,10 @@ public function testDataTableFields() {
               'value' => 0,
               'numeric' => TRUE,
             ],

    doesnβ€˜t match my version:

     public function testDataTableFields() {
        $entity_test_type = new ConfigEntityType([
          'class' => ConfigEntityBase::class,
          'id' => 'entity_test_bundle',
          'entity_keys' => [
            'id' => 'type',
            'label' => 'name',
          ],
        ]);

    Including all the following changes.
    Iβ€˜m running Drupal 10.1.0. Does the version 10.1.1 make that difference?

    regards

  • This does seem not to work on 10.3.2. Despite, had apply patch manually due to incompatibility, I think I did it right.
    Also, in standard case you don't need this patch at all imho, enough to add Filter Criteria on Relationship, eg. in my case Default Translation = Yes. However, this seems not to work when I want to display different content Type where one does not have reference at all, despite Relationship is Not Required.

  • First commit to issue fork.
  • Status changed to Needs review 3 months ago
  • πŸ‡«πŸ‡·France duaelfr Montpellier, France

    Rerolled on 11.x in a MR.

  • πŸ‡«πŸ‡·France duaelfr Montpellier, France
  • Pipeline finished with Success
    3 months ago
    Total: 619s
    #259740
  • First commit to issue fork.
  • Status changed to RTBC 3 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Only rebased to be able to run test-only feature

    1) Drupal\Tests\views\Kernel\Entity\EntityViewsDataTest::testDataTableFields
    Failed asserting that two arrays are equal.
    --- Expected
    +++ Actual
    @@ @@
         'field' => 'entity_id'
         'extra' => Array (
             0 => [...]
    -        1 => [...]
         )
     )
    /builds/issue/drupal-2737619/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php:509
    2) Drupal\Tests\views\Kernel\Entity\EntityViewsDataTest::testRevisionTableFields
    Failed asserting that two arrays are equal.
    --- Expected
    +++ Actual
    @@ @@
         'field' => 'entity_id'
         'extra' => Array (
             0 => [...]
    -        1 => [...]
         )
     )
    /builds/issue/drupal-2737619/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php:644
    FAILURES!
    Tests: 8, Assertions: 315, Failures: 2.
    Exiting with EXIT_CODE=1
    

    Which shows coverage so removing the tag for that.
    Manually testing appears to be working.

    Only question I have is making the new join requires a CR but I'm like 30/70 about that so won't hold up the issue.

  • Pipeline finished with Success
    3 months ago
    Total: 812s
    #279290
  • πŸ‡¨πŸ‡¦Canada Shiraz Dindar Sooke, BC

    Heads up! This patch (#41) is no longer working.

    Between Drupal 10.2 and 10.3 views entity relationships code was refactored, such that the change in patch #41 to views.views.inc no longer works. The patch still applies, but it attempts to add a join to $target_base_table at a point where that variable no longer exists. The most obvious symptom of this is in watchdog you will see "Warning: Undefined variable $target_base_table", aside from fact that the original problem this patch addressed will reoccur.

    I tried to redo the patch to work on the refactored views relationship code by adding the joins elsewhere but was unsuccessful. I then tried doing the joins for my own views in my a views_query_alter hook and was unsuccessful there too. Eventually my solution was to simply add a where expression in a views_query_alter hook:

    $query->addWhereExpression(0, 'node__' . $ref_field . '.langcode = node_field_data.langcode');

    wherein $ref_field is the translatable field used in the relationship.

    A join is more efficient but I'm happy with this for now.

    Note, I haven't checked out the 11.x patch, but I suspect it would have the same problem. So I advise you check your watchdog for the aforementioned warnings if you are using that.

    Shiraz

  • πŸ‡³πŸ‡ΏNew Zealand quietone

    I read this issue and the MR. It all makes sense to me. But the last comment suggests that this is not working correctly and I was not able to follow the steps to reproduce in the issue summary. Step 9 includes adding "a contextual filter with a default argument of Content ID from UR". When I do that there are no results but in step 12 there should be 1 result. I was using a fresh install of Umami for testing.

    So, how about we get manual testing to confirm the change is working as expected. That should include making any changes to the steps to reproduce that may be needed.

  • πŸ‡¨πŸ‡¦Canada Shiraz Dindar Sooke, BC

    I'm just following up my last comment as it assumes the relationship field is a reverse relationship.

    Here's the code I wrote to take care of views with translated relationship fields causing duplicates in the view results. In now works with forward (normal) in addition to reverse relationships:

    /**
     * Implements hook_views_query_alter().
     */
    function my_module_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
      // Views bug: translated relationships (entity reference from parent to child)
      // does not filter by language. So enforce that here instead.
      $views_with_translatable_relationships = [
        'view_name_a' => [
          'type' => 'reverse',
          'field_name' => 'field_example_1',
        ],
        'view_name_b' => [
          'type' => 'reverse',
          'field_name' => 'field_example_2',
        ],
        'view_name_c'  => [
          'type' => 'forward', // this is not a reverse relationship
          'field_name' => 'field_example_3',
        ],
      ];
      foreach ($views_with_translatable_relationships as $view_name => $ref_field) {
        if ($view->id() === $view_name) {
          if ($ref_field['type'] == 'reverse') {
            $relationship_key = 'reverse__node__';
            $relationship_alias_prefix = 'node__';
          }
          else {
            $relationship_key = '';
            $relationship_alias_prefix = 'node_field_data_node__';
          }
          if (isset($view->relationship[$relationship_key . $ref_field['field_name']])) {
            /** @var \Drupal\views\Plugin\views\query\Sql $query */
            $query->addWhereExpression(0, $relationship_alias_prefix . $ref_field['field_name'] . '.langcode = node_field_data.langcode');
          }
        }
      }
    }
    
Production build 0.71.5 2024