プロジェクト

全般

プロフィール

Bug(バグ) #4168

opI18N::__() のパラメータに語形変化の設定をしたSnsTermインスタンスを渡しても反映されない

Youichi Kimura7ヶ月前に追加. 20日前に更新.

ステータス:
Pending Review(レビュー待ち)
優先度:
Normal(通常)
担当者:
対象バージョン:
開始日:
2017-02-27
期日:
進捗率:

50%

3.6 で発生するか:
Yes (はい)
3.8 で発生するか:
Yes (はい)

説明

Overview (概要)

SnsTerm の 複雑な使用例 に記載されている下記のようなコードが正しく動作せず、語形変化が適用されていない「friend」のまま出力される。

<?php echo __('%friend% are removed.', array('%friend%' => $op_term['friend']->pluralize()->fronting())); ?>

この問題は #1759 における 9b2f55d8 の修正以降から発生している。

これにより、opDiaryPlugin の日記作成画面を英語で表示した際に「My Friends」と表示されるべき箇所が「my friend」と表示される状態になっている。

Causes (原因)

前提として、SnsTerm は以下のような性質を持っている。

  1. SnsTerm インスタンスに設定した語形変化は SnsTerm::__toString() が呼ばれると初期状態に戻る
    • $term = Doctrine_Core::getTable('SnsTerm')->get('my_friend');
      $term->titleize();
      
      var_dump((string)$term); // "My Friend" 
      var_dump((string)$term); // "my friend" 
      
  2. SnsTerm インスタンスは SnsTermTable クラス内でキャッシュされる
    • $term = Doctrine_Core::getTable('SnsTerm')->get('my_friend');
      $term->titleize();
      
      // $term と同一のインスタンスが返る
      $term2 = Doctrine_Core::getTable('SnsTerm')->get('my_friend');
      var_dump((string)$term2); // "My Friend" 
      

それを踏まえて、opI18N::__() メソッドの動作を追うと以下のようになる。

  // 以下のように呼ばれる。期待する出力は「Friends are removed.」
  echo __('%friend% are removed.', array('%friend%' => $op_term['friend']->pluralize()->fronting()));

....

  // lib/i18n/opI18N.class.php
  public function __($string, $args = array(), $catalogue = 'messages')
  {
    if (empty($this->parsed[$string])) // 初回の呼び出しでは true になる
    {
      $this->parsed[$string] = array();

      $matches = array();
      preg_match_all('/%([a-zA-Z_]+)%/', $string, $matches); // 「%friend%」がヒットする

      array_shift($matches);

      foreach ($matches as $match)
      {
        foreach ($match as $v)
        {
          if ($this->terms[$v])
          {
            $term = $this->terms[$v]; // 性質 2 より、語形変化が適用されたままのインスタンスが返る
            if ($this->titleize) // デフォルトで false
            {
              $term = $term->titleize();
            }

            $this->parsed[$string]['%'.$v.'%'] = (string)$term; // ここで返るのは「Friends」
          }
        }
      }
    }

    $parsedString = $this->parsed[$string];
    if (is_array($args))
    {
      foreach ($args as $k => $v)
      {
        if ($v instanceof SnsTerm)
        {
          $args[$k] = (string)$v; // 性質 1 より、ここで返るのは「friend」
        }
      }
      $parsedString = array_merge($parsedString, $args); // 「Friends」が「friend」に上書きされる
    }

    // 「friend are removed.」が出力される (不具合)
    return parent::__($string, $parsedString, $catalogue);
  }

Way to fix (修正内容)

#1759 の修正を一旦取り消し、上記のような SnsTerm の不具合が生じないように #1759 の修正を再度行う。

スクリーンショット_2017-02-27_18.00.07.png 表示 (31.7 KB) Youichi Kimura, 2017-02-27 18:01


関連するチケット

関連している OpenPNE 3 - Bug(バグ) #1759: occurs "warning" when second argument of the __() i18n translation method is non-array (i18nの翻訳メソッド__の第二引数に配列以外を渡した場合に warning が発生する) Fixed(完了) 2010-11-08

履歴

#1 Youichi Kimura7ヶ月前に更新

  • 説明 を更新 (diff)

#2 Youichi Kimura7ヶ月前に更新

  • 関連している Bug(バグ) #1759: occurs "warning" when second argument of the __() i18n translation method is non-array (i18nの翻訳メソッド__の第二引数に配列以外を渡した場合に warning が発生する) を追加

#3 Youichi Kimura7ヶ月前に更新

  • 説明 を更新 (diff)
  • ステータスNew(新規) から Accepted(着手) に変更
  • 担当者Youichi Kimura にセット

#4 Youichi Kimura7ヶ月前に更新

  • ステータスAccepted(着手) から Pending Review(レビュー待ち) に変更
  • 進捗率0 から 50 に変更

下記 Pull Request にて修正しました
https://github.com/openpne/OpenPNE3/pull/451

#5 kaoru nishizoe6ヶ月前に更新

  • ステータスPending Review(レビュー待ち) から Rejected(差し戻し) に変更
  • 対象バージョンOpenPNE 3.9.0-old から OpenPNE 3.9.0 に変更

対象バージョン変更により修正内容の確認が必要であるため差し戻します。

#6 Youichi Kimura20日前に更新

  • ステータスRejected(差し戻し) から Pending Review(レビュー待ち) に変更

Pull Request の内容について old-master から master ブランチに rebase しました
https://github.com/openpne/OpenPNE3/pull/451

他の形式にエクスポート: Atom PDF