ENHANCEMENT Redirecting to translated page when original is requested with a 'locale' GET parameter (e.g. 'about-us/?locale=de_DE' will redirect to 'ueber-uns' with a 301 HTTP response). Implemented in ContentController->handleRequest(). (see #5001) (from r100937)

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@111545 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sam Minnee 2010-10-04 04:24:01 +00:00
parent 37bc333882
commit 94d98b18ac
4 changed files with 53 additions and 13 deletions

View File

@ -142,12 +142,11 @@ class ContentController extends Controller {
// control to a child controller. This allows for the creation of chains of controllers which correspond to a
// nested URL.
if($action && SiteTree::nested_urls() && !$this->hasAction($action)) {
// See ModelAdController->getNestedController() for similar logic
Translatable::disable_locale_filter();
$child = DataObject::get_one('SiteTree', sprintf (
"\"ParentID\" = %s AND \"URLSegment\" = '%s'", $this->ID, Convert::raw2sql($action)
));
Translatable::enable_locale_filter();
}
@ -157,6 +156,18 @@ class ContentController extends Controller {
$response = ModelAsController::controller_for($child)->handleRequest($request);
} else {
// If a specific locale is requested, and it doesn't match the page found by URLSegment,
// look for a translation and redirect (see #5001). Only happens on the last child in
// a potentially nested URL chain.
if($request->getVar('locale') && $this->dataRecord && $this->dataRecord->Locale != $request->getVar('locale')) {
$translation = $this->dataRecord->getTranslation($request->getVar('locale'));
if($translation) {
$response = new SS_HTTPResponse();
$response->redirect($translation->Link(), 301);
throw new SS_HTTPResponse_Exception($response);
}
}
Director::set_current_page($this->data());
$response = parent::handleRequest($request);
Director::set_current_page(null);

View File

@ -87,12 +87,16 @@ class ModelAsController extends Controller implements NestedController {
throw new Exception('ModelAsController->getNestedController(): was not passed a URLSegment value.');
}
// Find page by link, regardless of current locale settings
Translatable::disable_locale_filter();
$sitetree = DataObject::get_one('SiteTree', sprintf (
'"URLSegment" = \'%s\' %s', Convert::raw2sql($URLSegment), (SiteTree::nested_urls() ? 'AND "ParentID" = 0' : null)
));
$sitetree = DataObject::get_one(
'SiteTree',
sprintf(
'"URLSegment" = \'%s\' %s',
Convert::raw2sql($URLSegment),
(SiteTree::nested_urls() ? 'AND "ParentID" = 0' : null)
)
);
Translatable::enable_locale_filter();
if(!$sitetree) {
@ -113,6 +117,7 @@ class ModelAsController extends Controller implements NestedController {
}
}
// Enforce current locale setting to the loaded SiteTree object
if($sitetree->Locale) Translatable::set_current_locale($sitetree->Locale);
if(isset($_REQUEST['debug'])) {

View File

@ -728,9 +728,12 @@ class Translatable extends DataObjectDecorator implements PermissionProvider {
return false;
}
/**
* Note: The bulk of logic is in ModelAsController->getNestedController()
* and ContentController->handleRequest()
*/
function contentcontrollerInit($controller) {
Translatable::choose_site_locale();
$controller->Locale = Translatable::get_current_locale();
$controller->Locale = Translatable::choose_site_locale();
}
function modelascontrollerInit($controller) {

View File

@ -22,6 +22,8 @@ class TranslatableTest extends FunctionalTest {
private $origLocale;
protected $autoFollowRedirection = false;
function setUp() {
parent::setUp();
@ -40,6 +42,25 @@ class TranslatableTest extends FunctionalTest {
parent::tearDown();
}
function testLocaleGetParamRedirectsToTranslation() {
$origPage = $this->objFromFixture('Page', 'testpage_en');
$origPage->publish('Stage', 'Live');
$translatedPage = $origPage->createTranslation('de_DE');
$translatedPage->URLSegment = 'ueber-uns';
$translatedPage->write();
$translatedPage->publish('Stage', 'Live');
$response = $this->get($origPage->URLSegment);
$this->assertEquals(200, $response->getStatusCode(), 'Page request without Locale GET param doesnt redirect');
$response = $this->get(Controller::join_links($origPage->URLSegment, '?locale=de_DE'));
$this->assertEquals(301, $response->getStatusCode(), 'Locale GET param causes redirect if it exists');
$this->assertContains($translatedPage->URLSegment, $response->getHeader('Location'));
$response = $this->get(Controller::join_links($origPage->URLSegment, '?locale=xx_XX'));
$this->assertEquals(200, $response->getStatusCode(), 'Locale GET param without existing translation shows original page');
}
function testTranslationGroups() {
// first in french
$frPage = new SiteTree();