From 3d6500823ca8c95fe49041e152d95480b29722e2 Mon Sep 17 00:00:00 2001
From: Chad Little 
Date: Thu, 21 Feb 2013 14:10:22 -0800
Subject: [PATCH] Modernize People
Summary: Adds Crumbs, pht's, and checkout out mobile.
Test Plan: Added, removed people. Changed roles, checked iOS and Chrome.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Differential Revision: https://secure.phabricator.com/D5052
---
 ...PhabricatorEmailVerificationController.php |  25 +-
 .../PhabricatorPeopleController.php           |  34 ++-
 .../PhabricatorPeopleEditController.php       | 266 ++++++++++--------
 .../PhabricatorPeopleLdapController.php       |  35 +--
 .../PhabricatorPeopleListController.php       |  46 +--
 .../PhabricatorPeopleLogsController.php       |  51 ++--
 6 files changed, 261 insertions(+), 196 deletions(-)
diff --git a/src/applications/people/controller/PhabricatorEmailVerificationController.php b/src/applications/people/controller/PhabricatorEmailVerificationController.php
index 80432f15b0..84f4aa33fc 100644
--- a/src/applications/people/controller/PhabricatorEmailVerificationController.php
+++ b/src/applications/people/controller/PhabricatorEmailVerificationController.php
@@ -29,7 +29,7 @@ final class PhabricatorEmailVerificationController
       array(
         'href' => '/',
       ),
-      'Continue to Phabricator');
+      pht('Continue to Phabricator'));
     $home_link = hsprintf(
       '
%s
',
       $home_link);
@@ -39,26 +39,28 @@ final class PhabricatorEmailVerificationController
       array(
         'href' => '/settings/panel/email/',
       ),
-      'Return to Email Settings');
+      pht('Return to Email Settings'));
     $settings_link = hsprintf(
       '
%s
',
       $settings_link);
 
     if (!$email) {
       $content = id(new AphrontErrorView())
-        ->setTitle('Unable To Verify')
+        ->setTitle(pht('Unable To Verify'))
         ->appendChild(phutil_tag(
           'p',
           array(),
-          'The verification code is incorrect, the email address has been '.
+          pht('The verification code is incorrect, the email address has been '.
             'removed, or the email address is owned by another user. Make '.
-            'sure you followed the link in the email correctly.'));
+            'sure you followed the link in the email correctly.')));
     } else if ($email->getIsVerified()) {
+      $inst = pht('This email address has already been verified.');
       $content = id(new AphrontErrorView())
         ->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
-        ->setTitle('Address Already Verified')
+        ->setTitle(pht('Address Already Verified'))
         ->appendChild(hsprintf(
-          'This email address has already been verified.
%s',
+          '%s
%s',
+          $inst,
           $settings_link));
     } else {
 
@@ -67,11 +69,13 @@ final class PhabricatorEmailVerificationController
         $email->save();
       unset($guard);
 
+      $inst = pht('This email address has now been verified. Thanks!');
       $content = id(new AphrontErrorView())
         ->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
-        ->setTitle('Address Verified')
+        ->setTitle(pht('Address Verified'))
         ->appendChild(hsprintf(
-          'This email address has now been verified. Thanks!
%s%s',
+          '%s
%s%s',
+          $inst,
           $home_link,
           $settings_link));
     }
@@ -79,7 +83,8 @@ final class PhabricatorEmailVerificationController
     return $this->buildApplicationPage(
       $content,
       array(
-        'title' => 'Verify Email',
+        'title' => pht('Verify Email'),
+        'device' => true,
       ));
   }
 
diff --git a/src/applications/people/controller/PhabricatorPeopleController.php b/src/applications/people/controller/PhabricatorPeopleController.php
index fc2bad779e..1fb3ef2279 100644
--- a/src/applications/people/controller/PhabricatorPeopleController.php
+++ b/src/applications/people/controller/PhabricatorPeopleController.php
@@ -9,22 +9,42 @@ abstract class PhabricatorPeopleController extends PhabricatorController {
     $is_admin = $this->getRequest()->getUser()->getIsAdmin();
 
     if ($is_admin) {
-      $nav->addLabel('Create Users');
-      $nav->addFilter('edit', 'Create New User');
+      $nav->addLabel(pht('User Administration'));
+      $nav->addFilter('edit', pht('Create New User'));
       if (PhabricatorEnv::getEnvConfig('ldap.auth-enabled') === true) {
-        $nav->addFilter('ldap', 'Import from LDAP');
+        $nav->addFilter('ldap', pht('Import from LDAP'));
       }
     }
 
-    $nav->addLabel('Directory');
-    $nav->addFilter('people', 'User Directory', $this->getApplicationURI());
+    $nav->addFilter('people',
+      pht('User Directory'),
+      $this->getApplicationURI());
 
     if ($is_admin) {
-      $nav->addLabel('Logs');
-      $nav->addFilter('logs', 'Activity Logs');
+      $nav->addFilter('logs', pht('Activity Logs'));
     }
 
     return $nav;
   }
 
