Determining user language based on IP address (geolocation) - php

I've integrated two pieces of PHP code found on different websites. The first part of code finds out what country you are in and the second one determines the language. I have tried running it but with no luck. It does not give me a error, just a blank white screen.
Here is the code:
<?php
function visitor_country()
{
$client = #$_SERVER['HTTP_CLIENT_IP'];
$forward = #$_SERVER['HTTP_X_FORWARDED_FOR'];
$remote = $_SERVER['REMOTE_ADDR'];
$result = "Unknown";
if(filter_var($client, FILTER_VALIDATE_IP))
{
$ip = $client;
}
elseif(filter_var($forward, FILTER_VALIDATE_IP))
{
$ip = $forward;
}
else
{
$ip = $remote;
}
$ip_data = #json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=".$ip));
if($ip_data && $ip_data->geoplugin_countryName != null)
{
$result = $ip_data->geoplugin_countryName;
}
return $result;
}
session_start();
header('Cache-control: private'); // IE 6 FIX
if (isset($_GET['lang'])) {
$lang = $_GET['lang'];
// register the session and set the cookie
$_SESSION['lang'] = $lang;
setcookie('lang', $lang, time() + (3600 * 24 * 30));
} else if (isset($_SESSION['lang'])) {
$lang = $_SESSION['lang'];
} else if (isset($_COOKIE['lang'])) {
$lang = $_COOKIE['lang'];
} else {
$lang = 'en';
}
switch ($lang) {
case 'en':
$lang_file = 'lang.en.php';
break;
case 'de':
$lang_file = 'lang.de.php';
break;
if(visitor_country() == "Germany") {
default:
$lang_file = 'lang.de.php';
echo "Germany";
} else {
default:
$lang_file = 'lang.en.php';
echo "Not in Germany";
}
}
include_once 'languages/' . $lang_file;
?>
I could not include the language code, but rest assured it works as I use it on my site without auto-country detection.

You code returns an error: PHP Parse error: syntax error, unexpected 'default' (T_DEFAULT) in yourfile.php on line. It means that you're misusing default in switch statement. Replace your last part of your code with this:
default:
if(visitor_country() == "Germany") {
$lang_file = 'lang.de.php';
echo "Germany";
} else {
$lang_file = 'lang.en.php';
echo "Not in Germany";
}
Take out default from inside of if/else statement.
EDIT 1:
Make sure that PHP displays ERRORS, WARNING and NOTICES to properly debug your code:
ini_set('display_errors', -1);
EDIT 2:
If it was working without the switch statement, like you said, then you must make sure that files lang.en.php/lang.de.php really exist.
EDIT 3:
You are suppressing errors with having # in-front of json_decode(file_get_contents. Most likely you would have to edit your php.ini and enable allow_url_fopen to make it work. I bet if you remove #, you will get an error:
Warning: file_get_contents(): http:// wrapper is disabled in the server configuration by allow_url_fopen=0 in
I wouldn't strongly recommend using this kind of method to detect user language and enabling allow_url_fopen as it's possible security flaw! In case you're interested, I will provide you with much better solution for determining user browsers' language.

Related

redirect domain according to extension and language

