1

Usually we override services using RouteSubscribers, but i need to override a method of a class that is not a service. I need to alter the module of the core "views", the general structure of this module is:

> views
  > src
    > Entity
      > Render
        - ConfigurableLanguageRenderer.php
        - EntityTranslationRenderTrait.php

I need to override one method of one of those files.

In ConfigurableLanguageRenderer.php i need to override "getLanguage()" method or in EntityTranslationRenderTrait.php i need to override "getEntityTranslation()" method, but i don't know how override a trait or a class that is not a service, is that possible? Thanks.

--- More context ---

A hook_language_fallback_candidates_OPERATION_alter() was implemented and we have a custom priority candidates to return the content translated, but one validation in the views module broke my custom fallback candidates.

E.G: if the content was written in English(en), and you send in the view rest the parameter lang=en, the view will be skip to search the translation in the candidates and the hook_language_fallback... doesn't be executed because if you looking for a node in english and this article has english as default is not necessary to search translation and this return the original language of the content.

Then i need to alter the langcode that return $this->getEntityTranslationRenderer()->getLangcode($row)

  • ConfigurableLanguageRenderer.php

    public function getEntityTranslation(EntityInterface $entity, ResultRow $row) {
      // We assume the same language should be used for all entity fields
      // belonging to a single row, even if they are attached to different entity
      // types. Below we apply language fallback to ensure a valid value is always
      // picked.
      $translation = $entity;
      if ($entity instanceof TranslatableInterface && count($entity->getTranslationLanguages()) > 1) {
        $langcode = $this->getEntityTranslationRenderer()->getLangcode($row);
        $translation = $this->getEntityRepository()->getTranslationFromContext($entity, $langcode);
      }
      return $translation;
    }
    

So i need to alter those methods or alter the default language of the node, or if it's possible alter "context" to enter to the following validation: ($entity->language()->getId() != $langcode)

public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = []) {
    $translation = $entity;

    if ($entity instanceof TranslatableDataInterface && count($entity->getTranslationLanguages()) > 1) {
      if (empty($langcode)) {
        $langcode = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
        $entity->addCacheContexts(['languages:' . LanguageInterface::TYPE_CONTENT]);
      }

      // Retrieve language fallback candidates to perform the entity language
      // negotiation, unless the current translation is already the desired one.
      if ($entity->language()->getId() != $langcode) {
        $context['data'] = $entity;
        $context += ['operation' => 'entity_view', 'langcode' => $langcode];
        $candidates = $this->languageManager->getFallbackCandidates($context);

        // Ensure the default language has the proper language code.
        $default_language = $entity->getUntranslated()->language();
        $candidates[$default_language->getId()] = LanguageInterface::LANGCODE_DEFAULT;

        // Return the most fitting entity translation.
        foreach ($candidates as $candidate) {
          if ($entity->hasTranslation($candidate)) {
            $translation = $entity->getTranslation($candidate);
            break;
          }
        }
      }
    }

    return $translation;
  }

-- Update --

as @4k4 mentioned i overwritten the service EntityRepository.php and that solved my problem

class GlobalizationServiceProvider extends ServiceProviderBase {

  /**
  * {@inheritdoc}
  */
  public function alter(ContainerBuilder $container) {
    if ($container->hasDefinition('entity.repository')) {
      $definition = $container->getDefinition('entity.repository');
      $definition->setClass('Drupal\Globalization\CustomEntityRepository');
    }
  }
}
1
  • 1
    You might want to provide a bit of context as to what you're trying to achieve. There might be other ways to achieve what you're trying to do than this approach.
    – Joseph
    Oct 27, 2021 at 0:54

1 Answer 1

1

The first class is hard coded in the second class and the second class is a trait used in different field and row plugins. So you need to target one of those plugins. There are several ways. The preferred one is to assign a custom plugin ID to the extended plugin class and configure it in your custom View. If you want to override the plugin class in general see How do I replace a plugin?


The last method you've added in more context is in a service and you can implement MyEntityRepository::getTranslationFromContext() and then swap the class in a ServiceProvider (not RouteSubcriber): See altering existing services.

1
  • as @4k4 that was the solution to my problem, thanks
    – Mauricio
    Oct 28, 2021 at 20:19

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.