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