Wrong language used for inherited field value

Created on 17 June 2024, 13 days ago

Problem/Motivation

The inherited field values are always returned in the current language. This causes problems when accessing inherited fields on entities which are in a language different than the current language.

Steps to reproduce

  1. Set the current language to German
  2. Programmatically load a French translation of an entity.
  3. Read an inherited field on the entity.

Expected result: the field value should be in French.
Actual result: the German value is returned.

Proposed resolution

This appears to be caused by this line in FieldInheritancePluginBase::__construct():

 $this->langCode = $this->languageManager->getCurrentLanguage()->getId();

Instead of setting the language code to the current language, we should take the language from the entity that is inheriting the fields.

🐛 Bug report
Status

Active

Version

2.0

Component

Code

Created by

🇧🇬Bulgaria pfrenssen Sofia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @pfrenssen
  • Pipeline finished with Success
    13 days ago
    Total: 143s
    #201201
  • 🇧🇬Bulgaria pfrenssen Sofia

    The change in the MR fixes the problem for me. I am not sure if this is the right solution though. We are using a computed field, and these are not usually marked as translatable. However, reading the code in ContentEntityBase::getTranslatedField() it looks like if a field is not marked as translatable, then a copy of the field using the default language is always returned:

          // Non-translatable fields are always stored with
          // LanguageInterface::LANGCODE_DEFAULT as key.
          $default = $langcode == LanguageInterface::LANGCODE_DEFAULT;
          if (!$default && !$definition->isTranslatable()) { // <<<<<<<< If the field is not marked as translatable, the default language version is used for all translations.
            if (!isset($this->fields[$name][LanguageInterface::LANGCODE_DEFAULT])) {
              $this->fields[$name][LanguageInterface::LANGCODE_DEFAULT] = $this->getTranslatedField($name, LanguageInterface::LANGCODE_DEFAULT);
            }
            $this->fields[$name][$langcode] = &$this->fields[$name][LanguageInterface::LANGCODE_DEFAULT];
          }
    

    Unfortunately I couldn't write a test for the module in the time I had available, but here is a rough draft of a test that showcases the problem.

      /**
       * Tests that event instances are updated when the event series is translated.
       */
      public function testEventInstanceUpdatedWhenEventSeriesTranslated(): void {
        // Initially the event series is in German.
        $this->assertSame('de', $this->eventSeries->language()->getId(), 'The event series is in German.');
        $this->assertEquals('Vortrag zum Thema Designinnovation', $this->eventSeries->label(), 'The title of the event series is in German.');
    
        $instances = $this->eventSeries->getInstances();
        $instance = reset($instances);
        $this->assertCount(1, $instance->getTranslationLanguages(), 'There is only a German translation of the event instance.');
        $this->assertSame('de', $instance->language()->getId(), 'The event instance is in German.');
        $this->assertEquals('Vortrag zum Thema Designinnovation', $instance->label(), 'The title of the event instance is in German.');
    
        // Translate the event series to French.
        $translation = $this->eventSeries->addTranslation('fr', ['title' => 'Conférence sur le design d\'innovation']);
        $translation->save();
    
        $this->assertEquals('Conférence sur le design d\'innovation', $translation->label(), 'The title of the translation is in French.');
    
        // Check the event instance is also translated.
        $instances = $this->eventSeries->getInstances();
        $instance = reset($instances);
        $this->assertCount(2, $instance->getTranslationLanguages(), 'There are now 2 translations of the event instance.');
    
        $french_event_instance = $instance->getTranslation('fr');
        $this->assertSame('fr', $french_event_instance->language()->getId(), 'The French event instance is in French.');
        $this->assertEquals('Conférence sur le design d\'innovation', $french_event_instance->label(), 'The title of the event instance is in French.');
    }
    

    The last line fails in this test, but passes when the patch from the MR is applied.

Production build 0.69.0 2024