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;
/**
* @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
*/
@ -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
* 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) {
$this->addTranslatableFields($fields);
if ($this->owner->translatableFieldsAdded) return;
// Show a dropdown to create a new translation.
// This action is possible both when showing the "default language"
// 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');
$createButton->addExtraClass('createTranslationButton');
$this->owner->translatableFieldsAdded = true;
}
function updateSettingsFields(&$fields) {
@ -1003,6 +1024,7 @@ class Translatable extends DataExtension implements PermissionProvider {
}
protected function addTranslatableFields(&$fields) {
// used in LeftAndMain->init() to set language state when reading/writing record
$fields->push(new HiddenField("Locale", "Locale", $this->owner->Locale));
@ -1023,9 +1045,16 @@ class Translatable extends DataExtension implements PermissionProvider {
'ViewerGroups',
'EditorGroups',
'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",
// hence have to modify the original fields
$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)
foreach($allDataFields as $dataField) {
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 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
$fields->replaceField($dataField->getName(), $dataField->performReadonlyTransformation());
}
$this->translatableExcludes[] = $dataField->getName();
$this->translatableExcludes[] = $dataField->getName() . '_original';
}
} 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
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
added in overloaded getCMSFields() implementations. See Translatable->updateCMSFields() for details. 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.
The `[api:Translatable]` decorator applies only to the getCMSFields() method on DataObject or SiteTree and the getSettingsFields()
on SiteTree, not to any fields added in overloaded getCMSFields() implementations. See Translatable->updateCMSFields() for details.
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 calling a helper function from your getCMSFields() and getSettingsFields() functions.
:::php
class Page extends SiteTree {
@ -214,24 +214,27 @@ attach this behaviour to custom fields by using Translatable_Transformation as s
// Add fields as usual
$additionalField = new TextField('AdditionalProperty');
$fields->addFieldToTab('Root.Content.Main', $additionalField);
$fields->addFieldToTab('Root.Main', $additionalField);
// If a translation exists, exchange them with
// original/translation field pairs
$translation = $this->getTranslation(Translatable::default_locale());
if($translation && $this->Locale != Translatable::default_locale()) {
$transformation = new Translatable_Transformation($translation);
$fields->replaceField(
'AdditionalProperty',
$transformation->transformFormField($additionalField)
);
}
// Apply Translatable modifications
$this->applyTranslatableFieldsUpdate($fields, 'updateCMSFields');
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

View File

@ -220,7 +220,8 @@ class TranslatableTest extends FunctionalTest {
}
function testUpdateCMSFieldsOnSiteTree() {
$pageOrigLang = $this->objFromFixture('Page', 'testpage_en');
$pageOrigLang = new TranslatableTest_Page();
$pageOrigLang->write();
// first test with default language
$fields = $pageOrigLang->getCMSFields();
@ -233,6 +234,11 @@ class TranslatableTest extends FunctionalTest {
$fields->dataFieldByName('Title_original'),
'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"
$pageTranslated = $pageOrigLang->createTranslation('fr_FR');
@ -248,6 +254,16 @@ class TranslatableTest extends FunctionalTest {
$fields->dataFieldByName('Title_original'),
'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(
'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');