<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
|------------------------------------------------------------------------
| Code Igniter Language Detect Library
|
| Functionality: determine user's language from the browser's language
| preference settings and store its ISO code in the configuration entry 
| 'lang_selected'.
| The directory of the language files for the CI Language class is stored
| in the standard CI configuration entry 'language'.
|
| This class reads the following configuration entries:
|   $config['avail_lang'] = array(
|     'en'    => 'english',
|     'en_us' => 'english',
|     'de'    => 'german',
|     'es'    => 'spanish'
|   );
|   $config['lang_default'] = 'en';
|   $config['lang_selected'] = 'en';
|
| Full language codes such as en_uk, de_at are supported. If there is no
| configuration entry for them, their base language, i.e. en, de, etc. is used.
| If no match was found, the configured default language is taken.
|
| The selected ISO language code is included as URI segment in all links that
| are generated by the site_url function of the MY_Config class. Additionally
| a cookie is set that stores the selected code for a longer time period.
| The cookie can be configured by the following configuration values (all 
| other cookie parameters are taken from the standard CodeIgniter 
| configuration items):
|	$config['lang_cookie_name'] = 'xxx_language';
|	$config['lang_expiration']  = 63072000; // 2 years
|
| @package    CodeIgniter
| @subpackage Libraries
| @category	  I18N
| @copyright  Copyright (C) 2007 Roland Blochberger
| @author     Roland Blochberger
|
| @inpiredFrom Code Igniter Mini-App, Language Detect Library by George Dunlop
| @inpiredlink http://mini-app.peccavi.com
|
|
| This library is free software; you can redistribute it and/or
| modify it under the terms of the GNU Lesser General Public
| License as published by the Free Software Foundation; either
| version 2.1 of the License, or (at your option) any later version.
| 
| This library is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
| Lesser General Public License for more details.
| 
| You should have received a copy of the GNU Lesser General Public
| License along with this library; if not, write to the Free Software
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
|
*/
// Lang_detect Version
define('LANG_DETECT_VERSION',    '1.1.0');

class Lang_detect 
{
	var $obj;
	// make config item available locally
	var $lang_avail;
	// the user's language (directory name)
	var $lang_dir = '';

	/**
	 * Constructor
	 */
	function __construct()
	{
		$this->obj =& get_instance();
		// get list of supported languages
		$this->lang_avail = $this->obj->config->item('lang_avail');
		if (empty($this->lang_dir))
		{
			// language directory not yet set: detect the user's language
			$this->lang_dir = $this->detectLanguage();
		}
		log_message('debug', __CLASS__." class ".LANG_DETECT_VERSION." initialized (using $this->lang_dir)");
	}

	// --------------------------------------------------------------------
    
