0

I have a multilingual site with two view blocks, and a custom template for them.

I want to render both blocks in language A, but only one in language B.
Is it possible to avoid that one of them is rendered on a language basis, from the preprocess function?

4 Answers 4

5

Why preprocess?

Blocks have language visibility. Just configure that block to be shown only in a specific language.

2
  • thanks for the answer. So in preprocess it is not possible. Aug 18, 2016 at 14:54
  • 1
    @MudassarAli It is possible but why to bother that if there is existing solution? Or any reason that you don't want to make it in this way?
    – Jimmy Ko
    Aug 18, 2016 at 15:27
1

To anyone coming here from a search:

As Berdir says, for the problem described in the question we don't need to use preprocess.

However, if you need this for some other reason, the following hack does the trick, for whichever theme hook you want to target:

function mymodule_preprocess_HOOK(array &$variables, string $hook, array &$info): void {
  if (...) {
    $info['function'] = '';
  }
}

The $info array is a local variable in ThemeManager::render() that is loaded from the theme registry, and then passed to preprocess functions in a way that supports treating it as a by-reference parameter.

Setting $info['function'] overrides any template that would otherwise be rendered. If we use a function name that does not exist, we get an empty string as output.

In \Drupal\Core\Theme\ThemeManager::render():

    // Generate the output using either a function or a template.
    $output = '';
    if (isset($info['function'])) {
      if (function_exists($info['function'])) {
        // Theme functions do not render via the theme engine, so the output is
        // not autoescaped. However, we can only presume that the theme function
        // has been written correctly and that the markup is safe.
        $output = Markup::create($info['function']($variables));
      }
    }
    else {
      $render_function = 'twig_render_template';

Disclaimer: You need to determine case by case whether doing this in preprocess is the correct solution. This answer only describes a technical possibility.

10
  • Which HOOK in mymodule_preprocess_HOOK?
    – leymannx
    Jun 7, 2021 at 12:18
  • 1
    @leymannx For whichever theme hook you want to target. This is a generic answer that addresses the title of the question. The more specific question is better solved by setting the block visibility condition as suggested by Berdir. Also it seems the question author already had a specific preprocess function in mind.
    – donquixote
    Jun 7, 2021 at 13:53
  • 1
    We are currently using this trick with hook_preprocess_field(), hook_preprocess_layout() and hook_preprocess_paragraph(), to prevent rendering of empty wrappers.
    – donquixote
    Jun 7, 2021 at 13:55
  • I see, thanks for clarifying. 👍
    – leymannx
    Jun 7, 2021 at 18:10
  • 1
    FYI this trick doesn't work anymore since Drupal 9.4 because of these 2 changes: drupal.org/i/2760659 drupal.org/i/3097889 Aug 8, 2023 at 18:50
0

+1 from me for the answer from @Berdir.

If you really need to do this in preprocess, this depends, for which template the preprocess is:

In page you can remove a block from a region:

unset($variables['page']['myregion']['mytheme_myblock']);

In block template you can remove the content and if necessary the label to prevent any further rendering.

$variables['content'] = [];
$variables['label'] = [];

There should be similar solutions at any point in preprocess.

0

If the blocks are in a view, you can use Hide block if the view output is empty' = Yes & then set $view->result = []; in hook_views_post_render().

You can use nest other blocks in the views header to get this ability for the inner block too.

Example & detailed code:

Hide a view programatically D8

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.