Drupal - How do I alter a language item link?
Ok I found 2 ways to do that.
1. In a custom theme
You can alter variables in your my_theme.theme
file. You need to figure out the name of the function you need. ex: my_theme_preprocess_twig_file()
, in my case I needed my_theme_preprocess_links__language_block()
You need to take the twig file name and replace all -
for _
.
my_theme.theme
:
function my_theme_preprocess_links__language_block(&$variables) {
$currentLanguageCode = \Drupal::languageManager()
->getCurrentLanguage()
->getId();
// replace key of active language with 'activeLink'
foreach ($variables['links'] as $i => $link) {
/** @var \Drupal\language\Entity\ConfigurableLanguage $linkLanguage */
$linkLanguage = $link['link']['#options']['language'];
if ($currentLanguageCode == $linkLanguage->get('id')) {
$variables['links']['activeLink'] = $link;
unset($variables['links'][$i]);
}
}
// if there is only 2 languages remove active one
if (sizeof($variables['links']) == 2) {
unset($variables['links']['activeLink']);
// give class 'btn btn-primary' to alternate language
/** @var \Drupal\Core\Url $alternate */
$alternate = current($variables['links']);
$alternate['link']['#options']['attributes']['class'][] = 'btn';
$alternate['link']['#options']['attributes']['class'][] = 'btn-primary';
$variables['links'] = [$alternate];
}
}
2. In a custom module
You can also create a module that will change those same variables. There is a big difference in the values of the variables because this preprocess happened earlier in the flow. The name of the function is also quite different, ex: my_module_api_to_modify_alter()
. In my case I needed to modify the language_switch_links
from the language.api.php
. You can find all alter function by searching for *.api.php
files in drupal 8. Those are there as a reference for exactly that.
my_module.module
:
function my_module_language_switch_links_alter(&$variables) {
$currentLanguageCode = \Drupal::languageManager()
->getCurrentLanguage()
->getId();
// replace key of active language with 'activeLink'
foreach ($variables as $i => $link) {
/** @var \Drupal\language\Entity\ConfigurableLanguage $linkLanguage */
$linkLanguage = $link['language'];
if ($currentLanguageCode == $linkLanguage->get('id')) {
$variables['activeLink'] = $link;
unset($variables[$i]);
}
}
// if there is only 2 languages remove active one
if (sizeof($variables) == 2) {
unset($variables['activeLink']);
// give class 'btn btn-primary' to alternate language
/** @var \Drupal\Core\Url $alternate */
$alternate = current($variables);
$alternate['attributes']['class'][] = 'btn';
$alternate['attributes']['class'][] = 'btn-primary';
$variables = [$alternate];
}
}
And my Twig template for both cases links--language-block.html.twig
:
{% if links -%}
{%- if links|length == 1 -%}
{# show only alternate language button #}
{{ (links|first).link }}
{%- else -%}
{# show selected language in button and other languages in drop down #}
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{{ links['activeLink'].text }} <span class="caret"></span></button>
<ul class="dropdown-menu">
{% for key, item in links %}
{% if key is not same as("activeLink") %}
<li>{{ item.link }}</li>
{% endif %}
{% endfor %}
</ul>
{%- endif -%}
{%- endif %}