+  public function buildApplicationMenu() {
+    return $this->buildSideNavView()->getMenu();
+  }
+
+  public function buildApplicationCrumbs() {
+    $crumbs = parent::buildApplicationCrumbs();
+    // I'm sure this copypasty is wrong.
+    $is_admin = $this->getRequest()->getUser()->getIsAdmin();
+
+    if ($is_admin) {
+      $crumbs->addAction(
+        id(new PhabricatorMenuItemView())
+          ->setName(pht('Create New User'))
+          ->setHref($this->getApplicationURI('edit'))
+          ->setIcon('create'));
+    }
+
+    return $crumbs;
+  }
+
 }
diff --git a/src/applications/people/controller/PhabricatorPeopleEditController.php b/src/applications/people/controller/PhabricatorPeopleEditController.php
index 78100bf21d..0872bb335e 100644
--- a/src/applications/people/controller/PhabricatorPeopleEditController.php
+++ b/src/applications/people/controller/PhabricatorPeopleEditController.php
@@ -20,27 +20,41 @@ final class PhabricatorPeopleEditController
     $request = $this->getRequest();
     $admin = $request->getUser();
 
+    $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
     if ($this->id) {
       $user = id(new PhabricatorUser())->load($this->id);
       if (!$user) {
         return new Aphront404Response();
       }
       $base_uri = '/people/edit/'.$user->getID().'/';
+      $crumbs->addCrumb(
+        id(new PhabricatorCrumbView())
+          ->setName(pht('Edit User'))
+          ->setHref('/people/edit/'));
+      $crumbs->addCrumb(
+        id(new PhabricatorCrumbView())
+          ->setName($user->getFullName())
+          ->setHref($base_uri));
     } else {
       $user = new PhabricatorUser();
       $base_uri = '/people/edit/';
+      $crumbs->addCrumb(
+        id(new PhabricatorCrumbView())
+          ->setName(pht('Create New User'))
+          ->setHref($base_uri));
     }
 
     $nav = new AphrontSideNavFilterView();
     $nav->setBaseURI(new PhutilURI($base_uri));
-    $nav->addLabel('User Information');
-    $nav->addFilter('basic', 'Basic Information');
-    $nav->addFilter('role',  'Edit Roles');
-    $nav->addFilter('cert',  'Conduit Certificate');
-    $nav->addFilter('profile', 'View Profile', '/p/'.$user->getUsername().'/');
-    $nav->addLabel('Special');
-    $nav->addFilter('rename', 'Change Username');
-    $nav->addFilter('delete', 'Delete User');
+    $nav->addLabel(pht('User Information'));
+    $nav->addFilter('basic', pht('Basic Information'));
+    $nav->addFilter('role', pht('Edit Roles'));
+    $nav->addFilter('cert', pht('Conduit Certificate'));
+    $nav->addFilter('profile',
+      pht('View Profile'), '/p/'.$user->getUsername().'/');
+    $nav->addLabel(pht('Special'));
+    $nav->addFilter('rename', pht('Change Username'));
+    $nav->addFilter('delete', pht('Delete User'));
 
     if (!$user->getID()) {
       $this->view = 'basic';
@@ -53,9 +67,9 @@ final class PhabricatorPeopleEditController
     if ($request->getStr('saved')) {
       $notice = new AphrontErrorView();
       $notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
-      $notice->setTitle('Changes Saved');
+      $notice->setTitle(pht('Changes Saved'));
       $notice->appendChild(
-        phutil_tag('p', array(), 'Your changes were saved.'));
+        phutil_tag('p', array(), pht('Your changes were saved.')));
       $content[] = $notice;
     }
 
@@ -93,10 +107,12 @@ final class PhabricatorPeopleEditController
       $nav->appendChild($content);
     }
 
+    $nav->setCrumbs($crumbs);
     return $this->buildApplicationPage(
       $nav,
       array(
-        'title' => 'Edit User',
+        'title' => pht('Edit User'),
+        'device' => true,
       ));
   }
 