I'm trying to look for a solution for a multilanguage website. I have 4 domains:
domain.com
domain.be
domain.nl
domain.uk
According to the domain, the appropriate language has to be loaded.The language gets determined by ?lang=...
I have tried modrewrite in .htaccess but it does not suit my needs. When a user visits domain.com/page the .htaccess does not process the rules.
So I was thinking to do it with php.
Currently, the language and the cookie gets set by this piece php:
<?php
session_start();
header('Cache-control: private'); // IE 6 FIX
if(isSet($_GET['lang']))
{
$lang = $_GET['lang'];
// register the session and set the cookie
$_SESSION['lang'] = $lang;
setcookie('lang', $lang, time() + (3600 * 24 * 30));
}
else if(isSet($_SESSION['lang']))
{
$lang = $_SESSION['lang'];
}
else if(isSet($_COOKIE['lang']))
{
$lang = $_COOKIE['lang'];
}
else
{
$lang = 'en_eu';
}
switch ($lang) {
case 'nl_be':
$lang_file = 'nl_be.php';
break;
case 'nl_nl':
$lang_file = 'nl_nl.php';
break;
case 'en_us':
$lang_file = 'en_us.php';
break;
case 'en_uk':
$lang_file = 'en_us.php';
break;
case 'en_eu':
$lang_file = 'en_eu.php';
break;
default:
$lang_file = 'en_eu.php';
}
include_once 'components/languages/'.$lang_file;
?>
I was thinking to add a some lines to determine the domain name and add some if statements to determine the language according to the domain. But I don't really know how and if this is the right way of doing it.
<?php
$url = "//{$_SERVER['HTTP_HOST']}";
if ($url == domain.be) {
$lang = 'nl_be';
}
elseif ($url == domain.uk) {
$lang = 'en_uk';
}
else ( ) {
$lang = 'en_us';
}
?>
After reading this: https://support.google.com/webmasters/answer/182192?hl=en
Google suggest keeping different language versions on their own URLs.
As you already have the top level domains, I would just check the domain name and determine the language from that.
Then at the top of each page give the users language choice links:
English: example.com/node/1
French: example.fr/node/1
etc.
Hide the current language link.
And supplement the above with link elements in the head:
<link rel="alternate" hreflang="es" href="http://example.es/node/1" />
I have found the answer in this thread How to default to another language based on domain
It makes use of SetEnvIf in .htaccess and php handles the rest
code in .htaccess:
SetEnvIf Host "\.be$" SITE_LANGUAGE=nl_be
SetEnvIf Host "\.uk$" SITE_LANGUAGE=en_uk
and then call the SITE_LANGUAGE with:
$_SERVER['SITE_LANGUAGE'];
code in PHP:
<?php
session_start();
header('Cache-control: private'); // IE 6 FIX
$lang = $_SERVER['SITE_LANGUAGE'];
if(isSet($_GET['lang']))
{
$lang = $_GET['lang'];
// register the session and set the cookie
$_SESSION['lang'] = $lang;
setcookie('lang', $lang, time() + (3600 * 24 * 30));
}
else if(isSet($_SESSION['lang']))
{
$lang = $_SESSION['lang'];
}
else if(isSet($_COOKIE['lang']))
{
$lang = $_COOKIE['lang'];
}
else
{
$lang = 'en_eu';
}
switch ($lang) {
case 'nl_be':
$lang_file = 'nl_be.php';
break;
case 'nl_nl':
$lang_file = 'nl_nl.php';
break;
case 'en_us':
$lang_file = 'en_us.php';
break;
case 'en_uk':
$lang_file = 'en_us.php';
break;
case 'en_eu':
$lang_file = 'en_eu.php';
break;
default:
$lang_file = 'en_eu.php';
}
include_once 'components/languages/'.$lang_file;
?>

PHP code defaulting to an error when it shouldn't be

