Detect browser preferred language to serve html pages [duplicate] - php

This question already has answers here:
Detect Browser Language in PHP
(16 answers)
Closed 8 years ago.
I'm a designer with little coding knowledge outside of html/css. Reading on the 'net I find many references to some php using http_accept_language but cannot find a step-by-step "do this, do that" explanation and consequently I don't know what to do with / where to put the code that people present for the job.
I'm developing a site with an English main home page. There, users are presented with a choice of two branches. One branch will be only in English and the other in English plus 3 Scandinavian languages. The non-English pages are pre-translated, not created on the fly by Google.
I want that after arriving at the main home, a user who opts to go into the 4-language section will be initially served a page in the language of their browser (on all pages there will be always be a menu to manually select another language, if preferred).
Is this a job for php? If so I'd be grateful for some code and help in how to use it.

You can use HTTP_ACCEPT_LANGUAGE header. Save supported languages to array and then loop the header using foreach.
$languages = array('en', 'fi', 'sv', 'no');
$header = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach($header as $lang) {
if(in_array($lang, $languages)) {
header("Location: $lang.php"); // i.e. fi.php or se.php
break;
}
}
HTTP_ACCEPT_LANGUAGE contains something like this:
Accept-Language: en-gb,en;q=0.5
As you can see, there is multiple languages, en-gb and en. That's why it's clever to loop the header. If you prefer functions, here's one:
function get_user_lang() {
$languages = array('en', 'fi', 'sv', 'no');
$header = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach($header as $lang) {
if(in_array($lang, $languages)) {
return $lang; // i.e. fi.php or se.php
break;
}
}
}
echo 'Your language is ' . get_user_lang();
Step-by-step guide:
Create new files for each language. Name them like this: "fi.php" or "se.php".
Place the first code part to very top of your home page. That file must include .php ending, so it must be php file. If you don't understand, that should be where to place it:
<?php
$languages = array('en', 'fi', 'sv', 'no');
$header = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach($header as $lang) {
if(in_array($lang, $languages)) {
header("Location: $lang.php"); // i.e. fi.php or se.php
break;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
contents
</body>
</html>
Navigate to your home page in your browser. If your browser's language is english, it'll redirect to "en.php", if swedish; "se.php" and so on.
You can see all language codes from this link, swedish is "sv".

If you have the INTL extension you can use Locale::acceptFromHttp().
Here's the example from the PHP documentation.
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
echo $locale;
$locale will be something like "en_US". If you only want the language and not the country, use something like this:
$locale = explode('_', Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']));
echo $locale[0];

Related

$_SESSION based language selection is not working properly

My website has two languages: English and Russian. These languages' database names are EN and RU.
I use an old php+smarty script. This script's default language selection codes like this:
if(!isset($_SESSION)){
define('LANGUAGE_ID', 'EN');
} else if ($_SESSION['language'] == '')
{
define('LANGUAGE_ID', 'EN');
}
When I want to see a page in Russian, I visit any page with language phrase (?language=RU) like this:
http://www.example.com/index.php?language=RU
But these pages doesn't load in Russian firstly. When I clicked another link or refresh the page, then page loading in Russian. After saved the cookies, then I can see the pages in Russian when first visit. But If I delete the cookies in browser, then I couldn't see in Russian when first visit.
I tried lots of combinations but I couldn't find any solution. Do you have any idea?
Thank you very much...
Edit:
I found some codes in main.class.php:
function __construct($dbh,$smartyBuild) {
$this->dbh = $dbh;
$this->sitevar = #$smartyBuild->FetchSiteVar();
$this->smartybuild = #$smartyBuild;
if($_REQUEST['language'] !='')
{
$_SESSION['language'] = $_REQUEST['language'];
}
else
{
$langaugeAlready = mysql_fetch_array(mysql_query("select value from ".TABLE_PREFIX."sitevars where array_key = 'default_language_feed'"));
if($_SESSION['language'] == '')
{
$_SESSION['language'] = $langaugeAlready['value'];
}
}
if($_SESSION['language'] !='' )
{
define('LANGUAGE_ID', $_SESSION['language']);
}
else
{
define('LANGUAGE_ID', 'EN');
$_SESSION['language'] = 'EN';
}
}
Is the problem related with these codes?
Like I say, without all the code we are guessing a bit at what the problem is but, here goes...
It seems like you're only checking the $_SESSION variable for the language and not the $_GET variable (which gets the language from the URL). Therefore the value only changes after you refresh the page.
Try this. I am assuming your intention is to show English as a default and only Russian if it is defined in the url, but once defined to keep that language until it is put in the URL again.
//start a session. must be called first on all pages you want it to work on
session_start();
//first check if there's a new language coming from the URL
if(isset($_GET['language']))
{
// if we have a new language setting from the URL, check which one and save it in the session.
// we check it is EN or RO before saving into the session since I don't know what you're using it for later. eg part of a DB query which would be a security risk if it is anything other than EN or RO.
if($_GET['language'] == 'EN')
{
$_SESSION['language'] = 'EN';
}
if($_GET['language'] == 'RO')
{
$_SESSION['language'] = 'RO';
}
}
//now check the session variable, which will have been updated above if changed
if(isset($_SESSION['language']))
{
// already have a language saved, so let's use it
define('LANGUAGE_ID', $_SESSION['language']);
}
else
{
// no language from URL and no language saved, so default to english
define('LANGUAGE_ID', 'EN');
}

PHP language detection script

After I read some stuff on-line I came up with this PHP script to detect the browser's language and redirect the user to the correct website's version. Short said, if the user has a browser in Swedish, then the script should redirect to index.php, if not, then it should redirect the user to en.php.
It works fine in some computers and mobile phones and in others it blocks the website. I suppose that the script is not OK and is causing some conflict in older browsers.
So, could you please take a look at my script and tell me if I am doing anything wrong and how can I fix it?
Cheers!
<?php
include ('administration/fonts.php');
?><?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 == "sv"){
header("location: index.php");
exit();
}
else if($lc == "en"){
header("location: en.php");
exit();
}
?>
P.S. - Yes, the script is before the tag and there are no spaces between the "?>" tag and tag.
New answer after added details from the OP.
English users should be redirected, but Swedish user should stay on this site, so we'll rewrite the code like this (I added comments with // Reeno):
<?php
include ('administration/fonts.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'])){
// Reeno: I added strtolower() if some browser sends upper case letters
$lc = strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2));
}
// Now we simply evaluate that variable to detect specific languages
// Reeno: Redirect all non-Swedish users to the English page (they can have "en", but also "dk", "de", "fr"...
if($lc != "sv"){
header("location: http://www.domain.com/en.php");
exit();
}
// Reeno: Swedish users stay on this site
?>
HTML code...
Old answer
You check for $lc == "sv" and $lc == "en" but you forgot the third case: $lc could be empty!
Rewrite the if at the end like this, so everybody with a non Swedish browser will get to en.php:
if($lc == "sv"){
header("location: index.php");
exit();
}
else {
header("location: en.php");
exit();
}
?>
btw header("location: ..."); requires an absolute URI like header("location:http://www.domain.com/en.php"); (some clients also accept relative URIs)