@@ -123,10 +139,10 @@ final class PhabricatorPeopleEditController
 
         $new_email = $request->getStr('email');
         if (!strlen($new_email)) {
-          $errors[] = 'Email is required.';
-          $e_email = 'Required';
+          $errors[] = pht('Email is required.');
+          $e_email = pht('Required');
         } else if (!PhabricatorUserEmail::isAllowedAddress($new_email)) {
-          $e_email = 'Invalid';
+          $e_email = pht('Invalid');
           $errors[] = PhabricatorUserEmail::describeAllowedAddresses();
         } else {
           $e_email = null;
@@ -136,18 +152,18 @@ final class PhabricatorPeopleEditController
       $user->setRealName($request->getStr('realname'));
 
       if (!strlen($user->getUsername())) {
-        $errors[] = "Username is required.";
-        $e_username = 'Required';
+        $errors[] = pht("Username is required.");
+        $e_username = pht('Required');
       } else if (!PhabricatorUser::validateUsername($user->getUsername())) {
         $errors[] = PhabricatorUser::describeValidUsername();
-        $e_username = 'Invalid';
+        $e_username = pht('Invalid');
       } else {
         $e_username = null;
       }
 
       if (!strlen($user->getRealName())) {
-        $errors[] = 'Real name is required.';
-        $e_realname = 'Required';
+        $errors[] = pht('Real name is required.');
+        $e_realname = pht('Required');
       } else {
         $e_realname = null;
       }
@@ -184,7 +200,7 @@ final class PhabricatorPeopleEditController
             ->setURI('/people/edit/'.$user->getID().'/?saved=true');
           return $response;
         } catch (AphrontQueryDuplicateKeyException $ex) {
-          $errors[] = 'Username and email must be unique.';
+          $errors[] = pht('Username and email must be unique.');
 
           $same_username = id(new PhabricatorUser())
             ->loadOneWhere('username = %s', $user->getUsername());
@@ -192,11 +208,11 @@ final class PhabricatorPeopleEditController
             ->loadOneWhere('address = %s', $new_email);
 
           if ($same_username) {
-            $e_username = 'Duplicate';
+            $e_username = pht('Duplicate');
           }
 
           if ($same_email) {
-            $e_email = 'Duplicate';
+            $e_email = pht('Duplicate');
           }
         }
       }
@@ -205,7 +221,7 @@ final class PhabricatorPeopleEditController
     $error_view = null;
     if ($errors) {
       $error_view = id(new AphrontErrorView())
-        ->setTitle('Form Errors')
+        ->setTitle(pht('Form Errors'))
         ->setErrors($errors);
     }
 
@@ -226,14 +242,14 @@ final class PhabricatorPeopleEditController
     $form
       ->appendChild(
         id(new AphrontFormTextControl())
-          ->setLabel('Username')
+          ->setLabel(pht('Username'))
           ->setName('username')
           ->setValue($user->getUsername())
           ->setError($e_username)
           ->setDisabled($is_immutable))
       ->appendChild(
         id(new AphrontFormTextControl())
-          ->setLabel('Real Name')
+          ->setLabel(pht('Real Name'))
           ->setName('realname')
           ->setValue($user->getRealName())
           ->setError($e_realname));
@@ -241,7 +257,7 @@ final class PhabricatorPeopleEditController
     if (!$user->getID()) {
       $form->appendChild(
         id(new AphrontFormTextControl())
-          ->setLabel('Email')
+          ->setLabel(pht('Email'))
           ->setName('email')
           ->setDisabled($is_immutable)
           ->setValue($new_email)
@@ -250,14 +266,15 @@ final class PhabricatorPeopleEditController
     } else {
       $email = $user->loadPrimaryEmail();
       if ($email) {
-        $status = $email->getIsVerified() ? 'Verified' : 'Unverified';
+        $status = $email->getIsVerified() ?
+          pht('Verified') : pht('Unverified');
       } else {
-        $status = 'No Email Address';
+        $status = pht('No Email Address');
       }
 
       $form->appendChild(
         id(new AphrontFormStaticControl())
-          ->setLabel('Email')
+          ->setLabel(pht('Email'))
           ->setValue($status));
 
       $form->appendChild(
@@ -265,7 +282,7 @@ final class PhabricatorPeopleEditController
         ->addCheckbox(
           'welcome',
           1,
-          'Re-send "Welcome to Phabricator" email.',
+          pht('Re-send "Welcome to Phabricator" email.'),
           false));
 
     }
@@ -276,39 +293,39 @@ final class PhabricatorPeopleEditController
       $form
         ->appendChild(
           id(new AphrontFormSelectControl())
-            ->setLabel('Role')
+            ->setLabel(pht('Role'))
             ->setName('role')
             ->setValue('user')
             ->setOptions(
               array(
-                'user'  => 'Normal User',
-                'agent' => 'System Agent',
+                'user'  => pht('Normal User'),
+                'agent' => pht('System Agent'),
               ))
             ->setCaption(
-              'You can create a "system agent" account for bots, scripts, '.
-              'etc.'))
+              pht('You can create a "system agent" account for bots, '.
+              'scripts, etc.')))
         ->appendChild(
           id(new AphrontFormCheckboxControl())
             ->addCheckbox(
               'welcome',
               1,
-              'Send "Welcome to Phabricator" email.',
+              pht('Send "Welcome to Phabricator" email.'),
               $welcome_checked));
     } else {
       $roles = array();
 
       if ($user->getIsSystemAgent()) {
-        $roles[] = 'System Agent';
+        $roles[] = pht('System Agent');
       }
       if ($user->getIsAdmin()) {
-        $roles[] = 'Admin';
+        $roles[] = pht('Admin');
       }
       if ($user->getIsDisabled()) {
-        $roles[] = 'Disabled';
+        $roles[] = pht('Disabled');
       }
 
       if (!$roles) {
-        $roles[] = 'Normal User';
+        $roles[] = pht('Normal User');
       }
 
       $roles = implode(', ', $roles);
@@ -322,16 +339,17 @@ final class PhabricatorPeopleEditController
     $form
       ->appendChild(
         id(new AphrontFormSubmitControl())
-          ->setValue('Save'));
+          ->setValue(pht('Save')));
 
     $panel = new AphrontPanelView();
     if ($user->getID()) {
-      $panel->setHeader('Edit User');
+      $panel->setHeader(pht('Edit User'));
     } else {
-      $panel->setHeader('Create New User');
+      $panel->setHeader(pht('Create New User'));
     }
 
     $panel->appendChild($form);
