WordPress.org

Make WordPress Core

Changeset 2394


Ignore:
Timestamp:
02/28/2005 04:31:01 PM (15 years ago)
Author:
ryan
Message:

Bump php-gettext to version 1.0.3. http://mosquito.wordpress.org/view.php?id=1001 Mad props to Nico Kaiser.

Location:
trunk/wp-includes
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/gettext.php

    r1817 r2394  
    22/*
    33   Copyright (c) 2003 Danilo Segan <danilo@kvota.net>.
    4 
     4   Copyright (c) 2005 Nico Kaiser <nico@siriux.net>
     5   
    56   This file is part of PHP-gettext.
    67
     
    2122*/
    2223 
    23 
    24 
    25   // For start, we only want to read the MO files
    26 
     24/**
     25 * Provides a simple gettext replacement that works independently from
     26 * the system's gettext abilities.
     27 * It can read MO files and use them for translating strings.
     28 * The files are passed to gettext_reader as a Stream (see streams.php)
     29 *
     30 * This version has the ability to cache all strings and translations to
     31 * speed up the string lookup.
     32 * While the cache is enabled by default, it can be switched off with the
     33 * second parameter in the constructor (e.g. whenusing very large MO files
     34 * that you don't want to keep in memory)
     35 */
    2736class gettext_reader {
    28 //public:
    29   var $error = 0; // public variable that holds error code (0 if no error)
    30 //private:
    31   var $BYTEORDER = 0;
     37  //public:
     38   var $error = 0; // public variable that holds error code (0 if no error)
     39   
     40   //private:
     41  var $BYTEORDER = 0;        // 0: low endian, 1: big endian
    3242  var $STREAM = NULL;
    3343  var $short_circuit = false;
    34 
     44  var $enable_cache = false;
     45  var $originals = NULL;      // offset of original table
     46  var $translations = NULL;    // offset of translation table
     47  var $pluralheader = NULL;    // cache header field for plural forms
     48  var $total = 0;          // total string count
     49  var $table_originals = NULL;  // table for original strings (offsets)
     50  var $table_translations = NULL;  // table for translated strings (offsets)
     51  var $cache_translations = NULL;  // original -> translation mapping
     52
     53
     54  /* Methods */
     55 
     56   
     57  /**
     58   * Reads a 32bit Integer from the Stream
     59   *
     60   * @access private
     61   * @return Integer from the Stream
     62   */
    3563  function readint() {
    36     // Reads 4 byte value from $FD and puts it in int
    37     // $BYTEORDER specifies the byte order: 0 low endian, 1 big endian
    38     for ($i=0; $i<4; $i++) {
    39       $byte[$i]=ord($this->STREAM->read(1));
    40     }
    41     //print sprintf("pos: %d\n",$this->STREAM->currentpos());
    42     if ($this->BYTEORDER == 0)
    43       return (int)(($byte[0]) | ($byte[1]<<8) | ($byte[2]<<16) | ($byte[3]<<24));
    44     else
    45       return (int)(($byte[3]) | ($byte[2]<<8) | ($byte[1]<<16) | ($byte[0]<<24));
    46   }
    47 
    48   // constructor that requires StreamReader object
    49   function gettext_reader($Reader) {
     64      if ($this->BYTEORDER == 0) {
     65        // low endian
     66        return array_shift(unpack('V', $this->STREAM->read(4)));
     67      } else {
     68        // big endian
     69        return array_shift(unpack('N', $this->STREAM->read(4)));
     70      }
     71    }
     72
     73  /**
     74   * Reads an array of Integers from the Stream
     75   *
     76   * @param int count How many elements should be read
     77   * @return Array of Integers
     78   */
     79  function readintarray($count) {
     80    if ($this->BYTEORDER == 0) {
     81        // low endian
     82        return unpack('V'.$count, $this->STREAM->read(4 * $count));
     83      } else {
     84        // big endian
     85        return unpack('N'.$count, $this->STREAM->read(4 * $count));
     86      }
     87  }
     88 
     89  /**
     90   * Constructor
     91   *
     92   * @param object Reader the StreamReader object
     93   * @param boolean enable_cache Enable or disable caching of strings (default on)
     94   */
     95  function gettext_reader($Reader, $enable_cache = true) {
    5096    // If there isn't a StreamReader, turn on short circuit mode.
    5197    if (! $Reader) {
    52         $this->short_circuit = true;
    53         return;
    54     }
    55 
    56     // $MAGIC1 = (int)0x950412de; //bug in PHP 5
    57     $MAGIC1 = (int) - 1794895138;
    58     // $MAGIC2 = (int)0xde120495; //bug
    59     $MAGIC2 = (int) - 569244523;
    60 
     98      $this->short_circuit = true;
     99      return;
     100    }
     101   
     102    // Caching can be turned off
     103    $this->enable_cache = $enable_cache;
     104
     105    // $MAGIC1 = (int)0x950412de; //bug in PHP 5
     106    $MAGIC1 = (int) - 1794895138;
     107    // $MAGIC2 = (int)0xde120495; //bug
     108    $MAGIC2 = (int) - 569244523;
    61109
    62110    $this->STREAM = $Reader;
     
    70118      return false;
    71119    }
    72 
     120   
    73121    // FIXME: Do we care about revision? We should.
    74122    $revision = $this->readint();
    75 
    76     $total = $this->readint();
    77     $originals = $this->readint();
    78     $translations = $this->readint();
    79 
    80     $this->total = $total;
    81     $this->originals = $originals;
    82     $this->translations = $translations;
    83 
    84   }
    85 
    86   function load_tables($translations=false) {
    87     // if tables are loaded do not load them again
    88     if (!is_array($this->ORIGINALS)) {
    89       $this->ORIGINALS = array();
    90       $this->STREAM->seekto($this->originals);
    91       for ($i=0; $i<$this->total; $i++) {
    92     $len = $this->readint();
    93     $ofs = $this->readint();
    94     $this->ORIGINALS[] = array($len,$ofs);
    95       }
    96     }
    97 
    98     // similar for translations
    99     if ($translations and !is_array($this->TRANSLATIONS)) {
    100       $this->TRANSLATIONS = array();
    101       $this->STREAM->seekto($this->translations);
    102       for ($i=0; $i<$this->total; $i++) {
    103     $len = $this->readint();
    104     $ofs = $this->readint();
    105     $this->TRANSLATIONS[] = array($len,$ofs);
    106       }
    107     }
    108 
    109   }
    110 
    111   function get_string_number($num) {
    112     // get a string with particular number
    113     // TODO: Add simple hashing [check array, add if not already there]
    114     $this->load_tables();
    115     $meta = $this->ORIGINALS[$num];
    116     $length = $meta[0];
    117     $offset = $meta[1];
    118         if (! $length) {
    119             return '';
    120         }
     123   
     124    $this->total = $this->readint();
     125    $this->originals = $this->readint();
     126    $this->translations = $this->readint();
     127  }
     128 
     129  /**
     130   * Loads the translation tables from the MO file into the cache
     131   * If caching is enabled, also loads all strings into a cache
     132   * to speed up translation lookups
     133   *
     134   * @access private
     135   */
     136  function load_tables() {
     137    if (is_array($this->cache_translations) &&
     138      is_array($this->table_originals) &&
     139      is_array($this->table_translations))
     140      return;
     141   
     142    /* get original and translations tables */
     143    $this->STREAM->seekto($this->originals);
     144    $this->table_originals = $this->readintarray($this->total * 2);
     145    $this->STREAM->seekto($this->translations);
     146    $this->table_translations = $this->readintarray($this->total * 2);
     147   
     148    if ($this->enable_cache) {
     149      $this->cache_translations = array ();
     150      /* read all strings in the cache */
     151      for ($i = 0; $i < $this->total; $i++) {
     152        $this->STREAM->seekto($this->table_originals[$i * 2 + 2]);
     153        $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]);
     154        $this->STREAM->seekto($this->table_translations[$i * 2 + 2]);
     155        $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]);
     156        $this->cache_translations[$original] = $translation;
     157      }
     158    }
     159  }
     160 
     161  /**
     162   * Returns a string from the "originals" table
     163   *
     164   * @access private
     165   * @param int num Offset number of original string
     166   * @return string Requested string if found, otherwise ''
     167   */
     168  function get_original_string($num) {
     169    $length = $this->table_originals[$num * 2 + 1];
     170    $offset = $this->table_originals[$num * 2 + 2];
     171    if (! $length)
     172      return '';
    121173    $this->STREAM->seekto($offset);
    122174    $data = $this->STREAM->read($length);
    123175    return (string)$data;
    124176  }
    125 
    126   function get_translation_number($num) {
    127     // get a string with particular number
    128     // TODO: Add simple hashing [check array, add if not already there]
    129     $this->load_tables(true);
    130     $meta = $this->TRANSLATIONS[$num];
    131     $length = $meta[0];
    132     $offset = $meta[1];
     177 
     178  /**
     179   * Returns a string from the "translations" table
     180   *
     181   * @access private
     182   * @param int num Offset number of original string
     183   * @return string Requested string if found, otherwise ''
     184   */
     185  function get_translation_string($num) {
     186    $length = $this->table_translations[$num * 2 + 1];
     187    $offset = $this->table_translations[$num * 2 + 2];
     188    if (! $length)
     189      return '';
    133190    $this->STREAM->seekto($offset);
    134191    $data = $this->STREAM->read($length);
     
    136193  }
    137194 
    138   // binary search for string
    139   function find_string($string, $start,$end) {
    140     //print "start: $start, end: $end\n";
    141     if (abs($start-$end)<=1) {
    142       // we're done, if it's not it, bye bye
    143       $txt = $this->get_string_number($start);
     195  /**
     196   * Binary search for string
     197   *
     198   * @access private
     199   * @param string string
     200   * @param int start (internally used in recursive function)
     201   * @param int end (internally used in recursive function)
     202   * @return int string number (offset in originals table)
     203   */
     204  function find_string($string, $start = -1, $end = -1) {
     205    if (($start == -1) or ($end == -1)) {
     206      // find_string is called with only one parameter, set start end end
     207      $start = 0;
     208      $end = $this->total;
     209    }
     210    if (abs($start - $end) <= 1) {
     211      // We're done, now we either found the string, or it doesn't exist
     212      $txt = $this->get_original_string($start);
    144213      if ($string == $txt)
    145     return $start;
    146       else
    147     return -1;
    148     } elseif ($start>$end) {
    149       return $this->find_string($string,$end,$start);
    150     }  else {
    151       $half = (int)(($start+$end)/2);
    152       $tst = $this->get_string_number($half);
    153       $cmp = strcmp($string,$tst);
    154       if ($cmp == 0)
    155     return $half;
    156       elseif ($cmp<0)
    157     return $this->find_string($string,$start,$half);
    158       else
    159     return $this->find_string($string,$half,$end);
    160     }
    161   }
    162 
     214        return $start;
     215      else
     216        return -1;
     217    } else if ($start > $end) {
     218      // start > end -> turn around and start over
     219      return $this->find_string($string, $end, $start);
     220    } else {
     221      // Divide table in two parts
     222      $half = (int)(($start + $end) / 2);
     223      $cmp = strcmp($string, $this->get_original_string($half));
     224      if ($cmp == 0)
     225        // string is exactly in the middle => return it
     226        return $half;
     227      else if ($cmp < 0)
     228        // The string is in the upper half
     229        return $this->find_string($string, $start, $half);
     230      else
     231        // The string is in the lower half
     232        return $this->find_string($string, $half, $end);
     233    }
     234  }
     235 
     236  /**
     237   * Translates a string
     238   *
     239   * @access public
     240   * @param string string to be translated
     241   * @return string translated string (or original, if not found)
     242   */
    163243  function translate($string) {
    164     if ($this->short_circuit) {
     244    if ($this->short_circuit)
     245      return $string;
     246    $this->load_tables();     
     247   
     248    if ($this->enable_cache) {
     249      // Caching enabled, get translated string from cache
     250      if (array_key_exists($string, $this->cache_translations))
     251        return $this->cache_translations[$string];
     252      else
    165253        return $string;
    166     }
    167 
    168     $num = $this->find_string($string, 0, $this->total);
    169     if ($num == -1)
    170       return $string;
    171     else
    172       return $this->get_translation_number($num);
    173   }
    174 
     254    } else {
     255      // Caching not enabled, try to find string
     256      $num = $this->find_string($string);
     257      if ($num == -1)
     258        return $string;
     259      else
     260        return $this->get_translation_string($num);
     261    }
     262  }
     263
     264  /**
     265   * Get possible plural forms from MO header
     266   *
     267   * @access private
     268   * @return string plural form header
     269   */
    175270  function get_plural_forms() {
    176     // lets assume message number 0 is header
     271    // lets assume message number 0 is header 
    177272    // this is true, right?
    178 
     273    $this->load_tables();
     274   
    179275    // cache header field for plural forms
    180     if (is_string($this->pluralheader))
    181       return $this->pluralheader;
    182     else {
    183       $header = $this->get_translation_number(0);
    184 
    185       if (eregi("plural-forms: (.*)\n",$header,$regs)) {
    186     $expr = $regs[1];
    187       } else {
    188     $expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
    189       }
     276    if (! is_string($this->pluralheader)) {
     277      if ($this->enable_cache) {
     278        $header = $this->cache_translations[""];
     279      } else {
     280        $header = $this->get_translation_string(0);
     281      }
     282      if (eregi("plural-forms: (.*)\n", $header, $regs))
     283        $expr = $regs[1];
     284      else
     285        $expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
    190286      $this->pluralheader = $expr;
    191       return $expr;
    192     }
    193   }
    194 
     287    }
     288    return $this->pluralheader;
     289  }
     290
     291  /**
     292   * Detects which plural form to take
     293   *
     294   * @access private
     295   * @param n count
     296   * @return int array index of the right plural form
     297   */
    195298  function select_string($n) {
    196299    $string = $this->get_plural_forms();
     
    198301    $string = str_replace("n",$n,$string);
    199302    $string = str_replace('plural',"\$plural",$string);
    200 
     303   
    201304    $total = 0;
    202305    $plural = 0;
    203306
    204307    eval("$string");
    205     if ($plural>=$total) $plural = 0;
     308    if ($plural >= $total) $plural = 0;
    206309    return $plural;
    207310  }
    208311
     312  /**
     313   * Plural version of gettext
     314   *
     315   * @access public
     316   * @param string single
     317   * @param string plural
     318   * @param string number
     319   * @return translated plural form
     320   */
    209321  function ngettext($single, $plural, $number) {
    210322    if ($this->short_circuit) {
    211       if ($number != 1) return $plural;
    212       else return $single;
     323      if ($number != 1)
     324        return $plural;
     325      else
     326        return $single;
    213327    }
    214328
     
    216330    $select = $this->select_string($number);
    217331   
    218 
    219332    // this should contains all strings separated by NULLs
    220     $result = $this->find_string($single.chr(0).$plural,0,$this->total);
    221     if ($result == -1) {
    222       if ($number != 1) return $plural;
    223       else return $single;
     333    $key = $single.chr(0).$plural;
     334   
     335   
     336    if ($this->enable_cache) {
     337      if (! array_key_exists($key, $this->cache_translations)) {
     338        return ($number != 1) ? $plural : $single;
     339      } else {
     340        $result = $this->cache_translations[$key];
     341        $list = explode(chr(0), $result);
     342        return $list[$select];
     343      }
    224344    } else {
    225       $result = $this->get_translation_number($result);
    226    
    227       // lets try to parse all the NUL staff
    228       //$result = "proba0".chr(0)."proba1".chr(0)."proba2";
    229       $list = explode (chr(0), $result);
    230       return $list[$select];
     345      $num = $this->find_string($key);
     346      if ($num == -1) {
     347        return ($number != 1) ? $plural : $single;
     348      } else {
     349        $result = $this->get_translation_string($num);
     350        $list = explode(chr(0), $result);
     351        return $list[$select];
     352      }
    231353    }
    232354  }
     
    234356}
    235357
    236 
    237358?>
  • trunk/wp-includes/streams.php

    r1080 r2394  
    11<?php
    22/*
    3    Copyright (c) 2003 Danilo Segan <danilo@kvota.net>.
     3   Copyright (c) 2003, 2005 Danilo Segan <danilo@kvota.net>.
    44
    55   This file is part of PHP-gettext.
     
    104104
    105105  function read($bytes) {
    106     fseek($this->_fd, $this->_pos);
    107     $data = fread($this->_fd, $bytes);
    108     $this->_pos = ftell($this->_fd);
    109 
    110     return $data;
     106    if ($bytes) {
     107      fseek($this->_fd, $this->_pos);
     108      $data = fread($this->_fd, $bytes);
     109      $this->_pos = ftell($this->_fd);
     110     
     111      return $data;
     112    } else return '';
    111113  }
    112114
     
    131133}
    132134
     135// Preloads entire file in memory first, then creates a StringReader
     136// over it (it assumes knowledge of StringReader internals)
     137class CachedFileReader extends StringReader {
     138  function CachedFileReader($filename) {
     139    if (file_exists($filename)) {
     140
     141      $length=filesize($filename);
     142      $fd = fopen($filename,'rb');
     143
     144      if (!$fd) {
     145    $this->error = 3; // Cannot read file, probably permissions
     146    return false;
     147      }
     148      $this->_str = fread($fd, $length);
     149      fclose($fd);
     150
     151    } else {
     152      $this->error = 2; // File doesn't exist
     153      return false;
     154    }
     155  }
     156}
     157
     158
    133159?>
  • trunk/wp-includes/wp-l10n.php

    r2238 r2394  
    6767
    6868    if ( is_readable($mofile)) {
    69     $input = new FileReader($mofile);
     69    $input = new CachedFileReader($mofile);
    7070    }   else {
    7171        return;
Note: See TracChangeset for help on using the changeset viewer.