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