+    $panel->setNoBackground();
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
 
     return array($error_view, $panel);
@@ -355,7 +373,7 @@ final class PhabricatorPeopleEditController
       $logs = array();
 
       if ($is_self) {
-        $errors[] = "You can not edit your own role.";
+        $errors[] = pht("You can not edit your own role.");
       } else {
         $new_admin = (bool)$request->getBool('is_admin');
         $old_admin = (bool)$user->getIsAdmin();
@@ -383,7 +401,7 @@ final class PhabricatorPeopleEditController
     $error_view = null;
     if ($errors) {
       $error_view = id(new AphrontErrorView())
-        ->setTitle('Form Errors')
+        ->setTitle(pht('Form Errors'))
         ->setErrors($errors);
     }
 
@@ -393,9 +411,9 @@ final class PhabricatorPeopleEditController
       ->setAction($request->getRequestURI()->alter('saved', null));
 
     if ($is_self) {
+      $inst = pht('NOTE: You can not edit your own role.');
       $form->appendChild(hsprintf(
-        'NOTE: You can not edit your own '.
-        'role.
'));
+        '%s
', $inst));
     }
 
     $form
@@ -405,7 +423,7 @@ final class PhabricatorPeopleEditController
           ->addCheckbox(
             'is_admin',
             1,
-            'Administrator',
+            pht('Administrator'),
             $user->getIsAdmin())
           ->setDisabled($is_self))
       ->appendChild(
@@ -413,7 +431,7 @@ final class PhabricatorPeopleEditController
           ->addCheckbox(
             'is_disabled',
             1,
-            'Disabled',
+            pht('Disabled'),
             $user->getIsDisabled())
           ->setDisabled($is_self))
       ->appendChild(
@@ -421,7 +439,7 @@ final class PhabricatorPeopleEditController
           ->addCheckbox(
             'is_agent',
             1,
-            'System Agent (Bot/Script User)',
+            pht('System Agent (Bot/Script User)'),
             $user->getIsSystemAgent())
           ->setDisabled(true));
 
@@ -429,12 +447,13 @@ final class PhabricatorPeopleEditController
       $form
         ->appendChild(
           id(new AphrontFormSubmitControl())
-            ->setValue('Edit Role'));
+            ->setValue(pht('Edit Role')));
     }
 
     $panel = new AphrontPanelView();
-    $panel->setHeader('Edit Role');
+    $panel->setHeader(pht('Edit Role'));
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
+    $panel->setNoBackground();
     $panel->appendChild($form);
 
     return array($error_view, $panel);
@@ -444,37 +463,38 @@ final class PhabricatorPeopleEditController
     $request = $this->getRequest();
     $admin = $request->getUser();
 
+    $inst = pht('You can use this certificate '.
+        'to write scripts or bots which interface with Phabricator over '.
+        'Conduit.');
     $form = new AphrontFormView();
     $form
       ->setUser($admin)
       ->setAction($request->getRequestURI())
       ->appendChild(hsprintf(
-        'You can use this certificate '.
-        'to write scripts or bots which interface with Phabricator over '.
-        'Conduit.
'));
+        '%s
', $inst));
 
     if ($user->getIsSystemAgent()) {
       $form
         ->appendChild(
           id(new AphrontFormTextControl())
-            ->setLabel('Username')
+            ->setLabel(pht('Username'))
             ->setValue($user->getUsername()))
         ->appendChild(
           id(new AphrontFormTextAreaControl())
-            ->setLabel('Certificate')
+            ->setLabel(pht('Certificate'))
             ->setValue($user->getConduitCertificate()));
     } else {
       $form->appendChild(
         id(new AphrontFormStaticControl())
-          ->setLabel('Certificate')
+          ->setLabel(pht('Certificate'))
           ->setValue(
-            'You may only view the certificates of System Agents.'));
+            pht('You may only view the certificates of System Agents.')));
     }
 
     $panel = new AphrontPanelView();
-    $panel->setHeader('Conduit Certificate');
+    $panel->setHeader(pht('Conduit Certificate'));
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
-
+    $panel->setNoBackground();
     $panel->appendChild($form);
 
     return array($panel);
