HTMLを含む変数をt()関数を介して渡す-!プレースホルダーは削除されました


9

Drupal 8では、!(感嘆符)t()関数を含むプレースホルダーは削除されました。

HTMLを含む変数があります。

<span class="fullname_wrapper"><span class="first_name">John</span> <span class="last_name">Hancock</span> <span class="account_name_wrapper">(@JohnH)</span></span>

このHTMLは、サイトのどこにでも表示されるように特別にスタイル設定されるので、保持しておきます。

Drupal 7では、これを行うことができました。

t('Your name is !name', array('!name' => $name));

$ nameには、上記のHTMLが含まれています。ただし、Drupal 8では、感嘆符のパススループレースホルダーが削除されているため、これは機能しません。

私はこれを試しました:

t('Your name is :name', array(':name' => $name));

しかし、HTMLはまだエスケープされています。

@マークもHTMLをエスケープします。

D8のt()関数を介してHTMLを渡す方法を知っている人はいますか?

更新:

No Sssweatのコメントによると、私の!markはt()で機能するようです。だからここに私の実際のコードがあります:

drupal_set_message(
  $this->t(
    "@amount has been transferred to !account",
    array(
      '@amount' => '¥' . $form_state->getValue('amount'),
      '!account' => $this->accountService->formatAccountName($account)
    )
  )
);

そして、私はこのエラースタックを取得します:

User error: Invalid placeholder (!account) in string: @amount has been transferred to !account in Drupal\Component\Render\FormattableMarkup::placeholderFormat() (line 235 of core/lib/Drupal/Component/Render/FormattableMarkup.php).

Drupal\Component\Render\FormattableMarkup::placeholderFormat('@amount has been transferred to !user', Array) (Line: 204)
Drupal\Core\StringTranslation\TranslatableMarkup->render() (Line: 15)
Drupal\Core\StringTranslation\TranslatableMarkup->__toString() (Line: 451)
drupal_set_message(Object) (Line: 128)

ユーザーエラーは私が考えさせたものです!マークは許可されていませんが、誤診したに違いありません。ここで何が起こっているのか誰か知っていますか?


1
D8では、Devel Execude PHPブロックでテストすると$test = "<b>test</b>"; drupal_set_message(t('Something !var just happened.', array('!var' => $test)), 'warning'); 警告メッセージが表示され、単語testは太字になりエスケープされません。したがって、!D8 ではを使用しても問題なく動作するようです。
2016年


1
元の投稿を実際のコードと表示されているエラーメッセージで更新しました。
ジェイパン2016年

1
'!account' => '<b>test</b>'テスト目的で使用してみてください。それでもエラーが発生するかどうかを確認します。原因はおそらく$this->accountService->formatAccountName($account)有効なコードではありません。また、私の上のノートのテストメッセージは、私が使用していない$this->t(
ノーSssweat

2
これは、HTMLを翻訳システムに挿入するものではありません。文字列は「@amount has been transfer to @account」です。HTMLはありません。
ジェイパン2016年

回答:


23

t()関数に渡される引数は、MarkupInterfaceを実装ない限りエスケープされるようです。そのため、名前をオブジェクトとして表す必要があります。

use Drupal\Component\Render\FormattableMarkup;

$formatted_name = new FormattableMarkup(
  '<span class="fullname-wrapper">
    <span class="first-name">@first_name</span>
    <span class="last-name">@second_name</span>
    <span class="account-name-wrapper">(@user_name)</span>
   </span>',
  [
    '@first_name' => 'John',
    '@second_name' => 'Hancock',
    '@user_name' => '@JohnH',
  ]
);

drupal_set_message(t('Your name is @name', ['@name' => $formatted_name]));

1
ありがとう、それがまさに私が必要としていたことです。それは完全に機能しました。
ジェイパン

2
そのようなt関数を使用することは悪い習慣だと思います。
Eyal 2016年

4
いいえ、それはまさにt()関数が使用されることになっている方法です(私はD5以来Drupalを使用しています)。
ジェイパン2016年

2
@Eyalなぜそれが悪い習慣だと思いますか?'@amount has been transferred to @account'プレースホルダー付きの通常の文字列である翻訳に使用されています。のt()ようには使用しません$amount . t(' has been transferred to ') . $account。それは悪い習慣です。
kiamlaluno

1
SQLインジェクション、それが!プレースホルダーはD8で削除されました
Eyal 2016年

5

はい、表示されるユーザーエラーは、使用しているプレースホルダーがから認識されないことを意味しますt()FormattableMarkup::placeholderFormat()、舞台裏で仕事をするメソッドは、@ variable%variable:variableの 3つのプレースホルダータイプだけを認識します。プレースホルダーが別の文字で始まる場合、次のコードが実行され、表示されている動作が発生します。

  default:
    // We do not trigger an error for placeholder that start with an
    // alphabetic character.
    // @todo https://www.drupal.org/node/2807743 Change to an exception
    //   and always throw regardless of the first character.
    if (!ctype_alpha($key[0])) {
      // We trigger an error as we may want to introduce new placeholders
      // in the future without breaking backward compatibility.
      trigger_error('Invalid placeholder (' . $key . ') in string: ' . $string, E_USER_ERROR);
    }
    elseif (strpos($string, $key) !== FALSE) {
      trigger_error('Invalid placeholder (' . $key . ') in string: ' . $string, E_USER_DEPRECATED);
    }
    // No replacement possible therefore we can discard the argument.
    unset($args[$key]);
    break;

@variableの説明では、変数の値は次のようになります。

あなたの場合、私は次のコードを使用します。

use Drupal\Component\Render\FormattableMarkup;

drupal_set_message(
  $this->t(
    "@amount has been transferred to @account",
    [
      '@amount' => '¥' . $form_state->getValue('amount'),
      '@account' => new FormattableMarkup($this->accountService->formatAccountName($account), [])
    ]
  )
);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.