defaultLanguage = $default; $this->varname = $varname; $this->cookiePrefix = $cookiePrefix; $this->cookiePath = $cookiePath; $this->cookieDomain = $cookieDomain; if (isset($_REQUEST[$this->varname])) { $this->language = $_REQUEST[$this->varname]; setcookie( $this->cookiePrefix . $this->varname, $this->language, time() + 3024000, //+5 weeks; $this->cookiePath, $this->cookieDomain ); } else { #TODO: Get language from Browser $_SERVER["HTTP_ACCEPT_LANGUAGE"] $this->language = $this->defaultLanguage; } } function getUserLanguage() { return $this->language; } function getSelectorFormHTML($messages, $auto_submit = true, $name = "languageselector") { $html = ""; $html .= "
"; $html .= $this->getSelectorHTML($messages,$auto_submit); $html .= "getMessageEscaped("Ok")."\" id=\"".$name."submit\"/> "; $html .= "
"; if($auto_submit == true) $html .= ""; return $html; } function getSelectorHTML($messages,$auto_submit) { $html = ""; $languages = $messages->getAvailableLanguages(); $html.= "\n\t\t"; return $html; } function getSelectorListHTML($messages) { $html = ""; $languages = $messages->getAvailableLanguages(); foreach($languages as $choice => $name) { $html .= "varname)."=".htmlspecialchars($choice)."\" title=\"".htmlspecialchars($name)."\">".htmlspecialchars($choice)." | "; } return $html; } static function getSelector() { static $selector = NULL; if (!$selector) $selector = new Selector(); #TODO: use global config vars! return $selector; } } class TSMessagesFactory { function __construct($file = NULL, $connection = NULL, $prefix = NULL, $multilang = true, $memcachedserver = "localhost", $memcachedport = 11211) { $this->file = $file; $this->connection = ($connection == NULL) ? self::db_connect() : $connection; $this->prefix = $prefix; $this->useMultiLanguageFile = $multilang; $this->doublecheck = array(); $this->memcachedserver = $memcachedserver; $this->memcachedport = $memcachedport; $this->keys = array(); } static function db_connect() { static $connection = NULL; if(!$connection) { $path = "/home/".get_current_user()."/.my.cnf"; $x = parse_ini_file($path); $s = 'sql-s2'; $connection = mysql_connect($s, $x['user'],$x['password']); if (!$connection) throw new Exception("cannot connect to '$s' using username '".$x['user']."'"); } return $connection; } static function memcached_connect() { static $m = NULL; if(class_exists("Memcached")) { if(!$m) { $m = new Memcached(); $m->addServer(self::$memcachedserver, self::$memcachedport); } } else { $m = false; } return $m; } function createDefaultMessageObject($tool, $lang = NULL) { if (is_string($tool)) $tool = array( $tool, "toolserver"); if ($lang == NULL) $lang = ToolLanguageSelector::getSelector(); if (is_object($lang)) $lang = $lang->getUserLanguage(); if (is_string($lang)) $lang = array( $lang, "en" ); foreach($tool as $tn => $tk) { if(is_array($tk)) { $this->keys[$tn] = $tk; $tool[$tn] = $tn; } else if(is_string($tn)) { $tool[$tn] = $tn; } } return $this->createMessageObject($tool, $lang, NULL); } function createMessageObject($tool, $lang, $parent = NULL) { if (is_array($lang)) { $m = NULL; $langs = array_reverse($lang); foreach ($langs as $lang) { $m = $this->createMessageObject($tool, $lang, $parent); $parent = $m; } return $m; } if (is_array($tool)) { $m = NULL; $tools = array_reverse($tool); foreach ($tools as $tool) { $m = $this->createMessageObject($tool, $lang, $parent); $parent = $m; } return $m; } if($this->doublecheck[$lang][$tool] != true) { if ($this->file) $m = $this->createFileMessageObject($tool, $lang, $parent); else $m = $parent; if ($this->connection) $m = $this->createDatabaseMessageObject($tool, $lang, $m); $this->doublecheck[$lang][$tool] = true; } else { $m = $parent; } return $m; } protected function createFileMessageObject($tool, $lang, $parent = NULL) { if ($this->useMultiLanguageFile) return new MultiLanguagePhpFileMessages($this->file, $tool, $lang, $parent, $this->prefix); else return new SingleLanguagePhpFileMessages($this->file, $tool, $lang, $parent, $this->prefix); } protected function createDatabaseMessageObject($tool, $lang, $parent = NULL) { return new DatabaseMessages($this->connection, $tool, $lang, $parent, $this->prefix, $this->keys); } } class TSMessages { var $parent; var $prefix; var $messages; var $tool; var $language; function __construct($tool, $language, $messages, TSMessages $parent = NULL, $prefix = NULL) { $this->parent = $parent; $this->prefix = $prefix; $this->tool = $tool; $this->language = $language; $this->messages = $messages; } function dump() { print get_class($this); print "#{$this->tool}"; if ($this->prefix) print "(prefix:$prefix)"; print ":{$this->language}"; if ($this->parent) { print " -> "; $this->parent->dump(); } } function getMessageEscaped($key,$replacers=array(),$parse=true) { $m = $this->getMessage($key,$replacers,$parse); return $this->escape($m); } function escape($s) { return htmlspecialchars($s); } function getMessage($key,$replacers=array(),$parse=true) { if ($this->prefix!==NULL) $key = $prefix.$key; if (isset($this->messages[$key])) $msg = $this->messages[$key];//this language text else if ($this->parent) $msg = $this->parent->getMessage($key,array(),false);//parent language text else $msg = "*$key*";//key not found if($parse == true) $msg = $this->replace_wildcard($msg,$replacers); $msg = $this->parse_plural($msg); $msg = $this->set_bold($msg); $msg = $this->set_italic($msg); return $msg; } function replace_wildcard($msg,$replacers) { $r = 0; //array-counter $c = 1; //text-counter while($c != false) { if(!$replacers[$r]) $replacers[$r] = '*$'.$c.'*'; $msg = str_replace('$'.$c,$replacers[$r],$msg,$count); if($count != 0) { $r++; $c++; } else { $c = false; } } return $msg; } function parse_plural($msg) { $rgx_search = "/\{\{PLURAL:([0-9]{1,2})\|([^\}\|]*)\|([^\}\|]*)\}\}/ei"; do $msg = preg_replace($rgx_search,'$this->plural_select("\\1","\\2","\\3")',$msg,-1,$ct); while($ct != 0); return $msg; } function plural_select($nr,$singular,$plural) { settype($nr,"int"); if($nr == 1) return $singular; else return $plural; } function set_bold($msg) { $rgx_search = "/'''(.*)'''/U"; do $msg = preg_replace($rgx_search,'$1',$msg,-1,$ct); while($ct != 0); return $msg; } function set_italic($msg) { $rgx_search = "/''(.*)''/U"; do $msg = preg_replace($rgx_search,'$1',$msg,-1,$ct); while($ct != 0); return $msg; } function getKeys() { $keys = array_keys($this->messages); if ($this->parent) { $pkeys = $this->parent->getKeys(); $keys = array_unique(array_merge($keys, $pkeys)); } sort($keys); return $keys; } function getAvailableLanguages() { $usedsource = TSMessages::usedsource(NULL,NULL,NULL,true); $languages = array(); if($usedsource['db'] == 1) $languages = $this->getLanguagesFromDB($languages); if($usedsource['file'] == 1) $languages = $this->getLanguagesFromDir($languages,$usedsource['path']); if($usedsource['multilang'] == 1) $languages = $this->getLanguagesFromFile($languages,$usedsource['path']); $sql = "SELECT `lang`,`native_name` FROM toolserver.language WHERE"; foreach($languages as $language) { $sql .= " `lang` = '" . mysql_real_escape_string($language)."' OR"; } $sql = substr($sql,0,-2); $r = mysql_query( $sql, $this->connection ); if ( !$r ) throw new Exception( mysql_error() . " (" . mysql_errno() . ")"); while ($row = mysql_fetch_array($r)) { $langname[$row["lang"]] = $row["native_name"]; } foreach($languages as $language) { $languages[$language] = $langname[$language]; } return $languages; } private function getLanguagesFromDB($languages) { $sql = "SELECT `language` FROM toolserver.message "; $sql .= "WHERE `component` = '" . mysql_real_escape_string($this->maintool) . "'"; $r = mysql_query( $sql, $this->connection ); if ( !$r ) throw new Exception( mysql_error() . " (" . mysql_errno() . ")"); while ( $row = mysql_fetch_assoc( $r ) ) { $k = $row["language"]; $languages[$k] = $k; // $languages[de] = de } return $languages; } private function getLanguagesFromDir($languages,$curl) { $dh = opendir($curl); while(!is_bool($file = readdir($dh))) { if(substr($file, -9) == ".i18n.php") { $k = substr($file,strrpos($file,"-")+1,-9); $languages[$k] = $k; } } closedir($dh); return($languages); } private function getLanguagesFromFile($languages,$curl) { include($curl); if (!isset($messages)) throw new Exception("including $file did not define \$messages"); foreach($messages as $lang => $x) { $languages[$lang] = $lang; } return($languages); } static function usedsource($x,$filepath = NULL, $multilang = NULL, $return = false) { static $source = array("db" => 0, "file" => 0, "multilang" => NULL, "path" => NULL); switch($x) { case "db": $source['db'] = 1; break; case "file": $source['file'] = 1; $source['path'] = $filepath; break; case "multilang": $source['multilang'] = 1; $source['path'] = $multilang; break; } if($return == true) return $source; } } class MultiLanguagePhpFileMessages extends TSMessages { function __construct($file, $tool, $language, TSMessages $parent = NULL, $prefix = NULL) { parent::__construct( $tool, $language, self::loadMessages($file, $tool, $language), $parent, $prefix ); } static function loadMessages($file, $tool, $language) { if (is_dir($file)) { $file = "$file/$tool.i18n.php"; } if (!file_exists($file)) return array(); include($file); if (!isset($messages)) throw new Exception("including $file did not define \$messages"); TSMessages::usedsource("multilang",NULL,$file); return $messages[$language]; } } class SingleLanguagePhpFileMessages extends TSMessages { function __construct($filebase, $tool, $language, TSMessages $parent = NULL, $prefix = NULL) { parent::__construct( $tool, $language, self::loadMessages($filebase, $tool, $language), $parent, $prefix ); } static function loadMessages($filebase, $tool, $language) { if (is_dir($filebase)) { $file = "$filebase/$tool-$language.i18n.php"; } else if (!file_exists($filebase)) { $file = "$filebase-$language.i18n.php"; } else { $file = $filebase; } if(is_dir(dirname($file))) TSMessages::usedsource("file",dirname($file)); if (!file_exists($file)) return array(); include($file); if (!isset($messages)) throw new Exception("including $file did not define \$messages"); return $messages; } } class DatabaseMessages extends TSMessages { static $messageDatabase = "toolserver"; static $messageTable = "message"; function __construct($connection, $tool, $language, TSMessages $parent = NULL, $prefix = NULL, $toolkeys = NULL) { parent::__construct( $tool, $language, self::loadMessages($connection, $tool, $language, $toolkeys), $parent, $prefix, $toolkeys ); $this->connection = $connection; $this->maintool = $tool; } static function loadMessages($connection, $tool, $language, $toolkeys) { $m = TSMessagesFactory::memcached_connect(); if(is_array($toolkeys[$tool]))sort($toolkeys[$tool]); if($m !== false) { $memcached_key = $tool."#".$language; if(is_array($toolkeys[$tool])) $memcached_key .= "#".md5(implode("+",$toolkeys[$tool])); $ret = $m->get($memcached_key); if($ret) return $ret; } $db = self::$messageDatabase; $tb = self::$messageTable; $sql = "SELECT name, message FROM $db.$tb "; $sql .= " WHERE component = '" . mysql_real_escape_string($tool) . "'"; $sql .= " AND language = '" . mysql_real_escape_string($language) . "'"; if(is_array($toolkeys[$tool])) { if(count($toolkeys[$tool]) > 0){ $sql .= " AND ("; foreach($toolkeys[$tool] as $$toolkey) { $sql .= "name = '" . mysql_real_escape_string($$toolkey) . "' OR "; } $sql = substr($sql,0,-4).")"; } else { $sql .= " LIMIT 0 , 200"; } } else { $sql .= " LIMIT 0 , 200"; } $r = mysql_query( $sql, $connection ); if ( !$r ) throw new Exception( mysql_error() . " (" . mysql_errno() . ")"); $messages = array(); while ( $row = mysql_fetch_assoc( $r ) ) { $k = $row["name"]; $messages[$k] = $row["message"]; } TSMessages::usedsource("db"); if($m !== false) $m->set($memcached_key, $messages, time() + 7200); //2h cached self::testfunction($sql); return $messages; } static function testfunction($sql,$ret=false) { static $text = ""; $text .= $sql."\n
"; if($ret == true) return $text; } } ?>