@@ -492,13 +512,13 @@ final class PhabricatorPeopleEditController
 
       $username = $request->getStr('username');
       if (!strlen($username)) {
-        $e_username = 'Required';
-        $errors[] = 'New username is required.';
+        $e_username = pht('Required');
+        $errors[] = pht('New username is required.');
       } else if ($username == $user->getUsername()) {
-        $e_username = 'Invalid';
-        $errors[] = 'New username must be different from old username.';
+        $e_username = pht('Invalid');
+        $errors[] = pht('New username must be different from old username.');
       } else if (!PhabricatorUser::validateUsername($username)) {
-        $e_username = 'Invalid';
+        $e_username = pht('Invalid');
         $errors[] = PhabricatorUser::describeValidUsername();
       }
 
@@ -512,61 +532,67 @@ final class PhabricatorPeopleEditController
           return id(new AphrontRedirectResponse())
             ->setURI($request->getRequestURI()->alter('saved', true));
         } catch (AphrontQueryDuplicateKeyException $ex) {
-          $e_username = 'Not Unique';
-          $errors[] = 'Another user already has that username.';
+          $e_username = pht('Not Unique');
+          $errors[] = pht('Another user already has that username.');
         }
       }
     }
 
     if ($errors) {
       $errors = id(new AphrontErrorView())
-        ->setTitle('Form Errors')
+        ->setTitle(pht('Form Errors'))
         ->setErrors($errors);
     } else {
       $errors = null;
     }
 
+    $inst1 = pht('Be careful when renaming users!');
+    $inst2 = pht('The old username will no longer be tied to the user, so '.
+          'anything which uses it (like old commit messages) will no longer '.
+          'associate correctly. And if you give a user a username which some '.
+          'other user used to have, username lookups will begin returning '.
+          'the wrong user.');
+    $inst3 = pht('It is generally safe to rename newly created users (and '.
+          'test users and so on), but less safe to rename established users '.
+          'and unsafe to reissue a username.');
+    $inst4 = pht('Users who rely on password auth will need to reset their '.
+          'passwordafter their username is changed (their username is part '.
+          'of the salt in the password hash). They will receive an email '.
+          'with instructions on how to do this.');
+
     $form = new AphrontFormView();
     $form
       ->setUser($admin)
       ->setAction($request->getRequestURI())
       ->appendChild(hsprintf(
         ''.
-          'Be careful when renaming users! '.
-          'The old username will no longer be tied to the user, so anything '.
-          'which uses it (like old commit messages) will no longer associate '.
-          'correctly. And if you give a user a username which some other user '.
-          'used to have, username lookups will begin returning the wrong '.
-          'user.'.
+          '%s '.
+          '%s'.
         '
'.
         ''.
-          'It is generally safe to rename newly created users (and test users '.
-          'and so on), but less safe to rename established users and unsafe '.
-          'to reissue a username.'.
+          '%s'.
         '
'.
         ''.
-          'Users who rely on password auth will need to reset their password '.
-          'after their username is changed (their username is part of the '.
-          'salt in the password hash). They will receive an email with '.
-          'instructions on how to do this.'.
-        '
'))
+          '%s'.
+        '
', $inst1, $inst2, $inst3, $inst4))
       ->appendChild(
         id(new AphrontFormStaticControl())
-          ->setLabel('Old Username')
+          ->setLabel(pht('Old Username'))
           ->setValue($user->getUsername()))
       ->appendChild(
         id(new AphrontFormTextControl())
-          ->setLabel('New Username')
+          ->setLabel(pht('New Username'))
           ->setValue($username)
           ->setName('username')
           ->setError($e_username))
       ->appendChild(
         id(new AphrontFormSubmitControl())
-          ->setValue('Change Username'));
+          ->setValue(pht('Change Username')));
 
     $panel = new AphrontPanelView();
-    $panel->setHeader('Change Username');
+    $panel->setHeader(pht('Change Username'));
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
+    $panel->setNoBackground();
     $panel->appendChild($form);
 
     return array($errors, $panel);
@@ -576,13 +602,15 @@ final class PhabricatorPeopleEditController
     $request = $this->getRequest();
     $admin = $request->getUser();
 
+    $far1 = pht('As you stare into the gaping maw of the abyss, something '.
+        'hold you back.');
+    $far2 = pht('You can not delete your own account.');
+
     if ($user->getPHID() == $admin->getPHID()) {
       $error = new AphrontErrorView();
-      $error->setTitle('You Shall Journey No Farther');
+      $error->setTitle(pht('You Shall Journey No Farther'));
       $error->appendChild(hsprintf(
-        'As you stare into the gaping maw of the abyss, something holds '.
-        'you back.
'.
-        'You can not delete your own account.
'));
+        '%s
%s
', $far1, $far2));
       return $error;
     }
 
@@ -594,11 +622,11 @@ final class PhabricatorPeopleEditController
 
       $username = $request->getStr('username');
       if (!strlen($username)) {
-        $e_username = 'Required';
-        $errors[] = 'You must type the username to confirm deletion.';
+        $e_username = pht('Required');
+        $errors[] = pht('You must type the username to confirm deletion.');
       } else if ($username != $user->getUsername()) {
-        $e_username = 'Invalid';
-        $errors[] = 'You must type the username correctly.';
+        $e_username = pht('Invalid');
+        $errors[] = pht('You must type the username correctly.');
       }
 
       if (!$errors) {
@@ -612,49 +640,53 @@ final class PhabricatorPeopleEditController
 
     if ($errors) {
       $errors = id(new AphrontErrorView())
-        ->setTitle('Form Errors')
+        ->setTitle(pht('Form Errors'))
         ->setErrors($errors);
     } else {
       $errors = null;
     }
 
+    $str1 = pht('Be careful when deleting users!');
+    $str2 = pht('If this user interacted with anything, it is generally '.
+        'better to disable them, not delete them. If you delete them, it will '.
+        'no longer be possible to search for their objects, for example, '.
+        'and you will lose other information about their history. Disabling '.
+        'them instead will prevent them from logging in but not destroy '.
+        'any of their data.');
+    $str3 = pht('It is generally safe to delete newly created users (and '.
+          'test users and so on), but less safe to delete established users. '.
+          'If possible, disable them instead.');
+
     $form = new AphrontFormView();
     $form
       ->setUser($admin)
       ->setAction($request->getRequestURI())
       ->appendChild(hsprintf(
         ''.
-          'Be careful when deleting users! '.
-          'If this user interacted with anything, it is generally better '.
-          'to disable them, not delete them. If you delete them, it will '.
-          'no longer be possible to search for their objects, for example, '.
-          'and you will lose other information about their history. Disabling '.
-          'them instead will prevent them from logging in but not destroy '.
-          'any of their data.'.
+          '%s %s'.
         '
'.
         ''.
-          'It is generally safe to delete newly created users (and test users '.
-          'and so on), but less safe to delete established users. If '.
-          'possible, disable them instead.'.
-        '
'))
+          '%s'.
+        '', $str1, $str2, $str3))
       ->appendChild(
         id(new AphrontFormStaticControl())
-          ->setLabel('Username')
+          ->setLabel(pht('Username'))
           ->setValue($user->getUsername()))
       ->appendChild(
         id(new AphrontFormTextControl())
-          ->setLabel('Confirm')
+          ->setLabel(pht('Confirm'))
           ->setValue($username)
           ->setName('username')
-          ->setCaption("Type the username again to confirm deletion.")
+          ->setCaption(pht("Type the username again to confirm deletion."))
           ->setError($e_username))
       ->appendChild(
         id(new AphrontFormSubmitControl())
-          ->setValue('Delete User'));
+          ->setValue(pht('Delete User')));
 
     $panel = new AphrontPanelView();
-    $panel->setHeader('Delete User');
+    $panel->setHeader(pht('Delete User'));
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
+    $panel->setNoBackground();
     $panel->appendChild($form);
 
     return array($errors, $panel);
@@ -668,13 +700,13 @@ final class PhabricatorPeopleEditController
           'article/User_Guide_Account_Roles.html'),
         'target' => '_blank',
       ),
-      'User Guide: Account Roles');
+      pht('User Guide: Account Roles'));
 
