Location: PHPKode > projects > Simple Way to Usenet > libs/core/langs/langs.class.php
<?php
/**
 *  
 * @author  Benjamin Gillissen <hide@address.com>
 * 
 *	**************************************************************

	Copyright (C) 2009  Benjamin Gillissen
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program 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 General Public License for more details at:
	http://www.gnu.org/copyleft/gpl.html

 *	**************************************************************
 */

class langs {
	
	private static $charset;
	private static $CC;
	private static $_LANG;
	private static $_DB;
	private static $_DICO;
	private static $DICACHE;
	
	public static function load(){
		if ( isset(self::$_LANG) ){ return TRUE; }
		if ( ! isset(self::$CC) ){ 
			$run 		= Array(client_configs::SESSION=>'profile');
			$store		= Array(client_configs::PROFILE=>'site_profile');
			$run_update  = Array(client_configs::GET=>'', client_configs::POST=>'');
			$store_update= Array(client_configs::POST=>'');
			self::$CC = new client_configs($run, $store, $run_update, $store_update);
			unset($run, $store, $run_update, $store_update); 
		}
		$lang = self::negotiateLanguage();
		$class = 'lang_'.$lang;
		self::$_LANG 	= new $class();
		self::$charset 	= self::negotiateCharset();
		if ( FALSE === function_exists('iconv') AND FALSE === function_exists('libiconv') ){
			errors::raise('Missing PHP feature : libiconv, No charset convertion will be possible.', CORE_LOG_WARNING, 'LANG');
		}
		if ( ! headers_sent($file, $line) ){
			//here we know, lang and charset. let's make it know to client browser
			header("Content-type: text/html; charset=".self::$charset);
			errors::raise('Langs is using lang : '.self::$_LANG->lang().', charset : '.self::$charset, CORE_LOG_NOTICE, 'LANG');
			self::recode_from_client();
		} else {
			errors::raise('Langs could not send Content-Type Header, output started at : '.$file.':'.$line, CORE_LOG_ERROR, 'LANG');
		}
		return TRUE;
	}
	
	public static function getlangs(){ return configs::get('lang', 'langs'); }
	
	public static function islang($lang){ return (FALSE !== array_search($lang, self::getlangs())); }
	
	public static function getcharsets($lang=NULL){
		if ( $lang !== NULL ){
			if ( FALSE === self::islang($lang) ){ return FALSE; }
			//CORE::inclass("lang_$lang");
			$cb = "lang_$lang::charsets";
			errors::raise('lang::getcharsets('.$lang.') cb => '.$cb, CORE_LOG_ERROR, 'LANG');
			$r = @call_user_func($cb);
			errors::raise('cb result => '.print_r($r, TRUE), CORE_LOG_ERROR, 'LANG');
			if ( !empty($r) ){ return split(',', $r); }
			return FALSE;
		}
		if ( ! isset(self::$_LANG) ){ self::load(); }
		return split(',', self::$_LANG->charsets() );
	}
	
	public static function charset(){
		if ( !isset(self::$_LANG) ){ self::load(); }
		return self::$charset;
	}
	
	public static function lang(){
		if ( !isset(self::$_LANG) ){ self::load(); }
		return self::$_LANG->lang();
	}
	
	public static function fallback(){
		if ( !isset(self::$_LANG) ){ self::load(); }
		return self::$_LANG->fallback();
	}
	
	private static function negotiateLanguage(){
		if ( self::$CC->is_updated('lang') ){
			$new = self::$CC->get_updated('lang');
			if ( FALSE === self::islang($new) ){ 
				unset($new);self::$CC->del_update('lang'); 
			} else { 
				//store to sess, only profile page update profile eh
				self::$CC->store_updated('lang');
			}
			
		} elseif ( self::$CC->is_stored('lang') ){
			
			$new = self::$CC->get_stored('lang');
			if ( FALSE === self::islang($new) ){ unset($new);self::$CC->del_stored('lang'); }
			
		} elseif ( isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ){
			
			//errors::raise("Negotiating Language :: ".strtoupper($_SERVER['HTTP_ACCEPT_LANGUAGE']), CORE_LOG_NOTICE, 'LANG');
			$new = self::negotiate(self::getlangs(), strtoupper($_SERVER['HTTP_ACCEPT_LANGUAGE']));
			if ( FALSE !== $new ){ return $new; }
			unset($new); 
		}
		if ( ! isset($new) ){ $new = configs::get('lang', 'baselang');	}
		if ( FALSE === $new ){ 
			errors::raise('Active lang could not be determined !, plz check your lang.opt.php file', CORE_LOG_ERROR, 'LANG');
		}
		if ( FALSE === self::islang($new) ){ $new = 'EN'; } 
       	return $new; 
    }
    
