Skip to content
This repository
Browse code

FIX Correct Zend_Locale fallbacks in i18n/DateField/DateTimeField

Due to the recent change of translations to transifex, some
locales changed their names, which prompted a fix to
i18n::get_available_translations() (see 00ffe72).
This caused a regression where short locales are determined
from the YAML file names (e.g. "en"), but weren't matched up
with fully qualified locales from get_available_translations() (e.g. "en_US").
Since this list is used in the admin/myprofile dropdown for the Member.Locale value,
it didn't match up with any entries and defaulted to the first one ("Africaans").

Note that the behaviour of admin/myprofile is still a bit weird:
It defaults the locale on new members to the one set for the current administrator.
So if a site defaults to en_US in _config.php, but the admin happens to view
his backend in de_DE, all members he creates default to de_DE as well.

Thanks to @tractorcow for contributing and peer reviewing!
  • Loading branch information...
commit 1c31c098ee2cd4c8365d233fe134b0f228657340 1 parent c396645
Ingo Schommer authored August 20, 2013
16  forms/DateField.php
@@ -217,6 +217,8 @@ public function Type() {
217 217
 	 * @param String|Array $val 
218 218
 	 */
219 219
 	public function setValue($val) {
  220
+		$locale = new Zend_Locale($this->locale);
  221
+		
220 222
 		if(empty($val)) {
221 223
 			$this->value = null;
222 224
 			$this->valueObj = null;
@@ -226,7 +228,7 @@ public function setValue($val) {
226 228
 				if(is_array($val) && $this->validateArrayValue($val)) {
227 229
 					// set() gets confused with custom date formats when using array notation
228 230
 					if(!(empty($val['day']) || empty($val['month']) || empty($val['year']))) {
229  
-						$this->valueObj = new Zend_Date($val, null, $this->locale);
  231
+						$this->valueObj = new Zend_Date($val, null, $locale);
230 232
 						$this->value = $this->valueObj->toArray();
231 233
 					} else {
232 234
 						$this->value = $val;
@@ -234,8 +236,8 @@ public function setValue($val) {
234 236
 					}
235 237
 				}
236 238
 				// load ISO date from database (usually through Form->loadDataForm())
237  
-				else if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'), $this->locale)) {
238  
-					$this->valueObj = new Zend_Date($val, $this->getConfig('datavalueformat'), $this->locale);
  239
+				else if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'), $locale)) {
  240
+					$this->valueObj = new Zend_Date($val, $this->getConfig('datavalueformat'), $locale);
239 241
 					$this->value = $this->valueObj->toArray();
240 242
 				}
241 243
 				else {
@@ -247,15 +249,15 @@ public function setValue($val) {
247 249
 				// Caution: Its important to have this check *before* the ISO date fallback,
248 250
 				// as some dates are falsely detected as ISO by isDate(), e.g. '03/04/03'
249 251
 				// (en_NZ for 3rd of April, definetly not yyyy-MM-dd)
250  
-				if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('dateformat'), $this->locale)) {
251  
-					$this->valueObj = new Zend_Date($val, $this->getConfig('dateformat'), $this->locale);
252  
-					$this->value = $this->valueObj->get($this->getConfig('dateformat'), $this->locale);
  252
+				if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('dateformat'), $locale)) {
  253
+					$this->valueObj = new Zend_Date($val, $this->getConfig('dateformat'), $locale);
  254
+					$this->value = $this->valueObj->get($this->getConfig('dateformat'), $locale);
253 255
 					
254 256
 				}
255 257
 				// load ISO date from database (usually through Form->loadDataForm())
256 258
 				else if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'))) {
257 259
 					$this->valueObj = new Zend_Date($val, $this->getConfig('datavalueformat'));
258  
-					$this->value = $this->valueObj->get($this->getConfig('dateformat'), $this->locale);
  260
+					$this->value = $this->valueObj->get($this->getConfig('dateformat'), $locale);
259 261
 				}
260 262
 				else {
261 263
 					$this->value = $val;
16  forms/DatetimeField.php
@@ -115,6 +115,8 @@ public function Field($properties = array()) {
115 115
 	 *  the 'date' value may contain array notation was well (see {@link DateField->setValue()}).
116 116
 	 */
117 117
 	public function setValue($val) {
  118
+		$locale = new Zend_Locale($this->locale);
  119
+
118 120
 		// If timezones are enabled, assume user data needs to be reverted to server timezone
119 121
 		if($this->getConfig('usertimezone')) {
120 122
 			// Accept user input on timezone, but only when timezone support is enabled
@@ -130,7 +132,7 @@ public function setValue($val) {
130 132
 			$this->timeField->setValue(null);
131 133
 		} else {
132 134
 			// Case 1: String setting from database, in ISO date format
133  
-			if(is_string($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'), $this->locale)) {
  135
+			if(is_string($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'), $locale)) {
134 136
 				$this->value = $val;
135 137
 			}
136 138
 			// Case 2: Array form submission with user date format
@@ -145,13 +147,13 @@ public function setValue($val) {
145 147
 				$this->dateField->setValue($val['date']);
146 148
 				$this->timeField->setValue($val['time']);
147 149
 				if($this->dateField->dataValue() && $this->timeField->dataValue()) {
148  
-					$userValueObj = new Zend_Date(null, null, $this->locale);
  150
+					$userValueObj = new Zend_Date(null, null, $locale);
149 151
 					$userValueObj->setDate($this->dateField->dataValue(),
150 152
 						$this->dateField->getConfig('datavalueformat'));
151 153
 					$userValueObj->setTime($this->timeField->dataValue(),
152 154
 						$this->timeField->getConfig('datavalueformat'));
153 155
 					if($userTz) $userValueObj->setTimezone($dataTz);
154  
-					$this->value = $userValueObj->get($this->getConfig('datavalueformat'), $this->locale);
  156
+					$this->value = $userValueObj->get($this->getConfig('datavalueformat'), $locale);
155 157
 					unset($userValueObj);
156 158
 				} else {
157 159
 					// Validation happens later, so set the raw string in case Zend_Date doesn't accept it
@@ -168,8 +170,8 @@ public function setValue($val) {
168 170
 			}
169 171
 
170 172
 			// view settings (dates might differ from $this->value based on user timezone settings)
171  
-			if (Zend_Date::isDate($this->value, $this->getConfig('datavalueformat'), $this->locale)) {
172  
-				$valueObj = new Zend_Date($this->value, $this->getConfig('datavalueformat'), $this->locale);
  173
+			if (Zend_Date::isDate($this->value, $this->getConfig('datavalueformat'), $locale)) {
  174
+				$valueObj = new Zend_Date($this->value, $this->getConfig('datavalueformat'), $locale);
173 175
 				if($userTz) $valueObj->setTimezone($userTz);
174 176
 
175 177
 				// Set view values in sub-fields
@@ -177,9 +179,9 @@ public function setValue($val) {
177 179
 					$this->dateField->setValue($valueObj->toArray());
178 180
 				} else {
179 181
 					$this->dateField->setValue(
180  
-						$valueObj->get($this->dateField->getConfig('dateformat'), $this->locale));
  182
+						$valueObj->get($this->dateField->getConfig('dateformat'), $locale));
181 183
 				}
182  
-				$this->timeField->setValue($valueObj->get($this->timeField->getConfig('timeformat'), $this->locale));
  184
+				$this->timeField->setValue($valueObj->get($this->timeField->getConfig('timeformat'), $locale));
183 185
 			}
184 186
 		}
185 187
 
14  i18n/i18n.php
@@ -2231,13 +2231,11 @@ public static function get_existing_translations() {
2231 2231
 					// TODO Replace with CLDR list of actually available languages/regions
2232 2232
 					// Only allow explicitly registered locales, otherwise we'll get into trouble
2233 2233
 					// if the locale doesn't exist in Zend's CLDR data
2234  
-					$labelLocale = str_replace('-', '_', self::get_locale_from_lang($locale));
2235  
-					if(isset(self::$all_locales[$locale])) {
2236  
-						$locales[$locale] = self::$all_locales[$locale];	
2237  
-					} else if(isset(self::$all_locales[$labelLocale])) {
2238  
-						$locales[$locale] = self::$all_locales[$labelLocale];	
2239  
-					} 
2240  
-				} 
  2234
+					$fullLocale = self::get_locale_from_lang($locale);
  2235
+					if(isset($allLocales[$fullLocale])) {
  2236
+						$locales[$fullLocale] = $allLocales[$fullLocale];	
  2237
+					}
  2238
+				}
2241 2239
 			}
2242 2240
 		}
2243 2241
 
@@ -2354,7 +2352,7 @@ public static function get_lang_from_locale($locale) {
2354 2352
 	public static function get_locale_from_lang($lang) {
2355 2353
 		$subtags = Config::inst()->get('i18n', 'likely_subtags');
2356 2354
 		if(preg_match('/\-|_/', $lang)) {
2357  
-			return $lang;
  2355
+			return str_replace('-', '_', $lang);
2358 2356
 		} else if(isset($subtags[$lang])) {
2359 2357
 			return $subtags[$lang];
2360 2358
 		} else {
6  security/Member.php
@@ -1169,7 +1169,7 @@ public function getCMSFields() {
1169 1169
 		$password->setCanBeEmpty(true);
1170 1170
 		if(!$this->ID) $password->showOnClick = false;
1171 1171
 		$mainFields->replaceField('Password', $password);
1172  
-				
  1172
+
1173 1173
 		$mainFields->replaceField('Locale', new DropdownField(
1174 1174
 			"Locale", 
1175 1175
 			_t('Member.INTERFACELANG', "Interface Language", 'Language of the CMS'), 
@@ -1231,7 +1231,7 @@ public function getCMSFields() {
1231 1231
 		$permissionsTab = $fields->fieldByName("Root")->fieldByName('Permissions');
1232 1232
 		if($permissionsTab) $permissionsTab->addExtraClass('readonly');
1233 1233
 		
1234  
-		$defaultDateFormat = Zend_Locale_Format::getDateFormat($this->Locale);
  1234
+		$defaultDateFormat = Zend_Locale_Format::getDateFormat(new Zend_Locale($this->Locale));
1235 1235
 		$dateFormatMap = array(
1236 1236
 			'MMM d, yyyy' => Zend_Date::now()->toString('MMM d, yyyy'),
1237 1237
 			'yyyy/MM/dd' => Zend_Date::now()->toString('yyyy/MM/dd'),
@@ -1249,7 +1249,7 @@ public function getCMSFields() {
1249 1249
 		);
1250 1250
 		$dateFormatField->setValue($this->DateFormat);
1251 1251
 		
1252  
-		$defaultTimeFormat = Zend_Locale_Format::getTimeFormat($this->Locale);
  1252
+		$defaultTimeFormat = Zend_Locale_Format::getTimeFormat(new Zend_Locale($this->Locale));
1253 1253
 		$timeFormatMap = array(
1254 1254
 			'h:mm a' => Zend_Date::now()->toString('h:mm a'),
1255 1255
 			'H:mm' => Zend_Date::now()->toString('H:mm'),
6  tests/i18n/i18nTest.php
@@ -97,9 +97,9 @@ public function testTimeFormatCustom() {
97 97
 	
98 98
 	public function testGetExistingTranslations() {
99 99
 		$translations = i18n::get_existing_translations();
100  
-		$this->assertTrue(isset($translations['en']), 'Checking for en translation');
101  
-		$this->assertEquals($translations['en'], 'English (United States)');
102  
-		$this->assertTrue(isset($translations['de']), 'Checking for de_DE translation');
  100
+		$this->assertTrue(isset($translations['en_US']), 'Checking for en translation');
  101
+		$this->assertEquals($translations['en_US'], 'English (United States)');
  102
+		$this->assertTrue(isset($translations['de_DE']), 'Checking for de_DE translation');
103 103
 	}
104 104
 	
105 105
 	public function testDataObjectFieldLabels() {

0 notes on commit 1c31c09

Please sign in to comment.
Something went wrong with that request. Please try again.