-    return hsprintf(
-      ''.
-        'For a detailed explanation of account roles, see %s.'.
-      '
',
+    $inst = pht('For a detailed explanation of account roles, see %s.',
       $roles_link);
+    return hsprintf(
+      '%s
',
+      $inst);
   }
 
 }
diff --git a/src/applications/people/controller/PhabricatorPeopleLdapController.php b/src/applications/people/controller/PhabricatorPeopleLdapController.php
index 0567e90b4c..3e2e28f4d8 100644
--- a/src/applications/people/controller/PhabricatorPeopleLdapController.php
+++ b/src/applications/people/controller/PhabricatorPeopleLdapController.php
@@ -22,23 +22,23 @@ final class PhabricatorPeopleLdapController
       ->setUser($admin)
       ->appendChild(
         id(new AphrontFormTextControl())
-        ->setLabel('LDAP username')
+        ->setLabel(pht('LDAP username'))
         ->setName('username'))
       ->appendChild(
         id(new AphrontFormPasswordControl())
-        ->setLabel('Password')
+        ->setLabel(pht('Password'))
         ->setName('password'))
       ->appendChild(
         id(new AphrontFormTextControl())
-        ->setLabel('LDAP query')
-        ->setCaption('A filter such as (objectClass=*)')
+        ->setLabel(pht('LDAP query'))
+        ->setCaption(pht('A filter such as (objectClass=*)'))
         ->setName('query'))
       ->appendChild(
         id(new AphrontFormSubmitControl())
-        ->setValue('Search'));
+        ->setValue(pht('Search')));
 
     $panel = new AphrontPanelView();