	/**
	 * determine user's language.
	 * Use either the URI segment's or the cookie's language code or 
	 * determine the best match of the browser's languages with the 
	 * available languages.
	 * If no match s found, the configured default language is taken.
	 *
	 * @return language directory name, e.g 'english'
	 */
	function detectLanguage() 
	{
		$language = false;
		// obtain language code from URI segment if available
		$langu = $this->_uri_lang_detect();
		if ($langu !== false)
		{
			// check the URI's language code
			$language = $this->_checkLang($langu);
			if ($language !== false)
			{
				$lang = $langu;
				//log_message('debug', __CLASS__.".detectLanguage(): Use URI segment language: $langu ($language)");
			}
		}
		// if a language cookie available get its sanitized info
		$langc = $this->obj->input->cookie($this->obj->config->item('cookie_prefix').$this->obj->config->item('lang_cookie_name'), true);
		if ($langc !== false)
		{
			if (($language !== false) && ($langu !== $langc))
			{
				// URI has valid language but cookie has wrong language:
				// update cookie
				$this->_set_lang_cookie($langu);
			}
			if ($language === false)
			{
				// invalid or no URI language code: check the cookie's language
				$language = $this->_checkLang($langc);
				if ($language !== false)
				{
					 $lang = $langc;
					//log_message('debug', __CLASS__.".detectLanguage(): Use cookie language: $langc ($language)");
				}
			}
		}
		if ($language === false)
		{
			// no cookie/URI language code: check browser's languages
			$accept_langs = $this->obj->input->server('HTTP_ACCEPT_LANGUAGE');
			if ($accept_langs !== false)
			{
				//explode languages into array
				$accept_langs = strtolower($accept_langs);
				$accept_langs = explode(",", $accept_langs);
				//log_message('debug', __CLASS__.".detectLanguage(): browser languages: ".print_r($accept_langs, true));
				// check all of them
				foreach ($accept_langs as $lang)
				{
					//log_message('debug', __CLASS__.".detectLanguage(): Check lang: $lang");
					// remove all after ';'
					$pos = strpos($lang,';');
					if ($pos !== false)
					{ $lang = substr($lang,0,$pos); }
					// get CI language directory
					$language = $this->_checkLang($lang);
					// finish search if we support that language
					if ($language !== false)
					{
						// set cookie
						$this->_set_lang_cookie($lang);
						//log_message('debug', __CLASS__.".detectLanguage(): Use browser language: $lang ($language)");
						break;
					}
				}
			}
		}
		
		if ($language === false)
		{
			// no base language available or no browser language match: use default
			$lang = $this->obj->config->item('lang_default');
			// XXX Of course the default language has to be supported!
			$language = $this->lang_avail[$lang];
			// set cookie
			$this->_set_lang_cookie($lang);
			//log_message('debug', __CLASS__.".detectLanguage(): Use default language: $lang ($language)");
		}

		// set the configuration for the CI_Language class
		$this->obj->config->set_item('language', $language);
		// store the language code too
		$this->obj->config->set_item('lang_selected', $lang);
		//log_message('debug', __CLASS__.".detectLanguage(): Use language: $lang ($language)");
		return $language;
	}

	
	/**
	 * change the user's language.
	 * The new language will be displayed at the next page.
	 *
	 * @param string $lang the language code, e.g. en
	 * @return bool true if change was necessary.
	 */
	function changeLang($lang = null)
	{
		log_message('debug', "Lang_detect.changeLang($lang)");
	    if (empty($lang))
	    { 
			return false; 
		}

	    // check whether we support the new language
	    $language = $this->_checkLang($lang);
	    if ($language === false)
	    {
	        log_message('error', "The selected language '$lang' is not supported, language change not possible!"); 
	        return false; 
	    }
	    // get currently selected language
	    $_lang = $this->obj->config->item('lang_selected');
	    if (($_lang === false) || ($_lang != $lang))
	    {
	        log_message('debug', "Set language cookie");
	        $this->obj->load->helper('cookie');
	        // we have to change the language from the next request on
	        set_cookie($this->obj->config->item('lang_cookie_name'), 
	                   $lang,
	                   $this->obj->config->item('lang_expiration'),
	                   $this->obj->config->item('cookie_domain'),
	                   $this->obj->config->item('cookie_path'),
	                   $this->obj->config->item('cookie_prefix'));
	        return true;
	    }
	    return false;
	}	
	// --------------------------------------------------------------------
    
	/**
	 * set the language cookie.
	 *
	 * @access  private
	 * @param string $lang the language code, e.g. en
	 */
	function _set_lang_cookie($lang)
	{
		//log_message('debug', __CLASS__."._set_lang_cookie($lang)");
		if (!function_exists('set_cookie'))
		{
			$this->obj->load->helper('cookie');
		}
		set_cookie($this->obj->config->item('lang_cookie_name'), 
			$lang,
			$this->obj->config->item('lang_expiration'),
			$this->obj->config->item('cookie_domain'),
			$this->obj->config->item('cookie_path'),
			$this->obj->config->item('cookie_prefix'));
	}

	// --------------------------------------------------------------------
    
	/**
	 * fetch language code from URI segment if available.
	 *
	 * @access  private
	 * @return  mixed the language code; or FALSE if not found.
	 */
	function _uri_lang_detect()
	{
		if(sizeof($this->lang_avail) == 0){
			return FALSE;
		}
		$current_url = substr($this->obj->config->item('base_url'),0,-1).$_SERVER['REQUEST_URI'];
		
		foreach($this->lang_avail as $row => $lang){						
			$found = strpos($current_url,$this->obj->config->item('base_url').$row);			
			if($found !== FALSE){
				return $row;
			}		
		}		
		return FALSE;
	}
        
	// --------------------------------------------------------------------

	/**
	 * determine language directory 
	 *
	 * @param string $lang language code, e.g. en_uk
	 * @return string language directory or false if not found.
	 *                updates the $lang parameter!
	 */
	function _checkLang(&$lang)
	{
		//log_message('debug', __CLASS__."._checkLang($lang) trys '$lang'");
		if (!array_key_exists($lang, $this->lang_avail))
		{
			if (strlen($lang) == 2)
			{
				// we had already the base language: not found so give up
				//log_message('debug', __CLASS__."._checkLang($lang) '$lang' not available!");
				return false;
			}
			else
			{
				// try base language
				$lang = substr($lang, 0, 2);
				//log_message('debug', __CLASS__."._checkLang($lang) trys '$lang'");
				if (!array_key_exists($lang, $this->lang_avail))
				{
					// calculated base language also not found: give up
					//log_message('debug', __CLASS__."._checkLang($lang) '$lang' not available!");
					return false;
				}
			}
		}
		// get CI language directory
		//log_message('debug', __CLASS__."._checkLang($lang) uses '$lang'");
		return $this->lang_avail[$lang];
	}
}