From b72b5fc077827dab95096f9cbaa7bf477fe17ab9 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 8 Sep 2015 14:23:42 -0700 Subject: [PATCH] CRM-16373 - Localization - Rearrange load/save logic * Declare missing setting `languageLimit` * Allow saving admin form -- even when using makeMultilingual, makeSinglelingual, addLanguage, and/or languageLimit * Move onChange logic for `lcMessages` from `ConfigSetting::add()` to `onChangeLcMessages()` * Move locale init from `ConfigSetting::retrieve()` to `applyLocale()` --- CRM/Admin/Form/Setting/Localization.php | 43 ++++-- CRM/Core/BAO/ConfigSetting.php | 174 +++++++++++------------- CRM/Core/BAO/Setting.php | 3 +- settings/Localization.setting.php | 31 ++++- 4 files changed, 146 insertions(+), 105 deletions(-) diff --git a/CRM/Admin/Form/Setting/Localization.php b/CRM/Admin/Form/Setting/Localization.php index d8e9e29cd2..ead6d55efc 100644 --- a/CRM/Admin/Form/Setting/Localization.php +++ b/CRM/Admin/Form/Setting/Localization.php @@ -62,15 +62,15 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting { CRM_Utils_System::setTitle(ts('Settings - Localization')); $warningTitle = json_encode(ts("Warning")); - $lcMessages = CRM_Admin_Form_Setting_Localization::getDefaultLocaleOptions(); + $defaultLocaleOptions = CRM_Admin_Form_Setting_Localization::getDefaultLocaleOptions(); $domain = new CRM_Core_DAO_Domain(); $domain->find(TRUE); if ($domain->locales) { // add language limiter and language adder - $this->addCheckBox('languageLimit', ts('Available Languages'), array_flip($lcMessages), NULL, NULL, NULL, NULL, '   '); - $this->addElement('select', 'addLanguage', ts('Add Language'), array_merge(array('' => ts('- select -')), array_diff(CRM_Core_I18n::languages(), $lcMessages))); + $this->addCheckBox('languageLimit', ts('Available Languages'), array_flip($defaultLocaleOptions), NULL, NULL, NULL, NULL, '   '); + $this->addElement('select', 'addLanguage', ts('Add Language'), array_merge(array('' => ts('- select -')), array_diff(CRM_Core_I18n::languages(), $defaultLocaleOptions))); // add the ability to return to single language $warning = ts('This will make your CiviCRM installation a single-language one again. THIS WILL DELETE ALL DATA RELATED TO LANGUAGES OTHER THAN THE DEFAULT ONE SELECTED ABOVE (and only that language will be preserved).'); @@ -167,6 +167,8 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting { // retrieve default values for currencyLimit $this->_defaults['currencyLimit'] = array_keys(CRM_Core_OptionGroup::values('currencies_enabled')); + $this->_defaults['languageLimit'] = Civi::settings()->get('languageLimit'); + // CRM-5111: unset these two unconditionally, we don’t want them to stick – ever unset($this->_defaults['makeMultilingual']); unset($this->_defaults['makeSinglelingual']); @@ -248,8 +250,16 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting { // if we manipulated the language list, return to the localization admin screen $return = (bool) (CRM_Utils_Array::value('makeMultilingual', $values) or CRM_Utils_Array::value('addLanguage', $values)); + $filteredValues = $values; + unset($filteredValues['makeMultilingual']); + unset($filteredValues['makeSinglelingual']); + unset($filteredValues['addLanguage']); + unset($filteredValues['languageLimit']); + + Civi::settings()->set('languageLimit', CRM_Utils_Array::value('languageLimit', $values)); + // save all the settings - parent::commonProcess($values); + parent::commonProcess($filteredValues); if ($return) { CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/setting/localization', 'reset=1')); @@ -277,17 +287,17 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting { $locales = CRM_Core_I18n::languages(); if ($domain->locales) { // for multi-lingual sites, populate default language drop-down with available languages - $lcMessages = array(); + $defaultLocaleOptions = array(); foreach ($locales as $loc => $lang) { if (substr_count($domain->locales, $loc)) { - $lcMessages[$loc] = $lang; + $defaultLocaleOptions[$loc] = $lang; } } } else { - $lcMessages = $locales; + $defaultLocaleOptions = $locales; } - return $lcMessages; + return $defaultLocaleOptions; } /** @@ -311,4 +321,21 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting { return $_currencySymbols; } + public static function onChangeLcMessages($oldLocale, $newLocale, $metadata, $domainID) { + if ($oldLocale == $newLocale) { + return; + } + + $session = CRM_Core_Session::singleton(); + if ($newLocale && $session->get('userID')) { + $ufm = new CRM_Core_DAO_UFMatch(); + $ufm->contact_id = $session->get('userID'); + if ($newLocale && $ufm->find(TRUE)) { + $ufm->language = $newLocale; + $ufm->save(); + $session->set('lcMessages', $newLocale); + } + } + } + } diff --git a/CRM/Core/BAO/ConfigSetting.php b/CRM/Core/BAO/ConfigSetting.php index 051d7352a6..de61ec0eee 100644 --- a/CRM/Core/BAO/ConfigSetting.php +++ b/CRM/Core/BAO/ConfigSetting.php @@ -75,27 +75,6 @@ class CRM_Core_BAO_ConfigSetting { } } - //keep user preferred language up to date, CRM-7746 - $session = CRM_Core_Session::singleton(); - $lcMessages = CRM_Utils_Array::value('lcMessages', $params); - if ($lcMessages && $session->get('userID')) { - $languageLimit = CRM_Utils_Array::value('languageLimit', $params); - if (is_array($languageLimit) && - !in_array($lcMessages, array_keys($languageLimit)) - ) { - $lcMessages = $session->get('lcMessages'); - } - - $ufm = new CRM_Core_DAO_UFMatch(); - $ufm->contact_id = $session->get('userID'); - if ($lcMessages && $ufm->find(TRUE)) { - $ufm->language = $lcMessages; - $ufm->save(); - $session->set('lcMessages', $lcMessages); - $params['lcMessages'] = $lcMessages; - } - } - $domain->config_backend = serialize($params); $domain->save(); } @@ -139,95 +118,106 @@ class CRM_Core_BAO_ConfigSetting { } } - // are we in a multi-language setup? - $multiLang = $domain->locales ? TRUE : FALSE; + CRM_Core_BAO_ConfigSetting::applyLocale(Civi::settings($domain->id), $domain->locales); + } + } - // set the current language - $lcMessages = NULL; + /** + * Evaluate locale preferences and activate a chosen locale by + * updating session+global variables. + * + * @param \Civi\Core\SettingsBag $settings + * @param string $activatedLocales + * Imploded list of locales which are supported in the DB. + * @return array + */ + public static function applyLocale($settings, $activatedLocales) { + // are we in a multi-language setup? + $multiLang = $activatedLocales ? TRUE : FALSE; - $session = CRM_Core_Session::singleton(); + // set the current language + $chosenLocale = NULL; - // on multi-lang sites based on request and civicrm_uf_match - if ($multiLang) { - $lcMessagesRequest = CRM_Utils_Request::retrieve('lcMessages', 'String', $this); - $languageLimit = array(); - if (array_key_exists('languageLimit', $defaults) && is_array($defaults['languageLimit'])) { - $languageLimit = $defaults['languageLimit']; - } + $session = CRM_Core_Session::singleton(); - if (in_array($lcMessagesRequest, array_keys($languageLimit))) { - $lcMessages = $lcMessagesRequest; + // on multi-lang sites based on request and civicrm_uf_match + if ($multiLang) { + $languageLimit = array(); + if (is_array($settings->get('languageLimit'))) { + $languageLimit = $settings->get('languageLimit'); + } - //CRM-8559, cache navigation do not respect locale if it is changed, so reseting cache. - CRM_Core_BAO_Cache::deleteGroup('navigation'); - } - else { - $lcMessagesRequest = NULL; - } + $requestLocale = CRM_Utils_Request::retrieve('lcMessages', 'String'); + if (in_array($requestLocale, array_keys($languageLimit))) { + $chosenLocale = $requestLocale; - if (!$lcMessagesRequest) { - $lcMessagesSession = $session->get('lcMessages'); - if (in_array($lcMessagesSession, array_keys($languageLimit))) { - $lcMessages = $lcMessagesSession; - } - else { - $lcMessagesSession = NULL; - } - } + //CRM-8559, cache navigation do not respect locale if it is changed, so reseting cache. + // Ed: This doesn't sound good. + CRM_Core_BAO_Cache::deleteGroup('navigation'); + } + else { + $requestLocale = NULL; + } - if ($lcMessagesRequest) { - $ufm = new CRM_Core_DAO_UFMatch(); - $ufm->contact_id = $session->get('userID'); - if ($ufm->find(TRUE)) { - $ufm->language = $lcMessages; - $ufm->save(); - } - $session->set('lcMessages', $lcMessages); + if (!$requestLocale) { + $sessionLocale = $session->get('lcMessages'); + if (in_array($sessionLocale, array_keys($languageLimit))) { + $chosenLocale = $sessionLocale; + } + else { + $sessionLocale = NULL; } + } - if (!$lcMessages and $session->get('userID')) { - $ufm = new CRM_Core_DAO_UFMatch(); - $ufm->contact_id = $session->get('userID'); - if ($ufm->find(TRUE) && - in_array($ufm->language, array_keys($languageLimit)) - ) { - $lcMessages = $ufm->language; - } - $session->set('lcMessages', $lcMessages); + if ($requestLocale) { + $ufm = new CRM_Core_DAO_UFMatch(); + $ufm->contact_id = $session->get('userID'); + if ($ufm->find(TRUE)) { + $ufm->language = $chosenLocale; + $ufm->save(); } + $session->set('lcMessages', $chosenLocale); } - global $dbLocale; - - // try to inherit the language from the hosting CMS - if (!empty($defaults['inheritLocale'])) { - // FIXME: On multilanguage installs, CRM_Utils_System::getUFLocale() in many cases returns nothing if $dbLocale is not set - $dbLocale = $multiLang ? "_{$defaults['lcMessages']}" : ''; - $lcMessages = CRM_Utils_System::getUFLocale(); - if ($domain->locales and !in_array($lcMessages, explode(CRM_Core_DAO::VALUE_SEPARATOR, - $domain->locales - )) + + if (!$chosenLocale and $session->get('userID')) { + $ufm = new CRM_Core_DAO_UFMatch(); + $ufm->contact_id = $session->get('userID'); + if ($ufm->find(TRUE) && + in_array($ufm->language, array_keys($languageLimit)) ) { - $lcMessages = NULL; + $chosenLocale = $ufm->language; } + $session->set('lcMessages', $chosenLocale); } - - if (empty($lcMessages)) { - //CRM-11993 - if a single-lang site, use default - $lcMessages = CRM_Utils_Array::value('lcMessages', $defaults); + } + global $dbLocale; + + // try to inherit the language from the hosting CMS + if ($settings->get('inheritLocale')) { + // FIXME: On multilanguage installs, CRM_Utils_System::getUFLocale() in many cases returns nothing if $dbLocale is not set + $dbLocale = $multiLang ? ("_" . $settings->get('lcMessages')) : ''; + $chosenLocale = CRM_Utils_System::getUFLocale(); + if ($activatedLocales and !in_array($chosenLocale, explode(CRM_Core_DAO::VALUE_SEPARATOR, $activatedLocales))) { + $chosenLocale = NULL; } + } + + if (empty($chosenLocale)) { + //CRM-11993 - if a single-lang site, use default + $chosenLocale = $settings->get('lcMessages'); + } - // set suffix for table names - use views if more than one language - $dbLocale = $multiLang ? "_{$lcMessages}" : ''; + // set suffix for table names - use views if more than one language + $dbLocale = $multiLang ? "_{$chosenLocale}" : ''; - // FIXME: an ugly hack to fix CRM-4041 - global $tsLocale; - $tsLocale = $lcMessages; + // FIXME: an ugly hack to fix CRM-4041 + global $tsLocale; + $tsLocale = $chosenLocale; - // FIXME: as bad aplace as any to fix CRM-5428 - // (to be moved to a sane location along with the above) - if (function_exists('mb_internal_encoding')) { - mb_internal_encoding('UTF-8'); - } + // FIXME: as bad aplace as any to fix CRM-5428 + // (to be moved to a sane location along with the above) + if (function_exists('mb_internal_encoding')) { + mb_internal_encoding('UTF-8'); } } diff --git a/CRM/Core/BAO/Setting.php b/CRM/Core/BAO/Setting.php index d8eeadfc81..a9688fc9ac 100644 --- a/CRM/Core/BAO/Setting.php +++ b/CRM/Core/BAO/Setting.php @@ -381,7 +381,8 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting { Civi\Core\Resolver::singleton()->get($callback), unserialize($dao->value), $value, - $metadata + $metadata, + $domainID ); } } diff --git a/settings/Localization.setting.php b/settings/Localization.setting.php index 52ff3ba29e..4e57ffb6a4 100644 --- a/settings/Localization.setting.php +++ b/settings/Localization.setting.php @@ -210,7 +210,7 @@ return array( 'multiple' => 1, 'class' => 'crm-select2', ), - 'default' => 'null', + 'default' => NULL, 'add' => '4.3', 'title' => 'Available Countries', 'is_domain' => 1, @@ -234,7 +234,7 @@ return array( 'multiple' => 1, 'class' => 'crm-select2', ), - 'default' => 'null', + 'default' => NULL, 'add' => '4.3', 'title' => 'Available States and Provinces', 'is_domain' => 1, @@ -407,14 +407,34 @@ return array( 'title' => 'Fiscal Year Start', 'description' => '', ), + 'languageLimit' => array( + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'languageLimit', + 'type' => 'Array', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array( + 'multiple' => 1, + 'class' => 'crm-select2', + ), + 'default' => NULL, + 'add' => '4.3', + 'title' => 'Available Languages (Multi-lingual)', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => NULL, + 'pseudoconstant' => array( + 'callback' => 'CRM_Core_I18n::languages', + ), + ), 'lcMessages' => array( 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'lcMessages', 'prefetch' => 1, // prefetch causes it to be cached in config settings. Usually this is a transitional setting. Some things like urls are permanent. Remove this comment if you have assessed & it should be permanent - //'config_only' => 1, - //@todo - see https://wiki.civicrm.org/confluence/display/CRMDOC/Settings+Reference#SettingsReference-Convertingaconfigobjecttoasetting on removing this deprecated value 'type' => 'String', 'quick_form_type' => 'Select', 'html_type' => 'Select', @@ -431,6 +451,9 @@ return array( 'pseudoconstant' => array( 'callback' => 'CRM_Admin_Form_Setting_Localization::getDefaultLocaleOptions', ), + 'on_change' => array( + 'CRM_Admin_Form_Setting_Localization::onChangeLcMessages', + ), ), 'legacyEncoding' => array( 'add' => '4.7', -- 2.25.1