Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
fee14197 | 4 | | CiviCRM version 5 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
8c9251b3 | 6 | | Copyright CiviCRM LLC (c) 2004-2018 | |
6a488035 TO |
7 | +--------------------------------------------------------------------+ |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
10 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
11 | | under the terms of the GNU Affero General Public License | | |
12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
13 | | | | |
14 | | CiviCRM is distributed in the hope that it will be useful, but | | |
15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
17 | | See the GNU Affero General Public License for more details. | | |
18 | | | | |
19 | | You should have received a copy of the GNU Affero General Public | | |
20 | | License and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
d25dd0ee | 26 | */ |
6a488035 TO |
27 | |
28 | /** | |
29 | * | |
30 | * @package CRM | |
8c9251b3 | 31 | * @copyright CiviCRM LLC (c) 2004-2018 |
6a488035 TO |
32 | */ |
33 | ||
34 | /** | |
ce064e4f | 35 | * This class generates form components for Localization. |
6a488035 TO |
36 | */ |
37 | class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting { | |
8a61528e TO |
38 | |
39 | protected $_settings = array( | |
9c325795 | 40 | 'contact_default_language' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, |
8a61528e TO |
41 | 'countryLimit' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, |
42 | 'customTranslateFunction' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
43 | 'defaultContactCountry' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
44 | 'defaultContactStateProvince' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
45 | 'defaultCurrency' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
46 | 'fieldSeparator' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
47 | 'inheritLocale' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
48 | 'lcMessages' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
49 | 'legacyEncoding' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
50 | 'monetaryThousandSeparator' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
51 | 'monetaryDecimalPoint' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
52 | 'moneyformat' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
53 | 'moneyvalueformat' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
54 | 'provinceLimit' => CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME, | |
55 | ); | |
6a488035 TO |
56 | |
57 | /** | |
eceb18cc | 58 | * Build the form object. |
6a488035 TO |
59 | */ |
60 | public function buildQuickForm() { | |
61 | $config = CRM_Core_Config::singleton(); | |
62 | ||
6a488035 TO |
63 | CRM_Utils_System::setTitle(ts('Settings - Localization')); |
64 | ||
fe25a292 | 65 | $warningTitle = json_encode(ts("Warning")); |
b72b5fc0 | 66 | $defaultLocaleOptions = CRM_Admin_Form_Setting_Localization::getDefaultLocaleOptions(); |
8a61528e | 67 | |
6a488035 TO |
68 | $domain = new CRM_Core_DAO_Domain(); |
69 | $domain->find(TRUE); | |
6a488035 | 70 | |
8a61528e | 71 | if ($domain->locales) { |
6a488035 | 72 | // add language limiter and language adder |
b72b5fc0 TO |
73 | $this->addCheckBox('languageLimit', ts('Available Languages'), array_flip($defaultLocaleOptions), NULL, NULL, NULL, NULL, ' '); |
74 | $this->addElement('select', 'addLanguage', ts('Add Language'), array_merge(array('' => ts('- select -')), array_diff(CRM_Core_I18n::languages(), $defaultLocaleOptions))); | |
6a488035 TO |
75 | |
76 | // add the ability to return to single language | |
fe25a292 | 77 | $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).'); |
6a488035 | 78 | $this->assign('warning', $warning); |
fe25a292 | 79 | $warning = json_encode($warning); |
6a488035 | 80 | $this->addElement('checkbox', 'makeSinglelingual', ts('Return to Single Language'), |
fe25a292 | 81 | NULL, array('onChange' => "if (this.checked) CRM.alert($warning, $warningTitle)") |
6a488035 TO |
82 | ); |
83 | } | |
84 | else { | |
fe25a292 | 85 | $warning = ts('Enabling multiple languages changes the schema of your database, so make sure you know what you are doing when enabling this function; making a database backup is strongly recommended.'); |
6a488035 | 86 | $this->assign('warning', $warning); |
fe25a292 | 87 | $warning = json_encode($warning); |
6a488035 TO |
88 | $validTriggerPermission = CRM_Core_DAO::checkTriggerViewPermission(TRUE); |
89 | ||
90 | if ($validTriggerPermission && | |
344b05bc | 91 | !\Civi::settings()->get('logging') |
6a488035 TO |
92 | ) { |
93 | $this->addElement('checkbox', 'makeMultilingual', ts('Enable Multiple Languages'), | |
fe25a292 | 94 | NULL, array('onChange' => "if (this.checked) CRM.alert($warning, $warningTitle)") |
6a488035 TO |
95 | ); |
96 | } | |
97 | } | |
9c325795 TO |
98 | $this->addElement('select', 'contact_default_language', ts('Default Language for users'), |
99 | CRM_Admin_Form_Setting_Localization::getDefaultLanguageOptions()); | |
6a488035 TO |
100 | |
101 | $includeCurrency = &$this->addElement('advmultiselect', 'currencyLimit', | |
8a61528e | 102 | ts('Available Currencies') . ' ', self::getCurrencySymbols(), |
6a488035 TO |
103 | array( |
104 | 'size' => 5, | |
105 | 'style' => 'width:150px', | |
106 | 'class' => 'advmultiselect', | |
107 | ) | |
108 | ); | |
109 | ||
110 | $includeCurrency->setButtonAttributes('add', array('value' => ts('Add >>'))); | |
111 | $includeCurrency->setButtonAttributes('remove', array('value' => ts('<< Remove'))); | |
112 | ||
6a488035 TO |
113 | $this->addFormRule(array('CRM_Admin_Form_Setting_Localization', 'formRule')); |
114 | ||
115 | parent::buildQuickForm(); | |
116 | } | |
117 | ||
e0ef6999 EM |
118 | /** |
119 | * @param $fields | |
120 | * | |
121 | * @return array|bool | |
122 | */ | |
00be9182 | 123 | public static function formRule($fields) { |
6a488035 TO |
124 | $errors = array(); |
125 | if (CRM_Utils_Array::value('monetaryThousandSeparator', $fields) == | |
126 | CRM_Utils_Array::value('monetaryDecimalPoint', $fields) | |
127 | ) { | |
128 | $errors['monetaryThousandSeparator'] = ts('Thousands Separator and Decimal Delimiter can not be the same.'); | |
129 | } | |
130 | ||
131 | if (strlen($fields['monetaryThousandSeparator']) == 0) { | |
132 | $errors['monetaryThousandSeparator'] = ts('Thousands Separator can not be empty. You can use a space character instead.'); | |
133 | } | |
134 | ||
135 | if (strlen($fields['monetaryThousandSeparator']) > 1) { | |
136 | $errors['monetaryThousandSeparator'] = ts('Thousands Separator can not have more than 1 character.'); | |
137 | } | |
138 | ||
139 | if (strlen($fields['monetaryDecimalPoint']) > 1) { | |
140 | $errors['monetaryDecimalPoint'] = ts('Decimal Delimiter can not have more than 1 character.'); | |
141 | } | |
142 | ||
143 | if (trim($fields['customTranslateFunction']) && | |
144 | !function_exists(trim($fields['customTranslateFunction'])) | |
145 | ) { | |
146 | $errors['customTranslateFunction'] = ts('Please define the custom translation function first.'); | |
147 | } | |
148 | ||
149 | // CRM-7962, CRM-7713, CRM-9004 | |
150 | if (!empty($fields['defaultContactCountry']) && | |
8cc574cf | 151 | (!empty($fields['countryLimit']) && |
6a488035 TO |
152 | (!in_array($fields['defaultContactCountry'], $fields['countryLimit'])) |
153 | ) | |
154 | ) { | |
155 | $errors['defaultContactCountry'] = ts('Please select a default country that is in the list of available countries.'); | |
b05e28de | 156 | } |
6a488035 TO |
157 | |
158 | return empty($errors) ? TRUE : $errors; | |
159 | } | |
160 | ||
f2ac86d1 | 161 | /** |
162 | * Set the default values for the form. | |
163 | * | |
164 | * @return array | |
165 | */ | |
00be9182 | 166 | public function setDefaultValues() { |
6a488035 TO |
167 | parent::setDefaultValues(); |
168 | ||
169 | // CRM-1496 | |
170 | // retrieve default values for currencyLimit | |
171 | $this->_defaults['currencyLimit'] = array_keys(CRM_Core_OptionGroup::values('currencies_enabled')); | |
172 | ||
b72b5fc0 TO |
173 | $this->_defaults['languageLimit'] = Civi::settings()->get('languageLimit'); |
174 | ||
6a488035 TO |
175 | // CRM-5111: unset these two unconditionally, we don’t want them to stick – ever |
176 | unset($this->_defaults['makeMultilingual']); | |
177 | unset($this->_defaults['makeSinglelingual']); | |
178 | return $this->_defaults; | |
179 | } | |
180 | ||
181 | public function postProcess() { | |
182 | $values = $this->exportValues(); | |
183 | ||
6a488035 TO |
184 | //cache contact fields retaining localized titles |
185 | //though we changed localization, so reseting cache. | |
186 | CRM_Core_BAO_Cache::deleteGroup('contact fields'); | |
187 | ||
188 | //CRM-8559, cache navigation do not respect locale if it is changed, so reseting cache. | |
189 | CRM_Core_BAO_Cache::deleteGroup('navigation'); | |
190 | ||
191 | // we do this only to initialize monetary decimal point and thousand separator | |
192 | $config = CRM_Core_Config::singleton(); | |
193 | ||
ece6501c | 194 | // save enabled currencies and default currency in option group 'currencies_enabled' |
6a488035 TO |
195 | // CRM-1496 |
196 | if (empty($values['currencyLimit'])) { | |
197 | $values['currencyLimit'] = array($values['defaultCurrency']); | |
198 | } | |
ece6501c | 199 | elseif (!in_array($values['defaultCurrency'], $values['currencyLimit'])) { |
6a488035 TO |
200 | $values['currencyLimit'][] = $values['defaultCurrency']; |
201 | } | |
202 | ||
ece6501c | 203 | self::updateEnabledCurrencies($values['currencyLimit'], $values['defaultCurrency']); |
6a488035 TO |
204 | |
205 | // unset currencyLimit so we dont store there | |
206 | unset($values['currencyLimit']); | |
207 | ||
208 | // make the site multi-lang if requested | |
a7488080 | 209 | if (!empty($values['makeMultilingual'])) { |
6a488035 TO |
210 | CRM_Core_I18n_Schema::makeMultilingual($values['lcMessages']); |
211 | $values['languageLimit'][$values['lcMessages']] = 1; | |
212 | // make the site single-lang if requested | |
213 | } | |
a7488080 | 214 | elseif (!empty($values['makeSinglelingual'])) { |
6a488035 TO |
215 | CRM_Core_I18n_Schema::makeSinglelingual($values['lcMessages']); |
216 | $values['languageLimit'] = ''; | |
217 | } | |
218 | ||
219 | // add a new db locale if the requested language is not yet supported by the db | |
220 | if (!CRM_Utils_Array::value('makeSinglelingual', $values) and CRM_Utils_Array::value('addLanguage', $values)) { | |
221 | $domain = new CRM_Core_DAO_Domain(); | |
222 | $domain->find(TRUE); | |
223 | if (!substr_count($domain->locales, $values['addLanguage'])) { | |
224 | CRM_Core_I18n_Schema::addLocale($values['addLanguage'], $values['lcMessages']); | |
225 | } | |
226 | $values['languageLimit'][$values['addLanguage']] = 1; | |
227 | } | |
228 | ||
229 | // if we manipulated the language list, return to the localization admin screen | |
02fc859b | 230 | $return = (bool) (CRM_Utils_Array::value('makeMultilingual', $values) or CRM_Utils_Array::value('addLanguage', $values)); |
6a488035 | 231 | |
b72b5fc0 TO |
232 | $filteredValues = $values; |
233 | unset($filteredValues['makeMultilingual']); | |
234 | unset($filteredValues['makeSinglelingual']); | |
235 | unset($filteredValues['addLanguage']); | |
236 | unset($filteredValues['languageLimit']); | |
237 | ||
238 | Civi::settings()->set('languageLimit', CRM_Utils_Array::value('languageLimit', $values)); | |
239 | ||
6a488035 | 240 | // save all the settings |
b72b5fc0 | 241 | parent::commonProcess($filteredValues); |
6a488035 TO |
242 | |
243 | if ($return) { | |
244 | CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/setting/localization', 'reset=1')); | |
245 | } | |
246 | } | |
96025800 | 247 | |
ece6501c ML |
248 | |
249 | /** | |
250 | * Replace available currencies by the ones provided | |
251 | * | |
252 | * @param $currencies array of currencies ['USD', 'CAD'] | |
253 | * @param $default default currency | |
254 | */ | |
255 | public static function updateEnabledCurrencies($currencies, $default) { | |
256 | ||
257 | // sort so that when we display drop down, weights have right value | |
258 | sort($currencies); | |
259 | ||
260 | // get labels for all the currencies | |
261 | $options = array(); | |
262 | ||
263 | $currencySymbols = CRM_Admin_Form_Setting_Localization::getCurrencySymbols(); | |
264 | for ($i = 0; $i < count($currencies); $i++) { | |
265 | $options[] = array( | |
266 | 'label' => $currencySymbols[$currencies[$i]], | |
267 | 'value' => $currencies[$i], | |
268 | 'weight' => $i + 1, | |
269 | 'is_active' => 1, | |
270 | 'is_default' => $currencies[$i] == $default, | |
271 | ); | |
272 | } | |
273 | ||
274 | $dontCare = NULL; | |
275 | CRM_Core_OptionGroup::createAssoc('currencies_enabled', $options, $dontCare); | |
276 | ||
277 | } | |
278 | ||
279 | ||
8a61528e TO |
280 | /** |
281 | * @return array | |
282 | */ | |
283 | public static function getAvailableCountries() { | |
284 | $i18n = CRM_Core_I18n::singleton(); | |
285 | $country = array(); | |
286 | CRM_Core_PseudoConstant::populate($country, 'CRM_Core_DAO_Country', TRUE, 'name', 'is_active'); | |
287 | $i18n->localizeArray($country, array('context' => 'country')); | |
288 | asort($country); | |
289 | return $country; | |
290 | } | |
291 | ||
292 | /** | |
8246bca4 | 293 | * Get the default locale options. |
294 | * | |
8a61528e TO |
295 | * @return array |
296 | */ | |
297 | public static function getDefaultLocaleOptions() { | |
298 | $domain = new CRM_Core_DAO_Domain(); | |
299 | $domain->find(TRUE); | |
300 | $locales = CRM_Core_I18n::languages(); | |
301 | if ($domain->locales) { | |
302 | // for multi-lingual sites, populate default language drop-down with available languages | |
b72b5fc0 | 303 | $defaultLocaleOptions = array(); |
8a61528e TO |
304 | foreach ($locales as $loc => $lang) { |
305 | if (substr_count($domain->locales, $loc)) { | |
b72b5fc0 | 306 | $defaultLocaleOptions[$loc] = $lang; |
8a61528e TO |
307 | } |
308 | } | |
309 | } | |
310 | else { | |
b72b5fc0 | 311 | $defaultLocaleOptions = $locales; |
8a61528e | 312 | } |
b72b5fc0 | 313 | return $defaultLocaleOptions; |
8a61528e TO |
314 | } |
315 | ||
316 | /** | |
317 | * Get a list of currencies (with their symbols). | |
318 | * | |
319 | * @return array | |
320 | * Array('USD' => 'USD ($)'). | |
321 | */ | |
322 | public static function getCurrencySymbols() { | |
323 | $symbols = CRM_Core_PseudoConstant::get('CRM_Contribute_DAO_Contribution', 'currency', array( | |
324 | 'labelColumn' => 'symbol', | |
325 | 'orderColumn' => TRUE, | |
326 | )); | |
327 | $_currencySymbols = array(); | |
328 | foreach ($symbols as $key => $value) { | |
329 | $_currencySymbols[$key] = "$key"; | |
330 | if ($value) { | |
331 | $_currencySymbols[$key] .= " ($value)"; | |
332 | } | |
333 | } | |
334 | return $_currencySymbols; | |
335 | } | |
336 | ||
f2ac86d1 | 337 | /** |
338 | * Update session and uf_match table when the locale is updated. | |
339 | * | |
340 | * @param string $oldLocale | |
341 | * @param string $newLocale | |
342 | * @param array $metadata | |
343 | * @param int $domainID | |
344 | */ | |
b72b5fc0 TO |
345 | public static function onChangeLcMessages($oldLocale, $newLocale, $metadata, $domainID) { |
346 | if ($oldLocale == $newLocale) { | |
347 | return; | |
348 | } | |
349 | ||
350 | $session = CRM_Core_Session::singleton(); | |
351 | if ($newLocale && $session->get('userID')) { | |
352 | $ufm = new CRM_Core_DAO_UFMatch(); | |
353 | $ufm->contact_id = $session->get('userID'); | |
354 | if ($newLocale && $ufm->find(TRUE)) { | |
355 | $ufm->language = $newLocale; | |
356 | $ufm->save(); | |
357 | $session->set('lcMessages', $newLocale); | |
358 | } | |
359 | } | |
360 | } | |
361 | ||
ece6501c ML |
362 | public static function onChangeDefaultCurrency($oldCurrency, $newCurrency, $metadata) { |
363 | if ($oldCurrency == $newCurrency) { | |
364 | return; | |
365 | } | |
366 | ||
367 | // ensure that default currency is always in the list of enabled currencies | |
368 | $currencies = array_keys(CRM_Core_OptionGroup::values('currencies_enabled')); | |
369 | if (!in_array($newCurrency, $currencies)) { | |
370 | if (empty($currencies)) { | |
371 | $currencies = array($values['defaultCurrency']); | |
372 | } | |
373 | else { | |
374 | $currencies[] = $newCurrency; | |
375 | } | |
376 | ||
377 | CRM_Admin_Form_Setting_Localization::updateEnabledCurrencies($currencies, $newCurrency); | |
378 | } | |
379 | ||
380 | } | |
381 | ||
9c325795 TO |
382 | /** |
383 | * @return array | |
384 | */ | |
385 | public static function getDefaultLanguageOptions() { | |
386 | return array( | |
387 | '*default*' => ts('Use default site language'), | |
388 | 'undefined' => ts('Leave undefined'), | |
389 | 'current_site_language' => ts('Use language in use at the time'), | |
390 | ); | |
391 | } | |
392 | ||
6a488035 | 393 | } |