Source of file MultilingualRootURLController.php
Size: 13,284 Bytes - Last Modified: 2021-12-23T10:58:00+00:00
/var/www/docs.ssmods.com/process/src/code/control/MultilingualRootURLController.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 | <?php class MultilingualRootURLController extends RootURLController { /** * Tells the routing controllers to use the locale url or not i.e /en_US/ instead of /en/ * @default false * @config MultilingualRootURLController.UseLocaleURL */ private static $UseLocaleURL=false; /** * Tells the routing controllers to use a dashed locale or not i.e /en-us/ instead of /en_US/ requires MultilingualRootURLController.UseLocaleURL to be true * @default false * @config MultilingualRootURLController.UseDashLocale */ private static $UseDashLocale=false; /** * * @default false * @config MultilingualRootURLController.use_country_only */ private static $use_country_only=false; public function handleRequest(SS_HTTPRequest $request, DataModel $model=null) { self::$is_at_root=true; $this->setDataModel($model); $this->pushCurrent(); $this->init(); //Get the locale from the language param if($language=$request->param('Language')) { if(MultilingualRootURLController::config()->use_country_only) { $locale=self::get_locale_from_country($request->param('Language')); if(empty($locale)) { //Locale not found 404 try { $response=ErrorPage::response_for(404); $this->httpError(404, ($response ? $response:'The requested page could not be found.')); }catch(SS_HTTPResponse_Exception $responseException) { $result=$responseException->getResponse(); } return $result; } }else if(MultilingualRootURLController::config()->UseLocaleURL) { if(MultilingualRootURLController::config()->UseDashLocale) { //Language is missing a dash 404 if(strpos($language, '-')===false) { //Locale not found 404 try { $response=ErrorPage::response_for(404); $this->httpError(404, ($response ? $response:'The requested page could not be found.')); }catch(SS_HTTPResponse_Exception $responseException) { $result=$responseException->getResponse(); } return $result; } $locale=explode('-', $language); $locale[1]=strtoupper($locale[1]); //Make sure that the language is all lowercase if($language==implode('-', $locale)) { //Locale not found 404 try { $response=ErrorPage::response_for(404); $this->httpError(404, ($response ? $response:'The requested page could not be found.')); }catch(SS_HTTPResponse_Exception $responseException) { $result=$responseException->getResponse(); } return $result; } $locale=implode('_', $locale); }else { //Language is missing an underscore 404 if(strpos($language, '_')===false) { //Locale not found 404 try { $response=ErrorPage::response_for(404); $this->httpError(404, ($response ? $response:'The requested page could not be found.')); }catch(SS_HTTPResponse_Exception $responseException) { $result=$responseException->getResponse(); } return $result; } $locale=$language; } }else if(strpos($language, '_')!==false || strpos($language, '-')!==false) {//If the url has a locale in it when the settings are off //Locale not found 404 try { $response=ErrorPage::response_for(404); $this->httpError(404, ($response ? $response:'The requested page could not be found.')); }catch(SS_HTTPResponse_Exception $responseException) { $result=$responseException->getResponse(); } return $result; }else {//Potentially a language code $locale=i18n::get_locale_from_lang($language); } if(in_array($locale, Translatable::get_allowed_locales())) { Cookie::set('language', $locale); Translatable::set_current_locale($locale); i18n::set_locale($locale); if(!DB::isActive() || !ClassInfo::hasTable('SiteTree')) { $this->response=new SS_HTTPResponse(); $this->response->redirect(Director::absoluteBaseURL().'dev/build?returnURL='.(isset($_GET['url']) ? urlencode($_GET['url']):null)); return $this->response; } $request->setUrl($language.'/'.self::get_homepage_link().'/'); $request->match('$Language/$URLSegment//$Action', true); $controller=new MultilingualModelAsController(); $result=$controller->handleRequest($request, $model); $this->popCurrent(); return $result; }else { $locale=Translatable::default_locale(); if(MultilingualRootURLController::config()->UseLocaleURL || MultilingualRootURLController::config()->use_country_only) { if(MultilingualRootURLController::config()->UseDashLocale) { $language=str_replace('_', '-', strtolower($locale)); }else { $language=$locale; } //For country only the language code in the url should be just the country code if(MultilingualRootURLController::config()->use_country_only) { $language=strtolower(preg_replace('/^(.*?)_(.*?)$/', '$2', $language)); } }else { $language=Translatable::default_lang(); } //URL Param Locale is not allowed so redirect to default $this->redirect(Controller::join_links(Director::baseURL(), $language).'/', 301); $this->popCurrent(); return $this->response; } } //No Locale Param so detect browser language and redirect if($locale=self::detect_browser_locale()) { if(MultilingualRootURLController::config()->use_country_only) { $language=$locale; }else if(MultilingualRootURLController::config()->UseLocaleURL || MultilingualRootURLController::config()->use_country_only) { if(MultilingualRootURLController::config()->UseDashLocale) { $language=str_replace('_', '-', strtolower($locale)); }else { $language=$locale; } }else { $language=i18n::get_lang_from_locale($locale); } Cookie::set('language', $locale); //For country only the language code in the url should be just the country code if(MultilingualRootURLController::config()->use_country_only) { $language=strtolower(preg_replace('/^(.*?)_(.*?)$/', '$2', $language)); } $this->redirect(Controller::join_links(Director::baseURL(), $language).'/', 301); $this->popCurrent(); return $this->response; } if(MultilingualRootURLController::config()->UseLocaleURL || MultilingualRootURLController::config()->use_country_only) { if(MultilingualRootURLController::config()->UseDashLocale) { $language=str_replace('_', '-', strtolower(Translatable::default_locale())); }else { $language=Translatable::default_locale(); } //For country only the language code in the url should be just the country code if(MultilingualRootURLController::config()->use_country_only) { $language=strtolower(preg_replace('/^(.*?)_(.*?)$/', '$2', $language)); } }else { $language=Translatable::default_lang(); } $this->redirect(Controller::join_links(Director::baseURL(), $language.'/'), 301); $this->popCurrent(); return $this->response; } /** * Determines the locale best matching the given list of browser locales * @return {string} The matching locale, or null if none could be determined */ public static function detect_browser_locale() { if($locale=Cookie::get('language')) { if(in_array($locale, Translatable::get_allowed_locales())) { return $locale; }else { Cookie::force_expiry('language'); } } // Given multiple canditates, narrow down the final result using the client's preferred languages $inputLocales=(array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER) ? $_SERVER['HTTP_ACCEPT_LANGUAGE']:null); if(empty($inputLocales)) { return null; } // Generate mapping of priority => list of languages at this priority // break up string into pieces (languages and q factors) preg_match_all('/(?<code>[a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(?<priority>1|0\.[0-9]+))?/i', $inputLocales, $parsedLocales); $prioritisedLocales=array(); if(count($parsedLocales['code'])) { // create a list like "en" => 0.8 $parsedLocales=array_combine($parsedLocales['code'], $parsedLocales['priority']); // Generate nested list of priorities => [languages] foreach($parsedLocales as $language => $priority) { $priority=(empty($priority) ? 1.0:floatval($priority)); if(empty($prioritisedLocales[$priority])) { $prioritisedLocales[$priority] = array(); } $prioritisedLocales[$priority][]=$language; } // sort list based on value krsort($prioritisedLocales, SORT_NUMERIC); } // Check each requested language against loaded languages foreach($prioritisedLocales as $priority=>$parsedLocales) { foreach($parsedLocales as $browserLocale) { foreach(Translatable::get_allowed_locales() as $language) { if(stripos(preg_replace('/_/', '-', $language), $browserLocale)===0) { return $language; } } } } return null; } /** * Returns TRUE if a request to a certain page should be redirected to the site root (i.e. if the page acts as the home page). * @param {SiteTree} $page * @return {bool} */ public static function should_be_on_root(SiteTree $page) { if(!self::$is_at_root && self::get_homepage_link()==trim($page->RelativeLink(true), '/')) { return true; } return false; } /** * Finds the locale based on the allowed locales and the country code * @param {string} $country Country to try and find a locale for * @return {string} Can potentially return null if there were no matches */ public static function get_locale_from_country($country) { $potentialLocales=preg_grep('/_'.preg_quote(strtoupper($country), '/').'$/', Translatable::get_allowed_locales()); //Verify there is only one match if(count($potentialLocales)>1) { user_error('Warning there are multiple allowed locales ("'.implode('", "', $potentialLocales).'") matching the given country "'.strtoupper($country).'" you should not use the MultilingualRootURLController.use_country_only with the current set of allowed locales: "'.implode('", "', Translatable::get_allowed_locales()).'"', E_USER_WARNING); } //Pop off the first element in the array return array_shift($potentialLocales); } } ?> |