I had a PHP developer create a redirection script that redirects users in specific states to another URL, while letting everyone else visit the website.
The problem is it's redirecting everyone who doesn't match a state listed to the error URL, when it should be letting them visit the site.
I think there's a return missing? What do you guys think?
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
require_once '/vendor/autoload.php';
use MaxMind\Db\Reader;
$databaseFile = '/geoip/GeoIP2-City.mmdb';
$ipWhiteList = ['123', '321'];
if(!in_array($_SERVER["REMOTE_ADDR"], $ipWhiteList)) {
$reader = new Reader($databaseFile);
$iso_code = $reader->get($_SERVER["REMOTE_ADDR"])['subdivisions'][0]['iso_code'];
if (!isset($_REQUEST['HTTP_REFERER'])) {
switch($iso_code) {
case NJ:
$url = 'http://example.com';
break;
case DE:
$url = 'http://example.com';
break;
default:
$url = 'http://www.example.com/?=error';
break;
}
$reader->close();
header('Location: '.$url);
die();
} else {
if(strpos($_SERVER['HTTP_REFERER'], "example2.com") > -1) {
echo "You were redirected from ".urldecode($_REQUEST['referer']).", but it is not available in your area (".$iso_code.").";
break;
} else {
echo "Welcome!";
break;
}
}
}
?>
Maybe try loading all the valid values, and checking to make sure it's valid, even if it's not NJ/DE.
if (in_array($state, array('NJ', 'DE'))) {
// Redirect
} elseif (!in_array($states, $all_states_array)) {
// Go to error.
}
The else is implied, in that the script will just continue working. You could structure this several different ways, depending on how much you need to extend it:
if (!in_array($state, $all_states_array)) {
// Error
}
if (in_array($state, array('NJ', 'DE'))) {
// Redirect
}
You could also add all the cases:
case 'DE':
// Do something;
break;
case 'NJ':
// Do soemthing;
break;
case 'PA':
case 'AL':
case 'NY':
case 'OK':
case 'TX':
...
// Valid, but not the right target.
break;
default:
// show error
Try this. If the state is not from NJ or DE, then do nothing.
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
require_once '/vendor/autoload.php';
use MaxMind\Db\Reader;
$databaseFile = '/geoip/GeoIP2-City.mmdb';
$ipWhiteList = ['123', '321'];
if(!in_array($_SERVER["REMOTE_ADDR"], $ipWhiteList)) {
$reader = new Reader($databaseFile);
$iso_code = $reader->get($_SERVER["REMOTE_ADDR"])['subdivisions'][0]['iso_code'];
if (!isset($_REQUEST['HTTP_REFERER'])) {
switch($iso_code) {
case NJ:
$url = 'http://example.com';
header('Location: '.$url);
die();
break;
case DE:
$url = 'http://example.com';
header('Location: '.$url);
die();
break;
default:
}
$reader->close();
} else {
if(strpos($_SERVER['HTTP_REFERER'], "example2.com") > -1) {
echo "You were redirected from ".urldecode($_REQUEST['referer']).", but it is not available in your area (".$iso_code.").";
break;
} else {
echo "Welcome!";
break;
}
}
}
?>

Language problems (Cookie/Session)

I have problem with language on my page. When i choose one language it take it corectly, all content change, but when i reload or go to another page the language change back to default language, something with cookies are not corect :/. On localhost all works good but on hosting dont work.
Code:
<?php
session_start();
header('Cache-control: private');
if(isSet($_GET['lang']))
{
$lang = $_GET['lang'];
$_SESSION['lang'] = $lang;
session_set_cookie_params('lang', $lang, time() + (3600 * 24 * 30));
}
else if(isSet($_SESSION['lang']))
{
$lang = $_SESSION['lang'];
}
else if(isSet($_COOKIE['lang']))
{
$lang = $_COOKIE['lang'];
}
else
{
$lang = 'lv';
}
switch ($lang) {
case 'lv':
$lang_file = 'lv.php';
break;
case 'ru':
$lang_file = 'ru.php';
break;
default:
$lang_file = 'lv.php';
}
include_once 'lang/'.$lang_file;
?>
I suggest to check the answers here:
PHP Session data not being saved
Code that you showed us works well, so it must be a server/configuration issue. Good luck :)
Why are you using session_set_cookie_params and not setcookie?
Adding the ?lang parameter on every link is going to be tiresome. And bloat your code and make it less readable.

include_once gives an error when variable isn't passed in the url