    private static function negotiateCharset(){
		$langcharset = self::getcharsets();
		if ( self::$CC->is_updated('charset') ){
			$new = self::$CC->get_updated('charset');
			if ( FALSE === array_search($new, $langcharset) ){ 
				unset($new);self::$CC->del_update('charset'); 
			} else { 
				//store to sess, only profile page update profile eh
				self::$CC->store_updated('charset');
			}
			
		} elseif ( self::$CC->is_stored('charset') ){
			
			$new = self::$CC->get_stored('charset');
			if ( FALSE === array_search($new, $langcharset) ){ unset($new);self::$CC->del_stored($var); }
			
		} elseif ( isset($_SERVER['HTTP_ACCEPT_CHARSET']) ){

			//errors::raise("Negociating Charset :: ".strtoupper($_SERVER['HTTP_ACCEPT_CHARSET']), CORE_LOG_NOTICE, 'LANG');
			$new = self::negotiate($langcharset, strtoupper($_SERVER['HTTP_ACCEPT_CHARSET']));
			if ( FALSE === $new ){ unset($new); }

		}
		if ( ! isset($new) ){ $new = $langcharset[0];	}
       	return $new;
	}
	
    private static function negotiate($opts, $accept){
    	$accepts = split(',', $accept);
    	foreach($accepts  as $k => $opt ){
    		$opt = array_map('trim', explode(';', $opt));
   			$o = $opt[0];
   			$q = 1;
    		if ( isset($opt[1]) ){ $q = (float) str_replace('Q=', '', $opt[1]); }
    		if ( FALSE !== array_search($o, $opts) ){
    			$matches[$o] = ($q * 1000) - @count($matches);
    		}
        }
        if ( isset($matches) ){
        	asort($matches, SORT_NUMERIC);
        	///errors::raise("Negotiation Results :: ".print_r($matches, TRUE), CORE_LOG_DEBUG, 'LANG');
        	$matches = array_keys($matches);
        	return end($matches);
        }
        return FALSE; 
    }
    

    
	public static function dico_translate($ref, $args, $dico, $forcefb=NULL){
		if ( !isset(self::$_LANG) ){ self::load(); }
		if ( !chrono::isinit('dico') ){ chrono::init('dico'); }
		$chr = chrono::start('dico');
		if ( !isset(self::$DICACHE[$dico]) ){
			$ps = split(":", configs::get('lang', 'dicos'));
			if ( isset($forcefb) ){ $lang = $forcefb; } else { $lang = self::lang(); }
			foreach($ps as $k=>&$path){ $path .= '/'.$lang; }
			$file = CORE::getdeps($ps, $dico, NULL,'dico', 'htm');
			unset($ps);
			if ( FALSE === $file ){ chrono::pause('dico', $chr);return FALSE; }
			$obj = new dico_tidy();
			if ( FALSE === $obj->load($file) ){ chrono::pause('dico', $chr);return FALSE; }
			self::$DICACHE[$dico] = $obj->readall();
		}
		if ( is_array($args) ){ $cref="S_"; } else { $cref="W_"; }
		$cref .= md5(html_entity_decode($ref)); 	
		if ( isset(self::$DICACHE[$dico][$cref]) ){
			$o = self::$DICACHE[$dico][$cref];
			if ( is_array($args) ){ foreach($args as $k => $val ){ $o = str_replace('%'.$k.'%', $val, $o); } }
			chrono::pause('dico', $chr);
			return $o; 
		}
		chrono::pause('dico', $chr);
		return $ref;	
	}
	
/*
  
 	private static function dico_search($dico, $fbkey=NULL){
		$ps = split(":", configs::get('lang', 'dicos'));
		$fb = self::fallback();
		if ( $fbkey === NULL ){
			foreach($ps as $k=>$path){ $ps[$k] .= '/'.self::lang(); } 
		} else {
			foreach($ps as $k=>$path){ $ps[$k] .= '/'.$fb[$fbkey]; }
		}
		if ( $dico !== NULL ){
			$o[0] = CORE::getdeps($ps, $dico, NULL,'dico', 'htm');
			if ( FALSE == $o[0] ){ return FALSE; }
			return $o;
		} else {
			return CORE::searchdeps($ps, '', NULL, 'dico', 'htm');
		}
	}
	
	private static function dico_getref($file, $tl, $ref, $args=NULL){
		$obj = new dico_tidy();
 		if ( FALSE === $obj->load($file) ){ return FALSE; }
 		if ( $tl != $obj->lang() ){ 
 			errors::raise("Language do not match for file $file, expected:$tl and got:".$obj->lang(), CORE_LOG_WARNING, 'LANG');
 			return FALSE; 
 		}
 		$o = $obj->get($ref, $args);
 		$obj->unload();
 		return $o;
	}	
	
	public static function dico_translate_old($ref, $args=NULL, $dico=NULL){
		//return $ref;
		if ( !isset(self::$_LANG) ){ self::load(); }
		if ( !chrono::isinit('dico') ){ chrono::init('dico'); }
		$chr = chrono::start('dico');
		
		$dicos = self::dico_search($dico);
		if (FALSE !== $dicos){
			//some dicos has been found, lets search for $ref in them
			foreach($dicos as $k => $file){
				$o = self::dico_getref($file, self::lang(), $ref, $args);
				if ( FALSE !== $o ){
					chrono::pause('dico', $chr);
					return $o; 
				}
			}
			if ($dico === NULL ) { errors::raise("Ref '$ref' was not found in ".self::lang()." Dicos, trying fallbacks !", CORE_LOG_WARNING, 'LANG');
			} else { errors::raise("Ref '$ref' was not found in ".self::lang()." Dico '$dico', trying fallbacks !", CORE_LOG_WARNING, 'LANG'); }
		} elseif ($dico === NULL ) { errors::raise('No Dicos could be found in '.self::lang().', trying fallback language', CORE_LOG_WARNING, 'LANG');
		} else { errors::raise("Dico '$dico' was not found, trying fallback language", CORE_LOG_WARNING, 'LANG'); }
		//hmm not found in base language, lets checks in fallbacks ones.
		$fb = self::fallback();
		$sl = self::getlangs();
		if ( !is_array($fb) ){ chrono::pause('dico', $chr);return FALSE; }
		foreach($fb as $k =>$lang){
			if ( FALSE !== array_search($lang, $sl) ){
				$tr[] = $lang;
				$dicos = self::dico_search($dico, $k);
				if (FALSE !== $dicos){
					foreach($dicos as $k => $file){
						$o = self::dico_getref($file, $lang, $ref, $args);
						if ( FALSE !== $o ){ chrono::pause('dico', $chr);return $o; }
					}
				}
			} else { errors::raise("Fallback language '$lang' is not supported by this website, skiping !", CORE_LOG_NOTICE, 'LANG'); }
		}
		if ( isset($tr) ){
			if ($dico === NULL ) { errors::raise("Ref '$ref' was not found in ".implode(', ', $tr)." Dicos !", CORE_LOG_ERROR, 'LANG');
			} else { errors::raise("Ref '$ref' was not found in ".implode(', ', $tr)." Dico '$dico' !", CORE_LOG_ERROR, 'LANG'); }
		}
		chrono::pause('dico', $chr);
		return FALSE;
	}
	

	
	
	
	
	public static function dbobj_translate($obj, $objid, $field, $args=NULL){
 		$cnf = configs::get('lang', 'object_CNF');
 		return self::db_translate($cnf, $obj, $objid, $field, $args);
 	}
 	 	
 	public static function get_country($ccode){
 		$cnf = configs::get('lang', 'countries_CNF');
 		return self::db_translate($cnf, '', $ccode, '');
	}
	
	public static function get_language($lang){
		$cnf = configs::get('lang', 'languages_CNF');
 		return self::db_translate($cnf, '', $lang, '');
	}
 	
	
	private static function db_translate($cnf, $obj, $objid, $field, $args=NULL){
 		if ( !isset(self::$_LANG) ){ self::load(); }
 		$obj = new dico_db($cnf);
 		$o = $obj->get_databyinfos($obj, $objid, $field, self::lang());
 		if ( FALSE === $o ){
 			$o = $obj->get_databyinfos($obj, $objid, $field, self::fallback());
 			if ( FALSE === $o ){ return FALSE; }
 		}
 		if ( $args === NULL ){ return $o; }
 		foreach($args as $k => $val ){ $o = str_replace("%$k%", $val, $o); }
 		return $o;
 	}
 	
*/	 	
 	
 	
 	public static function date_notime($stamp){
	 	if ( !isset(self::$_LANG) ){ self::load(); }
 		return self::$_LANG->date_notime($stamp);
 	}
 	
