public function testValidateTranslation() { $tests = array('a < 2' => array('a < 2' => true, 'b < 3' => true, '2 > a' => false, 'a<2' => false), 'We <em>win</em>' => array('We <em>win</em>' => true, 'We </em>win<em>' => true, 'We win' => false, 'We <em onmouseover="">win</em>' => false), 'We <em title="%s">win</em> & triumph' => array('We <em title="%s">triumph</em> & win' => true, 'We <em title="%s">win</em> and triumph' => false), 'beer' => array('pivo' => true, 'b<>r' => false, 'b&&r' => false)); $translator = new PhutilTranslator(); foreach ($tests as $original => $translations) { foreach ($translations as $translation => $expect) { $valid = $expect ? "valid" : "invalid"; $this->assertEqual($expect, $translator->validateTranslation($original, $translation), "'{$original}' should be {$valid} with '{$translation}'."); } } }
/** * This function does not usually need to be called directly. Instead, call * @{function:phabricator_date}, @{function:phabricator_time}, or * @{function:phabricator_datetime}. * * @param int Unix epoch timestamp. * @param PhabricatorUser User viewing the timestamp. * @param string Date format, as per DateTime class. * @return string Formatted, local date/time. */ function phabricator_format_local_time($epoch, $user, $format) { if (!$epoch) { // If we're missing date information for something, the DateTime class will // throw an exception when we try to construct an object. Since this is a // display function, just return an empty string. return ''; } $user_zone = $user->getTimezoneIdentifier(); static $zones = array(); if (empty($zones[$user_zone])) { $zones[$user_zone] = new DateTimeZone($user_zone); } $zone = $zones[$user_zone]; // NOTE: Although DateTime takes a second DateTimeZone parameter to its // constructor, it ignores it if the date string includes timezone // information. Further, it treats epoch timestamps ("@946684800") as having // a UTC timezone. Set the timezone explicitly after constructing the object. try { $date = new DateTime('@' . $epoch); } catch (Exception $ex) { // NOTE: DateTime throws an empty exception if the format is invalid, // just replace it with a useful one. throw new Exception(pht("Construction of a DateTime() with epoch '%s' " . "raised an exception.", $epoch)); } $date->setTimeZone($zone); return PhutilTranslator::getInstance()->translateDate($format, $date); }
public function testPHT() { PhutilTranslator::setInstance(new PhutilTranslator()); $this->assertEqual('beer', pht('beer')); $this->assertEqual('1 beer(s)', pht('%d beer(s)', 1)); PhutilTranslator::getInstance()->addTranslations(array('%d beer(s)' => array('%d beer', '%d beers'))); $this->assertEqual('1 beer', pht('%d beer(s)', 1)); PhutilTranslator::getInstance()->setLanguage('cs'); PhutilTranslator::getInstance()->addTranslations(array('%d beer(s)' => array('%d pivo', '%d piva', '%d piv'))); $this->assertEqual('5 piv', pht('%d beer(s)', 5)); }
public final function willBeginExecution() { $request = $this->getRequest(); $user = new PhabricatorUser(); $phusr = $request->getCookie('phusr'); $phsid = $request->getCookie('phsid'); if (strlen($phusr) && $phsid) { $info = queryfx_one($user->establishConnection('r'), 'SELECT u.* FROM %T u JOIN %T s ON u.phid = s.userPHID AND s.type LIKE %> AND s.sessionKey = %s', $user->getTableName(), 'phabricator_session', 'web-', $phsid); if ($info) { $user->loadFromArray($info); } } $translation = $user->getTranslation(); if ($translation && $translation != PhabricatorEnv::getEnvConfig('translation.provider')) { $translation = newv($translation, array()); PhutilTranslator::getInstance()->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations()); } $request->setUser($user); if ($user->getIsDisabled() && $this->shouldRequireEnabledUser()) { $disabled_user_controller = new PhabricatorDisabledUserController($request); return $this->delegateToController($disabled_user_controller); } $event = new PhabricatorEvent(PhabricatorEventType::TYPE_CONTROLLER_CHECKREQUEST, array('request' => $request, 'controller' => get_class($this))); $event->setUser($user); PhutilEventEngine::dispatchEvent($event); $checker_controller = $event->getValue('controller'); if ($checker_controller != get_class($this)) { return $this->delegateToController($checker_controller); } if (PhabricatorEnv::getEnvConfig('darkconsole.enabled')) { if ($user->getConsoleEnabled() || PhabricatorEnv::getEnvConfig('darkconsole.always-on')) { $console = new DarkConsoleCore(); $request->getApplicationConfiguration()->setConsole($console); } } if ($this->shouldRequireLogin() && !$user->getPHID()) { $login_controller = new PhabricatorLoginController($request); return $this->delegateToController($login_controller); } if ($this->shouldRequireEmailVerification()) { $email = $user->loadPrimaryEmail(); if (!$email) { throw new Exception("No primary email address associated with this account!"); } if (!$email->getIsVerified()) { $verify_controller = new PhabricatorMustVerifyEmailController($request); return $this->delegateToController($verify_controller); } } if ($this->shouldRequireAdmin() && !$user->getIsAdmin()) { return new Aphront403Response(); } }
public function testPht() { PhutilTranslator::setInstance(new PhutilTranslator()); $this->assertEqual('beer', pht('beer')); $this->assertEqual('1 beer(s)', pht('%d beer(s)', 1)); $english_locale = PhutilLocale::loadLocale('en_US'); PhutilTranslator::getInstance()->setLocale($english_locale); PhutilTranslator::getInstance()->setTranslations(array('%d beer(s)' => array('%d beer', '%d beers'))); $this->assertEqual('1 beer', pht('%d beer(s)', 1)); $czech_locale = PhutilLocale::loadLocale('cs_CZ'); PhutilTranslator::getInstance()->setLocale($czech_locale); PhutilTranslator::getInstance()->setTranslations(array('%d beer(s)' => array('%d pivo', '%d piva', '%d piv'))); $this->assertEqual('5 piv', pht('%d beer(s)', 5)); }
public function testSetInstance() { $english_translator = $this->newTranslator('en_US'); PhutilTranslator::setInstance($english_translator); $original = PhutilTranslator::getInstance(); $this->assertEqual('color', pht('color')); $british_locale = PhutilLocale::loadLocale('en_GB'); $british = new PhutilTranslator(); $british->setLocale($british_locale); $british->setTranslations(array('color' => 'colour')); PhutilTranslator::setInstance($british); $this->assertEqual('colour', pht('color')); PhutilTranslator::setInstance($original); $this->assertEqual('color', pht('color')); }
PhutilErrorHandler::setErrorListener(array('DarkConsoleErrorLogPluginAPI', 'handleErrors')); foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) { phutil_load_library($library); } if (PhabricatorEnv::getEnvConfig('phabricator.setup')) { try { PhabricatorSetup::runSetup(); } catch (Exception $ex) { echo "EXCEPTION!\n"; echo $ex; } return; } phabricator_detect_bad_base_uri(); $translation = PhabricatorEnv::newObjectFromConfig('translation.provider'); PhutilTranslator::getInstance()->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations()); $host = $_SERVER['HTTP_HOST']; $path = $_REQUEST['__path__']; switch ($host) { default: $config_key = 'aphront.default-application-configuration-class'; $application = PhabricatorEnv::newObjectFromConfig($config_key); break; } $application->setHost($host); $application->setPath($path); $application->willBuildRequest(); $request = $application->buildRequest(); $write_guard = new AphrontWriteGuard(array($request, 'validateCSRF')); PhabricatorEventEngine::initialize(); $application->setRequest($request);
* * - Next to 'arcanist/'. * - Anywhere in the normal PHP 'include_path'. * - Inside 'arcanist/externals/includes/'. * * When looking in these places, we expect to find a 'libphutil/' directory. */ function arcanist_adjust_php_include_path() { // The 'arcanist/' directory. $arcanist_dir = dirname(dirname(__FILE__)); // The parent directory of 'arcanist/'. $parent_dir = dirname($arcanist_dir); // The 'arcanist/externals/includes/' directory. $include_dir = implode(DIRECTORY_SEPARATOR, array($arcanist_dir, 'externals', 'includes')); $php_include_path = ini_get('include_path'); $php_include_path = implode(PATH_SEPARATOR, array($parent_dir, $php_include_path, $include_dir)); ini_set('include_path', $php_include_path); } arcanist_adjust_php_include_path(); if (getenv('ARC_PHUTIL_PATH')) { @(include_once getenv('ARC_PHUTIL_PATH') . '/scripts/__init_script__.php'); } else { @(include_once 'libphutil/scripts/__init_script__.php'); } if (!@constant('__LIBPHUTIL__')) { echo "ERROR: Unable to load libphutil. Put libphutil/ next to arcanist/, or " . "update your PHP 'include_path' to include the parent directory of " . "libphutil/, or symlink libphutil/ into arcanist/externals/includes/.\n"; exit(1); } PhutilTranslator::getInstance()->addTranslations(array('Locally modified path(s) are not included in this revision:' => array('A locally modified path is not included in this revision:', 'Locally modified paths are not included in this revision:'), 'They will NOT be committed. Commit this revision anyway?' => array('It will NOT be committed. Commit this revision anyway?', 'They will NOT be committed. Commit this revision anyway?'), 'Revision includes changes to path(s) that do not exist:' => array('Revision includes changes to a path that does not exist:', 'Revision includes changes to paths that do not exist:'), 'This diff includes file(s) which are not valid UTF-8 (they contain ' . 'invalid byte sequences). You can either stop this workflow and fix ' . 'these files, or continue. If you continue, these files will be ' . 'marked as binary.' => array('This diff includes a file which is not valid UTF-8 (it has invalid ' . 'byte sequences). You can either stop this workflow and fix it, or ' . 'continue. If you continue, this file will be marked as binary.', 'This diff includes files which are not valid UTF-8 (they contain ' . 'invalid byte sequences). You can either stop this workflow and fix ' . 'these files, or continue. If you continue, these files will be ' . 'marked as binary.'), 'AFFECTED FILE(S)' => array('AFFECTED FILE', 'AFFECTED FILES'), 'Do you want to mark these files as binary and continue?' => array('Do you want to mark this file as binary and continue?', 'Do you want to mark these files as binary and continue?'), 'Do you want to amend these files to the commit?' => array('Do you want to amend this file to the commit?', 'Do you want to amend these files to the commit?'), 'Do you want to add these files to the commit?' => array('Do you want to add this file to the commit?', 'Do you want to add these files to the commit?'), 'line(s)' => array('line', 'lines'), '%d test(s)' => array('%d test', '%d tests'), '%d assertion(s) passed.' => array('%d assertion passed.', '%d assertions passed.'))); phutil_load_library(dirname(dirname(__FILE__)) . '/src/');
public static function setInstance(PhutilTranslator $instance) { self::$instance = $instance; }
public function testHTMLTranslations() { $string = '%s awoke <strong>suddenly</strong> at %s.'; $when = '<4 AM>'; $translator = new PhutilTranslator(); // When no components are HTML, everything is treated as a string. $who = '<span>Abraham</span>'; $translation = $translator->translate($string, $who, $when); $this->assertEqual(true, gettype($translation) == 'string'); $this->assertEqual('<span>Abraham</span> awoke <strong>suddenly</strong> at <4 AM>.', $translation); // When at least one component is HTML, everything is treated as HTML. $who = phutil_tag('span', array(), 'Abraham'); $translation = $translator->translate($string, $who, $when); $this->assertEqual(true, $translation instanceof PhutilSafeHTML); $this->assertEqual('<span>Abraham</span> awoke <strong>suddenly</strong> at <4 AM>.', $translation->getHTMLContent()); }
/** * Translate a string. It uses a translator set by * `PhutilTranslator::setInstance()` or translations specified by * `PhutilTranslator::getInstance()->addTranslations()` and language rules set * by `PhutilTranslator::getInstance()->setLanguage()`. * * @param string Translation identifier with sprintf() placeholders. * @param mixed Value to select the variant from (e.g. singular or plural). * @param ... Next values referenced from $text. * @return string Translated string with substituted values. * * @group internationalization */ function pht($text, $variant = null) { $args = func_get_args(); $translator = PhutilTranslator::getInstance(); return call_user_func_array(array($translator, 'translate'), $args); }
public static function setLocaleCode($locale_code) { if (!$locale_code) { return; } if ($locale_code == self::$localeCode) { return; } try { $locale = PhutilLocale::loadLocale($locale_code); $translations = PhutilTranslation::getTranslationMapForLocale($locale_code); $override = self::getEnvConfig('translation.override'); if (!is_array($override)) { $override = array(); } PhutilTranslator::getInstance()->setLocale($locale)->setTranslations($override + $translations); self::$localeCode = $locale_code; } catch (Exception $ex) { // Just ignore this; the user likely has an out-of-date locale code. } }
public function willBeginExecution() { $request = $this->getRequest(); if ($request->getUser()) { // NOTE: Unit tests can set a user explicitly. Normal requests are not // permitted to do this. PhabricatorTestCase::assertExecutingUnitTests(); $user = $request->getUser(); } else { $user = new PhabricatorUser(); $session_engine = new PhabricatorAuthSessionEngine(); $phsid = $request->getCookie(PhabricatorCookies::COOKIE_SESSION); if (strlen($phsid)) { $session_user = $session_engine->loadUserForSession(PhabricatorAuthSession::TYPE_WEB, $phsid); if ($session_user) { $user = $session_user; } } else { // If the client doesn't have a session token, generate an anonymous // session. This is used to provide CSRF protection to logged-out users. $phsid = $session_engine->establishSession(PhabricatorAuthSession::TYPE_WEB, null, $partial = false); // This may be a resource request, in which case we just don't set // the cookie. if ($request->canSetCookies()) { $request->setCookie(PhabricatorCookies::COOKIE_SESSION, $phsid); } } if (!$user->isLoggedIn()) { $user->attachAlternateCSRFString(PhabricatorHash::digest($phsid)); } $request->setUser($user); } $translation = $user->getTranslation(); if ($translation && $translation != PhabricatorEnv::getEnvConfig('translation.provider')) { $translation = newv($translation, array()); PhutilTranslator::getInstance()->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations()); } $preferences = $user->loadPreferences(); if (PhabricatorEnv::getEnvConfig('darkconsole.enabled')) { $dark_console = PhabricatorUserPreferences::PREFERENCE_DARK_CONSOLE; if ($preferences->getPreference($dark_console) || PhabricatorEnv::getEnvConfig('darkconsole.always-on')) { $console = new DarkConsoleCore(); $request->getApplicationConfiguration()->setConsole($console); } } // NOTE: We want to set up the user first so we can render a real page // here, but fire this before any real logic. $restricted = array('code'); foreach ($restricted as $parameter) { if ($request->getExists($parameter)) { if (!$this->shouldAllowRestrictedParameter($parameter)) { throw new Exception(pht('Request includes restricted parameter "%s", but this ' . 'controller ("%s") does not whitelist it. Refusing to ' . 'serve this request because it might be part of a redirection ' . 'attack.', $parameter, get_class($this))); } } } if ($this->shouldRequireEnabledUser()) { if ($user->isLoggedIn() && !$user->getIsApproved()) { $controller = new PhabricatorAuthNeedsApprovalController($request); return $this->delegateToController($controller); } if ($user->getIsDisabled()) { $controller = new PhabricatorDisabledUserController($request); return $this->delegateToController($controller); } } $event = new PhabricatorEvent(PhabricatorEventType::TYPE_CONTROLLER_CHECKREQUEST, array('request' => $request, 'controller' => $this)); $event->setUser($user); PhutilEventEngine::dispatchEvent($event); $checker_controller = $event->getValue('controller'); if ($checker_controller != $this) { return $this->delegateToController($checker_controller); } $auth_class = 'PhabricatorAuthApplication'; $auth_application = PhabricatorApplication::getByClass($auth_class); // Require partial sessions to finish login before doing anything. if (!$this->shouldAllowPartialSessions()) { if ($user->hasSession() && $user->getSession()->getIsPartial()) { $login_controller = new PhabricatorAuthFinishController($request); $this->setCurrentApplication($auth_application); return $this->delegateToController($login_controller); } } // Check if the user needs to configure MFA. $need_mfa = $this->shouldRequireMultiFactorEnrollment(); $have_mfa = $user->getIsEnrolledInMultiFactor(); if ($need_mfa && !$have_mfa) { // Check if the cache is just out of date. Otherwise, roadblock the user // and require MFA enrollment. $user->updateMultiFactorEnrollment(); if (!$user->getIsEnrolledInMultiFactor()) { $mfa_controller = new PhabricatorAuthNeedsMultiFactorController($request); $this->setCurrentApplication($auth_application); return $this->delegateToController($mfa_controller); } } if ($this->shouldRequireLogin()) { // This actually means we need either: // - a valid user, or a public controller; and // - permission to see the application. $allow_public = $this->shouldAllowPublic() && PhabricatorEnv::getEnvConfig('policy.allow-public'); // If this controller isn't public, and the user isn't logged in, require // login. if (!$allow_public && !$user->isLoggedIn()) { $login_controller = new PhabricatorAuthStartController($request); $this->setCurrentApplication($auth_application); return $this->delegateToController($login_controller); } if ($user->isLoggedIn()) { if ($this->shouldRequireEmailVerification()) { if (!$user->getIsEmailVerified()) { $controller = new PhabricatorMustVerifyEmailController($request); $this->setCurrentApplication($auth_application); return $this->delegateToController($controller); } } } // If the user doesn't have access to the application, don't let them use // any of its controllers. We query the application in order to generate // a policy exception if the viewer doesn't have permission. $application = $this->getCurrentApplication(); if ($application) { id(new PhabricatorApplicationQuery())->setViewer($user)->withPHIDs(array($application->getPHID()))->executeOne(); } } // NOTE: We do this last so that users get a login page instead of a 403 // if they need to login. if ($this->shouldRequireAdmin() && !$user->getIsAdmin()) { return new Aphront403Response(); } }
* - Next to 'arcanist/'. * - Anywhere in the normal PHP 'include_path'. * - Inside 'arcanist/externals/includes/'. * * When looking in these places, we expect to find a 'libphutil/' directory. */ function arcanist_adjust_php_include_path() { // The 'arcanist/' directory. $arcanist_dir = dirname(dirname(__FILE__)); // The parent directory of 'arcanist/'. $parent_dir = dirname($arcanist_dir); // The 'arcanist/externals/includes/' directory. $include_dir = implode(DIRECTORY_SEPARATOR, array($arcanist_dir, 'externals', 'includes')); $php_include_path = ini_get('include_path'); $php_include_path = implode(PATH_SEPARATOR, array($parent_dir, $php_include_path, $include_dir)); ini_set('include_path', $php_include_path); } arcanist_adjust_php_include_path(); if (getenv('ARC_PHUTIL_PATH')) { @(include_once getenv('ARC_PHUTIL_PATH') . '/scripts/__init_script__.php'); } else { @(include_once 'libphutil/scripts/__init_script__.php'); } if (!@constant('__LIBPHUTIL__')) { echo "ERROR: Unable to load libphutil. Put libphutil/ next to arcanist/, or " . "update your PHP 'include_path' to include the parent directory of " . "libphutil/, or symlink libphutil/ into arcanist/externals/includes/.\n"; exit(1); } phutil_load_library(dirname(dirname(__FILE__)) . '/src/'); PhutilTranslator::getInstance()->setLocale(PhutilLocale::loadLocale('en_US'))->setTranslations(PhutilTranslation::getTranslationMapForLocale('en_US'));
public function send() { $to_phids = $this->getToPHIDs(); if (!$to_phids) { throw new Exception('No "To:" users provided!'); } $cc_phids = $this->getCCPHIDs(); $attachments = $this->buildAttachments(); $template = new PhabricatorMetaMTAMail(); $actor_handle = $this->getActorHandle(); $reply_handler = $this->getReplyHandler(); if ($actor_handle) { $template->setFrom($actor_handle->getPHID()); } $template->setIsHTML($this->shouldMarkMailAsHTML())->setParentMessageID($this->parentMessageID)->addHeader('Thread-Topic', $this->getThreadTopic()); $template->setAttachments($attachments); $template->setThreadID($this->getThreadID(), $this->isFirstMailAboutRevision()); if ($this->heraldRulesHeader) { $template->addHeader('X-Herald-Rules', $this->heraldRulesHeader); } $revision = $this->revision; if ($revision) { if ($revision->getAuthorPHID()) { $template->addHeader('X-Differential-Author', '<' . $revision->getAuthorPHID() . '>'); } $reviewer_phids = $revision->getReviewers(); if ($reviewer_phids) { // Add several headers to support e-mail clients which are not able to // create rules using regular expressions or wildcards (namely Outlook). $template->addPHIDHeaders('X-Differential-Reviewer', $reviewer_phids); // Add it also as a list to allow matching of the first reviewer and // also for backwards compatibility. $template->addHeader('X-Differential-Reviewers', '<' . implode('>, <', $reviewer_phids) . '>'); } if ($cc_phids) { $template->addPHIDHeaders('X-Differential-CC', $cc_phids); $template->addHeader('X-Differential-CCs', '<' . implode('>, <', $cc_phids) . '>'); // Determine explicit CCs (those added by humans) and put them in a // header so users can differentiate between Herald CCs and human CCs. $relation_subscribed = DifferentialRevision::RELATION_SUBSCRIBED; $raw = $revision->getRawRelations($relation_subscribed); $reason_phids = ipull($raw, 'reasonPHID'); $reason_handles = id(new PhabricatorObjectHandleData($reason_phids))->loadHandles(); $explicit_cc = array(); foreach ($raw as $relation) { if (!$relation['reasonPHID']) { continue; } $type = $reason_handles[$relation['reasonPHID']]->getType(); if ($type == PhabricatorPHIDConstants::PHID_TYPE_USER) { $explicit_cc[] = $relation['objectPHID']; } } if ($explicit_cc) { $template->addPHIDHeaders('X-Differential-Explicit-CC', $explicit_cc); $template->addHeader('X-Differential-Explicit-CCs', '<' . implode('>, <', $explicit_cc) . '>'); } } } $template->setIsBulk(true); $template->setRelatedPHID($this->getRevision()->getPHID()); $mailtags = $this->getMailTags(); if ($mailtags) { $template->setMailTags($mailtags); } $phids = array(); foreach ($to_phids as $phid) { $phids[$phid] = true; } foreach ($cc_phids as $phid) { $phids[$phid] = true; } $phids = array_keys($phids); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $objects = id(new PhabricatorObjectHandleData($phids))->loadObjects(); $to_handles = array_select_keys($handles, $to_phids); $cc_handles = array_select_keys($handles, $cc_phids); $this->prepareBody(); $mails = $reply_handler->multiplexMail($template, $to_handles, $cc_handles); $original_translator = PhutilTranslator::getInstance(); if (!PhabricatorMetaMTAMail::shouldMultiplexAllMail()) { $translation = PhabricatorEnv::newObjectFromConfig('translation.provider'); $translator = id(new PhutilTranslator())->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations()); } try { foreach ($mails as $mail) { if (PhabricatorMetaMTAMail::shouldMultiplexAllMail()) { $translation = newv($mail->getTranslation($objects), array()); $translator = id(new PhutilTranslator())->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations()); PhutilTranslator::setInstance($translator); } $body = $this->buildBody() . "\n" . $reply_handler->getRecipientsSummary($to_handles, $cc_handles); $mail->setSubject($this->renderSubject())->setSubjectPrefix($this->getSubjectPrefix())->setVarySubjectPrefix($this->renderVaryPrefix())->setBody($body); $event = new PhabricatorEvent(PhabricatorEventType::TYPE_DIFFERENTIAL_WILLSENDMAIL, array('mail' => $mail)); PhutilEventEngine::dispatchEvent($event); $mail = $event->getValue('mail'); $mail->saveAndSend(); } } catch (Exception $ex) { PhutilTranslator::setInstance($original_translator); throw $ex; } PhutilTranslator::setInstance($original_translator); }
private static function initializeCommonEnvironment() { PhutilErrorHandler::initialize(); self::buildConfigurationSourceStack(); // Force a valid timezone. If both PHP and Phabricator configuration are // invalid, use UTC. $tz = PhabricatorEnv::getEnvConfig('phabricator.timezone'); if ($tz) { @date_default_timezone_set($tz); } $ok = @date_default_timezone_set(date_default_timezone_get()); if (!$ok) { date_default_timezone_set('UTC'); } // Prepend '/support/bin' and append any paths to $PATH if we need to. $env_path = getenv('PATH'); $phabricator_path = dirname(phutil_get_library_root('phabricator')); $support_path = $phabricator_path . '/support/bin'; $env_path = $support_path . PATH_SEPARATOR . $env_path; $append_dirs = PhabricatorEnv::getEnvConfig('environment.append-paths'); if (!empty($append_dirs)) { $append_path = implode(PATH_SEPARATOR, $append_dirs); $env_path = $env_path . PATH_SEPARATOR . $append_path; } putenv('PATH=' . $env_path); // Write this back into $_ENV, too, so ExecFuture picks it up when creating // subprocess environments. $_ENV['PATH'] = $env_path; PhabricatorEventEngine::initialize(); $translation = PhabricatorEnv::newObjectFromConfig('translation.provider'); PhutilTranslator::getInstance()->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations()); }