NEW Make it easier to show original values for custom fields.

This commit is contained in:
Simon Elvery 2012-11-02 18:52:20 +10:00 committed by Ingo Schommer
parent 9454eb31e5
commit 44f8180110
3 changed files with 83 additions and 21 deletions

View File

@ -213,6 +213,14 @@ class Translatable extends DataExtension implements PermissionProvider {
*/ */
protected static $allowed_locales = null; protected static $allowed_locales = null;
/**
* @var array An array of fields which should be excluded from
* being transformed in the CMS for translated dataobjects. This
* includes some default excludes and any field which has already
* been transformed.
*/
protected $translatableExcludes = null;
/** /**
* Reset static configuration variables to their default values * Reset static configuration variables to their default values
*/ */
@ -927,6 +935,14 @@ class Translatable extends DataExtension implements PermissionProvider {
//-----------------------------------------------------------------------------------------------// //-----------------------------------------------------------------------------------------------//
function applyTranslatableFieldsUpdate($fields, $type) {
if (method_exists($this, $type)) {
$this->$type($fields);
} else {
throw new InvalidArgumentException("Method $type does not exist on object of type ". get_class($this));
}
}
/** /**
* If the record is not shown in the default language, this method * If the record is not shown in the default language, this method
* will try to autoselect a master language which is shown alongside * will try to autoselect a master language which is shown alongside
@ -945,6 +961,8 @@ class Translatable extends DataExtension implements PermissionProvider {
function updateCMSFields(FieldList $fields) { function updateCMSFields(FieldList $fields) {
$this->addTranslatableFields($fields); $this->addTranslatableFields($fields);
if ($this->owner->translatableFieldsAdded) return;
// Show a dropdown to create a new translation. // Show a dropdown to create a new translation.
// This action is possible both when showing the "default language" // This action is possible both when showing the "default language"
// and a translation. Include the current locale (record might not be saved yet). // and a translation. Include the current locale (record might not be saved yet).
@ -996,6 +1014,9 @@ class Translatable extends DataExtension implements PermissionProvider {
$langDropdown->addExtraClass('languageDropdown no-change-track'); $langDropdown->addExtraClass('languageDropdown no-change-track');
$createButton->addExtraClass('createTranslationButton'); $createButton->addExtraClass('createTranslationButton');
$this->owner->translatableFieldsAdded = true;
} }
function updateSettingsFields(&$fields) { function updateSettingsFields(&$fields) {
@ -1003,6 +1024,7 @@ class Translatable extends DataExtension implements PermissionProvider {
} }
protected function addTranslatableFields(&$fields) { protected function addTranslatableFields(&$fields) {
// used in LeftAndMain->init() to set language state when reading/writing record // used in LeftAndMain->init() to set language state when reading/writing record
$fields->push(new HiddenField("Locale", "Locale", $this->owner->Locale)); $fields->push(new HiddenField("Locale", "Locale", $this->owner->Locale));
@ -1023,9 +1045,16 @@ class Translatable extends DataExtension implements PermissionProvider {
'ViewerGroups', 'ViewerGroups',
'EditorGroups', 'EditorGroups',
'CanViewType', 'CanViewType',
'CanEditType' 'CanEditType',
'NewTransLang',
'createtranslation'
); );
$this->translatableExcludes = ( isset($this->translatableExcludes) && is_array($this->translatableExcludes) )
? array_merge($this->translatableExcludes, $excludeFields)
: $excludeFields;
// if a language other than default language is used, we're in "translation mode", // if a language other than default language is used, we're in "translation mode",
// hence have to modify the original fields // hence have to modify the original fields
$creating = false; $creating = false;
@ -1059,7 +1088,7 @@ class Translatable extends DataExtension implements PermissionProvider {
// (fields are object references, so we can replace them with the translatable CompositeField) // (fields are object references, so we can replace them with the translatable CompositeField)
foreach($allDataFields as $dataField) { foreach($allDataFields as $dataField) {
if($dataField instanceof HiddenField) continue; if($dataField instanceof HiddenField) continue;
if(in_array($dataField->getName(), $excludeFields)) continue; if(in_array($dataField->getName(), $this->translatableExcludes)) continue;
if(in_array($dataField->getName(), $translatableFieldNames)) { if(in_array($dataField->getName(), $translatableFieldNames)) {
// if the field is translatable, perform transformation // if the field is translatable, perform transformation
@ -1068,6 +1097,8 @@ class Translatable extends DataExtension implements PermissionProvider {
// else field shouldn't be editable in translation-mode, make readonly // else field shouldn't be editable in translation-mode, make readonly
$fields->replaceField($dataField->getName(), $dataField->performReadonlyTransformation()); $fields->replaceField($dataField->getName(), $dataField->performReadonlyTransformation());
} }
$this->translatableExcludes[] = $dataField->getName();
$this->translatableExcludes[] = $dataField->getName() . '_original';
} }
} elseif($this->owner->isNew()) { } elseif($this->owner->isNew()) {

View File

@ -197,10 +197,10 @@ Keep in mind that the `[api:Translatable]` extension currently doesn't support t
translated - all custom properties will automatically be fetched from their translated record on the database. This means translated - all custom properties will automatically be fetched from their translated record on the database. This means
you don't have to explicitly mark any custom properties as being translatable. you don't have to explicitly mark any custom properties as being translatable.
The `[api:Translatable]` decorator applies only to the getCMSFields() method on DataObject or SiteTree, not to any fields The `[api:Translatable]` decorator applies only to the getCMSFields() method on DataObject or SiteTree and the getSettingsFields()
added in overloaded getCMSFields() implementations. See Translatable->updateCMSFields() for details. By default, custom on SiteTree, not to any fields added in overloaded getCMSFields() implementations. See Translatable->updateCMSFields() for details.
fields in the CMS won't show an original readonly value on a translated record, although they will save correctly. You can By default, custom fields in the CMS won't show an original readonly value on a translated record, although they will save correctly. You can
attach this behaviour to custom fields by using Translatable_Transformation as shown below. attach this behaviour to custom fields by calling a helper function from your getCMSFields() and getSettingsFields() functions.
:::php :::php
class Page extends SiteTree { class Page extends SiteTree {
@ -214,24 +214,27 @@ attach this behaviour to custom fields by using Translatable_Transformation as s
// Add fields as usual // Add fields as usual
$additionalField = new TextField('AdditionalProperty'); $additionalField = new TextField('AdditionalProperty');
$fields->addFieldToTab('Root.Content.Main', $additionalField); $fields->addFieldToTab('Root.Main', $additionalField);
// If a translation exists, exchange them with // Apply Translatable modifications
// original/translation field pairs $this->applyTranslatableFieldsUpdate($fields, 'updateCMSFields');
$translation = $this->getTranslation(Translatable::default_locale());
if($translation && $this->Locale != Translatable::default_locale()) {
$transformation = new Translatable_Transformation($translation);
$fields->replaceField(
'AdditionalProperty',
$transformation->transformFormField($additionalField)
);
}
return $fields; return $fields;
} }
} function getSettingsFields() {
$fields = parent::getSettingsFields();
// Add fields as usual
$additionalField = new TextField('AdditionalProperty');
$fields->addFieldToTab('Root.Main', $additionalField);
// Apply Translatable modifications
$this->applyTranslatableFieldsUpdate($fields, 'updateSettingsFields');
return $fields;
}
}
### Translating the Homepage ### Translating the Homepage

View File

@ -220,7 +220,8 @@ class TranslatableTest extends FunctionalTest {
} }
function testUpdateCMSFieldsOnSiteTree() { function testUpdateCMSFieldsOnSiteTree() {
$pageOrigLang = $this->objFromFixture('Page', 'testpage_en'); $pageOrigLang = new TranslatableTest_Page();
$pageOrigLang->write();
// first test with default language // first test with default language
$fields = $pageOrigLang->getCMSFields(); $fields = $pageOrigLang->getCMSFields();
@ -233,6 +234,11 @@ class TranslatableTest extends FunctionalTest {
$fields->dataFieldByName('Title_original'), $fields->dataFieldByName('Title_original'),
'Translatable doesnt modify fields if called in default language (e.g. "non-translation mode")' 'Translatable doesnt modify fields if called in default language (e.g. "non-translation mode")'
); );
$this->assertInstanceOf(
'TextField',
$fields->dataFieldByName('TranslatableProperty'),
'Has custom field'
);
// then in "translation mode" // then in "translation mode"
$pageTranslated = $pageOrigLang->createTranslation('fr_FR'); $pageTranslated = $pageOrigLang->createTranslation('fr_FR');
@ -248,6 +254,16 @@ class TranslatableTest extends FunctionalTest {
$fields->dataFieldByName('Title_original'), $fields->dataFieldByName('Title_original'),
'Translatable adds the original value as a ReadonlyField in "translation mode"' 'Translatable adds the original value as a ReadonlyField in "translation mode"'
); );
$this->assertInstanceOf(
'ReadonlyField',
$fields->dataFieldByName('TranslatableProperty_original'),
'Retains original custom field'
);
$this->assertInstanceOf(
'TextField',
$fields->dataFieldByName('TranslatableProperty'),
'Adds custom fields as ReadonlyField'
);
} }
@ -990,6 +1006,18 @@ class TranslatableTest_Page extends Page implements TestOnly {
static $db = array( static $db = array(
'TranslatableProperty' => 'Text' 'TranslatableProperty' => 'Text'
); );
function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab(
'Root.Main',
new TextField('TranslatableProperty')
);
$this->applyTranslatableFieldsUpdate($fields, 'updateCMSFields');
return $fields;
}
} }
DataObject::add_extension('TranslatableTest_DataObject', 'TranslatableTest_Extension'); DataObject::add_extension('TranslatableTest_DataObject', 'TranslatableTest_Extension');