Jump to content

Automatic Language Detection and Redirection in Multilingual Site


Recommended Posts

Hi everyone,

I'm working on a multilingual site in ProcessWire with three languages: Spanish (default), English, and Portuguese. I've already implemented a manual language switcher that works correctly, but I would like the site to automatically detect the user's browser language and redirect them to the specific language version.

  • Users with their browser language set to Spanish should be redirected to mysite.com
  • Users with their browser language set to English should be redirected to mysite.com/en
  • Users with their browser language set to Portuguese should be redirected to mysite.com/pt
  • Users with any other browser language should be redirected to mysite.com/en

Can anyone guide me on how to achieve this? I would appreciate any advice, code examples, or modules that could help me implement this functionality.

Thanks in advance!

Link to comment
Share on other sites

The script is in my templates/init.php file. You have to change the switch statement. Change zh to pt and replace de with es.

You need to put google on an exclusion list, so the bot get's not redirected! That is important, because the bot will visit with "en" language and will kick out all other language out of the index, if you force a redirect on them.

The redirect function:

function crawlerDetect($USER_AGENT){
	# Bots we DON'T want to redirected
	$crawlers = array(
		'Google' => 'Google',
		'Lighthouse' => 'Chrome-Lighthouse',
		'MSN' => 'msnbot',
		'Rambler' => 'Rambler',
		'Yahoo' => 'Yahoo',
		'AbachoBOT' => 'AbachoBOT',
		'accoona' => 'Accoona',
		'AcoiRobot' => 'AcoiRobot',
		'ASPSeek' => 'ASPSeek',
		'CrocCrawler' => 'CrocCrawler',
		'Dumbot' => 'Dumbot',
		'FAST-WebCrawler' => 'FAST-WebCrawler',
		'GeonaBot' => 'GeonaBot',
		'Gigabot' => 'Gigabot',
		'Lycos spider' => 'Lycos',
		'MSRBOT' => 'MSRBOT',
		'Altavista robot' => 'Scooter',
		'AltaVista robot' => 'Altavista',
		'ID-Search Bot' => 'IDBot',
		'eStyle Bot' => 'eStyle',
		'Scrubby robot' => 'Scrubby',
		'Facebook' => 'facebookexternalhit',
	);
	$crawlers_agents = implode('|',$crawlers);
	if (strpos($crawlers_agents, $USER_AGENT) === false)
	return false;
	else {
		return TRUE;
	}
}

# The setLang var is that for the hole session it will not enforce the redirect anymore
# I have in the footer of my sites a language dropdown as override in case the user want to visit the 
# other language - or in case the automatic ist wrong
$USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
if(crawlerDetect($USER_AGENT)) {
	$session->set('setLang','1');
};

if(!$session->get('setLang')) {
	if ($_SERVER['HTTP_ACCEPT_LANGUAGE'] != '') {
		# I take the first two letters of the sended language and compare it in a switch
		# statement
		$accept_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2);
		switch ($accept_lang) {
			case 'de':
				$session->set('setLang','1');
				if($page->url != "/") {
					$url = $page->localUrl('default');
					$session->redirect($url);
				}
				break;

			case 'en':
				$session->set('setLang','1');
				if($page->url != "/en/") {
					$url = $page->localUrl('en');
					$session->redirect($url);
				}
				break;

			case 'zh':
				$session->set('setLang','1');
				if($page->url != "/zh-cn/") {
					$url = $page->localUrl('zh-cn');
					$session->redirect($url);
				}
				break;

			default:
				$session->set('setLang','1');
				if($page->url != "/en/") {
					$url = $page->localUrl('en');
					$session->redirect($url);
				}
				break;
		}
	}
	else {
		$session->set('setLang','1');
	}
};

The dropdown (is building also in the templates/init.php above the redirect function) - also make here the same changes as above, case 'default' to es (your base language set in ProcessWire and zh to pt, and the default case in the bottom to en, as the wish fallback:

$current_lang = $languages->getLanguage();

switch ($current_lang->name) {
	# set all placeholder variable for the users language
	# also the attribute then for the html tag
	case 'default':
		$class_lang = 'language-de-de';
		$hreflang = 'de';
		$lang_url = $wire->page->localUrl("default");
		break;
	
	case 'en':
		$class_lang = '';
		$hreflang = 'en';
		$lang_url = $wire->page->localUrl("en");
		break;
	
	case 'zh-cn':
		$class_lang = '';
		$hreflang = 'zh-cn';
		$lang_url = $wire->page->localUrl("zh-cn");
		break;
	
	default:
		$class_lang = 'language-de-de';
		$hreflang = 'de';
		$lang_url = $wire->page->localUrl("default");
		break;
}
# The Dropwdon Linkt Text as PRocessWire Language Var, that can be set in the language module 
$drop_title = __("Sprache ändern");

$lang_li = '';

foreach($languages as $language) {
	// if(!$page->viewable($language)) continue; // is page viewable in this language?
	if($language->id == $user->language->id) {
		$lang_li .= "<li class='current'>";
	} else {
		$lang_li .= "<li>";
		$url = $wire->page->localUrl($language); 
	$hreflang_drop = $home->getLanguageValue($language, 'name'); 
	$lang_li .= "<a class='drop-item' hreflang='$hreflang_drop' href='$url'>$language->title</a></li>";
	}
	
}
# Now comes the dropdonw. Build at with the framework/dropdown lib you want and change it accordingly. $drop_title for the titel of the menu 
# and then $lang_li for all the collect <li> above
$lang_dropdown = '
	<div class="dropdown">
		<button class="drop-toggle" type="button" aria-expanded="false" onclick="dropFunc()">
	<svg width="18px" height="18px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#fff" style="transform: translate(0, 3px);"><path d="M2 5H9M16 5H13.5M9 5L13.5 5M9 5V3M13.5 5C12.6795 7.73513 10.9612 10.3206 9 12.5929M4 17.5C5.58541 16.1411 7.376 14.4744 9 12.5929M9 12.5929C8 11.5 6.4 9.3 6 8.5M9 12.5929L12 15.5" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M13.5 21L14.6429 18M21.5 21L20.3571 18M14.6429 18L17.5 10.5L20.3571 18M14.6429 18H20.3571" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
			'. $drop_title .'
		</button>
		<ul id="drop-menu" class="drop-menu">
			'. $lang_li .'
		</ul>
	</div>
';

Then in my templates/_main.php in the footer, I call $lang_dropdown for the dropdown menu for manual override.

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

@Tiberium, Wow... just wow.

Thank you so much for providing the code! I really appreciate your help. I’ll give it a try later today and let you know how it goes. Thanks again for your support!

 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...