/** * If the record is not shown in the default language, this method * will try to autoselect a master language which is shown alongside * the normal formfields as a readonly representation. * This gives translators a powerful tool for their translation workflow * without leaving the translated page interface. * Translatable also adds a new tab "Translation" which shows existing * translations, as well as a formaction to create new translations based * on a dropdown with available languages. * * @todo This is specific to SiteTree and CMSMain * @todo Implement a special "translation mode" which triggers display of the * readonly fields, so you can translation INTO the "default language" while * seeing readonly fields as well. */ function updateCMSFields(FieldSet &$fields) { // Don't apply these modifications for normal DataObjects - they rely on CMSMain logic if (!$this->owner instanceof SiteTree) { return; } // used in CMSMain->init() to set language state when reading/writing record $fields->push(new HiddenField("Locale", "Locale", $this->owner->Locale)); // Don't allow translation of virtual pages because of data inconsistencies (see #5000) $excludedPageTypes = array('VirtualPage'); foreach ($excludedPageTypes as $excludedPageType) { if (is_a($this->owner, $excludedPageType)) { return; } } $excludeFields = array('ViewerGroups', 'EditorGroups', 'CanViewType', 'CanEditType'); // if a language other than default language is used, we're in "translation mode", // hence have to modify the original fields $creating = false; $baseClass = $this->owner->class; $allFields = $fields->toArray(); while (($p = get_parent_class($baseClass)) != "DataObject") { $baseClass = $p; } // try to get the record in "default language" $originalRecord = $this->owner->getTranslation(Translatable::default_locale()); // if no translation in "default language", fall back to first translation if (!$originalRecord) { $translations = $this->owner->getTranslations(); $originalRecord = $translations ? $translations->First() : null; } $isTranslationMode = $this->owner->Locale != Translatable::default_locale(); // 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). $alreadyTranslatedLocales = $this->getTranslatedLocales(); $alreadyTranslatedLocales[$this->owner->Locale] = $this->owner->Locale; if ($originalRecord && $isTranslationMode) { $originalLangID = Session::get($this->owner->ID . '_originalLangID'); // Remove parent page dropdown $fields->removeByName("ParentType"); $fields->removeByName("ParentID"); $translatableFieldNames = $this->getTranslatableFields(); $allDataFields = $fields->dataFields(); $transformation = new Translatable_Transformation($originalRecord); // iterate through sequential list of all datafields in fieldset // (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->Name(), $excludeFields)) { continue; } if (in_array($dataField->Name(), $translatableFieldNames)) { // if the field is translatable, perform transformation $fields->replaceField($dataField->Name(), $transformation->transformFormField($dataField)); } else { // else field shouldn't be editable in translation-mode, make readonly $fields->replaceField($dataField->Name(), $dataField->performReadonlyTransformation()); } } } elseif ($this->owner->isNew()) { $fields->addFieldsToTab('Root', new Tab(_t('Translatable.TRANSLATIONS', 'Translations'), new LiteralField('SaveBeforeCreatingTranslationNote', sprintf('<p class="message">%s</p>', _t('Translatable.NOTICENEWPAGE', 'Please save this page before creating a translation'))))); } $fields->addFieldsToTab('Root', new Tab('Translations', _t('Translatable.TRANSLATIONS', 'Translations'), new HeaderField('CreateTransHeader', _t('Translatable.CREATE', 'Create new translation'), 2), $langDropdown = new LanguageDropdownField("NewTransLang", _t('Translatable.NEWLANGUAGE', 'New language'), $alreadyTranslatedLocales, 'SiteTree', 'Locale-English', $this->owner), $createButton = new InlineFormAction('createtranslation', _t('Translatable.CREATEBUTTON', 'Create')))); $createButton->includeDefaultJS(false); if ($alreadyTranslatedLocales) { $fields->addFieldToTab('Root.Translations', new HeaderField('ExistingTransHeader', _t('Translatable.EXISTING', 'Existing translations:'), 3)); $existingTransHTML = '<ul>'; foreach ($alreadyTranslatedLocales as $i => $langCode) { $existingTranslation = $this->owner->getTranslation($langCode); if ($existingTranslation) { $existingTransHTML .= sprintf('<li><a href="%s">%s</a></li>', sprintf('admin/show/%d/?locale=%s', $existingTranslation->ID, $langCode), i18n::get_locale_name($langCode)); } } $existingTransHTML .= '</ul>'; $fields->addFieldToTab('Root.Translations', new LiteralField('existingtrans', $existingTransHTML)); } $langDropdown->addExtraClass('languageDropdown'); $createButton->addExtraClass('createTranslationButton'); }