From c8beba696c1b6eca3cfd006c77da4be822e730a2 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Sat, 10 Jan 2009 12:15:30 +0000 Subject: [PATCH] Merged, debugged and enhanced Translatable patches from branches/translatable at r64523, r64523, 64523, thanks wakeless! API CHANGE Changed Translatable schema from auxilliary tables (SiteTree_lang, SiteTree_lang_Live) to automatically filtered records on the original table (SiteTree, SiteTree_Live), using $Lang and $OriginalID properties. Incompatible update to old schema, migration script is in the works. API CHANGE Removed Translatable::get_one(), Translatable::write() ENHANCEMENT Simplified Translatable tree generation by using getSiteTreeFor() in CMSMain->createtranslation() ENHANCEMENT Added AllChildrenIncludingDeleted(), augmentNumChildrenCountQuery(), augmentAllChildrenIncludingDeleted(), augmentStageChildren() to Translatable class to allow for more stable tree generation. ENHANCEMENT Moved definition of Translatable schema from augmentDatabase() to Translatable->extraStatics() ENHANCEMENT Changes to the CMS language selection refresh the whole admin interface instead of the tree only. This way we can add a URL parameter ?lang= to /admin, which makes the specific language bookmarkable and reloadable. Changes to LangSelector.js ENHANCEMENT Added fallback to ModelAsController->getNestedController() to fetch page with matching URLSegment but different language in case no page is found in the current language. ENHANCEMENT Added helper methods to Translatable: getTranslation(), hasTranslation(), isTranslation(), findOriginalIDs() ENHANCEMENT Getters and setters for Translatable->getOriginalPage() etc. ENHANCEMENT Hooking Translatable into ModelAsController and ContentController initialization in order to call choose_site_lang() ENHANCEMENT Simplified Translatable->augmentSQL(), augmentWrite() by not using auxilliary tables ENHANCEMENT Showing clickable links for Translations in Translatable->updateCMSFields() BUGFIX Modifying Hierarchy/SiteTree Children getters to accept optional "context" which can be used to set a language explicitly through the $Lang property, rather than implicitly reyling on the static Translatable::current_lang() BUGFIX Fixed TranslatableTest to work with new datamodel BUGFIX Temporarily disabled cookie/session selection in Translatable::choose_site_lang() until we have a good test suite for the side effects. MINOR Added "untranslated" CSS styles to tree nodes and marking them as inactive/grey git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@69959 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- code/CMSMain.php | 131 ++++++++++++++++++------------------- css/cms_left.css | 6 +- javascript/LangSelector.js | 18 +---- 3 files changed, 69 insertions(+), 86 deletions(-) diff --git a/code/CMSMain.php b/code/CMSMain.php index 8d8d904d..9b63168b 100644 --- a/code/CMSMain.php +++ b/code/CMSMain.php @@ -82,8 +82,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr public function init() { parent::init(); + // "Lang" attribute is either explicitly added by LeftAndMain Javascript logic, + // or implied on a translated record (see {@link Translatable->updateCMSFields()}). if(Translatable::is_enabled()) { - $this->Lang = $this->requestParams["lang"] ? $this->requestParams["lang"] : Translatable::default_lang(); + // $Lang serves as a "context" which can be inspected by Translatable - hence it + // has the same name as the database property on Translatable. + if($this->getRequest()->requestVar("Lang")) { + $this->Lang = $this->getRequest()->requestVar("Lang"); + } elseif($this->getRequest()->requestVar("lang")) { + $this->Lang = $this->getRequest()->requestVar("lang"); + } else { + $this->Lang = Translatable::default_lang(); + } Translatable::set_reading_lang($this->Lang); } @@ -487,14 +497,13 @@ JS; list($dummy, $className, $parentID, $suffix) = array_pad(explode('-',$id),4,null); if(Translatable::is_enabled()) { - if (!Translatable::is_default_lang()) { - $originalItem = Translatable::get_original($className,Session::get("{$id}_originalLangID")); - if ($setID) $originalItem->ID = $id; - else { - $originalItem->ID = null; - Translatable::creating_from(Session::get($id.'_originalLangID')); - } - return $originalItem; + if (Translatable::default_lang() != $this->Lang) { + Translatable::set_reading_lang(Translatable::default_lang()); + $originalItem = DataObject::get_by_id($className,$suffix); + Translatable::set_reading_lang($this->Lang); + $translation = $originalItem->getTranslation($this->Lang); + if($setID) $translation->ID = $id; + return $translation; } } @@ -1425,62 +1434,32 @@ HTML; //is it's a clean switch (to an existing language deselect the current page) if (is_string($lang)) $dontunloadPage = true; $lang = (is_string($lang) ? $lang : urldecode($this->urlParams['ID'])); + + $this->Lang = $lang; + Translatable::set_reading_lang($lang); + + Translatable::set_reading_lang(Translatable::default_lang()); + $siteTree = $this->getSiteTreeFor("SiteTree"); + Translatable::set_reading_lang($lang); + if ($lang != Translatable::default_lang()) { - Translatable::set_reading_lang(Translatable::default_lang()); - $tree_class = $this->stat('tree_class'); - $obj = new $tree_class; - $allIDs = $obj->getDescendantIDList(); - $allChildren = $obj->AllChildren(); - $classesMap = $allChildren->map('ID','ClassName'); - $titlesMap = $allChildren->map(); - Translatable::set_reading_lang($lang); - $obj = new $tree_class; - $languageIDs = $obj->getDescendantIDList(); - $notcreatedlist = array_diff($allIDs,$languageIDs); - FormResponse::add("$('addpage').getElementsByTagName('button')[0].disabled=true;"); - FormResponse::add("$('Form_AddPageOptionsForm').getElementsByTagName('div')[1].getElementsByTagName('input')[0].disabled=true;"); +// FormResponse::add("$('addpage').getElementsByTagName('button')[0].disabled=true;"); +// FormResponse::add("$('Form_AddPageOptionsForm').getElementsByTagName('div')[1].getElementsByTagName('input')[0].disabled=true;"); FormResponse::add("$('Translating_Message').innerHTML = 'Translating mode - ".i18n::get_language_name($lang)."';"); FormResponse::add("Element.removeClassName('Translating_Message','nonTranslating');"); } else { - Translatable::set_reading_lang($lang); - FormResponse::add("$('addpage').getElementsByTagName('button')[0].disabled=false;"); - FormResponse::add("$('Form_AddPageOptionsForm').getElementsByTagName('div')[1].getElementsByTagName('input')[0].disabled=false;"); + Translatable::set_reading_lang(Translatable::default_lang()); +// FormResponse::add("$('addpage').getElementsByTagName('button')[0].disabled=false;"); +// FormResponse::add("$('Form_AddPageOptionsForm').getElementsByTagName('div')[1].getElementsByTagName('input')[0].disabled=false;"); FormResponse::add("Element.addClassName('Translating_Message','nonTranslating');"); } - $obj = singleton($this->stat('tree_class')); - $obj->markPartialTree(); - $siteTree = $obj->getChildrenAsUL("", ' - "
  • ID\" class=\"" . $child->CMSTreeClasses($extraArg) . "\">" . - "Link(),0,-1), "show", $child->ID) . "\" " . (($child->canEdit() || $child->canAddChildren()) ? "" : "class=\"disabled\"") . " title=\"' . _t('LeftAndMain.PAGETYPE') . '".$child->class."\" >" . - (Convert::raw2js($child->TreeTitle())) . - "" -' - ,$this, true); - $rootLink = $this->Link() . '0'; - $siteTree = "
  • " . - _t('LeftAndMain.SITECONTENT') . "" - . $siteTree . "
  • "; - FormResponse::add("$('sitetree').innerHTML ='". ereg_replace("[\n]","\\\n",$siteTree) ."';"); + FormResponse::add("$('sitetree').parentNode.innerHTML ='". ereg_replace("[\n]","\\\n",$siteTree) ."';"); FormResponse::add("SiteTree.applyTo('#sitetree');"); - if (isset($notcreatedlist)) { - foreach ($notcreatedlist as $notcreated) { - if ($notcreated == $donotcreate) continue; - $id = "new-{$classesMap[$notcreated]}-0-$notcreated"; - Session::set($id . '_originalLangID',$notcreated); - $treeTitle = Convert::raw2js($titlesMap[$notcreated]); - $response = <<getRecord($originalLangID); $temporalID = "new-$record->RecordClassName-$record->ParentID-$originalLangID"; Session::set($temporalID . '_originalLangID',$originalLangID); + $tree = $this->switchlanguage($langCode, $originalLangID); + FormResponse::add(<<getitem(). The CMS submits the currently selected language + // through javascript, which will cause $Lang to be written to the database. + // @todo Explicitly set $Lang property for in-memory object so we don't need javascript modifying GET-calls to save the new object $newrecord = clone $record; $newrecord->ID = $temporalID; + $newrecord->Lang = $langCode; + //FormResponse::add("$('sitetree').getTreeNodeByIdx($originalLangID).selectTreeNode();"); + + // @todo New node is currently added at the end of the tree, + // rather than replacing the position of the original page + FormResponse::add(<<ID); +var oldParentNode = $('sitetree').getTreeNodeByIdx($record->ParentID); +oldParentNode.removeTreeNode(oldNode); +JS +); + return $this->returnItemToUser($newrecord); } diff --git a/css/cms_left.css b/css/cms_left.css index 02393008..68e5db5d 100644 --- a/css/cms_left.css +++ b/css/cms_left.css @@ -341,9 +341,9 @@ ul.contextMenu li a:hover { text-decoration: none; } -ul.tree li.untranslated a:link, -ul.tree li.untranslated a:hover, -ul.tree li.untranslated a:visited { +ul.tree span.untranslated a:link, +ul.tree span.untranslated a:hover, +ul.tree span.untranslated a:visited { color: #ccc } diff --git a/javascript/LangSelector.js b/javascript/LangSelector.js index caad1ea5..29d5e1b9 100755 --- a/javascript/LangSelector.js +++ b/javascript/LangSelector.js @@ -8,19 +8,14 @@ LangSelectorClass.prototype = { initialize: function() { if(this.selectedIndex != 0) { - this.showlangtree(); _TRANSLATING_LANG = this.value; } }, - onshow: function() { - if(this.value) this.showlangtree(); - }, - onchange: function(e, val) { if(this.value != _TRANSLATING_LANG) { _TRANSLATING_LANG = this.value; - this.showlangtree(); + document.location = 'admin/?lang=' + this.value; } }, @@ -37,17 +32,6 @@ LangSelectorClass.prototype = { } this.value = lang; } - }, - - showlangtree: function() { - if(this.value) { - $('sitetree').innerHTML='