web-dev-qa-db-fra.com

Comment modifier un lien d'élément de langue?

Je cherche à modifier la sortie par défaut de Drupal 8 liens dans une certaine situation, le sélecteur de langue. Idéalement, je veux pouvoir le faire dans un modèle twig et ne pas avoir à produire un fichier php massif qui écrase toute la génération de liens système et ajouter un GRAND si pour les cas je dois écraser.

Je pense que la disposition de sortie devrait être contrôlable dans le modèle twig similaire à cette réponse (cette réponse génère la même URL pour toutes les langues)

J'utilise bootstrap comme thème de base, donc j'aimerais utiliser le balisage bootstrap pour mes liens (btn btn-primary, dropdown)

Voici mon code que j'essaye de faire links--language-block.html.twig

{%- if links|length == 2 -%}
    {# show only alternate language button #}
    {%- for key, item in links -%}
        {%- if not item.attributes['#options']['set_active_class'] -%} {# <--- this is always true!? #}
            <a href="{{ item.link['#url'] }}" class="btn btn-primary">{{ item.link['#title'] }}</a> {# #url is always the same what ever the language it is pointing to! #}
        {%- endif -%}
    {%- endfor -%}
{%- elseif links|length > 2  -%}
    {# show selected language in button and other languages in drop down #}
    <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{{ selectedLanguage }}<span class="caret"></span></button>
    <ul class="dropdown-menu">
        {% for key, item in links %}
            {%- if not item.attributes['#options']['set_active_class'] -%} {# <--- this is always true!? #}
            <li><a href="{{ item.link['#url'] }}">{{ item.link['#title'] }}</a></li>
            {% endif %}
        {% endfor %}
    </ul>
{%- endif -%}

Quelqu'un a une idée sur la façon de procéder?

7
Guillaume Bois

Ok, j'ai trouvé 2 façons de le faire.

1. Dans un thème personnalisé

Vous pouvez modifier des variables dans votre fichier my_theme.theme. Vous devez déterminer le nom de la fonction dont vous avez besoin. ex: my_theme_preprocess_twig_file(), dans mon cas, j'avais besoin de my_theme_preprocess_links__language_block() Vous devez prendre le nom de fichier twig et remplacer tous les - pour _.

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. Dans un module personnalisé

Vous pouvez également créer un module qui modifiera ces mêmes variables. Il y a une grande différence dans les valeurs des variables car ce prétraitement s'est produit plus tôt dans le flux. Le nom de la fonction est également très différent, ex: my_module_api_to_modify_alter(). Dans mon cas, j'avais besoin de modifier le language_switch_links À partir du language.api.php. Vous pouvez trouver toutes les fonctions alter en recherchant les fichiers *.api.php Dans drupal 8. Ceux-ci sont là comme référence pour cela exactement.

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];
  }
}

Et mon Twig modèle pour les deux cas l inks--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 %}
13
Guillaume Bois

J'ai fait cette adaptation du sélecteur de langue de sorte que lorsqu'il trouve un nœud avec un article de type, et ce n'est pas une traduction dans une langue différente, cela changerait le lien pour être la page d'accueil.

Cela devait être fait dans un module plutôt que dans le thème.

J'en avais besoin car j'avais une énorme différence dans le nombre d'articles traduits par langue.

function HOOK_language_switch_links_alter(array &$links, $type, \Drupal\Core\Url $url){
$currentLanguageCode = \Drupal::languageManager()
->getCurrentLanguage()
->getId();
// look at all links.
foreach ($links as $link) {
  // Only work on links that are not in the current page language.
  $lang_id = $link['language']->get('id');
  if ($currentLanguageCode != $lang_id) {
    // Trying to get the node.
    $node = \Drupal::request()->attributes->get('node');
    // Making sure its an object and has the method getType and is Article.
    if (!empty((object) $node) 
      && method_exists($node, 'getType')
      && $node->getType() == 'article') {
      //  We know its an article, checking for languages.
      $flipped = array_flip(array_keys($node->getTranslationLanguages()));
      // Using flipped array rather than in_array
      if (!isset($flipped[$lang_id])) {
        // Translation not available.
        $links[$lang_id]['url'] = Url::fromRoute('<front>');
      }
    }
  }
 }
}

N'oubliez pas d'ajouter l'instruction use pour Drupal\Core\Url et de la supprimer des arguments de la fonction, elle est également utilisée pour la nouvelle génération de route.

Notez également que vous devez utiliser un nouvel objet Url généré pour modifier l'url, il n'y a pas de méthode définie pour l'url existante ('<current>') pour la changer.

1
Andrew Killen