Wie ändere ich einen Link für Sprachelemente?

7

Ich möchte die Standardausgabe von Drupal 8 von Links in einer bestimmten Situation, dem Sprachumschalter, ändern. Idealerweise möchte ich dies in einer Zweigvorlage tun können und muss keine massive PHP-Datei erstellen, die das gesamte Link-Generierungssystem überschreibt, und eine GROSSE hinzufügen, wenn ich sie überschreiben muss.

Ich denke, das Ausgabelayout sollte in der Zweigvorlage ähnlich wie bei dieser Antwort steuerbar sein (diese Antwort gibt für jede Sprache dieselbe URL aus).

Ich verwende Bootstrap als Basisthema, daher möchte ich das Bootstrap-Markup für meine Links verwenden (btn btn-primary, Dropdown).

Hier ist mein Code, den ich machen möchte 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 -%}

Hat jemand eine Idee, wie das geht?

Guillaume Bois
quelle

Antworten:

13

Ok, ich habe zwei Möglichkeiten gefunden, das zu tun.

1. In einem benutzerdefinierten Thema

Sie können Variablen in Ihrer my_theme.themeDatei ändern . Sie müssen den Namen der Funktion herausfinden, die Sie benötigen. Beispiel: my_theme_preprocess_twig_file()In meinem Fall brauchte ich. my_theme_preprocess_links__language_block()Sie müssen den Namen der Zweigdatei nehmen und alle -für ersetzen _.

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 einem benutzerdefinierten Modul

Sie können auch ein Modul erstellen, das dieselben Variablen ändert. Es gibt einen großen Unterschied in den Werten der Variablen, da dieser Vorprozess früher im Ablauf stattgefunden hat. Der Name der Funktion ist auch ganz anders, zB : my_module_api_to_modify_alter(). In meinem Fall musste ich das language_switch_linksaus dem ändern language.api.php. Sie können alle Änderungsfunktionen finden, indem Sie *.api.phpin Drupal 8 nach Dateien suchen. Diese dienen als Referenz für genau das.

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

Und meine Zweigvorlage für beide Fälle 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 %}
Guillaume Bois
quelle
1

Ich habe diese Anpassung als Sprachumschalter vorgenommen, damit beim Ändern eines Knotens mit Typ Artikel und dies keine Übersetzung in einer anderen Sprache ist, der Link in die Startseite geändert wird.

Dies musste in einem Modul und nicht im Thema erfolgen.

Ich brauchte das, da ich einen großen Unterschied in der Anzahl der übersetzten Artikel pro Sprache hatte.

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>');
      }
    }
  }
 }
}

Vergessen Sie nicht, die use-Anweisung für Drupal \ Core \ Url hinzuzufügen und aus den Funktionsargumenten zu entfernen, die auch für die neue Routengenerierung verwendet werden.

Beachten Sie auch, dass Sie ein neu generiertes URL-Objekt verwenden müssen, um die URL zu ändern. Es gibt keine festgelegte Methode für die vorhandene URL ('<current>'), um sie zu ändern.

Andrew Killen
quelle