Words from Alejandro U. Alvarez
Posts tagged language
Visitor’s language detection in php
Apr 1st
Posted by alex in General talk
Is your site translated into more than one language? In case it is, you will find this topic really interesting, since it will allow you to automatically adapt your site's language to the user's.
In case your site is not translated, you can always use this to know the visitor's language... I'm sure you'll be able to find a good use for that information
The basics
The way this script will find the visitor's language is fairly simple. First it will "ask" the client (a.k.a the http request sender) for its user agent and for its language, if set.
For our script to work we will have set a list of our "available" languages. If you just want to detect it you could stop the script here and return the language. If you are detecting the language to use it for your website then continue reading:
Before the script checks if the language was on the list it would check if it was the default or primary language, then if not, it would look up in the available languages, and if not again, then it would return to the default language.
This is a very useful tool you can check out working on my main site: http://urbanoalvarez.es which is translated into both Spanish and English, and for you it will most probably be in English...
Now let's start looking at the code:
< ?php function dlang($Var) { if(empty($GLOBALS[$Var])) { $GLOBALS[$Var]=(!empty($GLOBALS['_SERVER'][$Var]))? $GLOBALS['_SERVER'][$Var]: (!empty($GLOBALS['HTTP_SERVER_VARS'][$Var]))? $GLOBALS['HTTP_SERVER_VARS'][$Var]:''; } } function language() { // Detect HTTP_ACCEPT_LANGUAGE & HTTP_USER_AGENT. dlang('HTTP_ACCEPT_LANGUAGE'); dlang('HTTP_USER_AGENT'); $_AL=strtolower($GLOBALS['HTTP_ACCEPT_LANGUAGE']); $_UA=strtolower($GLOBALS['HTTP_USER_AGENT']); // Try to detect Primary language if several languages are accepted. foreach($GLOBALS['_LANG'] as $K) { if(strpos($_AL, $K)===0) return $K; } // Try to detect any language if not yet detected. foreach($GLOBALS['_LANG'] as $K) { if(strpos($_AL, $K)!==false) return $K; } foreach($GLOBALS['_LANG'] as $K) { if(preg_match("/[\[\( ]{$K}[;,_\-\)]/",$_UA)) return $K; } // Return default language if language is not yet detected. return $GLOBALS['_DLANG']; } // Define default language. $GLOBALS['_DLANG']='es'; // Define all available languages. // WARNING: uncomment all available languages $GLOBALS['_LANG'] = array( 'es', 'en' ); ?>
Most of the important things in the above function are "self explanatory". If you have any problems understanding it, just ask!
Using it is very very simple, here is a simple script to see it working:
< ?php session_start(); include('lang.php'); //The language detection function echo language(); //Display the language ?>
As you can see using it is very simple, but it is still not perfect, because we still cannot change the language or store it, so we need another file, a session handler that will take care of storing and changing the language if neccesary.
File session.php:
< ?php //proc all page display include('lang.php'); //language detector class Session { var $lang; //Username given on sign-up var $url; //The page url current being viewed var $referrer; //Last recorded site page viewed /* Class constructor */ function Session(){ $this->time = time(); $this->startSession(); } function cf($filename){//function to clean a filename string so it is a valid filename $fp = explode('/',$filename); $num = count($fp); return $fp[$num-1]; } /** * startSession - Performs all the actions necessary to * initialize this session object. Tries to determine if the * the user has logged in already, and sets the variables * accordingly. Also takes advantage of this page load to * update the active visitors tables. */ function startSession(){ session_start(); //Tell PHP to start the session /* Set referrer page */ if(isset($_SESSION['url'])){ $this->referrer = $search = $this->cf($_SESSION['url']); }else{ $this->referrer = "/"; } /* Set current url */ $this->url = $_SESSION['url'] = $this->cf($_SERVER['PHP_SELF']); /* Set user-determined language: */ //set up languages array: $langs = array('en','es'); // if(isset($_GET['lang'])){ if(in_array($_GET['lang'],$langs)){ $this->lang = $_SESSION['lang'] = $_GET['lang']; } } if(!isset($_SESSION['lang']) || !in_array($_SESSION['lang'],$langs)){ $this->lang = $_SESSION['lang'] = language(); } } }; /** * Initialize session object - This must be initialized before * the form object because the form uses session variables, * which cannot be accessed unless the session has started. */ $session = new Session; ?>
And the way we would use this hole script now would be:
include('session.php'); //This does all the session work for us: echo $_SESSION['lang']; //Display the language
And to change it, place the following link anywhere in your site, without worrying for the location of the file!
<a href="?lang=es">Change to Spanish</a>
And now change "es" for any language code you have inside your $langs array (in this example: $langs = array('en','es');)
If you need help with the language codes visit this post, or download the demo zip and open otherLangs.php (With a text editor)
See it working
To see how this works, just go to my main page (http://urbanoalvarez.es) and change the language around (Top right corner)
Or visit the custom demo page, with all options in the same place (Not many actually, but enough
)
Download demo
Download zip file - 30Kb (664 downloads)
For suggestions, feedback, hates... please comment
Simple CMS with language changer functions (v. 1.1)
Mar 17th
Introduction:
Today I'll show you a way of translating your website very easily, and then have the browser detect user language automatically.
First you need some sort of php template system, I'll show you the one that I've developed, which is not very advanced but works perfectly for small sites.
What it does is in each page there is always a part that repeats. In my main page the repeating part is the header, left sidebars, and footer. And the only thing that changes is the content. What I did is a class called page, and that class generated the code needed for the header, sidebar and footer. The content is included from a folder called "content", which then contains subfolders, each named with the language code, so if the folder contains the spanish translation it would be named "es". (See all language codes)
Another class is "session", it does a check for new users or returning users based on session variables that store their preferred language, it also checks for the URI changer (?lang=...), and if none of that is found, it then checks for the user OS language, then checks if it is available and if it is, it sets it as preferred language of the site, if not, the default language is selected.
Codes for this:
The following codes must go in a folder structure like so "lib/content/". This can be change, but it makes it more easy to understand.
At the bottom of this there is a link to a zip file containing all necessary files to have this work
The filenames I used are: "page.php" for the page object, and "session.php" for the session object.
The page object (simplified):
//This contains the page object - Used to generate the page layout class Page { var $timep = 0; //functions to display a page: function genTop($title,$extraCSS='',$extraScripts='',$extras=''){ //for the top part (doctype...) //setup time counter $this->timep = round(microtime(), 3); //start file inclusion include('lib/content/core/doctype.htm'); //includes opening html tag and head include('lib/content/core/metas.htm'); //includes the meta data (All the same) $metaLang = $_SESSION['lang'].'-'.strtoupper($_SESSION['lang']); echo '<meta http-equiv="Content-Language" content="'.$metaLang.'" />'; //language meta tag if($title !== ''){ $title = $title.' | '; } //add | if necesary echo '<title>'.$title; switch($_SESSION['lang']){ case 'es': echo 'Fundacion Urbano Alvarez'; break; case 'en': echo 'Urbano Alvarez Foundation'; break; } echo '</title>'; include('lib/content/core/link-rel.htm'); //includes the linking css if($extraCSS !== ''){ //Get an array with all extra style sheets $css = explode(',',$extraCSS); $totalCSS = count($css); //now iterate through all extra css for($i=0; $i<$totalCSS; $i++){ echo '<link rel="stylesheet" type="text/css" href="'.$css[$i].'" media="all" />'; } // } include('lib/content/core/scripts.php'); //includes all javascript scripts if($extraScripts !== ''){ //get an array with all extra scripts $scripts = explode(',',$extraScripts); $totalScripts = count($scripts); //Now include all extra scripts for($i=0; $i<$totalScripts; $i++){ echo '<script language="javascript" type="text/javascript" src="'.$scripts[$i].'"></script>'; } // } echo $extras; // Any extra code that may be entered before the head echo '</head>'; // echo '<body>'; include('lib/content/core/top.php'); include('lib/content/core/left.php'); //The left navigation column echo '<div id="content">'; } function genContent($pageName=''){ global $session; if($pageName == ''){ $pageName = $session->url; } include('lib/content/'.$_SESSION['lang'].'/'.$pageName); } function genBottom($extraFooter='',$extraScripts=''){ if($_SESSION['lang'] == 'es'){ $changeLang = 'Cambiar idioma a: <a href="?lang=en">English</a>'; }else{ $changeLang = '...'; //Here goes code for extra stuff (I use it for stumbleupon) } echo '<p>'.$changeLang.'</p>'; echo '</div><!-- end .content -->'; echo '<div id="footer">'; echo '<div id="footerLeft"><img src="img/body/footerLeft.jpg" width="41" height="93" /></div>'; echo '<div id="footerText">'; $time2 = round(microtime(), 3); $gen = $time2 - $this->timep; if($_SESSION['lang'] == 'es'){ echo 'Spanish footer'; }else if($_SESSION['lang'] == 'en'){ echo 'English footer'; } if($extraFooter !== ''){ echo $extraFooter; } echo '</p>'; if($_SESSION['lang'] == 'es'){ echo 'Spanish bottom links'; }else if($_SESSION['lang'] == 'en'){ echo 'English bottom links'; } echo '</div>'; echo '</div><!-- end .footer -->'; include('lib/content/core/analytics.htm'); //google analytics code if($extraScripts!==''){ echo $extraScripts; } echo '</body></html>'; } }; ?>
So now the session class:
//proc all page display include('lib/content/lang.php'); //language detector include('lib/content/page.php'); $page = new Page; class Session { var $lang; //Username given on sign-up var $url; //The page url current being viewed var $referrer; //Last recorded site page viewed /* Class constructor */ function Session(){ $this->time = time(); $this->startSession(); } function cf($filename){//function to clean a filename string so it is a valid filename $fp = explode('/',$filename); $num = count($fp); return $fp[$num-1]; } /** * startSession - Performs all the actions necessary to * initialize this session object. Tries to determine if the * the user has logged in already, and sets the variables * accordingly. Also takes advantage of this page load to * update the active visitors tables. */ function startSession(){ session_start(); //Tell PHP to start the session /* Set referrer page */ if(isset($_SESSION['url'])){ $this->referrer = $search = $this->cf($_SESSION['url']); }else{ $this->referrer = "/"; } /* Set current url */ $this->url = $_SESSION['url'] = $this->cf($_SERVER['PHP_SELF']); /* Set user-determined language: */ //set up languages array: $langs = array('en','es'); // if(isset($_GET['lang'])){ if(in_array($_GET['lang'],$langs)){ $this->lang = $_SESSION['lang'] = $_GET['lang']; } } if(!isset($_SESSION['lang']) || !in_array($_SESSION['lang'],$langs)){ $this->lang = $_SESSION['lang'] = language(); } } }; /** * Initialize session object */ $session = new Session; ?>
Well so those are the classes used to format page display. I think they are pretty self-explanatory but if you have any doubt about their usage, comment it.
Using it:
So once you have all set up create a new php file in the root "/". I'll name it "test.php". This file is the generator of the test page. What you need now is a folder inside "lib/content/" with the language code of the language used. I have two, one with "es" and another one with "en", for spanish and english respectively.
To change languages, put a link with this: <a href="?lang=((New lang code here))">Change language to...</a>
Now paste the following code in there:
$title['es'] = 'Bienvenido a la pagina de prueba'; $title['en'] = 'Welcome to the test page'; $page->genTop($title[$_SESSION['lang']]); $page->genContent(); $page->genBottom(); ?>
What this does is it first includes the session.php, with the object initializers. Then it creates an array with the different titles, one for each language offered. Then it calls the object "page" to create the page, in three steps. Top, content, and footer.
The content is retrieved from the appropriate folder ("en" for english, "es" for spanish, and so on ...), by including a file called exactly the same as the generator file, so in this case ("test.php"), supposing you are browsing the english version, it will include the file "lib/content/en/test.php" which should contain plain html like the following:
<h2>This is a test page</h2> This is some content...
And this is it!
Download example (zip):
Here you can download a zip with all files for example purposes:
Pack with all necessary files (Zip package)
File structure of the zip:
- lib
- content
- page.php
- session.php
- lang.php
- otherLangs.php
- core
- doctype.htm
- metatags.htm
- Other .htm files needed
- en
- test.php
- es
- test.php
- content
- test.php
The otherLangs.php contains an array with all possible language codes, so if you don't know a language code you can check it there.
The lang.php file contains a function used to check the user preferred language, you can probably understand how it works by looking at it.