[ Index ]

PHP Cross Reference of Mambo 4.6.5

[ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/includes/phpgettext/ -> phpgettext.class.php (source)

   1  <?php
   2  /**
   3   * @version        0.9
   4   * @author      Carlos Souza
   5   * @copyright   Copyright (c) 2005 Carlos Souza <csouza@web-sense.net>
   6   * @package     PHPGettext
   7   * @license        MIT License (http://www.opensource.org/licenses/mit-license.php)
   8   * @link        http://phpgettext.web-sense.net
   9   *
  10   *
  11   */
  12  defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
  13  class PHPGettext
  14  {
  15      var $has_gettext;
  16  
  17      /**
  18       * The current locale. eg: en-GB
  19       */
  20      var $lang;
  21      /**
  22       * The current locale. eg: en-GB
  23       */
  24      var $locale;
  25  
  26      /**
  27       * The current domain
  28       */
  29      var $domain;
  30  
  31      /**
  32       * The current character set
  33       */
  34      var $charset;
  35  
  36      /**
  37       * Container for the loaded domains
  38       */
  39      var $text_domains = array();
  40  
  41      /**
  42       * The asssociative array of headers for the current domain
  43       */
  44      var $headers = array();
  45      /**
  46       * The asssociative array of messages for the current domain
  47       */
  48      var $messages = array();
  49  
  50      /**
  51       * The debugging flag
  52       */
  53      var $debug;
  54  
  55      function PHPGettext() {}
  56  
  57      /**
  58       *
  59       * Set and lookup the locale from the environment variables.
  60       * Priority order for gettext is:
  61       * 1. LANGUAGE
  62       * 2. LC_ALL
  63       * 3. LC_MESSAGE
  64       * 4. LANG
  65       *
  66       * @return unknown
  67       */
  68  
  69      function setVariable($variable){
  70          if ($this->has_gettext){
  71              $this->has_gettext = $this->has_gettext && @putenv($variable);
  72          }
  73      }
  74      
  75      function setlocale($lang, $locale=false) {
  76          $this->setvariable("LANGUAGE=$lang");
  77          $this->setvariable("LC_ALL=$lang");
  78          $this->setvariable("LC_MESSAGE=$lang");
  79          $this->setvariable("LANG=$lang");
  80          $this->lang =  $lang;
  81          if ($locale) {
  82              $this->locale =  setlocale(LC_ALL,$locale);
  83          }
  84      }
  85  
  86      function getlocale() {
  87          if (empty($this->locale)) {
  88              $langs = array( getenv('LANGUAGE'),
  89              getenv('LC_ALL'),
  90              getenv('LC_MESSAGE'),
  91              getenv('LANG')
  92              );
  93              foreach ($langs as $lang)
  94              if ($lang){
  95                  $this->locale = $lang;
  96                  break;
  97              }
  98          }
  99          return $this->locale;
 100      }
 101  
 102      /**
 103       * debugging function
 104       *
 105       */
 106      function output($message, $untranslated = false){
 107          switch ($this->debug)
 108          {
 109              case 2:
 110              $trace = debug_backtrace();
 111              $html = '<span style="border-bottom: thin solid %s" title="%s(%d)">T_(%s)</span>';
 112              $str = sprintf($html, ($untranslated ? 'red' : 'green'), str_replace('\\', '/', $trace[2]['file']), $trace[2]['line'], $message);
 113              break;
 114              case 1:
 115              $str    = sprintf('%sT_(%s)',$untranslated ? '!' : '', $message);
 116              break;
 117              case 0:
 118              default:
 119              $str    = $message;
 120              break;
 121          }
 122          return $str;
 123      }
 124  
 125      /**
 126       * Alias for gettext
 127       * will also output the result if $output = true
 128       */
 129      function _($message, $output = false){
 130          $return = $this->gettext($message);
 131          if ($output) {
 132              echo $return;
 133              return true;
 134          }
 135          return $return;
 136      }
 137  
 138      /**
 139       * Lookup a message in the current domain
 140       * returns translation if it exists or original message
 141       */
 142      function gettext($message){
 143          $translation = $message;
 144          if ($this->has_gettext){
 145              $translation = gettext($message);
 146          }
 147          else{
 148             $message = addslashes($message);
 149             $message = str_replace("\n", '\n', $message);
 150             $message = str_replace("\r", '\r', $message);
 151             if (isset($this->messages[$this->domain][$message])) {
 152              $translation = !empty($this->messages[$this->domain][$message]) ? $this->messages[$this->domain][$message] : $message;
 153              }
 154          }
 155          $untranslated = (strcmp($translation, $message) === 0) ? true : false;
 156          return $this->output($translation, $untranslated);
 157      }
 158  
 159      /**
 160       * Override the current domain
 161       * The dgettext() function allows you to override the current domain for a single message lookup.
 162       */
 163      function dgettext($domain, $message){
 164          $translation = $message;
 165          if (array_key_exists($domain, $this->messages)){
 166              if (isset($this->messages[$domain][$message]))
 167              $translation = !empty($this->messages[$domain][$message]) ? $this->messages[$domain][$message] : $message;
 168          }
 169          $untranslated = (strcmp($translation, $message) === 0) ? true : false;
 170          return $this->output($translation, $untranslated);
 171      }
 172  
 173      /**
 174       * Plural version of gettext
 175       */
 176      function ngettext($msgid, $msgid_plural, $count){
 177          if ($this->has_gettext){
 178              $translation = ngettext($msgid, $msgid_plural, $count);
 179          }else{
 180              $msgid = addslashes($msgid);
 181              $msgid = str_replace("\n", '\n', $msgid);
 182              $msgid = str_replace("\r", '\r', $msgid);
 183              $plural = $this->getplural($count, $this->domain);
 184              $original = array($msgid, $msgid_plural);
 185              if (isset($this->messages[$this->domain][$msgid]) && !is_array($this->messages[$this->domain][$msgid])){
 186                  $this->messages[$this->domain][$msgid] = array($this->messages[$this->domain][$msgid]);
 187              }
 188              if (isset($this->messages[$this->domain][$msgid][$plural])) {
 189                  $translation  = $this->messages[$this->domain][$msgid][$plural];
 190              } else {
 191                  $original   = array($msgid, $msgid_plural);
 192                  $translation  = $original[$plural];
 193              }
 194          }
 195          $untranslated = isset($original[$plural]) && (strcmp($translation, $original[$plural]) === 0) ? true : false;
 196          return $this->output($translation, $untranslated);
 197      }
 198      /**
 199       * Plural version of dgettext
 200       */
 201      function dngettext($domain, $msgid, $msgid_plural, $count){
 202          $original   = array($msgid, $msgid_plural);
 203          $plural = $this->getplural($count, $domain);
 204          if ($this->has_gettext){
 205              $translation = dngettext($domain, $msgid, $msgid_plural, $count);
 206          } else {
 207              $msgid = addslashes($msgid);
 208              $msgid = str_replace("\n", '\n', $msgid);
 209              $msgid = str_replace("\r", '\r', $msgid);
 210              if (isset($this->messages[$domain][$msgid][$plural])) {
 211                  $translation  = $this->messages[$domain][$msgid][$plural];
 212              } else {
 213                  $translation  = $original[$plural];
 214              }
 215          }
 216          $untranslated = (strcmp($translation, $original[$plural]) === 0) ? true : false;
 217          return $this->output($translation, $untranslated);
 218      }
 219  
 220      /**
 221       * Specify the character encoding in which the messages
 222       * from the DOMAIN message catalog will be returned
 223       *
 224       */
 225      function bind_textdomain_codeset($domain, $charset){
 226          if ($this->has_gettext){
 227              bind_textdomain_codeset($domain, $charset);
 228          }
 229          return $this->text_domains[$domain]["charset"] = $charset;
 230      }
 231  
 232      /**
 233       * Sets the path for a domain
 234       * if gettext is unavailable, translation files will be loaded here
 235       *
 236       */
 237      function bindtextdomain($domain, $path){
 238          if ($this->has_gettext){
 239              bindtextdomain($domain, $path);
 240          } else {
 241              $this->load($domain, $path);
 242          }
 243          return $this->text_domains[$domain]["path"] = $path;
 244      }
 245  
 246      /**
 247       * Sets the default domain textdomain
 248       */
 249      function textdomain($domain = null){
 250          if ($this->has_gettext) {
 251            $this->domain = textdomain($domain);
 252          }
 253          elseif (!is_null($domain)) {
 254              $this->domain = $domain;
 255              $this->load($domain, $this->text_domains[$this->domain]['path']);
 256          }
 257          return $this->domain;
 258      }
 259  
 260      /**
 261       * Overrides the domain for a single lookup
 262       * This function allows you to override the current domain for a single message lookup.
 263       * It also allows you to specify a category.
 264       * Categories are folders within the languages directory  .
 265       * currently, only LC_MESSAGES is implemented
 266       *
 267       *   The values for categories are:
 268       *   LC_CTYPE        0
 269       *   LC_NUMERIC      1
 270       *   LC_TIME         2
 271       *   LC_COLLATE      3
 272       *   LC_MONETARY     4
 273       *   LC_MESSAGES     5
 274       *   LC_ALL          6
 275       *
 276       *   not yet implemented
 277       */
 278      function dcgettext($domain, $message, $category){
 279          return $message;
 280      }
 281  
 282      /**
 283       * dcngettext -- Plural version of dcgettext
 284       * not yet implemented
 285       */
 286      function dcngettext($domain, $msg1, $msg2, $count, $category){
 287          return $msg1;
 288      }
 289  
 290  
 291      /**
 292       * Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;
 293       *
 294       * nplurals - total number of plurals
 295       * plural   - the plural index
 296       *
 297       * Plural-Forms: nplurals=1; plural=0;
 298       * 1 form only
 299       *
 300       * Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;
 301       * Plural-Forms: nplurals=2; plural=n != 1;
 302       * 2 forms, singular used for one only
 303       *
 304       * Plural-Forms: nplurals=2; plural=n>1;
 305       * 2 forms, singular used for zero and one
 306       *
 307       * Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;
 308       * 3 forms, special case for zero
 309       *
 310       * Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;
 311       * 3 forms, special cases for one and two
 312       *
 313       * Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;
 314       * 4 forms, special case for one and all numbers ending in 02, 03, or 04
 315       */
 316      function getplural($count, $domain) {
 317          if (isset($this->headers[$domain]['Plural-Forms'])) {
 318              $plural_forms = $this->headers[$domain]['Plural-Forms'];
 319              preg_match('/nplurals[\s]*[=]{1}[\s]*([\d]+);[\s]*plural[\s]*[=]{1}[\s]*(.*);/', $plural_forms, $matches);
 320              $nplurals   = $matches[1];
 321              $plural_exp = $matches[2];
 322              if ($nplurals == 1){
 323                  return 0;
 324              } else if ($nplurals > 1 && strpos($plural_exp, ':') === false) {
 325                  $plural =  'return ('.preg_replace('/n/', $count, $plural_exp).') ? 1 : 0;';
 326              } else {
 327                  $plural = 'return '.preg_replace('/n/', $count, $plural_exp).';';
 328              }
 329          } else {
 330              $plural = 'return '.preg_replace('/n/', $count, 'n != 1 ? 1 : 0;');
 331          }
 332          return eval($plural);
 333      }
 334  
 335      function load($domain, $path) {
 336          $root = dirname(__FILE__);
 337          require_once ($root.'/phpgettext.catalog.php');
 338          $catalog = new PHPGettext_catalog($domain, $path);
 339          $catalog->setproperty('mode', _MODE_MO_);
 340          $catalog->setproperty('lang', $this->lang);
 341          $catalog->load();
 342          $this->headers[$domain] = $catalog->headers;
 343          foreach ($catalog->strings as $string)
 344          $this->messages[$domain][$string->msgid] = $string->msgstr;
 345      }
 346      //Thank you - Inicio Agregado Andres Felipe Vargas
 347      function add($domain) {
 348          $catalog = new PHPGettext_catalog($domain, $this->text_domains[$this->domain]["path"]);
 349          $catalog->setproperty('mode', _MODE_MO_);
 350          $catalog->setproperty('lang', $this->lang);
 351          $catalog->load();
 352          foreach ($catalog->strings as $string)
 353          $this->messages[$this->domain][$string->msgid] = $string->msgstr;
 354      }
 355      //end Inicio Agregado Andres Felipe Vargas
 356  
 357  }
 358  
 359  
 360  class PHPGettextAdmin
 361  {
 362      var $has_gettext    = false;
 363      var $gettext_path   = '';
 364      var $debug          = false;
 365      var $is_windows     = false;
 366  
 367      function PHPGettextAdmin($useGettext = false, $debug = false)
 368      {
 369          $this->has_gettext = $useGettext;
 370          if (substr(strtoupper(PHP_OS), 0, 3) == 'WIN'){
 371              $this->is_windows = true;
 372          }
 373          if ($this->has_gettext){
 374              $this->has_gettext = $this->gettextAble();
 375          }
 376      }
 377  
 378      function gettextAble(){
 379          if (ini_get('open_basedir') || ini_get('safe_mode') || strstr(ini_get("disable_functions"),"exec")) {
 380              return false;
 381          }
 382  
 383          $cmd = 'xgettext --help';
 384          exec($cmd, $output, $return);
 385          if ($output) {
 386              return true;
 387          }
 388          return false;
 389      }
 390  
 391      /**
 392       * Enter description here...
 393       *
 394       * @param unknown_type $domain
 395       * @param unknown_type $langdir
 396       */
 397      function message_format ($domain, $textdomain, $lang, $enc='utf-8')
 398      {
 399          $path   = "$textdomain/$lang";
 400          if ($this->has_gettext) {
 401              $cmd = $this->escCommand("msgfmt")." -o ".$this->escPath("{$path}/LC_MESSAGES/{$domain}.mo")." ".$this->escPath("{$path}/{$domain}.po");
 402              return $this->execute($cmd);
 403          }
 404          $catalog = new PHPGettext_catalog($domain, $textdomain);
 405          $catalog->setproperty('mode', _MODE_PO_);
 406          $catalog->setproperty('lang', $lang);
 407          $catalog->load();
 408          $catalog->setproperty('mode', _MODE_MO_);
 409          $catalog->save();
 410          return true;
 411      }
 412      /**
 413       * Enter description here...
 414       *
 415       * @param unknown_type $domain
 416       * @param unknown_type $langdir
 417       */
 418      function compile($lang, $textdomain, $enc='utf-8', $plurals='nplurals=2; plural=n == 1 ? 0 : 1;') {
 419          if (!is_dir("$textdomain/$lang/LC_MESSAGES")) {
 420              mkdir("$textdomain/$lang/LC_MESSAGES/");
 421          }
 422          $catalog = new PHPGettext_catalog($lang, $textdomain);
 423          $catalog->setproperty('mode', _MODE_PO_);
 424          $catalog->setproperty('lang', $lang);
 425          $headers = $this->header($enc, $plurals);
 426          $catalog->setproperty('comments', $headers[0]);
 427          $catalog->setproperty('headers', $headers[1]);
 428          $catalog->load();
 429          $d = dir($textdomain."/".$lang);
 430          while (false !== ($file = $d->read())){
 431             if (preg_match('/.po$/', $file)){
 432                  list($file,$ext) = explode(".",$file);
 433                  $catalog_aux = new PHPGettext_catalog($file, $textdomain);
 434                  $catalog_aux->setproperty('mode', _MODE_PO_);
 435                  $catalog_aux->setproperty('lang', $lang);
 436                  $catalog_aux->load();
 437                  foreach ($catalog_aux->strings as $msgid => $string){
 438                     if (!$string->is_fuzzy){
 439                          if (is_array($string->msgstr) ){
 440                              if(in_array("",$string->msgstr)){
 441                                  continue;
 442                              }
 443                          } else if (!$string->msgstr){
 444                              continue;
 445                          }
 446                         $catalog->addentry($string->msgid, $string->msgid_plural,$string->msgstr, $string->comments );
 447                     }
 448                  }
 449             }
 450          }
 451          $catalog->setproperty('mode', _MODE_MO_);
 452          $catalog->save();
 453          return true;
 454      }
 455  
 456      /**
 457       * Enter description here...
 458       *
 459       * @param unknown_type $domain
 460       * @param unknown_type $langdir
 461       */
 462      function initialize_translation ($domain, $textdomain, $lang, $enc='utf-8')
 463      {
 464          if (!$this->has_gettext) {
 465              return false;
 466          }
 467          set_time_limit(120);
 468          $path   = "$textdomain/$lang";
 469          copy("$textdomain/untranslated/$domain.pot", "$path/ref.po");
 470          $cmd = $this->escCommand("msgmerge")." --width=80 --compendium ".$this->escPath("{$textdomain}/glossary/{$lang}.{$enc}.po")." -o ".$this->escPath("{$path}/{$domain}.po")." ".$this->escPath("{$path}/ref.po")." ".$this->escPath("{$textdomain}/untranslated/{$domain}.pot");
 471          $this->execute($cmd);
 472          unlink("$textdomain/$lang/ref.po");
 473      }
 474  
 475      /**
 476       * Enter description here...
 477       *
 478       * @param unknown_type $domain
 479       * @param unknown_type $langdir
 480       */
 481      
 482      function update_translation($domain, $textdomain, $lang, $enc='utf-8')
 483      {
 484          if (!file_exists("$textdomain/glossary/$lang.$enc.po")) return false;
 485          $catalog_aux = new PHPGettext_catalog($lang.".".$enc, $textdomain);
 486          $catalog_aux->setproperty('mode', _MODE_GLO_);
 487          $catalog_aux->setproperty('lang', $lang);
 488          $catalog_aux->load();
 489          foreach ($catalog_aux->strings as $msgid => $string){
 490             if (!$string->is_fuzzy){
 491                $trans[$string->msgid] = $string->msgstr;
 492             }
 493          }
 494          $catalog = new PHPGettext_catalog($domain, $textdomain);
 495          $catalog->setproperty('mode', _MODE_PO_);
 496          $catalog->setproperty('lang', $lang);
 497          $catalog->load();
 498          global $mapcharset;
 499          $charsets = explode("=",$catalog->headers["Content-Type"]);
 500          $codecharset = str_replace("\\n","",strtolower($charsets[1]));
 501          $NewEncoding = new ConvertCharset();
 502          foreach ($trans as $key => $tran){
 503                 if(trim($mapcharset[$codecharset])!="utf-8")
 504                      $trans[$key] = $NewEncoding->Convert($tran,"utf-8",trim($mapcharset[$codecharset]),false);
 505          }
 506          $catalog->translate($trans );
 507          $catalog->save();
 508          return true;
 509      }
 510      
 511      /**
 512       * Enter description here...
 513       *
 514       * @param unknown_type $domain
 515       * @param unknown_type $langdir
 516       */
 517  
 518      function add_to_dict($domain, $textdomain, $lang, $enc='utf-8', $plurals='nplurals=2; plural=n == 1 ? 0 : 1;') {
 519          $textdomain = rtrim($textdomain, '\/');
 520          $path = "$textdomain/$lang";
 521  
 522          if (!is_dir("$textdomain/glossary/")) {
 523              mkdir("$textdomain/glossary/");
 524          }
 525          
 526          $catalog = new PHPGettext_catalog($domain, $textdomain);
 527          $catalog->setproperty('mode', _MODE_PO_);
 528          $catalog->setproperty('lang', $lang);
 529          $catalog->setproperty('charset', $enc);
 530          $catalog->load();
 531  
 532          foreach ($catalog->strings as $msgid => $string){
 533             if (!$string->is_fuzzy){
 534                if (is_array($string->msgstr) ){
 535                    if(in_array("",$string->msgstr)){
 536                    continue;
 537                    }
 538                } else if (!$string->msgstr){
 539                    continue;
 540                }
 541                $new[$string->msgid] = $string;
 542             }
 543          }
 544  
 545          $glossary = new PHPGettext_catalog($lang.".".$enc, $textdomain);
 546          $glossary->setproperty('mode', _MODE_GLO_);
 547          $glossary->setproperty('lang', $lang);        
 548          if (!file_exists("$textdomain/glossary/$lang.$enc.po")) {
 549              $headers = $this->header($enc,$plurals);
 550              $glossary->setproperty('comments', $headers[0]);
 551              $glossary->setproperty('headers', $headers[1]);
 552              $glossary->save();
 553          }else{
 554              $glossary->load();
 555          }
 556          
 557          $glossary->merge($new );
 558          $glossary->save();
 559          
 560          $language = new mamboLanguage($lang);
 561          $language->save();
 562          return true;
 563      }
 564      /**
 565       * Enter description here...
 566       *
 567       * @param unknown_type $domain
 568       * @param unknown_type $langdir
 569       */
 570      function convert_charset($domain, $textdomain, $lang, $from_charset, $to_charset) {
 571  
 572          $path = "$textdomain/$lang";
 573          if ($this->has_gettext) {
 574              $cmd = $this->escCommand("msgconv")." --to-code=$to_charset -o ".$this->escPath("{$path}/{$domain}.po")." ".$this->escPath("{$path}/{$domain}.po");
 575              $ret = $this->execute($cmd);
 576              return $ret;
 577          }
 578  
 579          if (!class_exists('ConvertCharset')) {
 580              return false;
 581          }
 582  
 583          $catalog = new PHPGettext_catalog($domain, $textdomain);
 584          $catalog->setproperty('mode', _MODE_PO_);
 585          $catalog->setproperty('lang', $lang);
 586          $catalog->load();
 587          $catalog->headers['Content-Type'] = "text/plain; charset=$to_charset\n";
 588          $NewEncoding = new ConvertCharset();
 589          foreach ($catalog->strings as $index => $message) {
 590              if (empty($message->msgid_plural)) {
 591                  $catalog->strings[$index]->msgstr = $NewEncoding->Convert($message->msgstr,$from_charset,$to_charset,false);
 592              }
 593          }
 594          $catalog->save();
 595          return true;
 596      }
 597  
 598  
 599      /**
 600       * Invoke the xgettext utility with $args
 601       * the xgettext executable must be in PATH
 602       *
 603       * @param string the commandline arguments to gettext
 604       * @return unknown
 605       */
 606      function xgettext($domain, $textdomain, $php_sources, $lang='untranslated') {
 607          $path = mamboCore::get('rootPath');
 608          $n=count($php_sources);
 609          if (!$n) return false;
 610          $cmd  = $this->escCommand("xgettext");
 611          if (file_exists("$textdomain/$lang/$domain.pot")) $cmd  .= ' -j ';
 612          $cmd  .= " -n -c --sort-by-file --keyword=T_ --keyword=Tn_:1,2 --keyword=Td_:2 --keyword=Tdn_:2,3 --output-dir=".$this->escPath("{$textdomain}/{$lang}")." -o {$domain}.pot";
 613          if (count($php_sources) > 10) {
 614              $tmp_name = substr(uniqid(rand()),0,8).".txt";
 615              $tmpfile = $path."/media/$tmp_name";
 616              $fp = fopen($tmpfile, "w");
 617              fwrite($fp, implode("\r\n", $php_sources));
 618              fclose($fp);
 619              $cmd = $cmd." --files-from=".$this->escPath($tmpfile);
 620          } else {
 621              for($i=0;$i<$n;$i++){ 
 622                  $php_sources[$i] = $this->escPath($php_sources[$i]);
 623              }
 624              $cmd = $cmd." ".implode(" ", $php_sources);
 625          }
 626          $ret = $this->execute($cmd);
 627          @unlink($tmpfile);
 628  
 629          return $ret;
 630      }
 631  
 632      
 633      /**
 634       * Enter description here...
 635       *
 636       * @param unknown_type $domain
 637       * @param unknown_type $langdir
 638       */
 639      function execute($cmd) {
 640  
 641          if (!$this || !$this->has_gettext) return false;
 642  
 643          $lastline = exec($cmd, $output, $retval);
 644          if ($this->debug || $retval > 0) {
 645              $trace = debug_backtrace();
 646              $msg = "<div style=\"border: thin solid silver; text-align:left;margin-left:10px\">";
 647              $msg .= "<p><span style=\"font-weight:bold\">PHPGettextAdmin->execute('</span><i>$cmd</i><span style=\"font-weight:bold\">')</span><br />in ".str_replace($_SERVER['DOCUMENT_ROOT'], '', $trace[1]['file']).":{$trace[1]['line']}</p>";
 648              $msg .= "<p><em><strong>trace:</strong></em></p><ul>";
 649              for ($a=1; $a < 3; $a++)  {
 650                  $called = isset($trace[$a]['class']) ? $trace[$a]['class'] : '';
 651                  $called .= $trace[$a]['type'].$trace[$a]['function']."(".@implode(', ',$trace[$a]['args']).")";
 652                  $msg .= "<li>$called in ".str_replace($_SERVER['DOCUMENT_ROOT'], '', $trace[$a]['file'])." : {$trace[$a]['line']}</li>";
 653              }
 654              $msg .= "</ul>";
 655              $msg .= "<p><em><strong>return value:</strong></em>  $retval</p>";
 656              $msg .= "<p><em><strong>output:</strong></em> </p><pre>".implode("<br />",$output)."</pre>";
 657              $msg .= "</div>";
 658              echo $msg;
 659          }
 660          return $retval == 0;
 661      }
 662      
 663      function escCommand($command){
 664          if ($this->is_windows){
 665             $command = "call \"{$command}\"";
 666          }
 667          return $command;
 668      }
 669  
 670      function escPath($path){
 671          if ($this->is_windows){
 672             $path = "\"".str_replace("/","\\",$path)."\"";
 673          }
 674          return $path;
 675      }
 676  
 677      function header($charset='utf-8', $plurals='nplurals=2; plural=n == 1 ? 0 : 1;'){
 678          $year = date('Y');
 679          $comments = <<<EOT
 680  # Mambo
 681  # Copyright (C) 2005 - $year Mambo Foundation Inc.
 682  # This file is distributed under the same license as the Mambo package.
 683  # Translation Team <translation@mambo-foundation.org>, $year#
 684  #
 685  #, fuzzy
 686  EOT;
 687          $comments = explode("\n", $comments);
 688          $headers = array(
 689          'Project-Id-Version'    => 'Mambo 4.6',
 690          'Report-Msgid-Bugs-To'  => 'translation@mambo-foundation.org',
 691          'POT-Creation-Date'     => date('Y-m-d h:iO'),
 692          'PO-Revision-Date'      => date('Y-m-d h:iO'),
 693          'Last-Translator'       => 'Translation <translation@mambo-foundation.org>',
 694          'Language-Team'         => 'Translation <translation@mambo-foundation.org>',
 695          'MIME-Version'          => '1.0',
 696          'Content-Type'          => 'text/plain; charset='.$charset,
 697          'Content-Transfer-Encoding' => '8bit',
 698          'Plural-Forms'              => $plurals
 699          );
 700          return array($comments, $headers);
 701      }
 702  }
 703  
 704  /**
 705   * Enter description here...
 706   *
 707   * @return unknown
 708   */
 709  function &phpgettext(){
 710      static $gettext;
 711      $root = dirname(__FILE__);
 712      if (is_null($gettext)) {
 713          require_once ($root.'/phpgettext.class.php');
 714          $gettext = new PHPGettext();
 715          $gettext->has_gettext = true;
 716          if (!function_exists("gettext") || !function_exists("_")) {
 717              $gettext->has_gettext = false;
 718              require_once ($root.'/phpgettext.compat.php');
 719          }
 720      }
 721      return $gettext;
 722  }
 723  function T_($message) {
 724      $gettext =& phpgettext();
 725      $trans = $gettext->gettext($message);
 726      return $trans;
 727  }
 728  function Tn_($msg1, $msg2, $count) {
 729      $gettext =& phpgettext();
 730      return $gettext->ngettext($msg1, $msg2, $count);
 731  }
 732  function Td_($domain, $message) {
 733      $gettext =& phpgettext();
 734      return $gettext->dgettext($domain, $message);
 735  }
 736  function Tdn_($domain, $msg1, $msg2, $count) {
 737      $gettext =& phpgettext();
 738      return $gettext->dngettext($domain, $msg1, $msg2, $count);
 739  }
 740  ?>