Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

GetText.php

Go to the documentation of this file.
00001 <?php 00002 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 00003 // 00004 // Copyright (c) 2003 Laurent Bedubourg 00005 // 00006 // This library is free software; you can redistribute it and/or 00007 // modify it under the terms of the GNU Lesser General Public 00008 // License as published by the Free Software Foundation; either 00009 // version 2.1 of the License, or (at your option) any later version. 00010 // 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 // Lesser General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public 00017 // License along with this library; if not, write to the Free Software 00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 // 00020 // Authors: Laurent Bedubourg <laurent.bedubourg@free.fr> 00021 // 00022 00023 require_once "PEAR.php"; 00024 00025 define('GETTEXT_NATIVE', 1); 00026 define('GETTEXT_PHP', 2); 00027 00079 class GetText 00080 { 00088 function &_support($set=false) 00089 { 00090 static $supportObject; 00091 if ($set !== false) { 00092 $supportObject = $set; 00093 } elseif (!isset($supportObject)) { 00094 trigger_error("GetText not initialized !". endl. 00095 "Please call GetText::init() before calling ". 00096 "any GetText function !".endl 00097 , E_USER_ERROR); 00098 } 00099 return $supportObject; 00100 } 00101 00119 function init($managerType = GETTEXT_NATIVE) 00120 { 00121 if ($managerType == GETTEXT_NATIVE) { 00122 if (function_exists('gettext')) { 00123 return GetText::_support(new GetText_NativeSupport()); 00124 } 00125 } 00126 // fail back to php support 00127 return GetText::_support(new GetText_PHPSupport()); 00128 } 00129 00139 function setLanguage($langCode) 00140 { 00141 $support =& GetText::_support(); 00142 return $support->setLanguage($langCode); 00143 } 00144 00159 function addDomain($domain, $path=false) 00160 { 00161 $support =& GetText::_support(); 00162 return $support->addDomain($domain, $path); 00163 } 00164 00171 function gettext($key) 00172 { 00173 $support =& GetText::_support(); 00174 return $support->gettext($key); 00175 } 00176 00186 function setVar($key, $value) 00187 { 00188 $support =& GetText::_support(); 00189 return $support->setVar($key, $value); 00190 } 00191 00198 function setVars($hash) 00199 { 00200 $support =& GetText::_support(); 00201 return $support->setVars($hash); 00202 } 00203 00207 function reset() 00208 { 00209 $support =& GetText::_support(); 00210 return $support->reset(); 00211 } 00212 } 00213 00214 00221 class GetText_NativeSupport 00222 { 00223 var $_interpolationVars = array(); 00224 00229 function setLanguage($langCode) 00230 { 00231 putenv("LANG=$langCode"); 00232 putenv("LC_ALL=$langCode"); 00233 putenv("LANGUAGE=$langCode"); 00234 $set = setlocale(LC_ALL, "$langCode"); 00235 if ($set === false) { 00236 $str = sprintf('Language code "%s" not supported by your system', 00237 $langCode); 00238 $err = new GetText_Error($str); 00239 return PEAR::raiseError($err); 00240 } 00241 } 00242 00246 function addDomain($domain, $path=false) 00247 { 00248 if ($path === false) { 00249 bindtextdomain($domain, "./locale/"); 00250 } else { 00251 bindtextdomain($domain, $path); 00252 } 00253 textdomain($domain); 00254 } 00255 00261 function _getTranslation($key) 00262 { 00263 return gettext($key); 00264 } 00265 00266 00270 function reset() 00271 { 00272 $this->_interpolationVars = array(); 00273 } 00274 00278 function setVar($key, $value) 00279 { 00280 $this->_interpolationVars[$key] = $value; 00281 } 00282 00286 function setVars($hash) 00287 { 00288 $this->_interpolationVars = array_merge($this->_interpolationVars, 00289 $hash); 00290 } 00291 00298 function gettext($key) 00299 { 00300 $value = $this->_getTranslation($key); 00301 if ($value === false) { 00302 $str = sprintf('Unable to locate gettext key "%s"', $key); 00303 $err = new GetText_Error($str); 00304 return PEAR::raiseError($err); 00305 } 00306 00307 while (preg_match('/\$\{(.*?)\}/sm', $value, $m)) { 00308 list($src, $var) = $m; 00309 00310 // retrieve variable to interpolate in context, throw an exception 00311 // if not found. 00312 $varValue = $this->_getVar($var); 00313 if ($varValue === false) { 00314 $str = sprintf('Interpolation error, var "%s" not set', $var); 00315 $err = new GetText_Error($str); 00316 return PEAR::raiseError($err); 00317 } 00318 $value = str_replace($src, $varValue, $value); 00319 } 00320 return $value; 00321 } 00322 00329 function _getVar($name) 00330 { 00331 if (!array_key_exists($name, $this->_interpolationVars)) { 00332 return false; 00333 } 00334 return $this->_interpolationVars[$name]; 00335 } 00336 } 00337 00338 00348 class GetText_PHPSupport extends GetText_NativeSupport 00349 { 00350 var $_path = 'locale/'; 00351 var $_langCode = false; 00352 var $_domains = array(); 00353 var $_end = -1; 00354 var $_jobs = array(); 00355 00362 function setLanguage($langCode) 00363 { 00364 // if language already set, try to reload domains 00365 if ($this->_langCode !== false and $this->_langCode != $langCode) { 00366 foreach ($this->_domains as $domain) { 00367 $this->_jobs[] = array($domain->name, $domain->path); 00368 } 00369 $this->_domains = array(); 00370 $this->_end = -1; 00371 } 00372 00373 $this->_langCode = $langCode; 00374 00375 // this allow us to set the language code after 00376 // domain list. 00377 while (count($this->_jobs) > 0) { 00378 list($domain, $path) = array_shift($this->_jobs); 00379 $err = $this->addDomain($domain, $path); 00380 // error raised, break jobs 00381 if (PEAR::isError($err)) { 00382 return $err; 00383 } 00384 } 00385 } 00386 00394 function addDomain($domain, $path = "./locale/") 00395 { 00396 if (array_key_exists($domain, $this->_domains)) { 00397 return; 00398 } 00399 00400 if (!$this->_langCode) { 00401 $this->_jobs[] = array($domain, $path); 00402 return; 00403 } 00404 00405 $err = $this->_loadDomain($domain, $path); 00406 if (PEAR::isError($err)) { 00407 return $err; 00408 } 00409 00410 $this->_end++; 00411 } 00412 00424 function _loadDomain($domain, $path = "./locale") 00425 { 00426 $srcDomain = $path . "/$this->_langCode/LC_MESSAGES/$domain.po"; 00427 $phpDomain = $path . "/$this->_langCode/LC_MESSAGES/$domain.php"; 00428 00429 if (!file_exists($srcDomain)) { 00430 $str = sprintf('Domain file "%s" not found.', $srcDomain); 00431 $err = new GetText_Error($str); 00432 return PEAR::raiseError($err); 00433 } 00434 00435 $d = new GetText_Domain(); 00436 $d->name = $domain; 00437 $d->path = $path; 00438 00439 if (!file_exists($phpDomain) 00440 || (filemtime($phpDomain) < filemtime($srcDomain))) { 00441 00442 // parse and compile translation table 00443 $parser = new GetText_PHPSupport_Parser(); 00444 $hash = $parser->parse($srcDomain); 00445 if (!defined('GETTEXT_NO_CACHE')) { 00446 $comp = new GetText_PHPSupport_Compiler(); 00447 $err = $comp->compile($hash, $srcDomain); 00448 if (PEAR::isError($err)) { 00449 return $err; 00450 } 00451 } 00452 $d->_keys = $hash; 00453 } else { 00454 $d->_keys = include $phpDomain; 00455 } 00456 $this->_domains[] =& $d; 00457 } 00458 00462 function _getTranslation($key) 00463 { 00464 for ($i = $this->_end; $i >= 0; $i--) { 00465 if ($this->_domains[$i]->hasKey($key)) { 00466 return $this->_domains[$i]->get($key); 00467 } 00468 } 00469 return $key; 00470 } 00471 } 00472 00479 class GetText_Domain 00480 { 00481 var $name; 00482 var $path; 00483 00484 var $_keys = array(); 00485 00486 function hasKey($key) 00487 { 00488 return array_key_exists($key, $this->_keys); 00489 } 00490 00491 function get($key) 00492 { 00493 return $this->_keys[$key]; 00494 } 00495 } 00496 00503 class GetText_PHPSupport_Parser 00504 { 00505 var $_hash = array(); 00506 var $_currentKey; 00507 var $_currentValue; 00508 00515 function parse($file) 00516 { 00517 $this->_hash = array(); 00518 $this->_currentKey = false; 00519 $this->_currentValue = ""; 00520 00521 if (!file_exists($file)) { 00522 $str = sprintf('Unable to locate file "%s"', $file); 00523 $err = new GetText_Error($str); 00524 return PEAR::raiseError($err); 00525 } 00526 $i=0; 00527 $lines = file($file); 00528 foreach ($lines as $line) { 00529 $this->_parseLine($line, ++$i); 00530 } 00531 $this->_storeKey(); 00532 00533 return $this->_hash; 00534 } 00535 00541 function _parseLine($line, $nbr) 00542 { 00543 if (preg_match('/^\s*?#/', $line)) { return; } 00544 if (preg_match('/^\s*?msgid \"(.*?)(?!<\\\)\"/', $line, $m)) { 00545 $this->_storeKey(); 00546 $this->_currentKey = $m[1]; 00547 return; 00548 } 00549 if (preg_match('/^\s*?msgstr \"(.*?)(?!<\\\)\"/', $line, $m)) { 00550 $this->_currentValue .= $m[1]; 00551 return; 00552 } 00553 if (preg_match('/^\s*?\"(.*?)(?!<\\\)\"/', $line, $m)) { 00554 $this->_currentValue .= $m[1]; 00555 return; 00556 } 00557 } 00558 00564 function _storeKey() 00565 { 00566 if ($this->_currentKey === false) return; 00567 $this->_currentValue = str_replace('\\n', "\n", $this->_currentValue); 00568 $this->_hash[$this->_currentKey] = $this->_currentValue; 00569 $this->_currentKey = false; 00570 $this->_currentValue = ""; 00571 } 00572 } 00573 00574 00584 class GetText_PHPSupport_Compiler 00585 { 00589 function compile(&$hash, $sourcePath) 00590 { 00591 $destPath = preg_replace('/\.po$/', '.php', $sourcePath); 00592 $fp = @fopen($destPath, "w"); 00593 if (!$fp) { 00594 $str = sprintf('Unable to open "%s" in write mode.', $destPath); 00595 $err = new GetText_Error($str); 00596 return PEAR::raiseError($err); 00597 } 00598 fwrite($fp, '<?php' . "\n"); 00599 fwrite($fp, 'return array(' . "\n"); 00600 foreach ($hash as $key => $value) { 00601 $key = str_replace("'", "\\'", $key); 00602 $value = str_replace("'", "\\'", $value); 00603 fwrite($fp, ' \'' . $key . '\' => \'' . $value . "',\n"); 00604 } 00605 fwrite($fp, ');' . "\n"); 00606 fwrite($fp, '?>'); 00607 fclose($fp); 00608 } 00609 } 00610 00614 class GetText_Error extends PEAR_Error {} 00615 00616 ?>

Generated on Tue Jun 29 23:40:03 2004 for Mediawiki by doxygen 1.3.7