From 069e60d2ff92de015ba679621ca3a35949669824 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 3 Jun 2015 10:49:27 -0700 Subject: [PATCH] Send mail to targets in the user's translation Summary: Ref T6367. Test Plan: - Added and executed unit tests. - Sent mail to A (en_US) and B (en_A*). - Got one mail in English and one mail in ENGLISH. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6367 Differential Revision: https://secure.phabricator.com/D13142 --- src/__phutil_library_map__.php | 4 ++ .../base/controller/PhabricatorController.php | 5 +- .../PhabricatorRepositoryPushMailWorker.php | 3 +- ...habricatorApplicationTransactionEditor.php | 8 ++- src/infrastructure/env/PhabricatorEnv.php | 12 +++++ .../scope/PhabricatorLocaleScopeGuard.php | 54 +++++++++++++++++++ .../PhabricatorLocaleScopeGuardTestCase.php | 38 +++++++++++++ 7 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 src/infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php create mode 100644 src/infrastructure/internationalization/scope/__tests__/PhabricatorLocaleScopeGuardTestCase.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 1d8370f393..f313ea08ae 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1976,6 +1976,8 @@ phutil_register_library_map(array( 'PhabricatorListFilterUIExample' => 'applications/uiexample/examples/PhabricatorListFilterUIExample.php', 'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php', 'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php', + 'PhabricatorLocaleScopeGuard' => 'infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php', + 'PhabricatorLocaleScopeGuardTestCase' => 'infrastructure/internationalization/scope/__tests__/PhabricatorLocaleScopeGuardTestCase.php', 'PhabricatorLogTriggerAction' => 'infrastructure/daemon/workers/action/PhabricatorLogTriggerAction.php', 'PhabricatorLogoutController' => 'applications/auth/controller/PhabricatorLogoutController.php', 'PhabricatorLunarPhasePolicyRule' => 'applications/policy/rule/PhabricatorLunarPhasePolicyRule.php', @@ -5389,6 +5391,8 @@ phutil_register_library_map(array( 'PhabricatorListFilterUIExample' => 'PhabricatorUIExample', 'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase', + 'PhabricatorLocaleScopeGuard' => 'Phobject', + 'PhabricatorLocaleScopeGuardTestCase' => 'PhabricatorTestCase', 'PhabricatorLogTriggerAction' => 'PhabricatorTriggerAction', 'PhabricatorLogoutController' => 'PhabricatorAuthController', 'PhabricatorLunarPhasePolicyRule' => 'PhabricatorPolicyRule', diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php index 04bb633d4e..3476bb8f9a 100644 --- a/src/applications/base/controller/PhabricatorController.php +++ b/src/applications/base/controller/PhabricatorController.php @@ -114,10 +114,7 @@ abstract class PhabricatorController extends AphrontController { $request->setUser($user); } - $locale_code = $user->getTranslation(); - if ($locale_code) { - PhabricatorEnv::setLocaleCode($locale_code); - } + PhabricatorEnv::setLocaleCode($user->getTranslation()); $preferences = $user->loadPreferences(); if (PhabricatorEnv::getEnvConfig('darkconsole.enabled')) { diff --git a/src/applications/repository/worker/PhabricatorRepositoryPushMailWorker.php b/src/applications/repository/worker/PhabricatorRepositoryPushMailWorker.php index af9fcd4cfc..17c6d17d5b 100644 --- a/src/applications/repository/worker/PhabricatorRepositoryPushMailWorker.php +++ b/src/applications/repository/worker/PhabricatorRepositoryPushMailWorker.php @@ -42,7 +42,8 @@ final class PhabricatorRepositoryPushMailWorker $task_data = $this->getTaskData(); $viewer = $target->getViewer(); - // TODO: Swap locale to viewer locale. + + $locale = PhabricatorEnv::beginScopedLocale($viewer->getTranslation()); $logs = $event->getLogs(); diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php index f4f09dcdbc..bd77b7e98a 100644 --- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php +++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php @@ -2139,8 +2139,10 @@ abstract class PhabricatorApplicationTransactionEditor $mailed = array(); foreach ($targets as $target) { $original_actor = $this->getActor(); - $this->setActor($target->getViewer()); - // TODO: Swap locale to viewer locale. + + $viewer = $target->getViewer(); + $this->setActor($viewer); + $locale = PhabricatorEnv::beginScopedLocale($viewer->getTranslation()); $caught = null; try { @@ -2153,6 +2155,8 @@ abstract class PhabricatorApplicationTransactionEditor } $this->setActor($original_actor); + unset($locale); + if ($caught) { throw $ex; } diff --git a/src/infrastructure/env/PhabricatorEnv.php b/src/infrastructure/env/PhabricatorEnv.php index 4d1f8ad4a2..f6bf920dfe 100644 --- a/src/infrastructure/env/PhabricatorEnv.php +++ b/src/infrastructure/env/PhabricatorEnv.php @@ -129,7 +129,19 @@ final class PhabricatorEnv { self::setLocaleCode('en_US'); } + public static function beginScopedLocale($locale_code) { + return new PhabricatorLocaleScopeGuard($locale_code); + } + + public static function getLocaleCode() { + return self::$localeCode; + } + public static function setLocaleCode($locale_code) { + if (!$locale_code) { + return; + } + if ($locale_code == self::$localeCode) { return; } diff --git a/src/infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php b/src/infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php new file mode 100644 index 0000000000..d98436d2c2 --- /dev/null +++ b/src/infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php @@ -0,0 +1,54 @@ +key = last_key(self::$stack); + + PhabricatorEnv::setLocaleCode($code); + } + + public function __destruct() { + if ($this->destroyed) { + return; + } + $this->destroyed = true; + + // Remove this locale from the stack and set the new active locale. Usually, + // we're the last item on the stack, so this shortens the stack by one item + // and sets the locale underneath. However, it's possible that guards are + // being destroyed out of order, so we might just be removing an item + // somewhere in the middle of the stack. In this case, we won't actually + // change the locale, just set it to its current value again. + + unset(self::$stack[$this->key]); + PhabricatorEnv::setLocaleCode(end(self::$stack)); + } + +} diff --git a/src/infrastructure/internationalization/scope/__tests__/PhabricatorLocaleScopeGuardTestCase.php b/src/infrastructure/internationalization/scope/__tests__/PhabricatorLocaleScopeGuardTestCase.php new file mode 100644 index 0000000000..86cc533304 --- /dev/null +++ b/src/infrastructure/internationalization/scope/__tests__/PhabricatorLocaleScopeGuardTestCase.php @@ -0,0 +1,38 @@ +assertEqual('en_GB', PhabricatorEnv::getLocaleCode()); + unset($guard); + $this->assertEqual($original, PhabricatorEnv::getLocaleCode()); + + // Nest guards, then destroy them out of order. + $guard1 = PhabricatorEnv::beginScopedLocale('en_GB'); + $this->assertEqual('en_GB', PhabricatorEnv::getLocaleCode()); + $guard2 = PhabricatorEnv::beginScopedLocale('en_A*'); + $this->assertEqual('en_A*', PhabricatorEnv::getLocaleCode()); + unset($guard1); + $this->assertEqual('en_A*', PhabricatorEnv::getLocaleCode()); + unset($guard2); + $this->assertEqual($original, PhabricatorEnv::getLocaleCode()); + + // If you push `null`, that should mean "the default locale", not + // "the current locale". + $guard3 = PhabricatorEnv::beginScopedLocale('en_GB'); + $this->assertEqual('en_GB', PhabricatorEnv::getLocaleCode()); + $guard4 = PhabricatorEnv::beginScopedLocale(null); + $this->assertEqual($original, PhabricatorEnv::getLocaleCode()); + unset($guard4); + $this->assertEqual('en_GB', PhabricatorEnv::getLocaleCode()); + unset($guard3); + $this->assertEqual($original, PhabricatorEnv::getLocaleCode()); + + } + +}