multilingual website using $_SESSION

My website has two languages: French and English. The solution I chose is working but is causing me trouble. I use session in order to keep a "clean" url which is the same in English and in France.
My solution:
To choose the language, I locate the user using IP, and if it is not in France, i set
$_SESSION['language'] = "ENG"
Otherwise,
$_SESSION['language'] = "FRA"
Then I includes my file words.php which contains all the text like this:
if( $_SESSION['language'] == "ENG")
{
$word1 = "hello"
$word2 = ....
}
else
{
$word1 = "bonjour"
$word2 = ....
}
Finally on my website, I have several echo $word1;.
To change language, I have a two links (one for each language) to a webpage language.php with a get parameter that just change the session variable and redirect to the webpage:
if($_GET['l']=="1")
{
$_SESSION['language'] = "FRA";
header('Location: ' . htmlspecialchars($_SERVER['HTTP_REFERER']));
}
elseif($_GET['l']=="2")
{
$_SESSION['language'] = "ENG";
header('Location: ' . htmlspecialchars($_SERVER['HTTP_REFERER']));
}
My problem:
My main problem is that Google is indexing my website only in English ( guess because the IP of crawler is not in France?). In google.fr and google.com, my website is in English.
What can I do to have the website indexed in both languages?
You must use additional folders for languages. You can use example.com/fr for French content and example.com/en for English content.
You can tell this website is multilingual and multiregional to Google crawler bots. Edit this html code for your purpose.
<link rel=”alternate” href=”http://example.com/en-gb” hreflang=”en-gb” />
<link rel=”alternate” href=”http://example.com/en-us” hreflang=”en-us” />
<link rel=”alternate” href=”http://example.com/en-au” hreflang=”en-au” />
<link rel=”alternate” href=”http://example.com/” hreflang=”x-default” />

