@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Modernize Herald

Summary: Convert to responsive layout, pht, etc.

Test Plan: Test Herald on desktop and mobile.

Reviewers: epriestley, btrahan

Reviewed By: epriestley

CC: aran, Korvin

Differential Revision: https://secure.phabricator.com/D5976

+299 -281
+3 -3
src/applications/herald/adapter/HeraldCommitAdapter.php
··· 204 204 $result[] = new HeraldApplyTranscript( 205 205 $effect, 206 206 true, 207 - 'Great success at doing nothing.'); 207 + pht('Great success at doing nothing.')); 208 208 break; 209 209 case HeraldActionConfig::ACTION_EMAIL: 210 210 foreach ($effect->getTarget() as $phid) { ··· 213 213 $result[] = new HeraldApplyTranscript( 214 214 $effect, 215 215 true, 216 - 'Added address to email targets.'); 216 + pht('Added address to email targets.')); 217 217 break; 218 218 case HeraldActionConfig::ACTION_AUDIT: 219 219 foreach ($effect->getTarget() as $phid) { ··· 225 225 $result[] = new HeraldApplyTranscript( 226 226 $effect, 227 227 true, 228 - 'Triggered an audit.'); 228 + pht('Triggered an audit.')); 229 229 break; 230 230 case HeraldActionConfig::ACTION_FLAG: 231 231 $result[] = parent::applyFlagEffect(
+9 -9
src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
··· 217 217 $effect->setAction(HeraldActionConfig::ACTION_ADD_CC); 218 218 $effect->setTarget(array_keys($this->explicitCCs)); 219 219 $effect->setReason( 220 - 'CCs provided explicitly by revision author or carried over from a '. 221 - 'previous version of the revision.'); 220 + pht('CCs provided explicitly by revision author or carried over '. 221 + 'from a previous version of the revision.')); 222 222 $result[] = new HeraldApplyTranscript( 223 223 $effect, 224 224 true, 225 - 'Added addresses to CC list.'); 225 + pht('Added addresses to CC list.')); 226 226 } 227 227 228 228 $forbidden_ccs = array_fill_keys( ··· 236 236 $result[] = new HeraldApplyTranscript( 237 237 $effect, 238 238 true, 239 - 'OK, did nothing.'); 239 + pht('OK, did nothing.')); 240 240 break; 241 241 case HeraldActionConfig::ACTION_FLAG: 242 242 $result[] = parent::applyFlagEffect( ··· 269 269 $result[] = new HeraldApplyTranscript( 270 270 $effect, 271 271 true, 272 - 'Added these addresses to '.$op.' list. '. 273 - 'Others could not be added.'); 272 + pht('Added these addresses to %s list. '. 273 + 'Others could not be added.', $op)); 274 274 } 275 275 $result[] = new HeraldApplyTranscript( 276 276 $failed, 277 277 false, 278 - $op.' forbidden, these addresses have unsubscribed.'); 278 + pht('%s forbidden, these addresses have unsubscribed.', $op)); 279 279 } else { 280 280 $result[] = new HeraldApplyTranscript( 281 281 $effect, 282 282 true, 283 - 'Added addresses to '.$op.' list.'); 283 + pht('Added addresses to %s list.', $op)); 284 284 } 285 285 break; 286 286 case HeraldActionConfig::ACTION_REMOVE_CC: ··· 290 290 $result[] = new HeraldApplyTranscript( 291 291 $effect, 292 292 true, 293 - 'Removed addresses from CC list.'); 293 + pht('Removed addresses from CC list.')); 294 294 break; 295 295 default: 296 296 throw new Exception("No rules to handle action '{$action}'.");
+1 -1
src/applications/herald/adapter/HeraldDryRunAdapter.php
··· 25 25 $results[] = new HeraldApplyTranscript( 26 26 $effect, 27 27 false, 28 - 'This was a dry run, so no actions were actually taken.'); 28 + pht('This was a dry run, so no actions were actually taken.')); 29 29 } 30 30 return $results; 31 31 }
+4 -3
src/applications/herald/adapter/HeraldObjectAdapter.php
··· 22 22 return new HeraldApplyTranscript( 23 23 $effect, 24 24 false, 25 - 'Object already flagged.'); 25 + pht('Object already flagged.')); 26 26 } 27 27 28 28 $handle = PhabricatorObjectHandleData::loadOneHandle( ··· 38 38 $flag->setReasonPHID($user->getPHID()); 39 39 40 40 $flag->setColor($color); 41 - $flag->setNote('Flagged by Herald Rule "'.$rule->getName().'".'); 41 + $flag->setNote( 42 + pht('Flagged by Herald Rule "%s".', $rule->getName())); 42 43 $flag->save(); 43 44 44 45 return new HeraldApplyTranscript( 45 46 $effect, 46 47 true, 47 - 'Added flag.'); 48 + pht('Added flag.')); 48 49 } 49 50 50 51 }
+1 -1
src/applications/herald/application/PhabricatorApplicationHerald.php
··· 11 11 } 12 12 13 13 public function getShortDescription() { 14 - return 'Create Notification Rules'; 14 + return pht('Create Notification Rules'); 15 15 } 16 16 17 17 public function getTitleGlyph() {
+11 -11
src/applications/herald/config/HeraldActionConfig.php
··· 11 11 12 12 public static function getActionMessageMapForRuleType($rule_type) { 13 13 $generic_mappings = array( 14 - self::ACTION_NOTHING => 'Do nothing', 15 - self::ACTION_ADD_CC => 'Add emails to CC', 16 - self::ACTION_REMOVE_CC => 'Remove emails from CC', 17 - self::ACTION_EMAIL => 'Send an email to', 18 - self::ACTION_AUDIT => 'Trigger an Audit', 19 - self::ACTION_FLAG => 'Mark with flag', 14 + self::ACTION_NOTHING => pht('Do nothing'), 15 + self::ACTION_ADD_CC => pht('Add emails to CC'), 16 + self::ACTION_REMOVE_CC => pht('Remove emails from CC'), 17 + self::ACTION_EMAIL => pht('Send an email to'), 18 + self::ACTION_AUDIT => pht('Trigger an Audit'), 19 + self::ACTION_FLAG => pht('Mark with flag'), 20 20 ); 21 21 22 22 switch ($rule_type) { 23 23 case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 24 24 $specific_mappings = array( 25 - self::ACTION_AUDIT => 'Trigger an Audit for project', 25 + self::ACTION_AUDIT => pht('Trigger an Audit for project'), 26 26 ); 27 27 break; 28 28 case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 29 29 $specific_mappings = array( 30 - self::ACTION_ADD_CC => 'CC me', 31 - self::ACTION_REMOVE_CC => 'Remove me from CC', 32 - self::ACTION_EMAIL => 'Email me', 33 - self::ACTION_AUDIT => 'Trigger an Audit by me', 30 + self::ACTION_ADD_CC => pht('CC me'), 31 + self::ACTION_REMOVE_CC => pht('Remove me from CC'), 32 + self::ACTION_EMAIL => pht('Email me'), 33 + self::ACTION_AUDIT => pht('Trigger an Audit by me'), 34 34 ); 35 35 break; 36 36 case null:
+18 -18
src/applications/herald/config/HeraldConditionConfig.php
··· 21 21 const CONDITION_REGEXP_PAIR = 'regexp-pair'; 22 22 23 23 public static function getConditionMap() { 24 - static $map = array( 25 - self::CONDITION_CONTAINS => 'contains', 26 - self::CONDITION_NOT_CONTAINS => 'does not contain', 27 - self::CONDITION_IS => 'is', 28 - self::CONDITION_IS_NOT => 'is not', 29 - self::CONDITION_IS_ANY => 'is any of', 30 - self::CONDITION_IS_NOT_ANY => 'is not any of', 31 - self::CONDITION_INCLUDE_ALL => 'include all of', 32 - self::CONDITION_INCLUDE_ANY => 'include any of', 33 - self::CONDITION_INCLUDE_NONE => 'include none of', 34 - self::CONDITION_IS_ME => 'is myself', 35 - self::CONDITION_IS_NOT_ME => 'is not myself', 36 - self::CONDITION_REGEXP => 'matches regexp', 37 - self::CONDITION_RULE => 'matches:', 38 - self::CONDITION_NOT_RULE => 'does not match:', 39 - self::CONDITION_EXISTS => 'exists', 40 - self::CONDITION_NOT_EXISTS => 'does not exist', 41 - self::CONDITION_REGEXP_PAIR => 'matches regexp pair', 24 + $map = array( 25 + self::CONDITION_CONTAINS => pht('contains'), 26 + self::CONDITION_NOT_CONTAINS => pht('does not contain'), 27 + self::CONDITION_IS => pht('is'), 28 + self::CONDITION_IS_NOT => pht('is not'), 29 + self::CONDITION_IS_ANY => pht('is any of'), 30 + self::CONDITION_IS_NOT_ANY => pht('is not any of'), 31 + self::CONDITION_INCLUDE_ALL => pht('include all of'), 32 + self::CONDITION_INCLUDE_ANY => pht('include any of'), 33 + self::CONDITION_INCLUDE_NONE => pht('include none of'), 34 + self::CONDITION_IS_ME => pht('is myself'), 35 + self::CONDITION_IS_NOT_ME => pht('is not myself'), 36 + self::CONDITION_REGEXP => pht('matches regexp'), 37 + self::CONDITION_RULE => pht('matches:'), 38 + self::CONDITION_NOT_RULE => pht('does not match:'), 39 + self::CONDITION_EXISTS => pht('exists'), 40 + self::CONDITION_NOT_EXISTS => pht('does not exist'), 41 + self::CONDITION_REGEXP_PAIR => pht('matches regexp pair'), 42 42 ); 43 43 44 44 return $map;
+3 -3
src/applications/herald/config/HeraldContentTypeConfig.php
··· 8 8 const CONTENT_TYPE_OWNERS = 'owners'; 9 9 10 10 public static function getContentTypeMap() { 11 - static $map = array( 12 - self::CONTENT_TYPE_DIFFERENTIAL => 'Differential Revisions', 13 - self::CONTENT_TYPE_COMMIT => 'Commits', 11 + $map = array( 12 + self::CONTENT_TYPE_DIFFERENTIAL => pht('Differential Revisions'), 13 + self::CONTENT_TYPE_COMMIT => pht('Commits'), 14 14 /* TODO: Deal with this 15 15 self::CONTENT_TYPE_MERGE => 'Merge Requests', 16 16 self::CONTENT_TYPE_OWNERS => 'Owners Changes',
+20 -19
src/applications/herald/config/HeraldFieldConfig.php
··· 22 22 const FIELD_MERGE_REQUESTER = 'merge-requester'; 23 23 24 24 public static function getFieldMap() { 25 - static $map = array( 26 - self::FIELD_TITLE => 'Title', 27 - self::FIELD_BODY => 'Body', 28 - self::FIELD_AUTHOR => 'Author', 29 - self::FIELD_REVIEWER => 'Reviewer', 30 - self::FIELD_REVIEWERS => 'Reviewers', 31 - self::FIELD_CC => 'CCs', 32 - self::FIELD_TAGS => 'Tags', 33 - self::FIELD_DIFF_FILE => 'Any changed filename', 34 - self::FIELD_DIFF_CONTENT => 'Any changed file content', 35 - self::FIELD_REPOSITORY => 'Repository', 36 - self::FIELD_RULE => 'Another Herald rule', 37 - self::FIELD_AFFECTED_PACKAGE => 'Any affected package', 38 - self::FIELD_AFFECTED_PACKAGE_OWNER => "Any affected package's owner", 25 + $map = array( 26 + self::FIELD_TITLE => pht('Title'), 27 + self::FIELD_BODY => pht('Body'), 28 + self::FIELD_AUTHOR => pht('Author'), 29 + self::FIELD_REVIEWER => pht('Reviewer'), 30 + self::FIELD_REVIEWERS => pht('Reviewers'), 31 + self::FIELD_CC => pht('CCs'), 32 + self::FIELD_TAGS => pht('Tags'), 33 + self::FIELD_DIFF_FILE => pht('Any changed filename'), 34 + self::FIELD_DIFF_CONTENT => pht('Any changed file content'), 35 + self::FIELD_REPOSITORY => pht('Repository'), 36 + self::FIELD_RULE => pht('Another Herald rule'), 37 + self::FIELD_AFFECTED_PACKAGE => pht('Any affected package'), 38 + self::FIELD_AFFECTED_PACKAGE_OWNER => 39 + pht("Any affected package's owner"), 39 40 self::FIELD_NEED_AUDIT_FOR_PACKAGE => 40 - 'Affected packages that need audit', 41 - self::FIELD_DIFFERENTIAL_REVISION => 'Differential revision', 42 - self::FIELD_DIFFERENTIAL_REVIEWERS => 'Differential reviewers', 43 - self::FIELD_DIFFERENTIAL_CCS => 'Differential CCs', 44 - self::FIELD_MERGE_REQUESTER => 'Merge requester' 41 + pht('Affected packages that need audit'), 42 + self::FIELD_DIFFERENTIAL_REVISION => pht('Differential revision'), 43 + self::FIELD_DIFFERENTIAL_REVIEWERS => pht('Differential reviewers'), 44 + self::FIELD_DIFFERENTIAL_CCS => pht('Differential CCs'), 45 + self::FIELD_MERGE_REQUESTER => pht('Merge requester') 45 46 ); 46 47 47 48 return $map;
+3 -3
src/applications/herald/config/HeraldRuleTypeConfig.php
··· 6 6 const RULE_TYPE_PERSONAL = 'personal'; 7 7 8 8 public static function getRuleTypeMap() { 9 - static $map = array( 10 - self::RULE_TYPE_GLOBAL => 'Global', 11 - self::RULE_TYPE_PERSONAL => 'Personal', 9 + $map = array( 10 + self::RULE_TYPE_GLOBAL => pht('Global'), 11 + self::RULE_TYPE_PERSONAL => pht('Personal'), 12 12 ); 13 13 return $map; 14 14 }
+25 -9
src/applications/herald/controller/HeraldController.php
··· 5 5 public function buildStandardPageResponse($view, array $data) { 6 6 $page = $this->buildStandardPageView(); 7 7 8 - $page->setApplicationName('Herald'); 8 + $page->setApplicationName(pht('Herald')); 9 9 $page->setBaseURI('/herald/'); 10 10 $page->setTitle(idx($data, 'title')); 11 11 $page->setGlyph("\xE2\x98\xBF"); ··· 16 16 return $response->setContent($page->render()); 17 17 } 18 18 19 + public function buildApplicationMenu() { 20 + return $this->renderNav()->getMenu(); 21 + } 22 + 23 + public function buildApplicationCrumbs() { 24 + $crumbs = parent::buildApplicationCrumbs(); 25 + 26 + $crumbs->addAction( 27 + id(new PhabricatorMenuItemView()) 28 + ->setName(pht('Create Herald Rule')) 29 + ->setHref($this->getApplicationURI('new/')) 30 + ->setIcon('create')); 31 + 32 + return $crumbs; 33 + } 34 + 19 35 protected function renderNav() { 20 36 $nav = id(new AphrontSideNavFilterView()) 21 37 ->setBaseURI(new PhutilURI('/herald/')) 22 - ->addLabel('My Rules') 23 - ->addFilter('new', 'Create Rule'); 38 + ->addLabel(pht('My Rules')) 39 + ->addFilter('new', pht('Create Rule')); 24 40 25 41 $rules_map = HeraldContentTypeConfig::getContentTypeMap(); 26 42 foreach ($rules_map as $key => $value) { 27 43 $nav->addFilter("view/{$key}/personal", $value); 28 44 } 29 45 30 - $nav->addLabel('Global Rules'); 46 + $nav->addLabel(pht('Global Rules')); 31 47 32 48 foreach ($rules_map as $key => $value) { 33 49 $nav->addFilter("view/{$key}/global", $value); 34 50 } 35 51 36 52 $nav 37 - ->addLabel('Utilities') 38 - ->addFilter('test', 'Test Console') 39 - ->addFilter('transcript', 'Transcripts') 40 - ->addFilter('history', 'Edit Log'); 53 + ->addLabel(pht('Utilities')) 54 + ->addFilter('test', pht('Test Console')) 55 + ->addFilter('transcript', pht('Transcripts')) 56 + ->addFilter('history', pht('Edit Log')); 41 57 42 58 if ($this->getRequest()->getUser()->getIsAdmin()) { 43 - $nav->addLabel('Admin'); 59 + $nav->addLabel(pht('Admin')); 44 60 foreach ($rules_map as $key => $value) { 45 61 $nav->addFilter("view/{$key}/all", $value); 46 62 }
+5 -4
src/applications/herald/controller/HeraldDeleteController.php
··· 42 42 43 43 $dialog = new AphrontDialogView(); 44 44 $dialog->setUser($request->getUser()); 45 - $dialog->setTitle('Really delete this rule?'); 46 - $dialog->appendChild(hsprintf( 47 - "Are you sure you want to delete the rule '<strong>%s</strong>'?", 45 + $dialog->setTitle(pht('Really delete this rule?')); 46 + $dialog->setHeaderColor(PhabricatorActionHeaderView::HEADER_RED); 47 + $dialog->appendChild(pht( 48 + "Are you sure you want to delete the rule: %s?", 48 49 $rule->getName())); 49 - $dialog->addSubmitButton('Delete'); 50 + $dialog->addSubmitButton(pht('Delete')); 50 51 $dialog->addCancelButton('/herald/'); 51 52 $dialog->setSubmitURI($request->getPath()); 52 53
+20 -25
src/applications/herald/controller/HeraldHomeController.php
··· 36 36 37 37 $query->withContentTypes(array($this->contentType)); 38 38 39 - $is_admin_page = false; 40 39 $show_author = false; 41 40 $show_rule_type = false; 42 - $can_create = false; 43 41 $has_author_filter = false; 44 42 $author_filter_phid = null; 45 43 ··· 48 46 if (!$user->getIsAdmin()) { 49 47 return new Aphront400Response(); 50 48 } 51 - $is_admin_page = true; 52 49 $show_rule_type = true; 53 50 $show_author = true; 54 51 $has_author_filter = true; ··· 56 53 if ($author_filter_phid) { 57 54 $query->withAuthorPHIDs(array($author_filter_phid)); 58 55 } 59 - $rule_desc = 'All'; 56 + $rule_desc = pht('All'); 60 57 break; 61 58 case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 62 59 $query->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_GLOBAL)); 63 - $can_create = true; 64 - $rule_desc = 'Global'; 60 + $rule_desc = pht('Global'); 65 61 break; 66 62 case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 67 63 default: 68 64 $this->ruleType = HeraldRuleTypeConfig::RULE_TYPE_PERSONAL; 69 65 $query->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL)); 70 66 $query->withAuthorPHIDs(array($user->getPHID())); 71 - $can_create = true; 72 - $rule_desc = 'Personal'; 67 + $rule_desc = pht('Personal'); 73 68 break; 74 69 } 75 70 ··· 94 89 $panel->appendChild($pager); 95 90 $panel->setNoBackground(); 96 91 97 - $panel->setHeader("Herald: {$rule_desc} Rules for {$content_desc}"); 92 + $panel->setHeader( 93 + pht("Herald: %s Rules for %s", $rule_desc, $content_desc)); 98 94 99 - if ($can_create) { 100 - $panel->addButton( 101 - phutil_tag( 102 - 'a', 103 - array( 104 - 'href' => '/herald/new/'.$this->contentType.'/'.$this->ruleType.'/', 105 - 'class' => 'green button', 106 - ), 107 - 'Create New Herald Rule')); 108 - } 109 - 95 + $crumbs = $this 96 + ->buildApplicationCrumbs() 97 + ->addCrumb( 98 + id(new PhabricatorCrumbView()) 99 + ->setName(pht('Herald Rules')) 100 + ->setHref($this->getApplicationURI( 101 + 'view/'.$this->contentType.'/'.$this->ruleType))); 110 102 111 103 $nav = $this->renderNav(); 112 104 $nav->selectFilter('view/'.$this->contentType.'/'.$this->ruleType); ··· 116 108 } 117 109 118 110 $nav->appendChild($panel); 111 + $nav->setCrumbs($crumbs); 119 112 120 - return $this->buildStandardPageResponse( 113 + return $this->buildApplicationPage( 121 114 $nav, 122 115 array( 123 - 'title' => 'Herald', 124 - 'admin' => $is_admin_page, 116 + 'title' => pht('Herald'), 117 + 'dust' => true, 118 + 'device' => true, 125 119 )); 126 120 } 127 121 ··· 140 134 141 135 $form = id(new AphrontFormView()) 142 136 ->setUser($user) 137 + ->setNoShading(true) 143 138 ->appendChild( 144 139 id(new AphrontFormTokenizerControl()) 145 140 ->setName('set_phid') 146 141 ->setValue($tokens) 147 142 ->setLimit(1) 148 - ->setLabel('Filter Author') 143 + ->setLabel(pht('Filter Author')) 149 144 ->setDataSource('/typeahead/common/accounts/')) 150 145 ->appendChild( 151 146 id(new AphrontFormSubmitControl()) 152 - ->setValue('Apply Filter')); 147 + ->setValue(pht('Apply Filter'))); 153 148 154 149 $filter = new AphrontListFilterView(); 155 150 $filter->appendChild($form);
+13 -8
src/applications/herald/controller/HeraldNewController.php
··· 34 34 35 35 $captions = array( 36 36 HeraldRuleTypeConfig::RULE_TYPE_PERSONAL => 37 - 'Personal rules notify you about events. You own them, but they can '. 38 - 'only affect you.', 37 + pht('Personal rules notify you about events. You own them, but '. 38 + 'they can only affect you.'), 39 39 HeraldRuleTypeConfig::RULE_TYPE_GLOBAL => 40 - 'Global rules notify anyone about events. No one owns them, and '. 40 + pht('Global rules notify anyone about events. No one owns them, and '. 41 41 'anyone can edit them. Usually, Global rules are used to notify '. 42 - 'mailing lists.', 42 + 'mailing lists.'), 43 43 ); 44 44 45 45 $radio = id(new AphrontFormRadioButtonControl()) 46 - ->setLabel('Type') 46 + ->setLabel(pht('Type')) 47 47 ->setName('rule_type') 48 48 ->setValue($this->ruleType); 49 49 ··· 70 70 ->setValue(pht('Create Rule')) 71 71 ->addCancelButton('/herald/view/'.$this->contentType.'/')); 72 72 73 - $header = new PhabricatorHeaderView(); 74 - $header->setHeader(pht('Create New Herald Rule')); 73 + $crumbs = $this 74 + ->buildApplicationCrumbs() 75 + ->addCrumb( 76 + id(new PhabricatorCrumbView()) 77 + ->setName(pht('Create Herald Rule')) 78 + ->setHref($this->getApplicationURI( 79 + 'view/'.$this->contentType.'/'.$this->ruleType))); 75 80 76 81 $nav = $this->renderNav(); 77 82 $nav->selectFilter('new'); 78 - $nav->appendChild($header); 79 83 $nav->appendChild($form); 84 + $nav->setCrumbs($crumbs); 80 85 81 86 return $this->buildApplicationPage( 82 87 $nav,
+42 -34
src/applications/herald/controller/HeraldRuleController.php
··· 75 75 76 76 if ($errors) { 77 77 $error_view = new AphrontErrorView(); 78 - $error_view->setTitle('Form Errors'); 78 + $error_view->setTitle(pht('Form Errors')); 79 79 $error_view->setErrors($errors); 80 80 } else { 81 81 $error_view = null; ··· 109 109 ))) 110 110 ->appendChild( 111 111 id(new AphrontFormTextControl()) 112 - ->setLabel('Rule Name') 112 + ->setLabel(pht('Rule Name')) 113 113 ->setName('name') 114 114 ->setError($e_name) 115 115 ->setValue($rule->getName())); ··· 117 117 $form 118 118 ->appendChild( 119 119 id(new AphrontFormMarkupControl()) 120 - ->setValue(hsprintf( 121 - "This <strong>%s</strong> rule triggers for <strong>%s</strong>.", 122 - $rule_type_name, 123 - $content_type_name))) 120 + ->setValue(pht( 121 + "This %s rule triggers for %s.", 122 + phutil_tag('strong', array(), $rule_type_name), 123 + phutil_tag('strong', array(), $content_type_name)))) 124 124 ->appendChild( 125 125 id(new AphrontFormInsetView()) 126 - ->setTitle('Conditions') 126 + ->setTitle(pht('Conditions')) 127 127 ->setRightButton(javelin_tag( 128 128 'a', 129 129 array( ··· 132 132 'sigil' => 'create-condition', 133 133 'mustcapture' => true 134 134 ), 135 - 'Create New Condition')) 135 + pht('New Condition'))) 136 136 ->setDescription( 137 - hsprintf('When %s these conditions are met:', $must_match_selector)) 137 + pht('When %s these conditions are met:', $must_match_selector)) 138 138 ->setContent(javelin_tag( 139 139 'table', 140 140 array( ··· 144 144 ''))) 145 145 ->appendChild( 146 146 id(new AphrontFormInsetView()) 147 - ->setTitle('Action') 147 + ->setTitle(pht('Action')) 148 148 ->setRightButton(javelin_tag( 149 149 'a', 150 150 array( ··· 153 153 'sigil' => 'create-action', 154 154 'mustcapture' => true, 155 155 ), 156 - 'Create New Action')) 157 - ->setDescription(hsprintf( 156 + pht('New Action'))) 157 + ->setDescription(pht( 158 158 'Take these actions %s this rule matches:', 159 159 $repetition_selector)) 160 160 ->setContent(javelin_tag( ··· 166 166 ''))) 167 167 ->appendChild( 168 168 id(new AphrontFormSubmitControl()) 169 - ->setValue('Save Rule') 169 + ->setValue(pht('Save Rule')) 170 170 ->addCancelButton('/herald/view/'.$rule->getContentType().'/')); 171 171 172 172 $this->setupEditorBehavior($rule, $handles); 173 173 174 - $header = new PhabricatorHeaderView(); 175 - $header->setHeader( 176 - $rule->getID() 174 + $title = $rule->getID() 177 175 ? pht('Edit Herald Rule') 178 - : pht('Create Herald Rule')); 176 + : pht('Create Herald Rule'); 177 + 178 + $crumbs = $this 179 + ->buildApplicationCrumbs() 180 + ->addCrumb( 181 + id(new PhabricatorCrumbView()) 182 + ->setName($title) 183 + ->setHref('#')); 179 184 180 185 $nav = $this->renderNav(); 186 + $nav->setCrumbs($crumbs); 181 187 $nav->selectFilter( 182 188 'view/'.$rule->getContentType().'/'.$rule->getRuleType()); 183 189 $nav->appendChild( 184 190 array( 185 191 $error_view, 186 - $header, 187 192 $form, 188 193 )); 189 194 ··· 191 196 $nav, 192 197 array( 193 198 'title' => pht('Edit Rule'), 199 + 'dust' => true, 200 + 'device' => true, 194 201 )); 195 202 } 196 203 ··· 213 220 $errors = array(); 214 221 215 222 if (!strlen($rule->getName())) { 216 - $e_name = "Required"; 217 - $errors[] = "Rule must have a name."; 223 + $e_name = pht("Required"); 224 + $errors[] = pht("Rule must have a name."); 218 225 } 219 226 220 227 $data = json_decode($request->getStr('rule'), true); ··· 247 254 if ($cond_type == HeraldConditionConfig::CONDITION_REGEXP) { 248 255 if (@preg_match($obj->getValue(), '') === false) { 249 256 $errors[] = 250 - 'The regular expression "'.$obj->getValue().'" is not valid. '. 257 + pht('The regular expression "%s" is not valid. '. 251 258 'Regular expressions must have enclosing characters (e.g. '. 252 259 '"@/path/to/file@", not "/path/to/file") and be syntactically '. 253 - 'correct.'; 260 + 'correct.', $obj->getValue()); 254 261 } 255 262 } 256 263 ··· 258 265 $json = json_decode($obj->getValue(), true); 259 266 if (!is_array($json)) { 260 267 $errors[] = 261 - 'The regular expression pair "'.$obj->getValue().'" is not '. 262 - 'valid JSON. Enter a valid JSON array with two elements.'; 268 + pht('The regular expression pair "%s" is not '. 269 + 'valid JSON. Enter a valid JSON array with two elements.', 270 + $obj->getValue()); 263 271 } else { 264 272 if (count($json) != 2) { 265 273 $errors[] = 266 - 'The regular expression pair "'.$obj->getValue().'" must have '. 267 - 'exactly two elements.'; 274 + pht('The regular expression pair "%s" must have '. 275 + 'exactly two elements.', $obj->getValue()); 268 276 } else { 269 277 $key_regexp = array_shift($json); 270 278 $val_regexp = array_shift($json); 271 279 272 280 if (@preg_match($key_regexp, '') === false) { 273 281 $errors[] = 274 - 'The first regexp, "'.$key_regexp.'" in the regexp pair '. 275 - 'is not a valid regexp.'; 282 + pht('The first regexp, "%s" in the regexp pair '. 283 + 'is not a valid regexp.', $key_regexp); 276 284 } 277 285 if (@preg_match($val_regexp, '') === false) { 278 286 $errors[] = 279 - 'The second regexp, "'.$val_regexp.'" in the regexp pair '. 280 - 'is not a valid regexp.'; 287 + pht('The second regexp, "%s" in the regexp pair '. 288 + 'is not a valid regexp.', $val_regexp); 281 289 } 282 290 } 283 291 } ··· 320 328 $rule->saveTransaction(); 321 329 322 330 } catch (AphrontQueryDuplicateKeyException $ex) { 323 - $e_name = "Not Unique"; 324 - $errors[] = "Rule name is not unique. Choose a unique name."; 331 + $e_name = pht("Not Unique"); 332 + $errors[] = pht("Rule name is not unique. Choose a unique name."); 325 333 } 326 334 } 327 335 ··· 469 477 return AphrontFormSelectControl::renderSelectTag( 470 478 $rule->getMustMatchAll() ? 'all' : 'any', 471 479 array( 472 - 'all' => 'all of', 473 - 'any' => 'any of', 480 + 'all' => pht('all of'), 481 + 'any' => pht('any of'), 474 482 ), 475 483 array( 476 484 'name' => 'must_match',
+12 -2
src/applications/herald/controller/HeraldRuleEditHistoryController.php
··· 35 35 $panel->appendChild($list_view); 36 36 $panel->setNoBackground(); 37 37 38 + $crumbs = $this 39 + ->buildApplicationCrumbs($can_create = false) 40 + ->addCrumb( 41 + id(new PhabricatorCrumbView()) 42 + ->setName(pht('Edit History')) 43 + ->setHref($this->getApplicationURI('herald/history'))); 44 + 38 45 $nav = $this->renderNav(); 39 46 $nav->selectFilter('history'); 40 47 $nav->appendChild($panel); 48 + $nav->setCrumbs($crumbs); 41 49 42 - return $this->buildStandardPageResponse( 50 + return $this->buildApplicationPage( 43 51 $nav, 44 52 array( 45 - 'title' => 'Rule Edit History', 53 + 'title' => pht('Rule Edit History'), 54 + 'device' => true, 55 + 'dust' => true, 46 56 )); 47 57 } 48 58
+18 -16
src/applications/herald/controller/HeraldTestConsoleController.php
··· 15 15 $errors = array(); 16 16 if ($request->isFormPost()) { 17 17 if (!$object_name) { 18 - $e_name = 'Required'; 19 - $errors[] = 'An object name is required.'; 18 + $e_name = pht('Required'); 19 + $errors[] = pht('An object name is required.'); 20 20 } 21 21 22 22 if (!$errors) { ··· 25 25 if (preg_match('/^D(\d+)$/', $object_name, $matches)) { 26 26 $object = id(new DifferentialRevision())->load($matches[1]); 27 27 if (!$object) { 28 - $e_name = 'Invalid'; 29 - $errors[] = 'No Differential Revision with that ID exists.'; 28 + $e_name = pht('Invalid'); 29 + $errors[] = pht('No Differential Revision with that ID exists.'); 30 30 } 31 31 } else if (preg_match('/^r([A-Z]+)(\w+)$/', $object_name, $matches)) { 32 32 $repo = id(new PhabricatorRepository())->loadOneWhere( 33 33 'callsign = %s', 34 34 $matches[1]); 35 35 if (!$repo) { 36 - $e_name = 'Invalid'; 37 - $errors[] = 'There is no repository with the callsign '. 38 - $matches[1].'.'; 36 + $e_name = pht('Invalid'); 37 + $errors[] = pht('There is no repository with the callsign: %s.', 38 + $matches[1]); 39 39 } 40 40 $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( 41 41 'repositoryID = %d AND commitIdentifier = %s', 42 42 $repo->getID(), 43 43 $matches[2]); 44 44 if (!$commit) { 45 - $e_name = 'Invalid'; 46 - $errors[] = 'There is no commit with that identifier.'; 45 + $e_name = pht('Invalid'); 46 + $errors[] = pht('There is no commit with that identifier.'); 47 47 } 48 48 $object = $commit; 49 49 } else { 50 - $e_name = 'Invalid'; 51 - $errors[] = 'This object name is not recognized.'; 50 + $e_name = pht('Invalid'); 51 + $errors[] = pht('This object name is not recognized.'); 52 52 } 53 53 54 54 if (!$errors) { ··· 88 88 89 89 if ($errors) { 90 90 $error_view = new AphrontErrorView(); 91 - $error_view->setTitle('Form Errors'); 91 + $error_view->setTitle(pht('Form Errors')); 92 92 $error_view->setErrors($errors); 93 93 } else { 94 94 $error_view = null; 95 95 } 96 96 97 + $text = pht('Enter an object to test rules '. 98 + 'for, like a Diffusion commit (e.g., rX123) or a '. 99 + 'Differential revision (e.g., D123). You will be shown the '. 100 + 'results of a dry run on the object.'); 101 + 97 102 $form = id(new AphrontFormView()) 98 103 ->setUser($user) 99 104 ->appendChild(hsprintf( 100 - '<p class="aphront-form-instructions">Enter an object to test rules '. 101 - 'for, like a Diffusion commit (e.g., <tt>rX123</tt>) or a '. 102 - 'Differential revision (e.g., <tt>D123</tt>). You will be shown the '. 103 - 'results of a dry run on the object.</p>')) 105 + '<p class="aphront-form-instructions">%s</p>', $text)) 104 106 ->appendChild( 105 107 id(new AphrontFormTextControl()) 106 108 ->setLabel(pht('Object Name'))
+43 -31
src/applications/herald/controller/HeraldTranscriptController.php
··· 34 34 if (!$object_xscript) { 35 35 $notice = id(new AphrontErrorView()) 36 36 ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) 37 - ->setTitle('Old Transcript') 37 + ->setTitle(pht('Old Transcript')) 38 38 ->appendChild(phutil_tag( 39 39 'p', 40 40 array(), 41 - 'Details of this transcript have been garbage collected.')); 41 + pht('Details of this transcript have been garbage collected.'))); 42 42 $nav->appendChild($notice); 43 43 } else { 44 44 $filter = $this->getFilterPHIDs(); ··· 53 53 if ($xscript->getDryRun()) { 54 54 $notice = new AphrontErrorView(); 55 55 $notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE); 56 - $notice->setTitle('Dry Run'); 57 - $notice->appendChild( 58 - 'This was a dry run to test Herald rules, no actions were executed.'); 56 + $notice->setTitle(pht('Dry Run')); 57 + $notice->appendChild(pht('This was a dry run to test Herald '. 58 + 'rules, no actions were executed.')); 59 59 $nav->appendChild($notice); 60 60 } 61 61 ··· 82 82 ->setName($xscript->getID())); 83 83 $nav->setCrumbs($crumbs); 84 84 85 - return $this->buildStandardPageResponse( 85 + return $this->buildApplicationPage( 86 86 $nav, 87 87 array( 88 - 'title' => 'Transcript', 88 + 'title' => pht('Transcript'), 89 + 'device' => true, 90 + 'dust' => true, 89 91 )); 90 92 } 91 93 ··· 127 129 128 130 protected function getFilterMap() { 129 131 return array( 130 - self::FILTER_AFFECTED => 'Rules that Affected Me', 131 - self::FILTER_OWNED => 'Rules I Own', 132 - self::FILTER_ALL => 'All Rules', 132 + self::FILTER_AFFECTED => pht('Rules that Affected Me'), 133 + self::FILTER_OWNED => pht('Rules I Own'), 134 + self::FILTER_ALL => pht('All Rules'), 133 135 ); 134 136 } 135 137 ··· 295 297 } 296 298 297 299 if ($apply_xscript->getApplied()) { 298 - $outcome = hsprintf('<span class="outcome-success">SUCCESS</span>'); 300 + $success = pht('SUCCESS'); 301 + $outcome = 302 + hsprintf('<span class="outcome-success">%s</span>', $success); 299 303 } else { 300 - $outcome = hsprintf('<span class="outcome-failure">FAILURE</span>'); 304 + $failure = pht('FAILURE'); 305 + $outcome = 306 + hsprintf('<span class="outcome-failure">%s</span>', $failure); 301 307 } 302 308 303 309 $rows[] = array( ··· 313 319 } 314 320 315 321 $table = new AphrontTableView($rows); 316 - $table->setNoDataString('No actions were taken.'); 322 + $table->setNoDataString(pht('No actions were taken.')); 317 323 $table->setHeaders( 318 324 array( 319 - 'Action', 320 - 'Target', 321 - 'Details', 325 + pht('Action'), 326 + pht('Target'), 327 + pht('Details'), 322 328 )); 323 329 $table->setColumnClasses( 324 330 array( ··· 370 376 $cond_markup[] = phutil_tag( 371 377 'li', 372 378 array(), 373 - hsprintf( 379 + pht( 374 380 '%s Condition: %s %s %s%s', 375 381 $result, 376 382 $field_names[$cond->getFieldName()], ··· 380 386 } 381 387 382 388 if ($rule->getResult()) { 389 + $pass = pht('PASS'); 383 390 $result = hsprintf( 384 - '<span class="herald-outcome rule-pass">PASS</span>'); 391 + '<span class="herald-outcome rule-pass">%s</span>', $pass); 385 392 $class = 'herald-rule-pass'; 386 393 } else { 394 + $fail = pht('FAIL'); 387 395 $result = hsprintf( 388 - '<span class="herald-outcome rule-fail">FAIL</span>'); 396 + '<span class="herald-outcome rule-fail">%s</span>', $fail); 389 397 $class = 'herald-rule-fail'; 390 398 } 391 399 ··· 435 443 phutil_tag('ul', array(), $cond_markup))); 436 444 } 437 445 438 - $panel = new AphrontPanelView(); 439 - $panel->setHeader('Rule Details'); 440 - $panel->appendChild(phutil_tag( 441 - 'ul', 442 - array('class' => 'herald-explain-list'), 443 - $rule_markup)); 444 - 446 + $panel = ''; 447 + if ($rule_markup) { 448 + $panel = new AphrontPanelView(); 449 + $panel->setHeader(pht('Rule Details')); 450 + $panel->setNoBackground(); 451 + $panel->appendChild(phutil_tag( 452 + 'ul', 453 + array('class' => 'herald-explain-list'), 454 + $rule_markup)); 455 + } 445 456 return $panel; 446 457 } 447 458 ··· 457 468 $handles = $this->loadViewerHandles(array($phid)); 458 469 459 470 $data += array( 460 - 'Object Name' => $object_xscript->getName(), 461 - 'Object Type' => $object_xscript->getType(), 462 - 'Object PHID' => $phid, 463 - 'Object Link' => $handles[$phid]->renderLink(), 471 + pht('Object Name') => $object_xscript->getName(), 472 + pht('Object Type') => $object_xscript->getType(), 473 + pht('Object PHID') => $phid, 474 + pht('Object Link') => $handles[$phid]->renderLink(), 464 475 ); 465 476 } 466 477 ··· 501 512 )); 502 513 503 514 $panel = new AphrontPanelView(); 504 - $panel->setHeader('Object Transcript'); 515 + $panel->setHeader(pht('Object Transcript')); 516 + $panel->setNoBackground(); 505 517 $panel->appendChild($table); 506 518 507 519 return $panel;
+11 -9
src/applications/herald/controller/HeraldTranscriptListController.php
··· 64 64 'href' => '/herald/transcript/'.$xscript['id'].'/', 65 65 'class' => 'button small grey', 66 66 ), 67 - 'View Transcript'), 67 + pht('View Transcript')), 68 68 ); 69 69 } 70 70 71 71 $table = new AphrontTableView($rows); 72 72 $table->setHeaders( 73 73 array( 74 - 'Date', 75 - 'Time', 76 - 'Object', 77 - 'Dry Run', 78 - 'Duration', 79 - 'View', 74 + pht('Date'), 75 + pht('Time'), 76 + pht('Object'), 77 + pht('Dry Run'), 78 + pht('Duration'), 79 + pht('View'), 80 80 )); 81 81 $table->setColumnClasses( 82 82 array( ··· 105 105 ->setName(pht('Transcripts'))); 106 106 $nav->setCrumbs($crumbs); 107 107 108 - return $this->buildStandardPageResponse( 108 + return $this->buildApplicationPage( 109 109 $nav, 110 110 array( 111 - 'title' => 'Herald Transcripts', 111 + 'title' => pht('Herald Transcripts'), 112 + 'device' => true, 113 + 'dust' => true, 112 114 )); 113 115 } 114 116
+15 -24
src/applications/herald/view/HeraldRuleEditHistoryView.php
··· 21 21 } 22 22 23 23 public function render() { 24 - $rows = array(); 24 + $list = new PhabricatorObjectItemListView(); 25 + $list->setFlush(true); 26 + $list->setCards(true); 25 27 26 28 foreach ($this->edits as $edit) { 27 29 $name = nonempty($edit->getRuleName(), 'Unknown Rule'); ··· 43 45 break; 44 46 } 45 47 46 - $rows[] = array( 47 - $edit->getRuleID(), 48 - $this->handles[$edit->getEditorPHID()]->renderLink(), 49 - $details, 50 - phabricator_datetime($edit->getDateCreated(), $this->user), 51 - ); 48 + $editor = $this->handles[$edit->getEditorPHID()]->renderLink(); 49 + $date = phabricator_datetime($edit->getDateCreated(), $this->user); 50 + 51 + $item = id(new PhabricatorObjectItemView()) 52 + ->setObjectName(pht('Rule %d', $edit->getRuleID())) 53 + ->setSubHead($details) 54 + ->addIcon('none', $date) 55 + ->addByLine(pht('Editor: %s', $editor)); 56 + 57 + $list->addItem($item); 52 58 } 53 59 54 - $table = new AphrontTableView($rows); 55 - $table->setNoDataString("No edits for rule."); 56 - $table->setHeaders( 57 - array( 58 - 'Rule ID', 59 - 'Editor', 60 - 'Details', 61 - 'Edit Date', 62 - )); 63 - $table->setColumnClasses( 64 - array( 65 - '', 66 - '', 67 - 'wide', 68 - '', 69 - )); 60 + $list->setNoDataString(pht('No edits for rule.')); 70 61 71 - return $table->render(); 62 + return $list; 72 63 } 73 64 }
+22 -48
src/applications/herald/view/HeraldRuleListView.php
··· 34 34 35 35 $type_map = HeraldRuleTypeConfig::getRuleTypeMap(); 36 36 37 - $rows = array(); 38 - 37 + $list = new PhabricatorObjectItemListView(); 38 + $list->setFlush(true); 39 + $list->setCards(true); 39 40 foreach ($this->rules as $rule) { 40 41 41 42 if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) { 42 - $author = null; 43 + $author = pht('Global Rule'); 43 44 } else { 44 45 $author = $this->handles[$rule->getAuthorPHID()]->renderLink(); 46 + $author = pht('Editor: %s', $author); 45 47 } 46 48 47 - $name = phutil_tag( 48 - 'a', 49 - array( 50 - 'href' => '/herald/rule/'.$rule->getID().'/', 51 - ), 52 - $rule->getName()); 53 - 54 49 $edit_log = phutil_tag( 55 50 'a', 56 51 array( 57 52 'href' => '/herald/history/'.$rule->getID().'/', 58 53 ), 59 - 'View Edit Log'); 54 + pht('View Edit Log')); 60 55 61 56 $delete = javelin_tag( 62 57 'a', 63 58 array( 64 59 'href' => '/herald/delete/'.$rule->getID().'/', 65 60 'sigil' => 'workflow', 66 - 'class' => 'button small grey', 67 61 ), 68 - 'Delete'); 62 + pht('Delete')); 69 63 70 - $rows[] = array( 71 - $type_map[$rule->getRuleType()], 72 - $author, 73 - $name, 74 - $edit_log, 75 - $delete, 76 - ); 77 - } 64 + $item = id(new PhabricatorObjectItemView()) 65 + ->setObjectName($type_map[$rule->getRuleType()]) 66 + ->setHeader($rule->getName()) 67 + ->setHref('/herald/rule/'.$rule->getID().'/') 68 + ->addAttribute($edit_log) 69 + ->addIcon('none', $author) 70 + ->addAction( 71 + id(new PhabricatorMenuItemView()) 72 + ->setHref('/herald/delete/'.$rule->getID().'/') 73 + ->setIcon('delete') 74 + ->setWorkflow(true)); 78 75 79 - $table = new AphrontTableView($rows); 80 - $table->setNoDataString("No matching rules."); 76 + $list->addItem($item); 77 + } 81 78 82 - $table->setHeaders( 83 - array( 84 - 'Rule Type', 85 - 'Author', 86 - 'Rule Name', 87 - 'Edit Log', 88 - '', 89 - )); 90 - $table->setColumnClasses( 91 - array( 92 - '', 93 - '', 94 - 'wide pri', 95 - '', 96 - 'action' 97 - )); 98 - $table->setColumnVisibility( 99 - array( 100 - $this->showRuleType, 101 - $this->showAuthor, 102 - true, 103 - true, 104 - true, 105 - )); 79 + $list->setNoDataString(pht("No matching rules.")); 106 80 107 - return $table->render(); 81 + return $list; 108 82 } 109 83 }