123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- <?php
- class gettext_reader
- {
-
- public $error = 0;
-
- public $BYTEORDER = 0;
- public $STREAM = null;
- public $short_circuit = false;
- public $enable_cache = false;
- public $originals = null;
- public $translations = null;
- public $pluralheader = null;
- public $total = 0;
- public $table_originals = null;
- public $table_translations = null;
- public $cache_translations = null;
-
-
- public function readint()
- {
- if ($this->BYTEORDER == 0) {
-
- $input=unpack('V', $this->STREAM->read(4));
- return array_shift($input);
- } else {
-
- $input=unpack('N', $this->STREAM->read(4));
- return array_shift($input);
- }
- }
- public function read($bytes)
- {
- return $this->STREAM->read($bytes);
- }
-
- public function readintarray($count)
- {
- if ($this->BYTEORDER == 0) {
-
- return unpack('V'.$count, $this->STREAM->read(4 * $count));
- } else {
-
- return unpack('N'.$count, $this->STREAM->read(4 * $count));
- }
- }
-
- public function gettext_reader($Reader, $enable_cache = true)
- {
-
- if (! $Reader || isset($Reader->error)) {
- $this->short_circuit = true;
- return;
- }
-
- $this->enable_cache = $enable_cache;
- $MAGIC1 = "\x95\x04\x12\xde";
- $MAGIC2 = "\xde\x12\x04\x95";
- $this->STREAM = $Reader;
- $magic = $this->read(4);
- if ($magic == $MAGIC1) {
- $this->BYTEORDER = 1;
- } elseif ($magic == $MAGIC2) {
- $this->BYTEORDER = 0;
- } else {
- $this->error = 1;
- return false;
- }
-
- $revision = $this->readint();
- $this->total = $this->readint();
- $this->originals = $this->readint();
- $this->translations = $this->readint();
- }
-
- public function load_tables()
- {
- if (is_array($this->cache_translations) &&
- is_array($this->table_originals) &&
- is_array($this->table_translations)) {
- return;
- }
-
- if (!is_array($this->table_originals)) {
- $this->STREAM->seekto($this->originals);
- $this->table_originals = $this->readintarray($this->total * 2);
- }
- if (!is_array($this->table_translations)) {
- $this->STREAM->seekto($this->translations);
- $this->table_translations = $this->readintarray($this->total * 2);
- }
- if ($this->enable_cache) {
- $this->cache_translations = array();
-
- for ($i = 0; $i < $this->total; $i++) {
- $this->STREAM->seekto($this->table_originals[$i * 2 + 2]);
- $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]);
- $this->STREAM->seekto($this->table_translations[$i * 2 + 2]);
- $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]);
- $this->cache_translations[$original] = $translation;
- }
- }
- }
-
- public function get_original_string($num)
- {
- $length = $this->table_originals[$num * 2 + 1];
- $offset = $this->table_originals[$num * 2 + 2];
- if (! $length) {
- return '';
- }
- $this->STREAM->seekto($offset);
- $data = $this->STREAM->read($length);
- return (string)$data;
- }
-
- public function get_translation_string($num)
- {
- $length = $this->table_translations[$num * 2 + 1];
- $offset = $this->table_translations[$num * 2 + 2];
- if (! $length) {
- return '';
- }
- $this->STREAM->seekto($offset);
- $data = $this->STREAM->read($length);
- return (string)$data;
- }
-
- public function find_string($string, $start = -1, $end = -1)
- {
- if (($start == -1) or ($end == -1)) {
-
- $start = 0;
- $end = $this->total;
- }
- if (abs($start - $end) <= 1) {
-
- $txt = $this->get_original_string($start);
- if ($string == $txt) {
- return $start;
- } else {
- return -1;
- }
- } elseif ($start > $end) {
-
- return $this->find_string($string, $end, $start);
- } else {
-
- $half = (int)(($start + $end) / 2);
- $cmp = strcmp($string, $this->get_original_string($half));
- if ($cmp == 0) {
-
- return $half;
- } elseif ($cmp < 0) {
-
- return $this->find_string($string, $start, $half);
- } else {
-
- return $this->find_string($string, $half, $end);
- }
- }
- }
-
- public function translate($string)
- {
- if ($this->short_circuit) {
- return $string;
- }
- $this->load_tables();
- if ($this->enable_cache) {
-
- if (array_key_exists($string, $this->cache_translations)) {
- return $this->cache_translations[$string];
- } else {
- return $string;
- }
- } else {
-
- $num = $this->find_string($string);
- if ($num == -1) {
- return $string;
- } else {
- return $this->get_translation_string($num);
- }
- }
- }
-
- public function sanitize_plural_expression($expr)
- {
-
- $expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr);
-
- $expr .= ';';
- $res = '';
- $p = 0;
- for ($i = 0; $i < strlen($expr); $i++) {
- $ch = $expr[$i];
- switch ($ch) {
- case '?':
- $res .= ' ? (';
- $p++;
- break;
- case ':':
- $res .= ') : (';
- break;
- case ';':
- $res .= str_repeat(')', $p) . ';';
- $p = 0;
- break;
- default:
- $res .= $ch;
- }
- }
- return $res;
- }
-
- public function extract_plural_forms_header_from_po_header($header)
- {
- if (preg_match("/(^|\n)plural-forms: ([^\n]*)\n/i", $header, $regs)) {
- $expr = $regs[2];
- } else {
- $expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
- }
- return $expr;
- }
-
- public function get_plural_forms()
- {
-
-
- $this->load_tables();
-
- if (! is_string($this->pluralheader)) {
- if ($this->enable_cache) {
- $header = $this->cache_translations[""];
- } else {
- $header = $this->get_translation_string(0);
- }
- $expr = $this->extract_plural_forms_header_from_po_header($header);
- $this->pluralheader = $this->sanitize_plural_expression($expr);
- }
- return $this->pluralheader;
- }
-
- public function select_string($n)
- {
- if (!is_int($n)) {
- throw new InvalidArgumentException(
- "Select_string only accepts integers: " . $n
- );
- }
- $string = $this->get_plural_forms();
- $string = str_replace('nplurals', "\$total", $string);
- $string = str_replace("n", $n, $string);
- $string = str_replace('plural', "\$plural", $string);
- $total = 0;
- $plural = 0;
- eval("$string");
- if ($plural >= $total) {
- $plural = $total - 1;
- }
- return $plural;
- }
-
- public function ngettext($single, $plural, $number)
- {
- if ($this->short_circuit) {
- if ($number != 1) {
- return $plural;
- } else {
- return $single;
- }
- }
-
- $select = $this->select_string($number);
-
- $key = $single . chr(0) . $plural;
- if ($this->enable_cache) {
- if (! array_key_exists($key, $this->cache_translations)) {
- return ($number != 1) ? $plural : $single;
- } else {
- $result = $this->cache_translations[$key];
- $list = explode(chr(0), $result);
- return $list[$select];
- }
- } else {
- $num = $this->find_string($key);
- if ($num == -1) {
- return ($number != 1) ? $plural : $single;
- } else {
- $result = $this->get_translation_string($num);
- $list = explode(chr(0), $result);
- return $list[$select];
- }
- }
- }
- public function pgettext($context, $msgid)
- {
- $key = $context . chr(4) . $msgid;
- $ret = $this->translate($key);
- if (strpos($ret, "\004") !== false) {
- return $msgid;
- } else {
- return $ret;
- }
- }
- public function npgettext($context, $singular, $plural, $number)
- {
- $key = $context . chr(4) . $singular;
- $ret = $this->ngettext($key, $plural, $number);
- if (strpos($ret, "\004") !== false) {
- return $singular;
- } else {
- return $ret;
- }
- }
- }
|