index.php
<?php include_once 'lang.php'; ?>
lang.php
<?php
session_start();
header('Cache-control: private'); // IE 6 FIX
if (isSet($_GET['lang'])) {
$lang = $_GET['lang'];
// register the session and set the cookie
$_SESSION['lang'] = $lang;
setcookie("lang", $lang, time() + (3600 * 24 * 30));
}
else if (isSet($_SESSION['lang'])) {
$lang = $_SESSION['lang'];
}
else if (isSet($_COOKIE['lang'])) {
$lang = $_COOKIE['lang'];
}
else {
$lang = 'en';
}
switch ($lang) {
case 'en':
$lang_file = 'lang.en.php';
break;
case 'pl':
$lang_file = 'lang.pl.php';
break;
}
include_once 'languages/' . $lang_file;
?>
In lang.en.php and lang.pl.php I have arrays with content.
When website is opened for the first time I get two warnings:
Warning: include_once(languages/) [function.include-once]: failed to open stream: No such file or directory in blah/blah/blah/lang.php on line 37
Warning: include_once() [function.include]: Failed opening 'languages/' for inclusion (include_path='.:/usr/local/lib/php-5.2.17/lib/php') in blah/blah/blah/lang.php on line 37
Then when I select a language on the webpage, and variable "lang" is passed in the url (e.g. index.php?lang=en) everything works ok. How to fix it?
If you don't define a language, it tries to load 'languages/' (a directory). You should have a default in your switch statement. If you want the default language to be 'en', for example:
switch ($lang) {
case 'pl':
$lang_file = 'lang.pl.php';
break;
default: // en will fall here, too
$lang_file = 'lang.en.php';
break;
}
Otherwise $lang_file is undefined and will of course fail to load.
Maybe just add a default section for the switch:
switch($lang){
case 'en':
$lang_file='lang.en.php';
break;
case 'pl':
$lang_file='lang.pl.php';
break;
default:
// This will set a default language file.
$lang_file='lang.en.php';
}
include_once 'languages/'.$lang_file;
This time, when $lang is not set to 'en' or 'pl', the switch will return setting the $lang_file to lang.en.php. If you want pl to be set by default, however, you can change that.

php Aruba $_session issue

I'm testing this code in Localhost and on Server "Aruba".
In local environment it works perfectly while on Server I dont have the expected session value
When I echo out the $_SESSION['lang'] it outputs :
-the correct country code (Ex.'en') in localhost
-On the Aruba server $_SESSION['lang'] outputs the array named $lang (that you can find on lang.en.php)instead of the needed country code!!
Where am I wrong?
thanks
Luca
my home.php
require_once('/web/htdocs/www.mywebsite.com/home/includes/langSwitcher.inc');
echo $_SESSION['lang'];
[..]
my langSwitcher.inc
session_start();
header('Cache-control: private'); // IE 6 FIX
if(isset($_GET['lang']))
{
$lang = $_GET['lang'];
// register the session and set the cookie
$_SESSION['lang'] = $lang;
setcookie('lang', $lang, time() + (3600 * 24 * 30));
}
else if(isset($_SESSION['lang']))
{
$lang = $_SESSION['lang'];
}
else if(isset($_COOKIE['lang']))
{
$lang = $_COOKIE['lang'];
$_SESSION['lang']=$lang;
}
else
{
$lang = 'en';
$_SESSION['lang']=$lang;
}
switch ($lang)
{
case 'en':
$lang_file = 'lang.en.php';
break;
case 'it':
$lang_file = 'lang.it.php';
break;
}
include_once $lang_file;
my lang.en.php
/*
-----------------
Language: Italian
-----------------
*/
$langcode='en';
$lang = array();
$lang['PAGE_TITLE'] = 'pagetitle';
$lang['HEADER_TITLE'] = 'title header ';
$lang['SITE_NAME'] = 'name site';
$lang['HEADING'] = 'title';
It sounds like register_globals may be enabled (although that feature is deprecated). You can find out by running a phpinfo() and looking for the register_globals entry.
Assuming it is enabled, the only solution is to fix it in php.ini (you cannot override register_globals with an ini_set() call).
Well you are using $lang to keep the langcode, but also to store the array information. Perhaps in the langSwitcher.inc you should be using $langcode to store the session?
Because you are also settings the $lang var in the session their. On your server it seems to be using a reference to the $lang file, and therefor outputting the latest content set to $lang (which is the array) and on local it is storing the actual content of $lang.
Anyway, it can be solved by not using the same variable name to store two different items.

Categories