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 00ffe7294).
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!
This commit is contained in:
Ingo Schommer 2013-08-20 14:07:07 +02:00
parent c396645aed
commit 1c31c098ee
5 changed files with 30 additions and 28 deletions

View File

@ -217,6 +217,8 @@ class DateField extends TextField {
* @param String|Array $val
*/
public function setValue($val) {
$locale = new Zend_Locale($this->locale);
if(empty($val)) {
$this->value = null;
$this->valueObj = null;
@ -226,7 +228,7 @@ class DateField extends TextField {
if(is_array($val) && $this->validateArrayValue($val)) {
// set() gets confused with custom date formats when using array notation
if(!(empty($val['day']) || empty($val['month']) || empty($val['year']))) {
$this->valueObj = new Zend_Date($val, null, $this->locale);
$this->valueObj = new Zend_Date($val, null, $locale);
$this->value = $this->valueObj->toArray();
} else {
$this->value = $val;
@ -234,8 +236,8 @@ class DateField extends TextField {
}
}
// load ISO date from database (usually through Form->loadDataForm())
else if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'), $this->locale)) {
$this->valueObj = new Zend_Date($val, $this->getConfig('datavalueformat'), $this->locale);
else if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'), $locale)) {
$this->valueObj = new Zend_Date($val, $this->getConfig('datavalueformat'), $locale);
$this->value = $this->valueObj->toArray();
}
else {
@ -247,15 +249,15 @@ class DateField extends TextField {
// Caution: Its important to have this check *before* the ISO date fallback,
// as some dates are falsely detected as ISO by isDate(), e.g. '03/04/03'
// (en_NZ for 3rd of April, definetly not yyyy-MM-dd)
if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('dateformat'), $this->locale)) {
$this->valueObj = new Zend_Date($val, $this->getConfig('dateformat'), $this->locale);
$this->value = $this->valueObj->get($this->getConfig('dateformat'), $this->locale);
if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('dateformat'), $locale)) {
$this->valueObj = new Zend_Date($val, $this->getConfig('dateformat'), $locale);
$this->value = $this->valueObj->get($this->getConfig('dateformat'), $locale);
}
// load ISO date from database (usually through Form->loadDataForm())
else if(!empty($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'))) {
$this->valueObj = new Zend_Date($val, $this->getConfig('datavalueformat'));
$this->value = $this->valueObj->get($this->getConfig('dateformat'), $this->locale);
$this->value = $this->valueObj->get($this->getConfig('dateformat'), $locale);
}
else {
$this->value = $val;

View File

@ -115,6 +115,8 @@ class DatetimeField extends FormField {
* the 'date' value may contain array notation was well (see {@link DateField->setValue()}).
*/
public function setValue($val) {
$locale = new Zend_Locale($this->locale);
// If timezones are enabled, assume user data needs to be reverted to server timezone
if($this->getConfig('usertimezone')) {
// Accept user input on timezone, but only when timezone support is enabled
@ -130,7 +132,7 @@ class DatetimeField extends FormField {
$this->timeField->setValue(null);
} else {
// Case 1: String setting from database, in ISO date format
if(is_string($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'), $this->locale)) {
if(is_string($val) && Zend_Date::isDate($val, $this->getConfig('datavalueformat'), $locale)) {
$this->value = $val;
}
// Case 2: Array form submission with user date format
@ -145,13 +147,13 @@ class DatetimeField extends FormField {
$this->dateField->setValue($val['date']);
$this->timeField->setValue($val['time']);
if($this->dateField->dataValue() && $this->timeField->dataValue()) {
$userValueObj = new Zend_Date(null, null, $this->locale);
$userValueObj = new Zend_Date(null, null, $locale);
$userValueObj->setDate($this->dateField->dataValue(),
$this->dateField->getConfig('datavalueformat'));
$userValueObj->setTime($this->timeField->dataValue(),
$this->timeField->getConfig('datavalueformat'));
if($userTz) $userValueObj->setTimezone($dataTz);
$this->value = $userValueObj->get($this->getConfig('datavalueformat'), $this->locale);
$this->value = $userValueObj->get($this->getConfig('datavalueformat'), $locale);
unset($userValueObj);
} else {
// Validation happens later, so set the raw string in case Zend_Date doesn't accept it
@ -168,8 +170,8 @@ class DatetimeField extends FormField {
}
// view settings (dates might differ from $this->value based on user timezone settings)
if (Zend_Date::isDate($this->value, $this->getConfig('datavalueformat'), $this->locale)) {
$valueObj = new Zend_Date($this->value, $this->getConfig('datavalueformat'), $this->locale);
if (Zend_Date::isDate($this->value, $this->getConfig('datavalueformat'), $locale)) {
$valueObj = new Zend_Date($this->value, $this->getConfig('datavalueformat'), $locale);
if($userTz) $valueObj->setTimezone($userTz);
// Set view values in sub-fields
@ -177,9 +179,9 @@ class DatetimeField extends FormField {
$this->dateField->setValue($valueObj->toArray());
} else {
$this->dateField->setValue(
$valueObj->get($this->dateField->getConfig('dateformat'), $this->locale));
$valueObj->get($this->dateField->getConfig('dateformat'), $locale));
}
$this->timeField->setValue($valueObj->get($this->timeField->getConfig('timeformat'), $this->locale));
$this->timeField->setValue($valueObj->get($this->timeField->getConfig('timeformat'), $locale));
}
}

View File

@ -2231,11 +2231,9 @@ class i18n extends Object implements TemplateGlobalProvider {
// TODO Replace with CLDR list of actually available languages/regions
// Only allow explicitly registered locales, otherwise we'll get into trouble
// if the locale doesn't exist in Zend's CLDR data
$labelLocale = str_replace('-', '_', self::get_locale_from_lang($locale));
if(isset(self::$all_locales[$locale])) {
$locales[$locale] = self::$all_locales[$locale];
} else if(isset(self::$all_locales[$labelLocale])) {
$locales[$locale] = self::$all_locales[$labelLocale];
$fullLocale = self::get_locale_from_lang($locale);
if(isset($allLocales[$fullLocale])) {
$locales[$fullLocale] = $allLocales[$fullLocale];
}
}
}
@ -2354,7 +2352,7 @@ class i18n extends Object implements TemplateGlobalProvider {
public static function get_locale_from_lang($lang) {
$subtags = Config::inst()->get('i18n', 'likely_subtags');
if(preg_match('/\-|_/', $lang)) {
return $lang;
return str_replace('-', '_', $lang);
} else if(isset($subtags[$lang])) {
return $subtags[$lang];
} else {

View File

@ -1231,7 +1231,7 @@ class Member extends DataObject implements TemplateGlobalProvider {
$permissionsTab = $fields->fieldByName("Root")->fieldByName('Permissions');
if($permissionsTab) $permissionsTab->addExtraClass('readonly');
$defaultDateFormat = Zend_Locale_Format::getDateFormat($this->Locale);
$defaultDateFormat = Zend_Locale_Format::getDateFormat(new Zend_Locale($this->Locale));
$dateFormatMap = array(
'MMM d, yyyy' => Zend_Date::now()->toString('MMM d, yyyy'),
'yyyy/MM/dd' => Zend_Date::now()->toString('yyyy/MM/dd'),
@ -1249,7 +1249,7 @@ class Member extends DataObject implements TemplateGlobalProvider {
);
$dateFormatField->setValue($this->DateFormat);
$defaultTimeFormat = Zend_Locale_Format::getTimeFormat($this->Locale);
$defaultTimeFormat = Zend_Locale_Format::getTimeFormat(new Zend_Locale($this->Locale));
$timeFormatMap = array(
'h:mm a' => Zend_Date::now()->toString('h:mm a'),
'H:mm' => Zend_Date::now()->toString('H:mm'),

View File

@ -97,9 +97,9 @@ class i18nTest extends SapphireTest {
public function testGetExistingTranslations() {
$translations = i18n::get_existing_translations();
$this->assertTrue(isset($translations['en']), 'Checking for en translation');
$this->assertEquals($translations['en'], 'English (United States)');
$this->assertTrue(isset($translations['de']), 'Checking for de_DE translation');
$this->assertTrue(isset($translations['en_US']), 'Checking for en translation');
$this->assertEquals($translations['en_US'], 'English (United States)');
$this->assertTrue(isset($translations['de_DE']), 'Checking for de_DE translation');
}
public function testDataObjectFieldLabels() {