| [ Index ] |
|
Code source de eZ Publish 3.9.0 |
1 <?php 2 // 3 // Definition of eZTSTranslator class 4 // 5 // Created on: <07-Jun-2002 12:40:42 amos> 6 // 7 // SOFTWARE NAME: eZ publish 8 // SOFTWARE RELEASE: 3.9.0 9 // BUILD VERSION: 17785 10 // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS 11 // SOFTWARE LICENSE: GNU General Public License v2.0 12 // NOTICE: > 13 // This program is free software; you can redistribute it and/or 14 // modify it under the terms of version 2.0 of the GNU General 15 // Public License as published by the Free Software Foundation. 16 // 17 // This program is distributed in the hope that it will be useful, 18 // but WITHOUT ANY WARRANTY; without even the implied warranty of 19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 // GNU General Public License for more details. 21 // 22 // You should have received a copy of version 2.0 of the GNU General 23 // Public License along with this program; if not, write to the Free 24 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 25 // MA 02110-1301, USA. 26 // 27 // 28 29 /*! \file eztstranslator.php 30 */ 31 32 /*! 33 \class eZTSTranslator eztstranslator.php 34 \ingroup eZTranslation 35 \brief This provides internationalization using XML (.ts) files 36 37 */ 38 39 include_once ( "lib/ezi18n/classes/eztranslatorhandler.php" ); 40 include_once ( "lib/ezi18n/classes/eztextcodec.php" ); 41 include_once ( "lib/ezi18n/classes/eztranslationcache.php" ); 42 43 class eZTSTranslator extends eZTranslatorHandler 44 { 45 /*! 46 Construct the translator and loads the translation file $file if it is set and exists. 47 */ 48 function eZTSTranslator( $locale, $filename = null, $useCache = true ) 49 { 50 $this->UseCache = $useCache; 51 if ( isset( $GLOBALS['eZSiteBasics'] ) ) 52 { 53 $siteBasics = $GLOBALS['eZSiteBasics']; 54 if ( isset( $siteBasics['no-cache-adviced'] ) && $siteBasics['no-cache-adviced'] ) 55 $this->UseCache = false; 56 } 57 $this->BuildCache = false; 58 $this->eZTranslatorHandler( true ); 59 60 $this->Locale = $locale; 61 $this->File = $filename; 62 $this->Messages = array(); 63 $this->CachedMessages = array(); 64 $this->HasRestoredCache = false; 65 $this->RootCache = false; 66 } 67 68 /*! 69 \static 70 Initialize the ts translator and context if this is not already done. 71 */ 72 function &initialize( $context, $locale, $filename, $useCache = true ) 73 { 74 $tables =& $GLOBALS["eZTSTranslationTables"]; 75 $instance = false; 76 $file = $locale . '/' . $filename; 77 if ( isset( $tables[$file] ) and 78 get_class( $tables[$file] ) == "eztstranslator" ) 79 $instance =& $tables[$file]; 80 if ( $instance and 81 $instance->hasInitializedContext( $context ) ) 82 return $instance; 83 eZDebug::createAccumulatorGroup( 'tstranslator', 'TS translator' ); 84 eZDebug::accumulatorStart( 'tstranslator_init', 'tstranslator', 'TS init' ); 85 if ( !$instance ) 86 { 87 $instance = new eZTSTranslator( $locale, $filename, $useCache ); 88 $tables[$file] =& $instance; 89 $manager =& eZTranslatorManager::instance(); 90 $manager->registerHandler( $instance ); 91 } 92 $instance->load( $context ); 93 eZDebug::accumulatorStop( 'tstranslator_init' ); 94 return $instance; 95 } 96 97 /*! 98 \return true if the context \a $context is already initialized. 99 */ 100 function hasInitializedContext( $context ) 101 { 102 return isset( $this->CachedMessages[$context] ); 103 } 104 105 /*! 106 Tries to load the context \a $requestedContext for the translation and returns true if was successful. 107 */ 108 function load( $requestedContext ) 109 { 110 return $this->loadTranslationFile( $this->Locale, $this->File, $requestedContext ); 111 } 112 113 /*! 114 \private 115 */ 116 function loadTranslationFile( $locale, $filename, $requestedContext ) 117 { 118 include_once ( 'lib/ezfile/classes/ezdir.php' ); 119 120 // First try for current charset 121 $charset = eZTextCodec::internalCharset(); 122 $tsTimeStamp = false; 123 124 if ( !$this->RootCache ) 125 { 126 $ini =& eZINI::instance(); 127 $roots = array( $ini->variable( 'RegionalSettings', 'TranslationRepository' ) ); 128 $extensionBase = eZExtension::baseDirectory(); 129 $translationExtensions = $ini->variable( 'RegionalSettings', 'TranslationExtensions' ); 130 foreach ( $translationExtensions as $translationExtension ) 131 { 132 $extensionPath = $extensionBase . '/' . $translationExtension . '/translations'; 133 if ( file_exists( $extensionPath ) ) 134 { 135 $roots[] = $extensionPath; 136 } 137 } 138 $this->RootCache = array( 'roots' => $roots ); 139 } 140 else 141 { 142 $roots = $this->RootCache['roots']; 143 if ( isset( $this->RootCache['timestamp'] ) ) 144 $tsTimeStamp = $this->RootCache['timestamp']; 145 } 146 147 // Load cached translations if possible 148 if ( $this->UseCache == true ) 149 { 150 if ( !$tsTimeStamp ) 151 { 152 foreach ( $roots as $root ) 153 { 154 $path = eZDir::path( array( $root, $locale, $charset, $filename ) ); 155 if ( file_exists( $path ) ) 156 { 157 $timestamp = filemtime( $path ); 158 if ( $timestamp > $tsTimeStamp ) 159 $tsTimeStamp = $timestamp; 160 } 161 else 162 { 163 $path = eZDir::path( array( $root, $locale, $filename ) ); 164 if ( file_exists( $path ) ) 165 { 166 $timestamp = filemtime( $path ); 167 if ( $timestamp > $tsTimeStamp ) 168 $tsTimeStamp = $timestamp; 169 } 170 } 171 } 172 $this->RootCache['timestamp'] = $tsTimeStamp; 173 } 174 $key = 'cachecontexts'; 175 if ( $this->HasRestoredCache or 176 eZTranslationCache::canRestoreCache( $key, $tsTimeStamp ) ) 177 { 178 eZDebug::accumulatorStart( 'tstranslator_cache_load', 'tstranslator', 'TS cache load' ); 179 if ( !$this->HasRestoredCache ) 180 { 181 if ( !eZTranslationCache::restoreCache( $key ) ) 182 { 183 $this->BuildCache = true; 184 } 185 $contexts = eZTranslationCache::contextCache( $key ); 186 if ( !is_array( $contexts ) ) 187 $contexts = array(); 188 $this->HasRestoredCache = $contexts; 189 } 190 else 191 $contexts = $this->HasRestoredCache; 192 if ( !$this->BuildCache ) 193 { 194 $contextName = $requestedContext; 195 if ( !isset( $this->CachedMessages[$contextName] ) ) 196 { 197 eZDebug::accumulatorStart( 'tstranslator_context_load', 'tstranslator', 'TS context load' ); 198 if ( eZTranslationCache::canRestoreCache( $contextName, $tsTimeStamp ) ) 199 { 200 if ( !eZTranslationCache::restoreCache( $contextName ) ) 201 { 202 $this->BuildCache = true; 203 } 204 $this->CachedMessages[$contextName] = 205 eZTranslationCache::contextCache( $contextName ); 206 207 foreach ( $this->CachedMessages[$contextName] as $key => $msg ) 208 { 209 $this->Messages[$key] = $msg; 210 } 211 } 212 eZDebug::accumulatorStop( 'tstranslator_context_load' ); 213 } 214 } 215 eZDebugSetting::writeNotice( 'i18n-tstranslator', "Loading cached translation", "eZTSTranslator::loadTranslationFile" ); 216 eZDebug::accumulatorStop( 'tstranslator_cache_load' ); 217 if ( !$this->BuildCache ) 218 { 219 return true; 220 } 221 } 222 eZDebugSetting::writeNotice( 'i18n-tstranslator', 223 "Translation cache has expired. Will rebuild it from source.", 224 "eZTSTranslator::loadTranslationFile" ); 225 $this->BuildCache = true; 226 } 227 228 $status = false; 229 foreach ( $roots as $root ) 230 { 231 $path = eZDir::path( array( $root, $locale, $charset, $filename ) ); 232 if ( !file_exists( $path ) ) 233 { 234 $path = eZDir::path( array( $root, $locale, $filename ) ); 235 236 $ini =& eZINI::instance( "i18n.ini" ); 237 $fallbacks = $ini->variable( 'TranslationSettings', 'FallbackLanguages' ); 238 239 if ( array_key_exists( $locale, $fallbacks ) and $fallbacks[$locale] ) 240 { 241 $fallbackpath = eZDir::path( array( $root, $fallbacks[$locale], $filename ) ); 242 if ( !file_exists( $path ) and file_exists( $fallbackpath ) ) 243 $path = $fallbackpath; 244 } 245 246 if ( !file_exists( $path ) ) 247 { 248 eZDebug::writeError( "Could not load translation file: $path", "eZTSTranslator::loadTranslationFile" ); 249 continue; 250 } 251 } 252 253 eZDebug::accumulatorStart( 'tstranslator_load', 'tstranslator', 'TS load' ); 254 $fd = fopen( $path, "rb" ); 255 $trans_xml = fread( $fd, filesize( $path ) ); 256 fclose( $fd ); 257 258 include_once ( "lib/ezxml/classes/ezxml.php" ); 259 $xml = new eZXML(); 260 261 $tree =& $xml->domTree( $trans_xml, array(), true ); 262 263 if ( !$this->validateDOMTree( $tree ) ) 264 { 265 eZDebug::writeWarning( "XML text for file $path did not validate", 'eZTSTranslator::loadTranslationFile' ); 266 continue; 267 } 268 $status = true; 269 270 $treeRoot = $tree->get_root(); 271 $children = $treeRoot->children(); 272 foreach( $children as $child ) 273 { 274 if ( $child->type == 1 ) 275 { 276 if ( $child->name() == "context" ) 277 { 278 $this->handleContextNode( $child ); 279 } 280 else 281 eZDebug::writeError( "Unknown element name: " . $child->name(), 282 "eZTSTranslator::loadTranslationFile" ); 283 } 284 } 285 eZDebug::accumulatorStop( 'tstranslator_load' ); 286 } 287 288 // Save translation cache 289 if ( $this->UseCache == true && $this->BuildCache == true ) 290 { 291 eZDebug::accumulatorStart( 'tstranslator_store_cache', 'tstranslator', 'TS store cache' ); 292 if ( eZTranslationCache::contextCache( 'cachecontexts' ) == null ) 293 { 294 $contexts = array_keys( $this->CachedMessages ); 295 eZTranslationCache::setContextCache( 'cachecontexts', 296 $contexts ); 297 eZTranslationCache::storeCache( 'cachecontexts' ); 298 $this->HasRestoredCache = $contexts; 299 } 300 301 foreach ( $this->CachedMessages as $contextName => $context ) 302 { 303 if ( eZTranslationCache::contextCache( $contextName ) == null ) 304 eZTranslationCache::setContextCache( $contextName, $context ); 305 eZTranslationCache::storeCache( $contextName ); 306 } 307 $this->BuildCache = false; 308 eZDebug::accumulatorStop( 'tstranslator_store_cache' ); 309 } 310 311 return $status; 312 } 313 314 /*! 315 \static 316 Validates the DOM tree \a $tree and returns true if it is correct. 317 \warning There's no validation done yet. It checks if \a $tree is object only. 318 In all other cases it returns \c true for all DOM trees. 319 */ 320 function validateDOMTree( &$tree ) 321 { 322 if ( !is_object( $tree ) ) 323 return false; 324 325 return true; 326 /* $xmlSchema = '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 327 xmlns="http://www.w3.org/2001/XMLSchema/default"> 328 329 <xsd:annotation> 330 <xsd:documentation xml:lang="en"> 331 Translation message schema for ez.no. 332 Copyright 2002 ez.no. All rights reserved. 333 </xsd:documentation> 334 </xsd:annotation> 335 336 <xsd:element name="TS" type="TranslateRootType"/> 337 338 <xsd:complexType name="TranslateRootType"> 339 <xsd:sequence> 340 <xsd:element name="context" type="ContextType"/> 341 </xsd:sequence> 342 </xsd:complexType> 343 344 <xsd:complexType name="ContextType"> 345 <xsd:sequence> 346 <xsd:element name="name" type="xsd:string" /> 347 <xsd:element name="message" type="MessageType"/> 348 </xsd:sequence> 349 </xsd:complexType> 350 351 <xsd:complexType name="MessageType"> 352 <xsd:sequence> 353 <xsd:element name="source" type="xsd:string"/> 354 <xsd:element name="translation" type="TranslationType"/> 355 <xsd:element name="comment" type="xsd:string" minOccurs="0" maxOccurs="1"/> 356 </xsd:sequence> 357 </xsd:complexType> 358 359 <xsd:simpleType name="TranslationType"> 360 <xsd:restriction base="xsd:string"> 361 </xsd:restriction> 362 <xsd:attribute name="type" type="xsd:string" /> 363 </xsd:simpleType> 364 365 </xsd:schema>'; 366 367 include_once( "lib/ezxml/classes/ezschema.php" ); 368 369 $schema = new eZSchema( ); 370 $schema->setSchema( $xmlSchema ); 371 372 return $schema->validate( $tree );*/ 373 } 374 375 function handleContextNode( $context ) 376 { 377 $contextName = null; 378 $messages = array(); 379 $context_children = $context->children(); 380 381 foreach( $context_children as $context_child ) 382 { 383 if ( $context_child->type == 1 ) 384 { 385 if ( $context_child->name() == "name" ) 386 { 387 $name_el = $context_child->children(); 388 if ( count( $name_el ) > 0 ) 389 { 390 $name_el = $name_el[0]; 391 $contextName = $name_el->content; 392 } 393 } 394 break; 395 } 396 } 397 if ( !$contextName ) 398 { 399 eZDebug::writeError( "No context name found, skipping context", 400 "eZTSTranslator::handleContextNode" ); 401 return false; 402 } 403 foreach( $context_children as $context_child ) 404 { 405 if ( $context_child->type == 1 ) 406 { 407 $childName = $context_child->name(); 408 if ( $childName == "message" ) 409 { 410 $this->handleMessageNode( $contextName, $context_child ); 411 } 412 else if ( $childName == "name" ) 413 { 414 /* Skip name tags */ 415 } 416 else 417 { 418 eZDebug::writeError( "Unknown element name: $childName", 419 "eZTSTranslator::handleContextNode" ); 420 } 421 } 422 } 423 if ( $contextName === null ) 424 { 425 eZDebug::writeError( "No context name found, skipping context", 426 "eZTSTranslator::handleContextNode" ); 427 return false; 428 } 429 if ( !isset( $this->CachedMessages[$contextName] ) ) 430 $this->CachedMessages[$contextName] = array(); 431 432 return true; 433 } 434 435 function handleMessageNode( $contextName, &$message ) 436 { 437 $source = null; 438 $translation = null; 439 $comment = null; 440 $message_children = $message->children(); 441 foreach( $message_children as $message_child ) 442 { 443 if ( $message_child->type == 1 ) 444 { 445 if ( $message_child->name() == "source" ) 446 { 447 $source_el = $message_child->children(); 448 $source_el = $source_el[0]; 449 $source = $source_el->content; 450 } 451 else if ( $message_child->name() == "translation" ) 452 { 453 $translation_el = $message_child->children(); 454 if ( count( $translation_el ) > 0 ) 455 { 456 $translation_el = $translation_el[0]; 457 $translation = $translation_el->content; 458 } 459 } 460 else if ( $message_child->name() == "comment" ) 461 { 462 $comment_el = $message_child->children(); 463 $comment_el = $comment_el[0]; 464 $comment = $comment_el->content; 465 } 466 else 467 eZDebug::writeError( "Unknown element name: " . $message_child->name(), 468 "eZTSTranslator::handleMessageNode" ); 469 } 470 } 471 if ( $source === null ) 472 { 473 eZDebug::writeError( "No source name found, skipping message", 474 "eZTSTranslator::handleMessageNode" ); 475 return false; 476 } 477 if ( $translation === null ) 478 { 479 // eZDebug::writeError( "No translation, skipping message", "eZTSTranslator::messageNode" ); 480 return false; 481 } 482 /* we need to convert ourselves if we're using libxml stuff here */ 483 if ( get_class( $message ) == 'domelement' ) 484 { 485 $codec =& eZTextCodec::instance( "utf8" ); 486 $source = $codec->convertString( $source ); 487 $translation = $codec->convertString( $translation ); 488 $comment = $codec->convertString( $comment ); 489 } 490 491 $this->insert( $contextName, $source, $translation, $comment ); 492 return true; 493 } 494 495 /*! 496 \reimp 497 */ 498 function findKey( $key ) 499 { 500 $msg = null; 501 if ( isset( $this->Messages[$key] ) ) 502 { 503 $msg = $this->Messages[$key]; 504 } 505 return $msg; 506 } 507 508 /*! 509 \reimp 510 */ 511 function findMessage( $context, $source, $comment = null ) 512 { 513 // First try with comment, 514 $man = eZTranslatorManager::instance(); 515 $key = $man->createKey( $context, $source, $comment ); 516 517 if ( !isset( $this->Messages[$key] ) ) 518 { 519 // then try without comment for general translation 520 $key = $man->createKey( $context, $source ); 521 } 522 523 return $this->findKey( $key ); 524 } 525 526 /*! 527 \reimp 528 */ 529 function keyTranslate( $key ) 530 { 531 $msg = $this->findKey( $key ); 532 if ( $msg !== null ) 533 return $msg["translation"]; 534 else 535 { 536 return null; 537 } 538 } 539 540 /*! 541 \reimp 542 */ 543 function translate( $context, $source, $comment = null ) 544 { 545 $msg = $this->findMessage( $context, $source, $comment ); 546 if ( $msg !== null ) 547 { 548 return $msg["translation"]; 549 } 550 551 return null; 552 } 553 554 /*! 555 Inserts the \a $translation for the \a $context and \a $source as a translation message 556 and returns the key for the message. If $comment is non-null it will be included in the message. 557 558 If the translation message exists no new message is created and the existing key is returned. 559 */ 560 function insert( $context, $source, $translation, $comment = null ) 561 { 562 // eZDebug::writeDebug( "context=$context" ); 563 if ( $context == "" ) 564 $context = "default"; 565 $man =& eZTranslatorManager::instance(); 566 $key = $man->createKey( $context, $source, $comment ); 567 // if ( isset( $this->Messages[$key] ) ) 568 // return $key; 569 $msg = $man->createMessage( $context, $source, $comment, $translation ); 570 $msg["key"] = $key; 571 $this->Messages[$key] = $msg; 572 // Set array of messages to be cached 573 if ( $this->UseCache == true && $this->BuildCache == true ) 574 { 575 if ( !isset( $this->CachedMessages[$context] ) ) 576 $this->CachedMessages[$context] = array(); 577 $this->CachedMessages[$context][$key] = $msg; 578 } 579 return $key; 580 } 581 582 /*! 583 Removes the translation message with \a $context and \a $source. 584 Returns true if the message was removed, false otherwise. 585 586 If you have the translation key use removeKey() instead. 587 */ 588 function remove( $context, $source, $message = null ) 589 { 590 if ( $context == "" ) 591 $context = "default"; 592 $man =& eZTranslatorManager::instance(); 593 $key = $man->createKey( $context, $source, $message ); 594 if ( isset( $this->Messages[$key] ) ) 595 unset( $this->Messages[$key] ); 596 } 597 598 /*! 599 Removes the translation message with \a $key. 600 Returns true if the message was removed, false otherwise. 601 */ 602 function removeKey( $key ) 603 { 604 if ( isset( $this->Messages[$key] ) ) 605 unset( $this->Messages[$key] ); 606 } 607 608 /// \privatesection 609 /// Contains the hash table with message translations 610 var $Messages; 611 var $File; 612 var $UseCache; 613 var $BuildCache; 614 var $CachedMessages; 615 } 616 617 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sat Feb 24 10:30:04 2007 | par Balluche grâce à PHPXref 0.7 |