Axiom (v1.2.0)

A lightweight PHP framework
H:/Workspace/php-axiom/www/php-axiom/libraries/axiom/axLocale.class.php
Go to the documentation of this file.
00001 <?php
00017 class axLocale implements IteratorAggregate {
00018                 
00023                 const CACHE_FILE = 'locale.cache.php';
00024                 
00029                 protected static $_accepted_languages_cache;
00030                 
00035                 protected $_file;
00036                 
00041                 protected $_lang;
00042                 
00047                 protected $_cache_dir;
00048                 
00053                 protected $tree;
00054                 
00065                 public function __construct ($lang_file, $lang = "auto", $default_lang = "en", $cache_dir = false) {
00066                                 $this->_lang      = strtolower($lang);
00067                                 $this->_cache_dir = $cache_dir !== false ? realpath($cache_dir) : false;
00068                                 $this->_tree      = array();
00069                                 
00070                                 if (!$this->_file = realpath($lang_file)) {
00071                                                 throw new axMissingFileException($lang_file);
00072                                 }
00073                                 
00074                                 if ($this->_lang !== 'auto' && !setlocale(LC_ALL^LC_MESSAGES, $this->_lang)) {
00075                                                 throw new RuntimeException("Cannot set locale to {$this->_lang}");
00076                                 }
00077                 }
00078                 
00084                 public function __get ($key) {
00085                                 return $this->getIterator()->$key;
00086                 }
00087                 
00093                 public function getIterator () {
00094                                 if (empty($this->_tree)) {
00095                                                 if ($this->_cache_dir && is_readable($c = $this->_cache_dir . '/' . self::CACHE_FILE)) {
00096                                                                 require $c;
00097                                                                 $this->_tree = $tree;
00098                                                 }
00099                                                 else {
00100                                                                 $this->_generateTree();
00101                                                                 $this->_cache();
00102                                                 }
00103                                 }
00104                                 
00105                                 if ($this->_lang === 'auto' && !($this->_lang = $this->_determineLanguage()))
00106                                                 $this->_lang = $this->_default_lang;
00107                                 
00108                                 if (!isset($this->_tree[$this->_lang]))
00109                                                 throw new RuntimeException("Lang {$this->_lang} not available");
00110                                 
00111                                 return $this->_tree[$this->_lang];
00112                 }
00113                 
00123                 public function setLang ($lang) {
00124                                 if ($lang === "auto" && !($this->_lang = $this->_determineLanguage()))
00125                                                 return false;
00126                                 
00127                                 if (!setlocale(LC_ALL, $this->_lang = $lang))
00128                                                 return false;
00129                                 
00130                                 return $this;
00131                 }
00132                 
00137                 public function getLang () {
00138                     return $this->_lang;
00139                 }
00140                 
00146                 public function conv () {
00147                                 return localeconv();
00148                 }
00149                 
00159                 public function date ($time = null) {
00160                                 if ($time === null)
00161                                                 return date($this->date->format);
00162                                 else
00163                                                 return date($this->date->format, $time);
00164                 }
00165                 
00176                 public function date2string ($date) {
00177                     if (is_int($date)) {
00178                         $date = date('ymdHi', $date);
00179                     }
00180                     
00181                     $minusdate = date('ymdHi') - $date;
00182                     
00183                     if($minusdate > 88697640 && $minusdate < 100000000) {
00184                         $minusdate = $minusdate - 88697640;
00185                     }
00186                     
00187                     switch ($minusdate) {
00188                         case ($minusdate < 99):
00189                             if($minusdate == 1) {
00190                                 $date_string = $this->i18n('date.minutes_ago', 1) +1;
00191                             }
00192                             elseif($minusdate > 59) {
00193                                 $date_string = $this->i18n('date.minutes_ago', $minusdate - 40);
00194                             }
00195                             elseif($minusdate > 1 && $minusdate < 59) {
00196                                 $date_string = $this->i18n('date.minutes_ago', $minusdate);
00197                             }
00198                             break;
00199                         
00200                         case ($minusdate > 99 && $minusdate < 2359):
00201                             $flr = floor($minusdate * .01) +1;
00202                             if($flr == 1) {
00203                                 $date_string = $this->i18n('date.hours_ago', 1);;
00204                             }
00205                             else {
00206                                 $date_string = $this->i18n('date.hours_ago', $flr);
00207                             }
00208                             break;
00209                         
00210                         case ($minusdate > 2359 && $minusdate < 310000):
00211                             $flr = floor($minusdate * .0001) +1;
00212                             if($flr == 1) {
00213                                 $date_string = $this->i18n('date.days_ago', 1);
00214                             }
00215                             else {
00216                                 $date_string = $this->i18n('date.days_ago', $flr);
00217                             }
00218                             break;
00219                         
00220                         case ($minusdate > 310001 && $minusdate < 12320000):
00221                             $flr = floor($minusdate * .000001) +1;
00222                             if($flr == 1) {
00223                                 $date_string = $this->i18n('date.months_ago', 1);
00224                             }
00225                             else {
00226                                 $date_string = $this->i18n('date.months_ago', $flr);
00227                             }
00228                             break;
00229                         
00230                         case ($minusdate > 100000000):
00231                         default:
00232                             $flr = floor($minusdate * .00000001) +1;
00233                             if($flr == 1) {
00234                                 $date_string = $this->i18n('date.years_ago', 1);
00235                             }
00236                             else {
00237                                 $date_string = $this->i18n('date.years_ago', $flr);
00238                             }
00239                     }
00240                 
00241                     return $date_string;
00242                 }
00243                 
00251                 public function i18n ($key) {
00252                                 $args = func_get_args();
00253                                 array_shift($args);
00254                                 
00255                                 $msg = $this->getIterator();
00256                                 foreach (explode('.', $key) as $k)
00257                                                 $msg = $msg->$k;
00258                                                 
00259                                 if (!$msg->getValue()) {
00260                                                 trigger_error("Undefined translation {$key}");
00261                                                 return "";
00262                                 }
00263                                 
00264         switch (count($args)) {
00265             case 0: return $msg; break;
00266             case 1: return sprintf((string)$msg, $args[0]); break;
00267             case 2: return sprintf((string)$msg, $args[0], $args[1]); break;
00268             case 3: return sprintf((string)$msg, $args[0], $args[1], $args[2]); break;
00269             case 4: return sprintf((string)$msg, $args[0], $args[1], $args[2], $args[3]); break;
00270             case 5: return sprintf((string)$msg, $args[0], $args[1], $args[2], $args[3], $args[4]); break;
00271             default:
00272                 array_unshift($msg, $args);
00273                 return call_user_func_array('sprintf', $args);
00274                 break;
00275         }
00276                 }
00277                 
00284                 protected function _generateTree () {
00285                                 if (!is_file($this->_file) || !is_readable($this->_file))
00286             throw new axMissingFileException($this->_file);
00287                                 
00288         if (!$ini = parse_ini_file($this->_file, true))
00289             throw new RuntimeException("Cannot parse $file");
00290         
00291         foreach (array_keys($ini) as $key) {
00292             if (($offset = strpos($key, ':')) !== false && isset($ini[trim(substr($key, $offset+1))]))
00293                 $ini[$key] += $ini[trim(substr($key, $offset+1))];
00294                 
00295                                                 $tree = new axTreeItem;
00296                                                 foreach ($ini[$key] as $k => $v) {
00297                                                                 $p = explode('.', $k);
00298                                                                 $c = $tree;
00299                                                                 foreach ($p  as $sk)
00300                                                                                 $c = $c->$sk;
00301                                                                 $c->setValue($v);
00302                                                 }
00303                                                 $this->_tree[trim(substr($key, 0, $offset ? $offset : strlen($key)))] = $tree;
00304         }
00305                 }
00306                 
00314                 protected function _cache () {
00315                                 if (!$this->_cache_dir)
00316                                                 return false;
00317                                 
00318                                 $buffer = '<?php $tree=' . var_export($this->_tree, true) . '; ?>';
00319                                 return (boolean)file_put_contents($this->_cache_dir . '/' . self::CACHE_FILE, $buffer);
00320                 }
00321                 
00329     protected static function _getAcceptedLanguages () {
00330         if (isset(self::$_accepted_languages_cache))
00331             return self::$_accepted_languages_cache;
00332         
00333         $httplanguages = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
00334         $languages = array();
00335         if (empty($httplanguages)) {
00336             return $languages;
00337         }
00338         
00339         foreach (explode(',', $httplanguages) as $accept) {
00340             $result = preg_match('/^([a-z]{1,8}(?:[-_][a-z]{1,8})*)(?:;\s*q=(0(?:\.[0-9]{1,3})?|1(?:\.0{1,3})?))?$/i', $accept, $match);
00341 
00342             if (!$result) {
00343                 continue;
00344             }
00345             if (isset($match[2])) {
00346                 $quality = (float)$match[2];
00347             }
00348             else {
00349                 $quality = 1.0;
00350             }
00351             
00352             $countries   = explode('-', $match[1]);
00353             $region      = array_shift($countries);
00354             $country_sub = explode('_', $region);
00355             $region      = array_shift($country_sub);
00356             
00357             foreach($countries as $country)
00358                 $languages[$region . '_' . strtoupper($country)] = $quality;
00359             
00360             foreach($country_sub as $country)
00361                 $languages[$region . '_' . strtoupper($country)] = $quality;
00362 
00363             $languages[$region] = $quality;
00364         }
00365         
00366         return self::$_accepted_languages_cache = $languages;
00367     }
00368     
00376     protected function _determineLanguage () {
00377                 foreach ($this->_getAcceptedLanguages() as $accept => $priority) {
00378                                 if (isset($this->_tree[$accept]))
00379                                                 return $accept;
00380                 }
00381                 return false;
00382     }
00383 }
 All Data Structures Files Functions Variables