	public static function date_time($stamp){
 		if ( !isset(self::$_LANG) ){ self::load(); }
 		return self::$_LANG->date_time($stamp);
 	}

	public static function number($real, $prec=0){
		if ( ! isset(self::$_LANG) ){ self::load(); }
		return self::$_LANG->number($real, $prec);
	}
	
	public static function periode($intsec){
		if ( !isset(self::$_LANG) ){ self::load(); }
		return 'notdoneyet';
	}
	
	
	
	
	
	public static function output_for_client($str){
		echo self::recode_for_client($str);
		return TRUE;
	}
	
	public static function recode_for_client($str){
		$int = CORE::getintcharset();
		if ( empty($int) ){ $int = 'UTF-8'; }
		return self::recode($str, $int, self::$charset);
	}
	
	private static function recode_from_client(){
		$int = CORE::getintcharset();
		if ( isset($_GET) ){	$_GET  = self::recode($_GET, self::$charset, $int); }
		if ( isset($_POST) ){	$_POST = self::recode($_POST, self::$charset, $int); }
		if ( isset($_FILES) ){	$_FILES = self::recode($_FILES, self::$charset, $int); }		
	}
	
	public static function recode($str, $from, $to){
		//if ( $from == $to ){ return $str; }
		if ( is_array($str) ){
			foreach($str as $k => $v ){ $o[self::recode($k, $from, $to)] = self::recode($v, $from, $to); }
			if ( isset($o) ){ return $o; } else { return Array(); }
		} else {
			
			$int = CORE::getintcharset();
			$len = strlen($str);
			$offset=0;
			$BUFF = '';
			while( $offset <= $len ){
				$char = mb_substr($str, $offset, 1, $from);
				if ( function_exists('iconv') ){
					$n = @iconv($from, $to.'//TRANSLITE', $char);
					if ( FALSE === $n ){ $n = iconv($int, $to.'//TRANSLITE', '?'); }
				} elseif ( function_exists('libiconv') ){
					$n = @libiconv($from, $to.'//TRANSLITE', $char);
					if ( FALSE === $n ){ $n = libiconv($int, $to.'//TRANSLITE', '?'); }
				} else {
					$n = $char;
				}
				$BUFF .= $n;
				$offset++;
			}
			return $BUFF;
		}
		
	}

	
	public static function translate($ref, $args=NULL, $dico=NULL){
		return self::dico_translate($ref, $args, $dico);
 	}
 	
	public static function dbtranslate($obj, $objid, $field){
		return self::dbobj_translate($obj, $objid, $field);
 	}

 	
 	
 	public static function template_define(){
 		$o['lang'] = self::lang();
 		$o['charset'] = self::charset();
 		return $o;
 	}
}
Return current item: Simple Way to Usenet