PHP userland backwards compatibility layer that emulates PHP 5.5+ core functions.

⌈⌋ branch:  upgrade.php


Artifact Content

Artifact 10583d1783e784dd183252ad9810102146a3ab06:

  • File ext/gettext.php — part of check-in [8c74990127] at 2010-06-22 16:46:34 on branch trunk — upgradephp-11 (user: mario size: 7141)

<?php
/*
   Simulates gettext functionality. Understands .mo and .po files.
   Lookup of plural forms mostly work (but not fully compliant, no
   support for Plural-Forms: header). Categories/codesets are ignored.

   Besides using setlocale() you should change the $_ENV["LANG"] var
   to the desired language manually. Additionally all your scripts
   could contain following (may also work with standard gettext):
     $_ENV["LANGUAGE"] = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
   What's often more user-friendly than hardwired server-side values.
*/


#-- define if not there
if (!function_exists("gettext")) {

   #-- all-in-one combined implementation
   #   (in PHP only the first parameter is used)
   function gettext($msg, $msg2=NULL, $domain=NULL, $category=NULL, $plural=NULL, $config=NULL) {
      global $_GETTEXT;
      
      #-- params
      if (!isset($domain)) {
         $domain = $_GETTEXT["%domain"];
      }
      elseif (empty($_GETTEXT[$domain])) {
         bindtextdomain($domain);  // load from system dirs
      }
      #-- config
      if (isset($config)) {
         return false;
      }
      #-- plural array position (English)
      if (!isset($plural) || ($plural == 1)) {
         $pli = 0;
      }
      else {
         if (isset($msg2)) {
            $msg = $msg2;
         }
         $pli = 1;
      }
      // $pli = ($plural==1) ?0 :1;

      #-- look up
      if ($trans = $_GETTEXT[$domain][$msg]) {
         if (is_array($trans)) {
            if (!isset($trans[$pli])) {
               $pli = 0;
            }
            $trans = $trans[$pli];
         }
         if (strlen($trans)) {
            $msg = $trans;
         }
      }

      #-- give out whatever we have
      return($msg);
   }

   #-- wrappers
   function ngettext($msg1, $msg2, $plural) {
      return gettext($msg1, $msg2, NULL, NULL, $plural);
   }
   function dngettext($domain, $msg1, $msg2, $plural) {
      return gettext($msg1, $msg2, $domain, NULL, $plural);
   }
   function dcngettext($domain, $msg1, $msg2, $plural, $category) {
      return gettext($msg1, $msg2, $domain, $category, $plural);
   }
   function dcgettext($domain, $msg, $category) {
      return gettext($msg, NULL, $domain, $category);
   }
   function dgettext($domain, $msg) {
      return gettext($msg, NULL, $domain);
   }

   #-- settings
   function textdomain($default="NULL") {
      global $_GETTEXT;
      $prev = $_GETTEXT["%domain"];
      if (isset($default)) {
         $_GETTEXT["%domain"] = $default;
      }
      return $prev;
   }

   #-- loads data files
   function bindtextdomain($domain, $directory="/usr/share/locale:/usr/local/share/locale:./locale") {
      global $_GETTEXT;
      if (isset($_GETTEXT["domain"]) && (count($_GETTEXT["domain"]) > 3)) {
         return;  // don't load twice
      }
      $_GETTEXT[$domain]["%dir"] = $directory;
      $_GETTEXT["%locale"] = setlocale(LC_CTYPE, 0);

      #-- language directories
      $langs = "$_ENV[LANGUAGE],$_ENV[LC_ALL],$_ENV[LC_MESSAGE],$_ENV[LANG],"
            . "{$_GETTEXT['%locale']},$_SERVER[HTTP_ACCEPT_LANGUAGE],C,en";
      foreach (explode(",",$langs) as $d) {
         $d = trim($d);
         // $dir2[] = $d;
         $d = strtok($d, "@.-+=%:; ");
         if (strlen($d)) {
            $dir2[] = $d;
         }
         if (strpos($d, "_")) {
            $dir2[] = strtok($d, "_");
         }
      }
      
      #-- repeat
      foreach (explode(":", $directory) as $directory)
      foreach ($dir2 as $lang) {
        $base_fn = "$directory/$lang/LC_MESSAGES/$domain";

        #-- binary format
        if (file_exists($f = "$base_fn.mo") && ($f = fopen($f, "rb"))) {
           $data = fread($f, 1<<20);
           fclose($f);
           #-- check file magic
           if ($data) {
              extract(unpack("L1magic/L1version/L1count/L1o_msg/L1o_trn", substr($data, 0, 20)));
              if ((dechex($magic) == "950412de") && ($version == 0)) {
                 for ($n=0; $n<$count; $n++) {
                    #-- id
                    $r = unpack("L1len/L1offs", substr($data, $o_msg + $n * 8, 8));
                    $msgid = substr($data, $r["offs"], $r["len"]);
                    unset($msgid_plural);
                    if (strpos($msgid, "\000")) {
                       list($msgid, $msgid_plural) = explode("\000", $msgid);
                    }
                    #-- translation
                    $r = unpack("L1len/L1offs", substr($data, $o_trn + $n * 8, 8));
                    $msgstr = substr($data, $r["offs"], $r["len"]);
                    if (strpos($msgstr, "\000")) {
                       $msgstr = explode("\000", $msgstr);
                    }
                    #--  add
                    $_GETTEXT[$domain][$msgid] = $msgstr;
                    if (isset($msgid_plural)) {
                       $_GETTEXT[$domain][$msgid_plural] = &$_GETTEXT[$domain][$msgid];
                    }
                 }
              }
           }
           break;
        }

        #-- read from text file (not fully correct, and redundant because
        #   the original gettext/libintl doesn't support this at all)
        elseif (file_exists($f = "$base_fn.po") && ($f = fopen($f, "r"))) {
           do {
              $line = trim(fgets($f));
              if (isset($msgid) && isset($msgstr) && (empty($line) || ($line[0]=="m"))) {
                 foreach ($msgstr as $v) {
                    $_GETTEXT[$domain][$msgid[0]] = $v;
                 }
                 if ($msgid[1]) {
                    $_GETTEXT[$domain][$msgid[1]] = &$_GETTEXT[$domain][$msgid[0]];
                 }
                 unset($msgid);
                 unset($msgstr);
              }
              $space = strpos($line, " ");
              if ($line[0] == "#") {
                 continue;
              }
              elseif (strncmp($line, "msgid", 5)==0) {
                 $msgid[] = trim(substr($line, $space+1), '"');
              }
              elseif (strncmp($line, "msgstr", 6)==0) {
                 $msgstr[] = trim(substr($line, $space+1), '"');
              }
              elseif ($line[0] == '"') {
                 $line = trim($line, '"');
                 if (isset($msggstr)) {
                    $msgstr[count($msgstr)] .= $line;
                 }
                 else {
                    $msgid[count($msgid)] .= $line;
                 }
              }
           }
           while (!feof($f));
           if ($msgid && $msgstr) { $_GETTEXT[$domain][$msgid[0]] = $msgstr[0]; }
           
           fclose($f);
           break;
        }
        
      }//foreach

      #-- set as default textdomain
      if (empty($_GETTEXT["%domain"]) && (count($_GETTEXT[$domain]) > 1)) {
         $_GETTEXT["%domain"] = $domain;
      }
      return($domain);
   }

   #-- ignored setting (no idea what it really should do)
   function bind_textdomain_codeset($domain, $codeset) {
      global $_GETTEXT;
      $_GETTEXT[$domain]["%codeset"] = $codeset;
      return($domain);
   }

}


#-- define separately
if (!function_exists("_")) {
   function _($str) {
      return gettext($str);
   }
}



?>