web-dev-qa-db-ja.com

言語アイテムのリンクを変更するにはどうすればよいですか?

特定の状況での言語スイッチャーであるリンクのDrupal 8のデフォルト出力を変更しようとしています。理想的には、twigテンプレートでそれを実行できるようにし、リンク生成全体を上書きする 大規模なphpファイル を生成する必要がないようにしますシステムと上書きする必要がある場合のためにBIGを追加します。

出力レイアウトはtwigテンプレートで this answer (この回答はすべての言語で同じURLを出力します)と同様に制御可能である必要があると思います

bootstrapを基本テーマとして使用しているので、リンクにbootstrapマークアップを使用したい(btn btn-primary、ドロップダウン)

これが私が作ろうとしている私のコードです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 -%}

誰でもこれを行う方法についてアイデアがありますか?

7
Guillaume Bois

わかりました2つの方法を見つけました。

1.カスタムテーマ

_my_theme.theme_ファイルの変数を変更できます。必要な関数の名前を理解する必要があります。例:my_theme_preprocess_twig_file()、私の場合、私はmy_theme_preprocess_links__language_block()を必要としましたtwigファイル名を受け取り、すべての_-_を___。

_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.カスタムモジュール

同じ変数を変更するモジュールを作成することもできます。この前処理はフローの早い段階で行われたため、変数の値には大きな違いがあります。関数の名前もまったく異なります(例:my_module_api_to_modify_alter())。私の場合、_language_switch_links_から_language.api.php_を変更する必要がありました。 drupal 8で_*.api.php_ファイルを検索すると、すべての変更機能を見つけることができます。これらは、正確に参照するためのものです。

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

そして、私のTwig両方の場合のテンプレート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

この適応を言語スイッチャーにしたので、articleタイプのノードが見つかり、これが別の言語の翻訳ではなく、リンクがホームページになるように変更されました。

これは、テーマではなくモジュールで作成する必要がありました。

言語ごとに翻訳された記事の数に大きな違いがあったので、これが必要でした。

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

Drupal\Core\Urlのuseステートメントを追加して関数の引数から削除することを忘れないでください。これは新しいルートの生成にも使用されます。

また、URLを変更するには、新しく生成されたUrlオブジェクトを使用する必要があることに注意してください。既存のURL( '<current>')を変更するためのsetメソッドはありません。

1
Andrew Killen