0

In a custom module I created a custom admin route /admin/config/mymodule/rebuild whose controller renders a node into a variable. The purpose of the module is to send the rendered content to an external service.

The node has to be rendered using the default frontend theme (not the admin theme) and a specific language set by the controller.

I can switch from the active admin theme to the default frontend theme initializing the theme manager accordingly (reference).

Using a custom language negotiator I should be able to switch the language overriding defaults present in /admin/config/regional/language/detection (reference).

The issue is the language switch.

  • Dynamic content coming from fields is correctly translated

BUT

  • interface translations (| t filter and {% trans %} inside twig templates) don't get the language from my custom language negotiator. Language is taken from the current admin page URL (default behavior for the site)

Examples:

(in both cases my custom language negotiator is setting "es" as current language)

  • renders content and interface translations in spanish

    /es/admin/config/mymodule/rebuild

  • renders content in spanish but interface translations in english

    /en/admin/config/mymodule/rebuild

This method didn't work either.

What am I missing?

Update:

I found this post. The problem seems similar but no working solution has been provided.

The code:

mymodule.routing.yml

mymodule.rebuild:
  path: '/admin/config/mymodule/rebuild'
  defaults:
    _controller: '\Drupal\mymodule\Controller\RendererController::rebuild'
    _title: 'Renderer'
  requirements:
    _permission: 'access administration pages'

mymodule.services.yml

services:
  mymodule.language_negotiator:
    class: Drupal\mymodule\Language\CustomLanguageNegotiator
    arguments: ['@language_manager', '@plugin.manager.language_negotiation_method', '@config.factory', '@settings', '@request_stack']
    calls:
      - [initLanguageManager]

src/Controller/RendererController.php

namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\node\Entity\Node;

class RendererController extends ControllerBase {

  protected $themeManager;
  protected $themeInitialization;
  protected $frontTheme;
  protected $currentTheme;
  protected $viewBuilder;
  protected $languageManager;
  protected $currentLang;
  protected $customLanguageNegotiator;

  function __construct() {
    $this->languageManager = \Drupal::languageManager();
    $this->currentLang = $this->languageManager->getConfigOverrideLanguage();

    $this->customLanguageNegotiator = \Drupal::service('mymodule.language_negotiator');
    $this->languageManager->setNegotiator($this->customLanguageNegotiator);

    $frontThemeName = \Drupal::config('system.theme')->get('default');
    $this->themeManager = \Drupal::service('theme.manager');
    $this->themeInitialization = \Drupal::service('theme.initialization');
    $this->currentTheme = $this->themeManager->getActiveTheme();
    $this->frontTheme = $this->themeInitialization->initTheme($frontThemeName);

  }

  private function switchToDefaultTheme() {
    if ($this->frontTheme && $this->frontTheme->getName() != $this->currentTheme->getName()) {
      $this->themeManager->setActiveTheme($this->frontTheme);
    }
  }

  private function restoreCurrentTheme() {
    if ($this->currentTheme->getName() != $this->frontTheme->getName()) {
      $this->themeManager->setActiveTheme($this->currentTheme);
    }
  }

  private function setLanguage($langCode) {
    $this->languageManager->reset();
    $this->languageManager->getNegotiator()->setLanguageCode($langCode);
  }

  private function restoreLanguage() {
    $this->languageManager->reset();
    $this->languageManager->getNegotiator()
      ->setLanguageCode($this->currentLang->getId());
  }

  private function renderNode($node, $langCode) {
    $this->setLanguage($langCode);
    $build = $this->viewBuilder->view($node, "full", $langCode);
    $build['#cache']['max-age'] = 0;  // no cache
    $content = \Drupal::service('renderer')->renderPlain($build);
    return $content;
  }

  public function rebuild() {

    $nid = 10;
    $lang = "es";

    $node = $node = Node::load($nid);
    $this->viewBuilder = \Drupal::entityTypeManager()->getViewBuilder("node");
    $this->switchToDefaultTheme();

    $content = "";
    try {
      if ($node->hasTranslation($lang)) {
        $content = $this->renderNode($node, $lang);
      }

    } finally {
      $this->restoreCurrentTheme();
      $this->restoreLanguage();
    }


    $build = [
      '#type' => 'markup',
      '#markup' => $content,
    ];
    return $build;
  }

}

src/Language/CustomLanguageNegotiator.php

namespace Drupal\mymodule\Language;

use Drupal\language\LanguageNegotiator;

class CustomLanguageNegotiator extends LanguageNegotiator {

  private $languageCode = NULL;

  public function initializeType($type) {
    $language = NULL;
    $method_id = static::METHOD_ID;
    $availableLanguages = $this->languageManager->getLanguages();

    if ($this->languageCode && isset($availableLanguages[$this->languageCode])) {
      $language = $availableLanguages[$this->languageCode];
    }
    else {
      $language = $this->languageManager->getDefaultLanguage();
    }

    return [$method_id => $language];
  }


  public function setLanguageCode($languageCode) {
    $this->languageCode = $languageCode;
  }


}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.