-    $panel->setHeader('Import LDAP Users');
+    $panel->setHeader(pht('Import LDAP Users'));
     $panel->appendChild($form);
 
 
@@ -59,7 +59,8 @@ final class PhabricatorPeopleLdapController
     return $this->buildApplicationPage(
       $nav,
       array(
-        'title' => 'Import Ldap Users',
+        'title' => pht('Import Ldap Users'),
+        'device' => true,
       ));
   }
 
@@ -71,8 +72,8 @@ final class PhabricatorPeopleLdapController
 
     $panel = new AphrontErrorView();
     $panel->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
-    $panel->setTitle("Import Successful");
-    $errors = array("Successfully imported users from LDAP");
+    $panel->setTitle(pht("Import Successful"));
+    $errors = array(pht("Successfully imported users from LDAP"));
 
 
     foreach ($usernames as $username) {
@@ -92,9 +93,9 @@ final class PhabricatorPeopleLdapController
         $ldap_info->setLDAPUsername($username);
         $ldap_info->setUserID($user->getID());
         $ldap_info->save();
-        $errors[] = 'Successfully added ' . $username;
+        $errors[] = pht('Successfully added %s', $username);
       } catch (Exception $ex) {
-        $errors[] = 'Failed to add ' . $username . ' ' . $ex->getMessage();
+        $errors[] = pht('Failed to add %s %s', $username, $ex->getMessage());
       }
     }
 
@@ -127,23 +128,23 @@ final class PhabricatorPeopleLdapController
       $table = new AphrontTableView($results);
       $table->setHeaders(
         array(
-          'Username',
-          'Email',
-          'RealName',
-          'Import?',
+          pht('Username'),
+          pht('Email'),
+          pht('Real Name'),
+          pht('Import?'),
         ));
       $form->appendChild($table);
       $form->setAction($request->getRequestURI()
         ->alter('import', 'true')->alter('search', null))
         ->appendChild(
           id(new AphrontFormSubmitControl())
-          ->setValue('Import'));
+          ->setValue(pht('Import')));
 
 
       $panel->appendChild($form);
     } catch (Exception $ex) {
       $error_view = new AphrontErrorView();
-      $error_view->setTitle('LDAP Search Failed');
+      $error_view->setTitle(pht('LDAP Search Failed'));
       $error_view->setErrors(array($ex->getMessage()));
       return $error_view;
     }
diff --git a/src/applications/people/controller/PhabricatorPeopleListController.php b/src/applications/people/controller/PhabricatorPeopleListController.php
index f7eb21597a..b34e048b12 100644
--- a/src/applications/people/controller/PhabricatorPeopleListController.php
+++ b/src/applications/people/controller/PhabricatorPeopleListController.php
@@ -29,20 +29,20 @@ final class PhabricatorPeopleListController
     foreach ($users as $user) {
       $primary_email = $user->loadPrimaryEmail();
       if ($primary_email && $primary_email->getIsVerified()) {
-        $email = 'Verified';
+        $email = pht('Verified');
       } else {
-        $email = 'Unverified';
+        $email = pht('Unverified');
       }
 
       $status = array();
       if ($user->getIsDisabled()) {
-        $status[] = 'Disabled';
+        $status[] = pht('Disabled');
       }
       if ($user->getIsAdmin()) {
-        $status[] = 'Admin';
+        $status[] = pht('Admin');
       }
       if ($user->getIsSystemAgent()) {
-        $status[] = 'System Agent';
+        $status[] = pht('System Agent');
       }
       $status = implode(', ', $status);
 
@@ -64,19 +64,19 @@ final class PhabricatorPeopleListController
             'class' => 'button grey small',
             'href'  => '/people/edit/'.$user->getID().'/',
           ),
-          'Administrate User'),
+          pht('Administrate User')),
       );
     }
 
     $table = new AphrontTableView($rows);
     $table->setHeaders(
       array(
-        'Join Date',
-        'Time',
-        'Username',
-        'Real Name',
-        'Roles',
-        'Email',
+        pht('Join Date'),
+        pht('Time'),
+        pht('Username'),
+        pht('Real Name'),
+        pht('Roles'),
+        pht('Email'),
         '',
       ));
     $table->setColumnClasses(
@@ -101,19 +101,12 @@ final class PhabricatorPeopleListController
       ));
 
     $panel = new AphrontPanelView();
-    $panel->setHeader('People ('.number_format($count).')');
+    $panel->setHeader(pht('People (%d)', number_format($count)));
+    $panel->setNoBackground();
     $panel->appendChild($table);
     $panel->appendChild($pager);
 
     if ($is_admin) {
-      $panel->addButton(
-        phutil_tag(
-          'a',
-          array(
-            'href' => '/people/edit/',
-            'class' => 'button green',
-          ),
-          'Create New Account'));
       if (PhabricatorEnv::getEnvConfig('ldap.auth-enabled')) {
         $panel->addButton(
           phutil_tag(
@@ -122,18 +115,25 @@ final class PhabricatorPeopleListController
               'href' => '/people/ldap/',
               'class' => 'button green'
             ),
-            'Import from LDAP'));
+            pht('Import from LDAP')));
       }
     }
