diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteController.php index 19aec98a38..92ad83a0e6 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteController.php @@ -1,22 +1,70 @@ <?php /** * @group slowvote */ abstract class PhabricatorSlowvoteController extends PhabricatorController { + const VIEW_ALL = 'all'; + const VIEW_CREATED = 'created'; + const VIEW_VOTED = 'voted'; + public function buildStandardPageResponse($view, array $data) { $page = $this->buildStandardPageView(); - $page->setApplicationName('Slowvote'); + $page->setApplicationName(pht('Slowvote')); $page->setBaseURI('/vote/'); $page->setTitle(idx($data, 'title')); $page->setGlyph("\xE2\x9C\x94"); $page->appendChild($view); $response = new AphrontWebpageResponse(); return $response->setContent($page->render()); } + public function buildSideNavView($filter = null, $for_app = false) { + + $views = $this->getViews(); + $side_nav = new AphrontSideNavFilterView(); + $side_nav->setBaseURI(new PhutilURI('/vote/view/')); + foreach ($views as $key => $name) { + $side_nav->addFilter($key, $name); + } + if ($filter) { + $side_nav->selectFilter($filter, null); + } + + if ($for_app) { + $side_nav->addFilter('', pht('Create Question'), + $this->getApplicationURI('create/')); + } + + return $side_nav; + } + + public function buildApplicationMenu() { + return $this->buildSideNavView(null, true)->getMenu(); + } + + public function buildApplicationCrumbs() { + $crumbs = parent::buildApplicationCrumbs(); + + $crumbs->addAction( + id(new PhabricatorMenuItemView()) + ->setName(pht('Create Question')) + ->setHref($this->getApplicationURI('create/')) + ->setIcon('create')); + + return $crumbs; + } + + public function getViews() { + return array( + self::VIEW_ALL => pht('All Slowvotes'), + self::VIEW_CREATED => pht('Created'), + self::VIEW_VOTED => pht('Voted In'), + ); + } + } diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteCreateController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteCreateController.php index 9ffa72245f..6fdcf71539 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteCreateController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteCreateController.php @@ -1,147 +1,167 @@ <?php /** * @group slowvote */ final class PhabricatorSlowvoteCreateController extends PhabricatorSlowvoteController { public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $poll = new PhabricatorSlowvotePoll(); $poll->setAuthorPHID($user->getPHID()); $e_question = true; $e_response = true; $errors = array(); $responses = $request->getArr('response'); if ($request->isFormPost()) { $poll->setQuestion($request->getStr('question')); $poll->setResponseVisibility($request->getInt('response_visibility')); $poll->setShuffle((int)$request->getBool('shuffle', false)); $poll->setMethod($request->getInt('method')); if (!strlen($poll->getQuestion())) { - $e_question = 'Required'; - $errors[] = 'You must ask a poll question.'; + $e_question = pht('Required'); + $errors[] = pht('You must ask a poll question.'); } else { $e_question = null; } $responses = array_filter($responses); if (empty($responses)) { - $errors[] = 'You must offer at least one response.'; - $e_response = 'Required'; + $errors[] = pht('You must offer at least one response.'); + $e_response = pht('Required'); } else { $e_response = null; } if (empty($errors)) { $poll->save(); foreach ($responses as $response) { $option = new PhabricatorSlowvoteOption(); $option->setName($response); $option->setPollID($poll->getID()); $option->save(); } return id(new AphrontRedirectResponse()) ->setURI('/V'.$poll->getID()); } } $error_view = null; if ($errors) { $error_view = new AphrontErrorView(); - $error_view->setTitle('Form Errors'); + $error_view->setTitle(pht('Form Errors')); $error_view->setErrors($errors); } + $instructions = + phutil_tag( + 'p', + array( + 'class' => 'aphront-form-instructions', + ), + pht('Resolve issues and build consensus through '. + 'protracted deliberation.') + ); + $form = id(new AphrontFormView()) ->setUser($user) - ->appendChild(hsprintf( - '<p class="aphront-form-instructions">Resolve issues and build '. - 'consensus through protracted deliberation.</p>')) + ->appendChild($instructions) ->appendChild( id(new AphrontFormTextControl()) - ->setLabel('Question') + ->setLabel(pht('Question')) ->setName('question') ->setValue($poll->getQuestion()) ->setError($e_question)); for ($ii = 0; $ii < 10; $ii++) { $n = ($ii + 1); $response = id(new AphrontFormTextControl()) - ->setLabel("Response {$n}") + ->setLabel(pht("Response %d", $n)) ->setName('response[]') ->setValue(idx($responses, $ii, '')); if ($ii == 0) { $response->setError($e_response); } $form->appendChild($response); } $poll_type_options = array( - PhabricatorSlowvotePoll::METHOD_PLURALITY => 'Plurality (Single Choice)', - PhabricatorSlowvotePoll::METHOD_APPROVAL => 'Approval (Multiple Choice)', + PhabricatorSlowvotePoll::METHOD_PLURALITY => + pht('Plurality (Single Choice)'), + PhabricatorSlowvotePoll::METHOD_APPROVAL => + pht('Approval (Multiple Choice)'), ); $response_type_options = array( PhabricatorSlowvotePoll::RESPONSES_VISIBLE - => 'Allow anyone to see the responses', + => pht('Allow anyone to see the responses'), PhabricatorSlowvotePoll::RESPONSES_VOTERS - => 'Require a vote to see the responses', + => pht('Require a vote to see the responses'), PhabricatorSlowvotePoll::RESPONSES_OWNER - => 'Only I can see the responses', + => pht('Only I can see the responses'), ); $form ->appendChild( id(new AphrontFormSelectControl()) - ->setLabel('Vote Type') + ->setLabel(pht('Vote Type')) ->setName('method') ->setValue($poll->getMethod()) ->setOptions($poll_type_options)) ->appendChild( id(new AphrontFormSelectControl()) - ->setLabel('Responses') + ->setLabel(pht('Responses')) ->setName('response_visibility') ->setValue($poll->getResponseVisibility()) ->setOptions($response_type_options)) ->appendChild( id(new AphrontFormCheckboxControl()) - ->setLabel('Shuffle') + ->setLabel(pht('Shuffle')) ->addCheckbox( 'shuffle', 1, - 'Show choices in random order', + pht('Show choices in random order'), $poll->getShuffle())) ->appendChild( id(new AphrontFormSubmitControl()) - ->setValue('Create Slowvote') + ->setValue(pht('Create Slowvote')) ->addCancelButton('/vote/')); $panel = new AphrontPanelView(); $panel->setWidth(AphrontPanelView::WIDTH_FORM); - $panel->setHeader('Create Slowvote'); + $panel->setHeader(pht('Create Slowvote')); + $panel->setNoBackground(); $panel->appendChild($form); - return $this->buildStandardPageResponse( + $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('Create Slowvote')) + ->setHref($this->getApplicationURI().'create/') + ); + + return $this->buildApplicationPage( array( + $crumbs, $error_view, $panel, ), array( - 'title' => 'Create Slowvote', + 'title' => pht('Create Slowvote'), + 'device' => true, )); } } diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteListController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteListController.php index 19f16e9332..a2157bf268 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteListController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteListController.php @@ -1,167 +1,158 @@ <?php /** * @group slowvote */ final class PhabricatorSlowvoteListController extends PhabricatorSlowvoteController { private $view; - const VIEW_ALL = 'all'; - const VIEW_CREATED = 'created'; - const VIEW_VOTED = 'voted'; - public function willProcessRequest(array $data) { - $this->view = idx($data, 'view'); + $this->view = idx($data, 'view', parent::VIEW_ALL); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); - $views = array( - self::VIEW_ALL => 'All Slowvotes', - self::VIEW_CREATED => 'Created', - self::VIEW_VOTED => 'Voted In', - ); - - $view = isset($views[$this->view]) - ? $this->view - : self::VIEW_ALL; + $view = $this->view; + $views = $this->getViews(); - $side_nav = $this->renderSideNav($views, $view); + $side_nav = $this->buildSideNavView($view); $pager = new AphrontPagerView(); $pager->setOffset($request->getInt('page')); $pager->setURI($request->getRequestURI(), 'page'); $polls = $this->loadPolls($pager, $view); $phids = mpull($polls, 'getAuthorPHID'); $handles = $this->loadViewerHandles($phids); $rows = array(); foreach ($polls as $poll) { $rows[] = array( 'V'.$poll->getID(), phutil_tag( 'a', array( 'href' => '/V'.$poll->getID(), ), $poll->getQuestion()), $handles[$poll->getAuthorPHID()]->renderLink(), phabricator_date($poll->getDateCreated(), $user), phabricator_time($poll->getDateCreated(), $user), ); } $table = new AphrontTableView($rows); $table->setColumnClasses( array( '', 'pri wide', '', '', 'right', )); $table->setHeaders( array( - 'ID', - 'Poll', - 'Author', - 'Date', - 'Time', + pht('ID'), + pht('Poll'), + pht('Author'), + pht('Date'), + pht('Time'), )); + switch ($view) { + case self::VIEW_ALL: + $table_header = + pht('Slowvotes Not Yet Consumed by the Ravages of Time'); + break; + case self::VIEW_CREATED: + $table_header = + pht('Slowvotes Birthed from Your Noblest of Great Minds'); + break; + case self::VIEW_VOTED: + $table_header = + pht('Slowvotes Within Which You Express Your Mighty Opinion'); + break; + } + $panel = new AphrontPanelView(); - $panel->setHeader($this->getTableHeader($view)); - $panel->setCreateButton('Create Slowvote', '/vote/create/'); + $panel->setHeader($table_header); + $panel->setNoBackground(); $panel->appendChild($table); $panel->appendChild($pager); $side_nav->appendChild($panel); - return $this->buildStandardPageResponse( + $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName($views[$view]) + ->setHref($this->getApplicationURI()) + ); + $side_nav->setCrumbs($crumbs); + + return $this->buildApplicationPage( $side_nav, array( - 'title' => 'Slowvotes', + 'title' => pht('Slowvotes'), + 'device' => true, )); } private function loadPolls(AphrontPagerView $pager, $view) { $request = $this->getRequest(); $user = $request->getUser(); $poll = new PhabricatorSlowvotePoll(); $conn = $poll->establishConnection('r'); $offset = $pager->getOffset(); $limit = $pager->getPageSize() + 1; switch ($view) { case self::VIEW_ALL: $data = queryfx_all( $conn, 'SELECT * FROM %T ORDER BY id DESC LIMIT %d, %d', $poll->getTableName(), $offset, $limit); break; case self::VIEW_CREATED: $data = queryfx_all( $conn, 'SELECT * FROM %T WHERE authorPHID = %s ORDER BY id DESC LIMIT %d, %d', $poll->getTableName(), $user->getPHID(), $offset, $limit); break; case self::VIEW_VOTED: $choice = new PhabricatorSlowvoteChoice(); $data = queryfx_all( $conn, 'SELECT p.* FROM %T p JOIN %T o ON o.pollID = p.id WHERE o.authorPHID = %s GROUP BY p.id ORDER BY p.id DESC LIMIT %d, %d', $poll->getTableName(), $choice->getTableName(), $user->getPHID(), $offset, $limit); break; } $data = $pager->sliceResults($data); return $poll->loadAllFromArray($data); } - private function renderSideNav(array $views, $view) { - $side_nav = new AphrontSideNavFilterView(); - $side_nav->setBaseURI(new PhutilURI('/vote/view/')); - foreach ($views as $key => $name) { - $side_nav->addFilter($key, $name); - } - $side_nav->selectFilter($view, null); - return $side_nav; - } - - private function getTableHeader($view) { - static $headers = array( - self::VIEW_ALL - => 'Slowvotes Not Yet Consumed by the Ravages of Time', - self::VIEW_CREATED - => 'Slowvotes Birthed from Your Noblest of Great Minds', - self::VIEW_VOTED - => 'Slowvotes Within Which You Express Your Mighty Opinion', - ); - return idx($headers, $view); - } - } diff --git a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php index 5c39fda9d1..8a519a1e97 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php @@ -1,458 +1,459 @@ <?php /** * @group slowvote */ final class PhabricatorSlowvotePollController extends PhabricatorSlowvoteController { private $id; public function willProcessRequest(array $data) { $this->id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $viewer_phid = $user->getPHID(); $poll = id(new PhabricatorSlowvotePoll())->load($this->id); if (!$poll) { return new Aphront404Response(); } $options = id(new PhabricatorSlowvoteOption())->loadAllWhere( 'pollID = %d', $poll->getID()); $choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere( 'pollID = %d', $poll->getID()); $comments = id(new PhabricatorSlowvoteComment())->loadAllWhere( 'pollID = %d', $poll->getID()); $choices_by_option = mgroup($choices, 'getOptionID'); $comments_by_user = mpull($comments, null, 'getAuthorPHID'); $choices_by_user = mgroup($choices, 'getAuthorPHID'); $viewer_choices = idx($choices_by_user, $viewer_phid, array()); $viewer_comment = idx($comments_by_user, $viewer_phid, null); $comment_text = null; if ($viewer_comment) { $comment_text = $viewer_comment->getCommentText(); } if ($request->isFormPost()) { $comment = idx($comments_by_user, $viewer_phid, null); if ($comment) { $comment->delete(); } $comment_text = $request->getStr('comments'); if (strlen($comment_text)) { id(new PhabricatorSlowvoteComment()) ->setAuthorPHID($viewer_phid) ->setPollID($poll->getID()) ->setCommentText($comment_text) ->save(); } $votes = $request->getArr('vote'); switch ($poll->getMethod()) { case PhabricatorSlowvotePoll::METHOD_PLURALITY: // Enforce only one vote. $votes = array_slice($votes, 0, 1); break; case PhabricatorSlowvotePoll::METHOD_APPROVAL: // No filtering. break; default: throw new Exception("Unknown poll method!"); } foreach ($viewer_choices as $viewer_choice) { $viewer_choice->delete(); } foreach ($votes as $vote) { id(new PhabricatorSlowvoteChoice()) ->setAuthorPHID($viewer_phid) ->setPollID($poll->getID()) ->setOptionID($vote) ->save(); } return id(new AphrontRedirectResponse())->setURI('/V'.$poll->getID()); } require_celerity_resource('phabricator-slowvote-css'); $phids = array_merge( mpull($choices, 'getAuthorPHID'), mpull($comments, 'getAuthorPHID'), array( $poll->getAuthorPHID(), )); $query = new PhabricatorObjectHandleData($phids); $handles = $query->loadHandles(); $objects = $query->loadObjects(); if ($poll->getShuffle()) { shuffle($options); } $option_markup = array(); foreach ($options as $option) { $option_markup[] = $this->renderPollOption( $poll, $viewer_choices, $option); } $comments_by_option = array(); switch ($poll->getMethod()) { case PhabricatorSlowvotePoll::METHOD_PLURALITY: $choice_ids = array(); foreach ($choices_by_user as $user_phid => $user_choices) { $choice_ids[$user_phid] = head($user_choices)->getOptionID(); } foreach ($comments as $comment) { $choice = idx($choice_ids, $comment->getAuthorPHID()); if ($choice) { $comments_by_option[$choice][] = $comment; } } break; case PhabricatorSlowvotePoll::METHOD_APPROVAL: // All comments are grouped in approval voting. break; default: throw new Exception("Unknown poll method!"); } $result_markup = $this->renderResultMarkup( $poll, $options, $choices, $comments, $viewer_choices, $choices_by_option, $comments_by_option, $handles, $objects); if ($viewer_choices) { $instructions = - 'Your vote has been recorded... but there is still ample time to '. + pht('Your vote has been recorded... but there is still ample time to '. 'rethink your position. Have you thoroughly considered all possible '. - 'eventualities?'; + 'eventualities?'); } else { $instructions = - 'This is a weighty matter indeed. Consider your choices with the '. - 'greatest of care.'; + pht('This is a weighty matter indeed. Consider your choices with the '. + 'greatest of care.'); } $form = id(new AphrontFormView()) ->setUser($user) ->appendChild(hsprintf( '<p class="aphront-form-instructions">%s</p>', $instructions)) ->appendChild( id(new AphrontFormMarkupControl()) - ->setLabel('Vote') + ->setLabel(pht('Vote')) ->setValue($option_markup)) ->appendChild( id(new AphrontFormTextAreaControl()) - ->setLabel('Comments') + ->setLabel(pht('Comments')) ->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT) ->setName('comments') ->setValue($comment_text)) ->appendChild( id(new AphrontFormSubmitControl()) - ->setValue('Cautiously Engage in Deliberations')); + ->setValue(pht('Engage in Deliberations'))); $panel = new AphrontPanelView(); $panel->setHeader($poll->getQuestion()); $panel->setWidth(AphrontPanelView::WIDTH_WIDE); - + $panel->setNoBackground(); $panel->appendChild($form); $panel->appendChild(hsprintf('<br /><br />')); $panel->appendChild($result_markup); - return $this->buildStandardPageResponse( + return $this->buildApplicationPage( $panel, array( 'title' => 'V'.$poll->getID().' '.$poll->getQuestion(), + 'device' => true, )); } private function renderComments(array $comments, array $handles) { assert_instances_of($comments, 'PhabricatorSlowvoteComment'); assert_instances_of($handles, 'PhabricatorObjectHandle'); $viewer = $this->getRequest()->getUser(); $engine = PhabricatorMarkupEngine::newSlowvoteMarkupEngine(); $comment_markup = array(); foreach ($comments as $comment) { $handle = $handles[$comment->getAuthorPHID()]; $markup = $engine->markupText($comment->getCommentText()); require_celerity_resource('phabricator-remarkup-css'); $comment_markup[] = hsprintf( '<tr>'. '<th>'. '%s'. '<div class="phabricator-slowvote-datestamp">%s</div>'. '</th>'. '<td>'. '<div class="phabricator-remarkup">%s</div>'. '</td>'. '</tr>', $handle->renderLink(), phabricator_datetime($comment->getDateCreated(), $viewer), $markup); } if ($comment_markup) { $comment_markup = phutil_tag( 'table', array( 'class' => 'phabricator-slowvote-comments', ), $comment_markup); } else { $comment_markup = null; } return $comment_markup; } private function renderPollOption( PhabricatorSlowvotePoll $poll, array $viewer_choices, PhabricatorSlowvoteOption $option) { assert_instances_of($viewer_choices, 'PhabricatorSlowvoteChoice'); $id = $option->getID(); switch ($poll->getMethod()) { case PhabricatorSlowvotePoll::METHOD_PLURALITY: // Render a radio button. $selected_option = head($viewer_choices); if ($selected_option) { $selected = $selected_option->getOptionID(); } else { $selected = null; } if ($selected == $id) { $checked = "checked"; } else { $checked = null; } $input = phutil_tag( 'input', array( 'type' => 'radio', 'name' => 'vote[]', 'value' => $id, 'checked' => $checked, )); break; case PhabricatorSlowvotePoll::METHOD_APPROVAL: // Render a check box. $checked = null; foreach ($viewer_choices as $choice) { if ($choice->getOptionID() == $id) { $checked = 'checked'; break; } } $input = phutil_tag( 'input', array( 'type' => 'checkbox', 'name' => 'vote[]', 'checked' => $checked, 'value' => $id, )); break; default: throw new Exception("Unknown poll method!"); } if ($checked) { $checked_class = 'phabricator-slowvote-checked'; } else { $checked_class = null; } return phutil_tag( 'label', array( 'class' => 'phabricator-slowvote-label '.$checked_class, ), array($input, $option->getName())); } private function renderVoteCount( PhabricatorSlowvotePoll $poll, array $choices, array $chosen) { assert_instances_of($choices, 'PhabricatorSlowvoteChoice'); assert_instances_of($chosen, 'PhabricatorSlowvoteChoice'); switch ($poll->getMethod()) { case PhabricatorSlowvotePoll::METHOD_PLURALITY: $out_of_total = count($choices); break; case PhabricatorSlowvotePoll::METHOD_APPROVAL: // Count unique respondents for approval votes. $out_of_total = count(mpull($choices, null, 'getAuthorPHID')); break; default: throw new Exception("Unknown poll method!"); } return sprintf( '%d / %d (%d%%)', number_format(count($chosen)), number_format($out_of_total), $out_of_total ? round(100 * count($chosen) / $out_of_total) : 0); } private function renderResultMarkup( PhabricatorSlowvotePoll $poll, array $options, array $choices, array $comments, array $viewer_choices, array $choices_by_option, array $comments_by_option, array $handles, array $objects) { assert_instances_of($options, 'PhabricatorSlowvoteOption'); assert_instances_of($choices, 'PhabricatorSlowvoteChoice'); assert_instances_of($comments, 'PhabricatorSlowvoteComment'); assert_instances_of($viewer_choices, 'PhabricatorSlowvoteChoice'); assert_instances_of($handles, 'PhabricatorObjectHandle'); assert_instances_of($objects, 'PhabricatorLiskDAO'); $viewer_phid = $this->getRequest()->getUser()->getPHID(); $can_see_responses = false; $need_vote = false; switch ($poll->getResponseVisibility()) { case PhabricatorSlowvotePoll::RESPONSES_VISIBLE: $can_see_responses = true; break; case PhabricatorSlowvotePoll::RESPONSES_VOTERS: $can_see_responses = (bool)$viewer_choices; $need_vote = true; break; case PhabricatorSlowvotePoll::RESPONSES_OWNER: $can_see_responses = ($viewer_phid == $poll->getAuthorPHID()); break; } $result_markup = id(new AphrontFormLayoutView()) - ->appendChild(phutil_tag('h1', array(), 'Ongoing Deliberation')); + ->appendChild(phutil_tag('h1', array(), pht('Ongoing Deliberation'))); if (!$can_see_responses) { if ($need_vote) { - $reason = "You must vote to see the results."; + $reason = pht("You must vote to see the results."); } else { - $reason = "The results are not public."; + $reason = pht("The results are not public."); } $result_markup ->appendChild(hsprintf( '<p class="aphront-form-instructions"><em>%s</em></p>', $reason)); return $result_markup; } foreach ($options as $option) { $id = $option->getID(); $chosen = idx($choices_by_option, $id, array()); $users = array_select_keys($handles, mpull($chosen, 'getAuthorPHID')); if ($users) { $user_markup = array(); foreach ($users as $handle) { $object = idx($objects, $handle->getPHID()); if (!$object) { continue; } $profile_image = $handle->getImageURI(); $user_markup[] = phutil_tag( 'a', array( 'href' => $handle->getURI(), 'class' => 'phabricator-slowvote-facepile', ), phutil_tag( 'img', array( 'src' => $profile_image, ))); } } else { - $user_markup = 'This option has failed to appeal to anyone.'; + $user_markup = pht('This option has failed to appeal to anyone.'); } $comment_markup = $this->renderComments( idx($comments_by_option, $id, array()), $handles); $vote_count = $this->renderVoteCount( $poll, $choices, $chosen); $result_markup->appendChild(hsprintf( '<div>'. '<div class="phabricator-slowvote-count">%s</div>'. '<h1>%s</h1>'. '<hr class="phabricator-slowvote-hr" />'. '%s'. '<div style="clear: both;" />'. '<hr class="phabricator-slowvote-hr" />'. '%s'. '</div>', $vote_count, $option->getName(), phutil_tag('div', array(), $user_markup), $comment_markup)); } if ($poll->getMethod() == PhabricatorSlowvotePoll::METHOD_APPROVAL && $comments) { $comment_markup = $this->renderComments( $comments, $handles); $result_markup->appendChild( - phutil_tag('h1', array(), 'Motions Proposed for Consideration')); + phutil_tag('h1', array(), pht('Motions Proposed for Consideration'))); $result_markup->appendChild($comment_markup); } return $result_markup; } }