My project can switch between languages. The items are stored in a database, and using $_GET['lang'] in the database gives back the correct items. For now, only English and French are in use, so it works with this code :
if ($_GET['lang'] == 'fr' OR ($_GET['lang'] == 'en')) {
$header = getTranslation('header', $_GET['lang']);
$footer = getTranslation('footer', $_GET['lang']);
} else {
header('Location: error.php');
}
What I'm looking for is some way to be prepared in case a language is added in the db. The code below approaches what I need (and obviously didn't work).
while ($translations = $languagesList->fetch()) {
if ($_GET['lang'] == $translations['code']) {
$header = getTranslation('header', $_GET['lang']);
$footer = getTranslation('footer', $_GET['lang']);
} else {
header('Location: language.php');
}
}
Is there any way to create a code that would generate multiple if conditions based on the number of languages in the db ?
You should move the else part outside of the loop, as otherwise you will always execute it at some point in the loop iterations. Only when you have iterated through all possibilities, and you still have no match, then you can be sure there to have to navigate to the language page:
$header = null;
while ($translations = $languagesList->fetch()) {
if ($_GET['lang'] == $translations['code']) {
$header = getTranslation('header', $_GET['lang']);
$footer = getTranslation('footer', $_GET['lang']);
break; // No need to waste time to look further.
}
}
if ($header === null) {
header('Location: language.php');
}
But it would be smarter to prepare an SQL statement that gets you the result for the particular language only (with where code = ? and bind $_GET['lang'] to it). Then you don't have to iterate in PHP, which will in general be slower than what the database can provide. Instead you can just see whether you had 0 or 1 records back (Or use select count(*) and check whether that is 0 or not).
Easiest is to have a mapping in an array, check if your language is present there, and if so, do stuff. Something like this;
$languages = array('en', 'fr', 'de', '...');
$default_language = 'en';
$language = in_array($_GET['lang'], $languages) ? $_GET['lang'] : $default_language;
$header = getTranslation('header', $language);
As you can see I've set a default langauge which is used if the language in the query var cannot be found. How to create that array of languages is up to you (a simple query should suffice).
Related
My website by default is in English
But I can change the language, when a visitor visits our website with a url of a news item in Spanish:
example.com/es/news/718/url-title-article/
The url given as an example is a news in Spanish since the first folder or directory is named "es" example.com/es/news/718/url-title-article/ -> es
And, that's where the trick comes, since I have a function that allows me to obtain the name of the first folder or directory and if it matches with the given parameters, it should set a cookie with the language of that url, in this case Spanish -> "es".
if($FOLDER_LANG === "es" || $SUBDOMAIN_LANG === "es") {
setcookie ('language', 'es', time()+60*60*24*365, '/', 'example.com');
}
if(isset($_COOKIE['language'])){
if($_COOKIE['language']==='en'){
$WEBSITE_TITLE = " | WebSIte EN";
$LANG = 'en';
$language = "en";
}elseif($_COOKIE['language']==='es'){
$WEBSITE_TITLE = " | WebSite ES";
$LANG = 'es';
$language = "es";
}
} else {
$WEBSITE_TITLE = " | WebSite DEFAULT EN";
$LANG = 'en';
$language = "en";
}
But the problem, is that I have to reload the page to see the changes of the new language added to the site.
So how can you solve it without having to reload the site.
You need to write the logic which determines the language so it doesn't depend on the cookie.
So, before, where you might have had something like:
$language_data = get_i18n_data( $_COOKIES['language'] );
You would instead have something like:
function get_language() {
if($FOLDER_LANG === "es" || $SUBDOMAIN_LANG === "es") {
setcookie ('language', 'es', time()+60*60*24*365, '/', 'example.com');
return 'es'
}
return $_COOKIES['language'];
}
$language_data = get_i18n_data( get_language() );
The reason for refresh being needed is that $LANG and $language is set by an existing cookie and not the new one.
Analysing your code:
if($FOLDER_LANG === "es" || $SUBDOMAIN_LANG === "es") {
setcookie ('language', 'es', time()+60*60*24*365, '/', 'example.com');
}
Here, it's setting the cookie only in the header. It is not accessible until the page is reloaded.
One option is to add the following in the if condition:
$LANG = 'es';
$language = "es";
The rest of your code then reads existing cookies so this is what will load on the same page even if the cookie is set just before it:
A better way in my opinion is to keep it simple and expandable by using variable $language to drive the data:
$language = 'en'; //this is default
if(isset($_COOKIE['language'])){
$language = $_COOKIE['language'];
}
//now check if current $language is different to folder
if($FOLDER_LANG != $language || $SUBDOMAIN_LANG != $language) {
//this is condition depends on your variables. You might need && if both conditions should be met or modify as required
//set the language for this page (so no need for refresh and also set the cookie
$language = $FOLDER_LANG ? $FOLDER_LANG : $SUBDOMAIN_LANG; //sets to folder or sudomain language code if $FOLDER_LANG is empty. You can switch the two folders to priotorise the latter.
//now set the cookie
setcookie ('language', $language, time()+60*60*24*365, '/', 'example.com');
}
//now set the the title and the extra variable $LANG (you probably should choose one variable to use)
$WEBSITE_TITLE = " | WebSite . strtoupper($language)";
$LANG = $language;
Now you can support more languages and also won't need to refresh
This question already has answers here:
Detect Browser Language in PHP
(16 answers)
Closed 6 years ago.
EDIT: Wasn't a duplicate to began with. Originally was how to improve or use different code to redirect based on the visitor's COUNTRY.
Here is the code I'm currently using:
require_once('geo/geoip.inc');
$gi = geoip_open('geo/GeoIP.dat', GEOIP_MEMORY_CACHE);
$country = geoip_country_code_by_addr($gi, $_SERVER['REMOTE_ADDR']);
geoip_close($gi);
if ($country == 'FR') {
header('Location: http://fr.mysite.com');
}
if ($country == 'US') {
header('Location: http://us.mysite.com');
}
on a couple of static (html + javascript) viral sites that bring in around 100,000 visitors a day, sometimes more and sometimes less.
Are there any better (and free) solutions to redirect based on country? I recently switched from a dedicated server to a VPS and the current code seems to use a lot of CPU usage (or so I'm told by my host). I'll probably just go back to the dedicated server but I would still like to know if there is a better way, one that doesn't stress the server as much.
Also, since I'm redirecting based on language:
// french
if ($country == 'FR') {
header('Location: http://fr.mysite.com');
}
//french
if ($country == 'BE') {
header('Location: http://fr.mysite.com');
}
//french
if ($country == 'CA') {
header('Location: http://fr.mysite.com');
}
//english
if ($country == 'US') {
header('Location: http://us.mysite.com');
}
//english
if ($country == 'UK') {
header('Location: http://us.mysite.com');
}
and extremely tired right now, what's the better way? this or no:
//english
if ($country == 'US') || ($country == 'CA') {
header('Location: http://us.mysite.com');
}
So anyone visiting from US or Canada would be redirected to google.com
Thanks in advance
EDIT: Source ended up being an answer to the duplicate question.
If the only differences between the sites are languages and nothing to do with their actual country, you should be redirecting based on preferred language instead.
However, this gets really complex, as HTML headers can contain multiple languages, with certain languages preferred over others. A solution I found a while back, and unfortunately cannot find the original source to is to make a list of available languages, parse the languages out of the HTML Header with their order of preference, and determine based on that which redirect to follow:
I DO NOT OWN THE prefered_language() FUNCTION AND DID NOT TAKE ANY PART IN ITS CREATION!
But I can't find the original anywhere.. If someone else is able to, please, link it...
$available_languages = array("en", "fr");
$default_language = "en";
function prefered_language($available_languages, $http_accept_language) {
global $default_language;
$available_languages = array_flip($available_languages);
$langs = array();
preg_match_all('~([\w-]+)(?:[^,\d]+([\d.]+))?~', strtolower($http_accept_language), $matches, PREG_SET_ORDER);
foreach($matches as $match) {
list($a, $b) = explode('-', $match[1]) + array('', '');
$value = isset($match[2]) ? (float) $match[2] : 1.0;
if(isset($available_languages[$match[1]])) {
$langs[$match[1]] = $value;
continue;
}
if(isset($available_languages[$a])) {
$langs[$a] = $value - 0.1;
}
}
if($langs) {
arsort($langs);
return key($langs);
} else {
return $default_language;
}
}
if(isset($_COOKIE["client_lang"])){
$lang = $_COOKIE["client_lang"];
}else{
$lang = prefered_language($available_languages, strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"]));
setcookie("client_lang", $lang, time() + (86400 * 30 * ), "/");
}
header('Location: http://' . $lang . '.mysite.com');
I'd also suggest creating a cookie for the client's preferred language as I have done above, since this function will still require some CPU usage.
I am struggling with code that redirects a user to other pages based on language detection. I found this code which looks promising as so far I have not had any luck from other posts on this website. My only question is related to the first line of code. What do I put in the "" part on first line?
<?php
$lc = ""; // Initialize the language code variable
// Check to see that the global language server variable isset()
// If it is set, we cut the first two characters from that string
if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
$lc = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
}
// Now we simply evaluate that variable to detect specific languages
if($lc == "fr"){
header("location: index_french.php");
exit();
} else if($lc == "de"){
header("location: index_german.php");
exit();
}
?>
<h2>Hello Default Language User</h2>
<h3><?php echo "Your 2-letter Code is: ".$lc; ?></h3>
When I run this code I get an error message:
Warning: Cannot modify header information - headers already sent by (output started at /home/m3418630/public_html/sumoresources/index.php:3) in /home/m3418630/public_html/sumoresources/index.php on line 12
Can anyone explain why this happens?
thanks
In your code snippet, you have to set a default language to the variable $lc. It will be overwritten if the server sends a language code from the current request.
This snippet can detect language from user's browser
$locale = null;
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach ($languages as $lang) {
$lang = str_replace('-', '_', trim($lang));
if (false === strpos($lang, '_')) {
$locale = strtoupper($lang);
} else {
$lang = explode('_', $lang);
if (count($lang) == 3) {
$locale = strtolower($lang[0]) . ucfirst($lang[1]) . strtoupper($lang[2]);
} else {
$locale = strtolower($lang[0]) . strtoupper($lang[1]);
}
}
}
}
echo $locale;
see http://codepad.viper-7.com/F1XfU5
You don't put anything there, it's just initiating the variable as it says in the comment.
If you're getting a headers already sent error, that means your outputting information to the page before sending header(), you can't do this without buffering using ob_start(), ob_end_flush().
I have a web site made in 3 languages, but will (maybe) be expanded.
So I created a table on the database where I insert the languages of the Website.
As index.php I have a script. If the URI detected is "/" the script redirects to /language/index.php.
I'd like now to have a script which dinamically redirects based on HTTP_ACCEPT_LANGUAGE.
My problem is that, the following script I made works only with the first foreach run.
$abbr = $link->query("SELECT abbr AS langs FROM LANGS");
while($langs_db = mysqli_fetch_array($abbr)){
$site_langs[] = $langs_db['langs'];
}
$client_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
foreach($site_langs as $lang){
switch($client_lang){
case $client_lang == $lang:
header("location: http://www.mysite.com/$lang/index.php");
break;
default:
header("location: http://www.mysite.com/$lang/index.php");
break;
}
}
I thought a solution like:
case $client_lang == $lang:
$find "location: http://www.mysite.com/$lang/index.php";
break;
default:
$not_find = "location: http://www.mysite.com/$lang/index.php";
break;
And then:
if($find != ''){
header($find);
}else{
header(not_find);
}
But I'm not sure this it's a good idea...
Thank you!
// Set the default language as a fall back
$default_lang='en';
// Have an array with all languages your site supports
$langs=array('en', 'es', 'pt', /* etc... */);
// Query the browser's first preferred language
$client_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
// See if the language is supported otherwise redirect use the default one
$client_lang = (in_array($client_lang, $langs) ? $client_lang : $default_lang);
header("Location: /$client_lang/index.php");
Alternatively though you may want to consider gettext:
http://php.net/manual/en/book.gettext.php
i am creating a website by two language with php. to change language of pages , i create to link like this:
FA|EN
this two link is on a page named header.php that includes on some page.but in some pages is some parameters that send via URL . So that two link are not true and they Should be as follows:
FA|EN
my Question is how i create a dynamic links for all page Even if have some parameters.
You need to store the value in a global key, preferable php's $_SESSION
in the beginnen of your page you can then check with the following :
session_start(); // if not started already
$possible_languages = array('en', 'fr');
$default_language = 'fr';
$_SESSION['lang'] = ( isset($_GET['lang']) && in_array($_GET['lang']) ? $_GET['lang'] : $default_language );
From now on you can $_SESSION['lang'] where needed
You could use:
<?
$params = $_GET;
$params['lang'] = 'EN';
$qs = '?';
foreach($params as $k=>$v)
$qs .= $k.'='.urlencode($v).'&';
$url = substr($_SERVER['PHP_SELF'].$qs, 0, -1);
echo $url; //EN
$params['lang'] = 'FR';
$qs = '?';
foreach($params as $k=>$v)
$qs .= $k.'='.urlencode($v).'&';
$url = substr($_SERVER['PHP_SELF'].$qs, 0, -1);
echo $url; //FR
?>
First, store the language in session or cookie.
Second, build link creation mechanism for your website using the current language setting, do not echo the internal links directly. Important internal links should be created from functions so that they format can be change quickly later.