[ Index ] |
|
Code source de PRADO 3.0.6 |
1 <?php 2 3 /** 4 * MessageSource_gettext class file. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the BSD License. 8 * 9 * Copyright(c) 2004 by Qiang Xue. All rights reserved. 10 * 11 * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue} 12 * The latest version of PRADO can be obtained from: 13 * {@link http://prado.sourceforge.net/} 14 * 15 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> 16 * @version $Revision: 1.7 $ $Date: 2005/12/17 06:11:28 $ 17 * @package System.I18N.core 18 */ 19 20 /** 21 * Get the MessageSource class file. 22 */ 23 require_once(dirname(__FILE__).'/MessageSource.php'); 24 25 /** 26 * Get the Gettext class. 27 */ 28 require_once(dirname(__FILE__).'/Gettext/TGettext.php'); 29 30 /** 31 * MessageSource_gettext class. 32 * 33 * Using Gettext MO format as the message source for translation. 34 * The gettext classes are based on PEAR's gettext MO and PO classes. 35 * 36 * See the MessageSource::factory() method to instantiate this class. 37 * 38 * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com> 39 * @version v1.0, last update on Fri Dec 24 16:18:44 EST 2004 40 * @package System.I18N.core 41 */ 42 class MessageSource_gettext extends MessageSource 43 { 44 /** 45 * Message data filename extension. 46 * @var string 47 */ 48 protected $dataExt = '.mo'; 49 50 /** 51 * PO data filename extension 52 * @var string 53 */ 54 protected $poExt = '.po'; 55 56 /** 57 * Separator between culture name and source. 58 * @var string 59 */ 60 protected $dataSeparator = '.'; 61 62 function __construct($source) 63 { 64 $this->source = (string)$source; 65 } 66 67 68 /** 69 * Load the messages from a MO file. 70 * @param string MO file. 71 * @return array of messages. 72 */ 73 protected function &loadData($filename) 74 { 75 $mo = TGettext::factory('MO',$filename); 76 $mo->load(); 77 $result = $mo->toArray(); 78 79 $results = array(); 80 $count=0; 81 foreach($result['strings'] as $source => $target) 82 { 83 $results[$source][] = $target; //target 84 $results[$source][] = $count++; //id 85 $results[$source][] = ''; //comments 86 } 87 return $results; 88 } 89 90 /** 91 * Determin if the MO file source is valid. 92 * @param string MO file 93 * @return boolean true if valid, false otherwise. 94 */ 95 protected function isValidSource($filename) 96 { 97 return is_file($filename); 98 } 99 100 /** 101 * Get the MO file for a specific message catalogue and cultural 102 * vairant. 103 * @param string message catalogue 104 * @return string full path to the MO file. 105 */ 106 protected function getSource($variant) 107 { 108 return $this->source.'/'.$variant; 109 } 110 111 /** 112 * Get the last modified unix-time for this particular catalogue+variant. 113 * Just use the file modified time. 114 * @param string catalogue+variant 115 * @return int last modified in unix-time format. 116 */ 117 protected function getLastModified($source) 118 { 119 if(is_file($source)) 120 return filemtime($source); 121 else 122 return 0; 123 } 124 125 /** 126 * Get all the variants of a particular catalogue. 127 * @param string catalogue name 128 * @return array list of all variants for this catalogue. 129 */ 130 protected function getCatalogueList($catalogue) 131 { 132 $variants = explode('_',$this->culture); 133 $source = $catalogue.$this->dataExt; 134 135 $catalogues = array($source); 136 137 $variant = null; 138 139 for($i = 0, $k = count($variants); $i < $k; ++$i) 140 { 141 if(isset($variants[$i]{0})) 142 { 143 $variant .= ($variant)?'_'.$variants[$i]:$variants[$i]; 144 $catalogues[] = $catalogue.$this->dataSeparator. 145 $variant.$this->dataExt; 146 } 147 } 148 $byDir = $this->getCatalogueByDir($catalogue); 149 $catalogues = array_merge($byDir,array_reverse($catalogues)); 150 return $catalogues; 151 } 152 153 154 /** 155 * Traverse through the directory structure to find the catalogues. 156 * This should only be called by getCatalogueList() 157 * @param string a particular catalogue. 158 * @return array a list of catalogues. 159 * @see getCatalogueList() 160 */ 161 private function getCatalogueByDir($catalogue) 162 { 163 $variants = explode('_',$this->culture); 164 $catalogues = array(); 165 166 $variant = null; 167 168 for($i = 0, $k = count($variants); $i < $k; ++$i) 169 { 170 if(isset($variants[$i]{0})) 171 { 172 $variant .= ($variant)?'_'.$variants[$i]:$variants[$i]; 173 $catalogues[] = $variant.'/'.$catalogue.$this->dataExt; 174 } 175 } 176 return array_reverse($catalogues); 177 } 178 179 /** 180 * Get the variant for a catalogue depending on the current culture. 181 * @param string catalogue 182 * @return string the variant. 183 * @see save() 184 * @see update() 185 * @see delete() 186 */ 187 private function getVariants($catalogue='messages') 188 { 189 if(is_null($catalogue)) 190 $catalogue = 'messages'; 191 192 foreach($this->getCatalogueList($catalogue) as $variant) 193 { 194 $file = $this->getSource($variant); 195 $po = $this->getPOFile($file); 196 if(is_file($file) || is_file($po)) 197 return array($variant, $file, $po); 198 } 199 return false; 200 } 201 202 private function getPOFile($MOFile) 203 { 204 $filebase = substr($MOFile, 0, strlen($MOFile)-strlen($this->dataExt)); 205 return $filebase.$this->poExt; 206 } 207 208 /** 209 * Save the list of untranslated blocks to the translation source. 210 * If the translation was not found, you should add those 211 * strings to the translation source via the <b>append()</b> method. 212 * @param string the catalogue to add to 213 * @return boolean true if saved successfuly, false otherwise. 214 */ 215 function save($catalogue='messages') 216 { 217 $messages = $this->untranslated; 218 219 if(count($messages) <= 0) return false; 220 221 $variants = $this->getVariants($catalogue); 222 223 if($variants) 224 list($variant, $MOFile, $POFile) = $variants; 225 else 226 list($variant, $MOFile, $POFile) = $this->createMessageTemplate($catalogue); 227 228 if(is_writable($MOFile) == false) 229 throw new TIOException("Unable to save to file {$MOFile}, file must be writable."); 230 if(is_writable($POFile) == false) 231 throw new TIOException("Unable to save to file {$POFile}, file must be writable."); 232 233 //set the strings as untranslated. 234 $strings = array(); 235 foreach($messages as $message) 236 $strings[$message] = ''; 237 238 //load the PO 239 $po = TGettext::factory('PO',$POFile); 240 $po->load(); 241 $result = $po->toArray(); 242 243 $existing = count($result['strings']); 244 245 //add to strings to the existing message list 246 $result['strings'] = array_merge($result['strings'],$strings); 247 248 $new = count($result['strings']); 249 250 if($new > $existing) 251 { 252 //change the date 2004-12-25 12:26 253 $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s'); 254 255 $po->fromArray($result); 256 $mo = $po->toMO(); 257 if($po->save() && $mo->save($MOFile)) 258 { 259 if(!empty($this->cache)) 260 $this->cache->clean($variant, $this->culture); 261 return true; 262 } 263 else 264 return false; 265 } 266 return false; 267 } 268 269 /** 270 * Delete a particular message from the specified catalogue. 271 * @param string the source message to delete. 272 * @param string the catalogue to delete from. 273 * @return boolean true if deleted, false otherwise. 274 */ 275 function delete($message, $catalogue='messages') 276 { 277 $variants = $this->getVariants($catalogue); 278 if($variants) 279 list($variant, $MOFile, $POFile) = $variants; 280 else 281 return false; 282 283 if(is_writable($MOFile) == false) 284 throw new TIOException("Unable to modify file {$MOFile}, file must be writable."); 285 if(is_writable($POFile) == false) 286 throw new TIOException("Unable to modify file {$POFile}, file must be writable."); 287 288 $po = TGettext::factory('PO',$POFile); 289 $po->load(); 290 $result = $po->toArray(); 291 292 foreach($result['strings'] as $string => $value) 293 { 294 if($string == $message) 295 { 296 $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s'); 297 unset($result['strings'][$string]); 298 299 $po->fromArray($result); 300 $mo = $po->toMO(); 301 if($po->save() && $mo->save($MOFile)) 302 { 303 if(!empty($this->cache)) 304 $this->cache->clean($variant, $this->culture); 305 return true; 306 } 307 else 308 return false; 309 } 310 } 311 312 return false; 313 } 314 315 /** 316 * Update the translation. 317 * @param string the source string. 318 * @param string the new translation string. 319 * @param string comments 320 * @param string the catalogue of the translation. 321 * @return boolean true if translation was updated, false otherwise. 322 */ 323 function update($text, $target, $comments, $catalogue='messages') 324 { 325 $variants = $this->getVariants($catalogue); 326 if($variants) 327 list($variant, $MOFile, $POFile) = $variants; 328 else 329 return false; 330 331 if(is_writable($MOFile) == false) 332 throw new TIOException("Unable to update file {$MOFile}, file must be writable."); 333 if(is_writable($POFile) == false) 334 throw new TIOException("Unable to update file {$POFile}, file must be writable."); 335 336 337 $po = TGettext::factory('PO',$POFile); 338 $po->load(); 339 $result = $po->toArray(); 340 341 foreach($result['strings'] as $string => $value) 342 { 343 if($string == $text) 344 { 345 $result['strings'][$string] = $target; 346 $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s'); 347 348 $po->fromArray($result); 349 $mo = $po->toMO(); 350 351 if($po->save() && $mo->save($MOFile)) 352 { 353 if(!empty($this->cache)) 354 $this->cache->clean($variant, $this->culture); 355 return true; 356 } 357 else 358 return false; 359 } 360 } 361 362 return false; 363 } 364 365 366 /** 367 * Returns a list of catalogue as key and all it variants as value. 368 * @return array list of catalogues 369 */ 370 function catalogues() 371 { 372 return $this->getCatalogues(); 373 } 374 375 /** 376 * Returns a list of catalogue and its culture ID. This takes care 377 * of directory structures. 378 * E.g. array('messages','en_AU') 379 * @return array list of catalogues 380 */ 381 protected function getCatalogues($dir=null,$variant=null) 382 { 383 $dir = $dir?$dir:$this->source; 384 $files = scandir($dir); 385 386 $catalogue = array(); 387 388 foreach($files as $file) 389 { 390 if(is_dir($dir.'/'.$file) 391 && preg_match('/^[a-z]{2}(_[A-Z]{2,3})?$/',$file)) 392 { 393 394 $catalogue = array_merge($catalogue, 395 $this->getCatalogues($dir.'/'.$file, $file)); 396 } 397 398 $pos = strpos($file,$this->dataExt); 399 400 if($pos >0 401 && substr($file,-1*strlen($this->dataExt)) == $this->dataExt) 402 { 403 $name = substr($file,0,$pos); 404 $dot = strrpos($name,$this->dataSeparator); 405 $culture = $variant; 406 $cat = $name; 407 if(is_int($dot)) 408 { 409 $culture = substr($name, $dot+1,strlen($name)); 410 $cat = substr($name,0,$dot); 411 } 412 $details[0] = $cat; 413 $details[1] = $culture; 414 415 416 $catalogue[] = $details; 417 } 418 } 419 sort($catalogue); 420 421 return $catalogue; 422 } 423 424 protected function createMessageTemplate($catalogue) 425 { 426 if(is_null($catalogue)) 427 $catalogue = 'messages'; 428 $variants = $this->getCatalogueList($catalogue); 429 $variant = array_shift($variants); 430 $mo_file = $this->getSource($variant); 431 $po_file = $this->getPOFile($mo_file); 432 433 $dir = dirname($mo_file); 434 if(!is_dir($dir)) 435 { 436 @mkdir($dir); 437 @chmod($dir,0777); 438 } 439 if(!is_dir($dir)) 440 throw new TException("Unable to create directory $dir"); 441 442 $po = TGettext::factory('PO',$po_file); 443 $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s'); 444 $result['strings'] = array(); 445 446 $po->fromArray($result); 447 $mo = $po->toMO(); 448 if($po->save() && $mo->save($mo_file)) 449 return array($variant, $mo_file, $po_file); 450 else 451 throw TException("Unable to create file $po_file and $mo_file"); 452 } 453 } 454 455 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 21:07:04 2007 | par Balluche grâce à PHPXref 0.7 |