PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/ANS/Gettext/Gettext.php

https://github.com/eusonlito/Gettext
PHP | 340 lines | 241 code | 68 blank | 31 comment | 52 complexity | 7924add281604835be3b8c3185e54412 MD5 | raw file
  1. <?php
  2. /**
  3. * phpCan - http://idc.anavallasuiza.com/
  4. *
  5. * phpCan is released under the GNU Affero GPL version 3
  6. *
  7. * More information at license.txt
  8. *
  9. * Copyright (c) 2003 Danilo Segan <danilo@kvota.net>.
  10. * Copyright (c) 2005 Nico Kaiser <nico@siriux.net>
  11. * Copyright (c) 2010 A Navalla Suiza <idc@anavallasuiza.com>
  12. *
  13. * This file is part of PHP-gettext.
  14. *
  15. * PHP-gettext is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 2 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * PHP-gettext is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with PHP-gettext; if not, write to the Free Software
  27. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  28. */
  29. namespace ANS\Gettext;
  30. class Gettext
  31. {
  32. //public:
  33. public $error = 0; // public variable that holds error code (0 if no error)
  34. //private:
  35. private $BYTEORDER = 0; // 0: low endian, 1: big endian
  36. private $STREAM = NULL;
  37. private $originals = NULL; // offset of original table
  38. private $translations = NULL; // offset of translation table
  39. private $total = 0; // total string count
  40. private $table_originals = NULL; // table for original strings (offsets)
  41. private $table_translations = NULL; // table for translated strings (offsets)
  42. private $cache_translations = array(); // original -> translation mapping
  43. private $languages = array();
  44. private $language = '';
  45. private $default = '';
  46. private $path;
  47. private $files;
  48. private $loaded;
  49. private $cookie_key;
  50. private $Cookie;
  51. const MAGIC1 = -1794895138;
  52. const MAGIC2 = -569244523;
  53. const MAGIC3 = 2500072158;
  54. public function setCookie ($Cookie, $key)
  55. {
  56. $this->Cookie = $Cookie;
  57. $this->cookie_key = $key;
  58. }
  59. public function setPath ($path)
  60. {
  61. $path = preg_replace('#[/\\\]+#', '/', realpath($path).'/');
  62. if (!is_dir($path)) {
  63. throw new \Exception('Path '.$path.' doesn\'t exists');
  64. }
  65. $this->path = $path;
  66. }
  67. public function init ($files = false)
  68. {
  69. $this->loadLanguages($files);
  70. $this->setLanguage('', false);
  71. }
  72. public function loadLanguages ($files = false)
  73. {
  74. if ($this->languages) {
  75. return true;
  76. }
  77. $this->files = $files;
  78. if ($files) {
  79. foreach (glob($this->path.'/*.mo') as $language) {
  80. $this->languages[] = str_replace('.mo', '', strtolower(basename($language)));
  81. }
  82. } else {
  83. $languages = array();
  84. foreach (glob($this->path.'/*/*.mo') as $language) {
  85. $languages[] = strtolower(basename(dirname($language)));
  86. }
  87. $this->languages = array_unique($languages);
  88. }
  89. }
  90. public function getLanguages ()
  91. {
  92. return $this->languages;
  93. }
  94. public function setDefaultLanguage ($language)
  95. {
  96. $this->default = $language;
  97. }
  98. public function setLanguage ($language = '', $store = false)
  99. {
  100. if (!$language && !$this->language && !$this->default && !$this->Cookie) {
  101. return false;
  102. }
  103. $language = mb_strtolower($language);
  104. if ($this->language && ($language === $this->language)) {
  105. return $this->load();
  106. }
  107. if (!$language && $this->Cookie) {
  108. $cookie = $this->Cookie->get();
  109. if (isset($cookie[$this->cookie_key]) && $cookie[$this->cookie_key]) {
  110. $language = $cookie[$this->cookie_key];
  111. }
  112. }
  113. if (!$language && !$this->default) {
  114. return false;
  115. }
  116. $language = $language ?: $this->default;
  117. if (!in_array($language, $this->languages)) {
  118. return false;
  119. }
  120. $this->language = $language;
  121. $this->load();
  122. if ($this->Cookie && $store) {
  123. $this->Cookie->set(array($this->cookie_key => $this->language));
  124. }
  125. }
  126. public function getLanguage ()
  127. {
  128. return $this->language;
  129. }
  130. private function readInt ()
  131. {
  132. $read = $this->STREAM->read(4);
  133. if ($read === false) {
  134. return false;
  135. }
  136. if ($this->BYTEORDER == 0) {
  137. $read = unpack('V', $read); // low endian
  138. } else {
  139. $read = unpack('N', $read); // big endian
  140. }
  141. return array_shift($read);
  142. }
  143. private function readIntArray ($count)
  144. {
  145. if ($this->BYTEORDER == 0) {
  146. // low endian
  147. return unpack('V'.$count, $this->STREAM->read(4 * $count));
  148. } else {
  149. // big endian
  150. return unpack('N'.$count, $this->STREAM->read(4 * $count));
  151. }
  152. }
  153. public function load ()
  154. {
  155. if (!$this->language) {
  156. return false;
  157. } else if ($this->loaded === $this->language) {
  158. return true;
  159. }
  160. $this->cache_translations = array();
  161. if ($this->files) {
  162. $this->loadFile($this->path.$this->language.'.mo');
  163. } else {
  164. if (!is_dir($this->path.$this->language)) {
  165. return false;
  166. }
  167. foreach (glob($this->path.$this->language.'/*.mo') as $file) {
  168. $this->loadFile($file);
  169. }
  170. }
  171. }
  172. private function loadFile ($file)
  173. {
  174. if (!is_file($file)) {
  175. return false;
  176. }
  177. $Reader = new CachedFileReader($file);
  178. if (!$Reader || isset($Reader->error) ) {
  179. return false;
  180. }
  181. $this->STREAM = $Reader;
  182. $magic = $this->readInt();
  183. if (($magic == self::MAGIC1) || ($magic == self::MAGIC3)) { // to make sure it works for 64-bit platforms
  184. $this->BYTEORDER = 0;
  185. } elseif ($magic == (self::MAGIC2 & 0xFFFFFFFF)) {
  186. $this->BYTEORDER = 1;
  187. } else {
  188. $this->error = 1; // not MO file
  189. return false;
  190. }
  191. $this->loaded = $this->language;
  192. $this->readInt();
  193. $this->total = $this->readInt();
  194. $this->originals = $this->readInt();
  195. $this->translations = $this->readInt();
  196. $this->STREAM->seekto($this->originals);
  197. $this->table_originals = $this->readIntArray($this->total * 2);
  198. $this->STREAM->seekto($this->translations);
  199. $this->table_translations = $this->readIntArray($this->total * 2);
  200. for ($i = 0; $i < $this->total; $i++) {
  201. $this->STREAM->seekto($this->table_originals[$i * 2 + 2]);
  202. $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]);
  203. if ($original) {
  204. $this->STREAM->seekto($this->table_translations[$i * 2 + 2]);
  205. $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]);
  206. $this->cache_translations[$original] = $translation;
  207. }
  208. }
  209. unset($this->table_originals, $this->table_translations, $this->STREAM, $Reader);
  210. }
  211. public function translate ($string, $null = false)
  212. {
  213. if (isset($this->cache_translations[$string])) {
  214. return $this->cache_translations[$string];
  215. } else if ($null === true) {
  216. return null;
  217. } else {
  218. return $string;
  219. }
  220. }
  221. }
  222. class CachedFileReader
  223. {
  224. public $_pos;
  225. public $_str;
  226. public function __construct ($filename)
  227. {
  228. if (is_file($filename)) {
  229. $length = filesize($filename);
  230. $fd = fopen($filename,'rb');
  231. if (!$fd) {
  232. $this->error = 3; // Cannot read file, probably permissions
  233. return false;
  234. }
  235. $this->_str = fread($fd, $length);
  236. fclose($fd);
  237. } else {
  238. $this->error = 2; // File doesn't exist
  239. return false;
  240. }
  241. }
  242. public function StringReader ($str='')
  243. {
  244. $this->_str = $str;
  245. $this->_pos = 0;
  246. }
  247. public function read ($bytes)
  248. {
  249. $data = substr($this->_str, $this->_pos, $bytes);
  250. $this->_pos += $bytes;
  251. if (strlen($this->_str) < $this->_pos) {
  252. $this->_pos = strlen($this->_str);
  253. }
  254. return $data;
  255. }
  256. public function seekto ($pos)
  257. {
  258. $this->_pos = $pos;
  259. if (strlen($this->_str) < $this->_pos) {
  260. $this->_pos = strlen($this->_str);
  261. }
  262. return $this->_pos;
  263. }
  264. public function currentpos ()
  265. {
  266. return $this->_pos;
  267. }
  268. public function length ()
  269. {
  270. return strlen($this->_str);
  271. }
  272. }