*/
class I18nSubscriber implements EventSubscriberInterface {
+ /**
+ * Used for rolling back language to its original setting after the api call.
+ *
+ * @var array
+ */
+ public $originalLang = [];
+
/**
* @return array
*/
public static function getSubscribedEvents() {
return [
Events::PREPARE => ['onApiPrepare', Events::W_MIDDLE],
+ Events::RESPOND => ['onApiRespond', Events::W_LATE],
];
}
/**
+ * Support multi-lingual requests
+ *
* @param \Civi\API\Event\Event $event
* API preparation event.
*
public function onApiPrepare(\Civi\API\Event\Event $event) {
$apiRequest = $event->getApiRequest();
- // support multi-lingual requests
- if ($language = \CRM_Utils_Array::value('option.language', $apiRequest['params'])) {
- $this->setLocale($language);
+ $params = $apiRequest['params'];
+ if ($apiRequest['version'] < 4) {
+ $language = !empty($params['options']['language']) ? $params['options']['language'] : \CRM_Utils_Array::value('option.language', $params);
+ }
+ else {
+ $language = \CRM_Utils_Array::value('language', $params);
+ }
+ if ($language) {
+ $this->setLocale($language, $apiRequest['id']);
+ }
+ }
+
+ /**
+ * Reset language to the default.
+ *
+ * @param \Civi\API\Event\Event $event
+ *
+ * @throws \API_Exception
+ */
+ public function onApiRespond(\Civi\API\Event\Event $event) {
+ $apiRequest = $event->getApiRequest();
+
+ if (!empty($this->originalLang[$apiRequest['id']])) {
+ global $tsLocale;
+ global $dbLocale;
+ $tsLocale = $this->originalLang[$apiRequest['id']]['tsLocale'];
+ $dbLocale = $this->originalLang[$apiRequest['id']]['dbLocale'];
}
}
* Sets the tsLocale and dbLocale for multi-lingual sites.
* Some code duplication from CRM/Core/BAO/ConfigSetting.php retrieve()
* to avoid regressions from refactoring.
- * @param $lcMessagesRequest
+ * @param string $lcMessages
+ * @param int $requestId
* @throws \API_Exception
*/
- public function setLocale($lcMessagesRequest) {
- // We must validate whether the locale is valid, otherwise setting a bad
- // dbLocale could probably lead to sql-injection.
+ public function setLocale($lcMessages, $requestId) {
$domain = new \CRM_Core_DAO_Domain();
$domain->id = \CRM_Core_Config::domainID();
$domain->find(TRUE);
- // are we in a multi-language setup?
- $multiLang = $domain->locales ? TRUE : FALSE;
- $lcMessages = NULL;
-
- // on multi-lang sites based on request and civicrm_uf_match
- if ($multiLang) {
- $config = \CRM_Core_Config::singleton();
- $languageLimit = [];
- if (isset($config->languageLimit) and $config->languageLimit) {
- $languageLimit = $config->languageLimit;
+ // Check if the site is multi-lingual
+ if ($domain->locales && $lcMessages) {
+ // Validate language, otherwise a bad dbLocale could probably lead to sql-injection.
+ if (!array_key_exists($lcMessages, \Civi::settings()->get('languageLimit'))) {
+ throw new \API_Exception(ts('Language not enabled: %1', [1 => $lcMessages]));
}
- if (in_array($lcMessagesRequest, array_keys($languageLimit))) {
- $lcMessages = $lcMessagesRequest;
- }
- else {
- throw new \API_Exception(ts('Language not enabled: %1', [1 => $lcMessagesRequest]));
- }
- }
+ global $dbLocale;
+ global $tsLocale;
- global $dbLocale;
+ // Store original value to be restored in $this->onApiRespond
+ $this->originalLang[$requestId] = [
+ 'tsLocale' => $tsLocale,
+ 'dbLocale' => $dbLocale,
+ ];
- // set suffix for table names - use views if more than one language
- if ($lcMessages) {
- $dbLocale = $multiLang && $lcMessages ? "_{$lcMessages}" : '';
+ // Set suffix for table names - use views if more than one language
+ $dbLocale = "_{$lcMessages}";
- // FIXME: an ugly hack to fix CRM-4041
- global $tsLocale;
+ // Also set tsLocale - CRM-4041
$tsLocale = $lcMessages;
}
}