PHP/Smarty - Each file has it own language file

I am trying to get each file to have it own language file.
I am using a mix of osDate, SMF and my own code. osDate stores the language in the database, but I am not wanting this, I would like each file to have it own language file, so for example register has it own language file at lang/english/register.php.
I will be using Smarty, which is causing me the headache.
I have the below PHP code working, but don't know how to add or get the language side working.
Here is my current code.
tester1.php
<?php
if (!defined('SMARTY_DIR')) {
include_once('init_test.php');
}
$actionArray = array(
'register' => array('Register.php', 'Register'),
);
if (!isset($_REQUEST['action']) || !isset($actionArray[$_REQUEST['action']])) {
echo 'test';
} else {
require_once($actionArray[$_REQUEST['action']][0]);
call_user_func($actionArray[$_REQUEST['action']][1]);
}
$t->display('index.tpl');
?>
Register.php
<?php
function Register() {
global $t;
$t->assign('rendered_page', $t->fetch('register.tpl'));
}
?>
index.tpl
{$rendered_page}
register.tpl
Test: {$testlang}<br>
Title: {$title}
Language file - lang/english/register.php
<?php
$lang['testlang'] = 'working';
$lang['title'] = 'This is the title';
?>
So in the example Register needs to pass the language from Register.php to display in register.tpl.
I am aware I can assign each language string in the Register.php file, but I was hoping, I would be able to just assign the who register language file and then just call it at random, without having to assign each language string in Register.php
Any code, tips welcome.
I have tried Googling, but it hasn't come up with much.
You shouldn't pass rendered things into Smarty - you should be passing in an array of strings to use.
register.php
$lang = array(
'test' => "working",
'title' => "This is the title",
);
function Register() {
global $lang;
$t->assign('lang', $lang);
}
index.tpl
Test: {$lang['test']}<br>
Title: {$lang['title']}
Will do what you asked.
However - you don't want to code it like this as it will be incredibly painful to use when you inevitably need to pass in parameters to the strings.
You should define a Smarty function to display translated text with as many variables as needed e.g.
{translate string='Greeting' name=$user.name}
Where the translate function would pull the 'Greeting' string from the list of known strings which would be defined as Hello %name%. It would then replace %name% with the users name to say Hello John etc.

Internationalisation language switch?

I am using the internationalisation block for basic page translation between Spanish and English. By default the content is in Spanish. When I change the language to English the page content is translated, however the autonav appears blank. I have used page CID's to determine the language differences. In my header.php file for my theme I am using the follow statement:
if(!$c->getAttribute('english_menus')) {
$lh = Loader::helper('section', 'multilingual');
$lang = $lh->getLanguage();
$bt = BlockType::getByHandle('autonav');
$bt->controller->displayPages = 'custom';
if ($lang == "en_EN"){
$bt->controller->displayPagesCID = 166; //English section cID
} else {
$bt->controller->displayPagesCID = 171; //Spanish section cID
}
$bt->controller->orderBy = 'display_asc';
$bt->render('templates/top_nav/view');
}
This displays the top level navigation fine. however when the country flag is selected the auto nav menu disappears and does not display in english
Many Thanks
Do you mean to have the
if (! $c->getAttribute('english_menus')) {
at the top?
It doesn't make much sense to me. Any chance your english page (or whatever page you land on after the country flag) has that attribute set to something?

Categories