+    $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
+    $crumbs->addCrumb(
+        id(new PhabricatorCrumbView())
+          ->setName(pht('User Directory'))
+          ->setHref('/people/'));
 
     $nav = $this->buildSideNavView();
     $nav->selectFilter('people');
     $nav->appendChild($panel);
+    $nav->setCrumbs($crumbs);
 
     return $this->buildApplicationPage(
       $nav,
       array(
-        'title' => 'People',
+        'title' => pht('People'),
+        'device' => true,
       ));
   }
 }
diff --git a/src/applications/people/controller/PhabricatorPeopleLogsController.php b/src/applications/people/controller/PhabricatorPeopleLogsController.php
index b612722e4f..5436835a12 100644
--- a/src/applications/people/controller/PhabricatorPeopleLogsController.php
+++ b/src/applications/people/controller/PhabricatorPeopleLogsController.php
@@ -44,44 +44,44 @@ final class PhabricatorPeopleLogsController
       ->setUser($user)
       ->appendChild(
         id(new AphrontFormTokenizerControl())
-          ->setLabel('Filter Actor')
+          ->setLabel(pht('Filter Actor'))
           ->setName('actor')
           ->setLimit(1)
           ->setValue($actor_value)
           ->setDatasource('/typeahead/common/accounts/'))
       ->appendChild(
         id(new AphrontFormTokenizerControl())
-          ->setLabel('Filter User')
+          ->setLabel(pht('Filter User'))
           ->setName('user')
           ->setLimit(1)
           ->setValue($user_value)
           ->setDatasource('/typeahead/common/accounts/'))
       ->appendChild(
         id(new AphrontFormSelectControl())
-          ->setLabel('Show Activity')
+          ->setLabel(pht('Show Activity'))
           ->setName('activity')
           ->setValue($filter_activity)
           ->setOptions(
             array(
-              ''        => 'All Activity',
-              'admin'   => 'Admin Activity',
+              ''        => pht('All Activity'),
+              'admin'   => pht('Admin Activity'),
             )))
       ->appendChild(
         id(new AphrontFormTextControl())
-          ->setLabel('Filter IP')
+          ->setLabel(pht('Filter IP'))
           ->setName('ip')
           ->setValue($filter_ip)
           ->setCaption(
-            'Enter an IP (or IP prefix) to show only activity by that remote '.
-            'address.'))
+            pht('Enter an IP (or IP prefix) to show only activity by that '.
+            'remote address.')))
       ->appendChild(
         id(new AphrontFormTextControl())
-          ->setLabel('Filter Session')
+          ->setLabel(pht('Filter Session'))
           ->setName('session')
           ->setValue($filter_session))
       ->appendChild(
         id(new AphrontFormSubmitControl())
-          ->setValue('Filter Logs'));
+          ->setValue(pht('Filter Logs')));
 
     $log_table = new PhabricatorUserLog();
     $conn_r = $log_table->establishConnection('r');
@@ -183,15 +183,15 @@ final class PhabricatorPeopleLogsController
     $table = new AphrontTableView($rows);
     $table->setHeaders(
       array(
-        'Date',
-        'Time',
-        'Action',
-        'Actor',
-        'User',
-        'Old',
-        'New',
-        'IP',
-        'Session',
+        pht('Date'),
+        pht('Time'),
+        pht('Action'),
+        pht('Actor'),
+        pht('User'),
+        pht('Old'),
+        pht('New'),
+        pht('IP'),
+        pht('Session'),
       ));
     $table->setColumnClasses(
       array(
@@ -207,12 +207,18 @@ final class PhabricatorPeopleLogsController
       ));
 
     $panel = new AphrontPanelView();
-    $panel->setHeader('Activity Logs');
+    $panel->setHeader(pht('Activity Logs'));
+    $panel->setNoBackground();
     $panel->appendChild($table);
     $panel->appendChild($pager);
 
     $filter = new AphrontListFilterView();
     $filter->appendChild($form);
+    $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
+    $crumbs->addCrumb(
+        id(new PhabricatorCrumbView())
+          ->setName(pht('Activity Logs'))
+          ->setHref('/people/logs/'));
 
     $nav = $this->buildSideNavView();
     $nav->selectFilter('logs');
@@ -221,12 +227,13 @@ final class PhabricatorPeopleLogsController
         $filter,
         $panel,
       ));
-
+    $nav->setCrumbs($crumbs);
 
     return $this->buildApplicationPage(
       $nav,
       array(
-        'title' => 'Activity Logs',
+        'title' => pht('Activity Logs'),
+        'device' => true,
       ));
   }
 }