00001 <?php
00002
00006 class oxLang extends oxSuperCfg
00007 {
00013 private static $_instance = null;
00014
00020 protected $_sName = 'lang';
00021
00027 protected $_iBaseLanguageId = null;
00028
00034 protected $_iTplLanguageId = null;
00035
00041 protected $_iEditLanguageId = null;
00042
00048 protected $_aLangCache = array();
00049
00055 protected $_aAdminLangCache = array();
00056
00062 protected $_aAdminTplLanguageArray = null;
00063
00069 protected $_aLangAbbr = null;
00070
00076 public static function getInstance()
00077 {
00078 if ( defined('OXID_PHP_UNIT')) {
00079 if ( ($oClassMod = modInstances::getMod(__CLASS__)) && is_object($oClassMod) ) {
00080 return $oClassMod;
00081 } else {
00082 $inst = oxNew( 'oxLang' );
00083 modInstances::addMod( __CLASS__, $inst );
00084 return $inst;
00085 }
00086 }
00087
00088 if ( !self::$_instance instanceof oxLang ) {
00089
00090 self::$_instance = oxNew( 'oxLang');
00091 }
00092 return self::$_instance;
00093 }
00094
00101 public function resetBaseLanguage()
00102 {
00103 $this->_iBaseLanguageId = null;
00104 }
00105
00111 public function getBaseLanguage()
00112 {
00113 if ( $this->_iBaseLanguageId === null ) {
00114 $myConfig = $this->getConfig();
00115 $blAdmin = $this->isAdmin();
00116
00117
00118 if ( $blAdmin && ( ( $iSeLang = oxConfig::getParameter( 'changelang' ) ) !== null ) ) {
00119 $this->_iBaseLanguageId = $iSeLang;
00120 }
00121
00122 if ( is_null( $this->_iBaseLanguageId ) ) {
00123 $this->_iBaseLanguageId = oxConfig::getParameter( 'lang' );
00124 }
00125
00126
00127 $aLanguageUrls = $myConfig->getConfigParam( 'aLanguageURLs' );
00128
00129 if ( !$blAdmin && is_array( $aLanguageUrls ) ) {
00130 foreach ( $aLanguageUrls as $iId => $sUrl ) {
00131 if ( $myConfig->isCurrentUrl( $sUrl ) ) {
00132 $this->_iBaseLanguageId = $iId;
00133 break;
00134 }
00135 }
00136 }
00137
00138 if ( is_null( $this->_iBaseLanguageId ) ) {
00139 $this->_iBaseLanguageId = oxConfig::getParameter( 'language' );
00140 }
00141
00142
00143
00144 if ( is_null( $this->_iBaseLanguageId ) && !$blAdmin && !oxUtils::getInstance()->isSearchEngine() ) {
00145
00146
00147 $this->_iBaseLanguageId = oxUtilsServer::getInstance()->getOxCookie( 'language' );
00148
00149
00150 if ( is_null( $this->_iBaseLanguageId ) ) {
00151 $this->_iBaseLanguageId = $this->detectLanguageByBrowser();
00152 }
00153 }
00154
00155 if ( is_null( $this->_iBaseLanguageId ) ) {
00156 $this->_iBaseLanguageId = $myConfig->getConfigParam( 'sDefaultLang' );
00157 }
00158
00159 $this->_iBaseLanguageId = (int) $this->_iBaseLanguageId;
00160
00161
00162 $this->_iBaseLanguageId = $this->validateLanguage( $this->_iBaseLanguageId );
00163
00164
00165 oxUtilsServer::getInstance()->setOxCookie( 'language', $this->_iBaseLanguageId );
00166 }
00167 return $this->_iBaseLanguageId;
00168 }
00169
00175 public function getObjectTplLanguage()
00176 {
00177 if ( $this->_iObjectTplLanguageId === null ) {
00178 $this->_iObjectTplLanguageId = $this->getTplLanguage();
00179 $aLanguages = $this->getAdminTplLanguageArray();
00180 if ( !isset( $aLanguages[$this->_iObjectTplLanguageId] ) ||
00181 $aLanguages[$this->_iObjectTplLanguageId]->active == 0 ) {
00182 $this->_iObjectTplLanguageId = key( $aLanguages );
00183 }
00184 }
00185 return $this->_iObjectTplLanguageId;
00186 }
00187
00195 public function getTplLanguage()
00196 {
00197 if ( $this->_iTplLanguageId === null ) {
00198 $iSessLang = oxSession::getVar( 'tpllanguage' );
00199 $this->_iTplLanguageId = $this->isAdmin() ? $this->setTplLanguage( $iSessLang ) : $this->getBaseLanguage();
00200 }
00201 return $this->_iTplLanguageId;
00202 }
00203
00209 public function getEditLanguage()
00210 {
00211 if ( $this->_iEditLanguageId !== null ) {
00212 return $this->_iEditLanguageId;
00213 }
00214
00215 if ( !$this->isAdmin() ) {
00216 $this->_iEditLanguageId = $this->getBaseLanguage();
00217 } else {
00218
00219 $this->_iEditLanguageId = oxConfig::getParameter( 'editlanguage' );
00220
00221
00222 if ( "saveinnlang" == $this->getConfig()->getActiveView()->getFncName() ) {
00223 $iNewLanguage = oxConfig::getParameter( "new_lang");
00224 }
00225
00226 if ( isset( $iNewLanguage ) ) {
00227 $this->_iEditLanguageId = $iNewLanguage;
00228 oxSession::deleteVar( "new_lang" );
00229 }
00230
00231 if ( is_null( $this->_iEditLanguageId ) ) {
00232
00233 $this->_iEditLanguageId = $this->getBaseLanguage();
00234 }
00235 }
00236
00237
00238 $this->_iEditLanguageId = $this->validateLanguage( $this->_iEditLanguageId );
00239
00240 return $this->_iEditLanguageId;
00241 }
00242
00252 public function getLanguageArray( $iLanguage = null, $blOnlyActive = false, $blSort = false )
00253 {
00254 $myConfig = $this->getConfig();
00255
00256 if ( is_null($iLanguage) ) {
00257 $iLanguage = $this->_iBaseLanguageId;
00258 }
00259
00260 $aLanguages = array();
00261 $aConfLanguages = $myConfig->getConfigParam( 'aLanguages' );
00262 $aLangParams = $myConfig->getConfigParam( 'aLanguageParams' );
00263
00264 if ( is_array( $aConfLanguages ) ) {
00265 $i = 0;
00266 reset( $aConfLanguages );
00267 while ( list( $key, $val ) = each( $aConfLanguages ) ) {
00268
00269 if ( $blOnlyActive && is_array($aLangParams) ) {
00270
00271 if ( !$aLangParams[$key]['active'] ) {
00272 $i++;
00273 continue;
00274 }
00275 }
00276
00277 if ( $val ) {
00278 $oLang = new oxStdClass();
00279 $oLang->id = isset($aLangParams[$key]['baseId']) ? $aLangParams[$key]['baseId'] : $i;
00280 $oLang->oxid = $key;
00281 $oLang->abbr = $key;
00282 $oLang->name = $val;
00283
00284 if ( is_array( $aLangParams ) ) {
00285 $oLang->active = $aLangParams[$key]['active'];
00286 $oLang->sort = $aLangParams[$key]['sort'];
00287 }
00288
00289 $oLang->selected = ( isset( $iLanguage ) && $oLang->id == $iLanguage ) ? 1 : 0;
00290 $aLanguages[$oLang->id] = $oLang;
00291 }
00292 ++$i;
00293 }
00294 }
00295
00296 if ( $blSort && is_array($aLangParams) ) {
00297 uasort( $aLanguages, array($this, '_sortLanguagesCallback') );
00298 }
00299
00300 return $aLanguages;
00301 }
00302
00308 public function getAdminTplLanguageArray()
00309 {
00310 if ( $this->_aAdminTplLanguageArray === null ) {
00311
00312
00313 $aLangData = array();
00314 $aLangIds = $this->getLanguageIds();
00315
00316 $sSourceDir = $this->getConfig()->getStdLanguagePath( "", true, false );
00317 foreach ( glob( $sSourceDir."*", GLOB_ONLYDIR ) as $sDir ) {
00318 $sFilePath = "{$sDir}/lang.php";
00319 if ( file_exists( $sFilePath ) && is_readable( $sFilePath ) ) {
00320 $sLangName = "";
00321 $sAbbr = strtolower( basename( $sDir ) );
00322 if ( !in_array( $sAbbr, $aLangIds ) ) {
00323 include $sFilePath;
00324 $aLangData[$sAbbr] = new oxStdClass();
00325 $aLangData[$sAbbr]->name = $sLangName;
00326 $aLangData[$sAbbr]->abbr = $sAbbr;
00327 }
00328 }
00329 }
00330
00331 $this->_aAdminTplLanguageArray = $this->getLanguageArray();
00332 if ( count( $aLangData ) ) {
00333
00334
00335 ksort( $aLangData );
00336 $iSort = max( array_keys( $this->_aAdminTplLanguageArray ) );
00337
00338
00339 foreach ( $aLangData as $oLang ) {
00340 $oLang->id = $oLang->sort = ++$iSort;
00341 $oLang->selected = 0;
00342 $oLang->active = 0;
00343 $this->_aAdminTplLanguageArray[$iSort] = $oLang;
00344 }
00345 }
00346 }
00347
00348
00349 reset( $this->_aAdminTplLanguageArray );
00350 return $this->_aAdminTplLanguageArray;
00351 }
00352
00360 public function getLanguageAbbr( $iLanguage = null )
00361 {
00362 if ( $this->_aLangAbbr === null ) {
00363 $this->_aLangAbbr = array();
00364 if ( $this->isAdmin() ) {
00365 foreach ( $this->getAdminTplLanguageArray() as $oLang ) {
00366 $this->_aLangAbbr[$oLang->id] = $oLang->abbr;
00367 }
00368 } else {
00369 $this->_aLangAbbr = $this->getLanguageIds();
00370 }
00371 }
00372
00373 $iLanguage = isset( $iLanguage ) ? (int) $iLanguage : $this->getBaseLanguage();
00374 if ( isset( $this->_aLangAbbr[$iLanguage] ) ) {
00375 $iLanguage = $this->_aLangAbbr[$iLanguage];
00376 }
00377
00378 return $iLanguage;
00379 }
00380
00387 public function getLanguageNames()
00388 {
00389 $aConfLanguages = $this->getConfig()->getConfigParam( 'aLanguages' );
00390 $aLangIds = $this->getLanguageIds();
00391 $aLanguages = array();
00392 foreach ( $aLangIds as $iId => $sValue ) {
00393 $aLanguages[$iId] = $aConfLanguages[$sValue];
00394 }
00395 return $aLanguages;
00396 }
00397
00403 public function getLanguageIds()
00404 {
00405 $myConfig = $this->getConfig();
00406 $aIds = array();
00407
00408
00409 $aLangParams = $myConfig->getConfigParam( 'aLanguageParams' );
00410 if ( is_array( $aLangParams ) ) {
00411 foreach ( $aLangParams as $sAbbr => $aValue ) {
00412 $iBaseId = (int) $aValue['baseId'];
00413 $aIds[$iBaseId] = $sAbbr;
00414 }
00415 } else {
00416 $aIds = array_keys( $myConfig->getConfigParam( 'aLanguages' ) );
00417 }
00418
00419 return $aIds;
00420 }
00421
00434 public function translateString( $sStringToTranslate, $iLang = null, $blAdminMode = null )
00435 {
00436 $aLangCache = $this->_getLangTranslationArray( $iLang, $blAdminMode );
00437 $sText = isset( $aLangCache[$sStringToTranslate] ) ? $aLangCache[$sStringToTranslate] : $sStringToTranslate;
00438
00439 $blIsAdmin = isset( $blAdminMode ) ? $blAdminMode : $this->isAdmin();
00440 if ( !$blIsAdmin && $sText === $sStringToTranslate ) {
00441 $sText = $this->_readTranslateStrFromTextFile( $sStringToTranslate, $iLang, $blIsAdmin );
00442 }
00443
00444 return $sText;
00445 }
00446
00455 public function formatCurrency( $dValue, $oActCur = null )
00456 {
00457 if ( !$oActCur ) {
00458 $oActCur = $this->getConfig()->getActShopCurrencyObject();
00459 }
00460 return number_format( (double)$dValue, $oActCur->decimal, $oActCur->dec, $oActCur->thousand );
00461 }
00462
00471 public function formatVat( $dValue, $oActCur = null )
00472 {
00473 $iDecPos = 0;
00474 $sValue = ( string ) $dValue;
00475 $oStr = getStr();
00476 if ( ( $iDotPos = $oStr->strpos( $sValue, '.' ) ) !== false ) {
00477 $iDecPos = $oStr->strlen( $oStr->substr( $sValue, $iDotPos + 1 ) );
00478 }
00479
00480 $oActCur = $oActCur ? $oActCur : $this->getConfig()->getActShopCurrencyObject();
00481 $iDecPos = ( $iDecPos < $oActCur->decimal ) ? $iDecPos : $oActCur->decimal;
00482 return number_format( (double)$dValue, $iDecPos, $oActCur->dec, $oActCur->thousand );
00483 }
00484
00492 public function getLanguageTag( $iLanguage = null)
00493 {
00494 if ( !isset( $iLanguage ) ) {
00495 $iLanguage = $this->getBaseLanguage();
00496 }
00497
00498 $iLanguage = (int) $iLanguage;
00499
00500 return ( ( $iLanguage )?"_$iLanguage":"" );
00501 }
00502
00510 public function validateLanguage( $iLang = null )
00511 {
00512 $iLang = (int) $iLang;
00513
00514 $blAdmin = $this->isAdmin();
00515
00516
00517 $aLanguages = $this->getLanguageArray(null, !$blAdmin);
00518
00519 if ( !isset( $aLanguages[$iLang] ) && is_array( $aLanguages ) ) {
00520 $oLang = current( $aLanguages );
00521 if (isset($oLang->id)) {
00522 $iLang = $oLang->id;
00523 }
00524 }
00525
00526 return $iLang;
00527 }
00528
00536 public function setBaseLanguage( $iLang = null )
00537 {
00538 if ( is_null($iLang) ) {
00539 $iLang = $this->getBaseLanguage();
00540 } else {
00541 $this->_iBaseLanguageId = (int) $iLang;
00542 }
00543
00544 if ( defined( 'OXID_PHP_UNIT' ) ) {
00545 modSession::getInstance();
00546 }
00547
00548 oxSession::setVar( 'language', $iLang );
00549 }
00550
00558 public function setTplLanguage( $iLang = null )
00559 {
00560 $this->_iTplLanguageId = isset( $iLang ) ? (int) $iLang : $this->getBaseLanguage();
00561 if ( $this->isAdmin() ) {
00562 $aLanguages = $this->getAdminTplLanguageArray();
00563 if ( !isset( $aLanguages[$this->_iTplLanguageId] ) ) {
00564 $this->_iTplLanguageId = key( $aLanguages );
00565 }
00566 }
00567
00568 if ( defined( 'OXID_PHP_UNIT' ) ) {
00569 modSession::getInstance();
00570 }
00571
00572 oxSession::setVar( 'tpllanguage', $this->_iTplLanguageId );
00573 return $this->_iTplLanguageId;
00574 }
00575
00584 protected function _recodeLangArray( $aLangArray, $sCharset )
00585 {
00586 foreach ( $aLangArray as $sKey => $sValue ) {
00587 $aLangArray[$sKey] = iconv( $sCharset, 'UTF-8', $sValue );
00588 }
00589
00590 return $aLangArray;
00591 }
00592
00601 protected function _getLangFilesPathArray( $blAdmin, $iLang )
00602 {
00603 $myConfig = $this->getConfig();
00604 $aLangFiles = array();
00605
00606
00607 $sStdPath = $myConfig->getStdLanguagePath( "", $blAdmin, $iLang );
00608 if ( $sStdPath ) {
00609 $aLangFiles[] = $sStdPath . "lang.php";
00610 $aLangFiles = array_merge( $aLangFiles, glob( $sStdPath."*_lang.php" ) );
00611 }
00612
00613 $sCustPath = $myConfig->getLanguagePath( "", $blAdmin, $iLang );
00614 if ( $sCustPath && $sCustPath != $sStdPath ) {
00615 if ( is_readable( $sCustPath . "lang.php" ) ) {
00616 $aLangFiles[] = $sCustPath . "lang.php";
00617 }
00618 $aLangFiles = array_merge( $aLangFiles, glob( $sCustPath."*_lang.php" ) );
00619 }
00620
00621 return count( $aLangFiles ) ? $aLangFiles : false;
00622 }
00623
00632 protected function _getLangFileCacheName( $blAdmin, $iLang )
00633 {
00634 $myConfig = $this->getConfig();
00635 return "langcache_" . ( (int) $blAdmin ) . "_{$iLang}_" . $myConfig->getShopId() . "_" . $myConfig->getConfigParam( 'sTheme' );
00636 }
00637
00646 protected function _getLanguageFileData( $blAdmin = false, $iLang = 0 )
00647 {
00648 $myConfig = $this->getConfig();
00649 $myUtils = oxUtils::getInstance();
00650
00651 $sCacheName = $this->_getLangFileCacheName( $blAdmin, $iLang );
00652 $aLangCache = $myUtils->getLangCache( $sCacheName );
00653 if ( !$aLangCache && ( $aLangFiles = $this->_getLangFilesPathArray( $blAdmin, $iLang ) ) ) {
00654 $aLangCache[$iLang] = array();
00655 $sBaseCharset = false;
00656 foreach ( $aLangFiles as $sLangFile ) {
00657
00658 if ( file_exists( $sLangFile ) && is_readable( $sLangFile ) ) {
00659 include $sLangFile;
00660
00661
00662 if ( isset( $aLang['charset'] ) ) {
00663
00664
00665 if ( $myConfig->isUtf() ) {
00666 $aLang = $this->_recodeLangArray( $aLang, $aLang['charset'] );
00667
00668
00669 $aLang['charset'] = 'UTF-8';
00670 }
00671
00672 if ( !$sBaseCharset ) {
00673 $sBaseCharset = $aLang['charset'];
00674 }
00675
00676 $aLangCache[$iLang] = array_merge( $aLangCache[$iLang], $aLang );
00677 }
00678 }
00679 }
00680
00681
00682 if ( $sBaseCharset ) {
00683 $aLangCache[$iLang]['charset'] = $sBaseCharset;
00684 }
00685
00686
00687 $myUtils->setLangCache( $sCacheName, $aLangCache );
00688 }
00689
00690 return $aLangCache;
00691 }
00692
00701 protected function _getCacheLanguageId( $blAdmin, $iLang = null )
00702 {
00703 $iLang = ( $iLang === null && $blAdmin ) ? $this->getTplLanguage() : $iLang;
00704 if ( !isset( $iLang ) ) {
00705 $iLang = $this->getBaseLanguage();
00706 if ( !isset( $iLang ) ) {
00707 $iLang = 0;
00708 }
00709 }
00710
00711 return (int) $iLang;
00712 }
00713
00722 protected function _getLangTranslationArray( $iLang = null, $blAdmin = null )
00723 {
00724 startProfile("_getLangTranslationArray");
00725
00726 $blAdmin = isset( $blAdmin ) ? $blAdmin : $this->isAdmin();
00727 $iLang = $this->_getCacheLanguageId( $blAdmin, $iLang );
00728 $aLangCache = $blAdmin ? $this->_aAdminLangCache : $this->_aLangCache;
00729 if ( !isset( $aLangCache[$iLang] ) ) {
00730
00731 $aLangCache = $this->_getLanguageFileData( $blAdmin, $iLang );
00732 if ( $blAdmin ) {
00733 $this->_aAdminLangCache = $aLangCache;
00734 } else {
00735 $this->_aLangCache = $aLangCache;
00736 }
00737 }
00738
00739 stopProfile("_getLangTranslationArray");
00740
00741
00742 return ( isset( $aLangCache[$iLang] ) ? $aLangCache[$iLang] : array() );
00743 }
00744
00754 protected function _readTranslateStrFromTextFile( $sStringToTranslate, $iLang = null, $blIsAdmin = null )
00755 {
00756 $blIsAdmin = isset( $blIsAdmin ) ? $blIsAdmin : $this->isAdmin();
00757 $iLang = ( $iLang === null && $blIsAdmin)?$this->getTplLanguage():$iLang;
00758 if ( !isset( $iLang ) ) {
00759 $iLang = (int) $this->getBaseLanguage();
00760 }
00761
00762 $sFileName = $this->getConfig()->getLanguagePath('lang.txt', $blIsAdmin, $iLang);
00763 if ( is_file ( $sFileName ) && is_readable( $sFileName ) ) {
00764
00765 static $aUserLangCache = array();
00766
00767 if ( !isset( $aUserLangCache[$sFileName] ) ) {
00768 $handle = @fopen( $sFileName, "r" );
00769 if ( $handle === false ) {
00770 return $sStringToTranslate;
00771 }
00772
00773 $contents = fread( $handle, filesize ( $sFileName ) );
00774 fclose( $handle );
00775 $fileArray = explode( "\n", $contents );
00776 $aUserLangCache[$sFileName] = array();
00777 $aLang = &$aUserLangCache[$sFileName];
00778 $oStr = getStr();
00779
00780 while ( list( $nr,$line ) = each( $fileArray ) ) {
00781 $line = ltrim( $line );
00782 if ( $line[0]!="#" && $oStr->strpos( $line, "=" ) > 0 ) {
00783 $index = trim( $oStr->substr( $line, 0, $oStr->strpos($line, "=" ) ) );
00784 $value = trim( $oStr->substr( $line, $oStr->strpos( $line, "=" ) + 1, $oStr->strlen( $line ) ) );
00785 $aLang[trim($index)] = trim($value);
00786 }
00787 }
00788 }
00789
00790 if ( !isset( $aLang ) && isset( $aUserLangCache[$sFileName] ) ) {
00791 $aLang = &$aUserLangCache[$sFileName];
00792 }
00793
00794 if ( isset( $aLang[$sStringToTranslate] ) ) {
00795 $sStringToTranslate = $aLang[$sStringToTranslate];
00796 }
00797 }
00798
00799 return $sStringToTranslate;
00800 }
00801
00810 protected function _sortLanguagesCallback( $a1, $a2 )
00811 {
00812 return ($a1->sort > $a2->sort);
00813 }
00814
00820 public function getName()
00821 {
00822 return $this->_sName;
00823 }
00824
00830 public function getFormLang()
00831 {
00832 $sLang = null;
00833 if ( !$this->isAdmin()) {
00834 $sLang = "<input type=\"hidden\" name=\"".$this->getName()."\" value=\"". $this->getBaseLanguage() . "\">";
00835 }
00836 return $sLang;
00837 }
00838
00846 public function getUrlLang( $iLang = null )
00847 {
00848 $sLang = null;
00849 if ( !$this->isAdmin()) {
00850 $iLang = isset( $iLang ) ? $iLang : $this->getBaseLanguage();
00851 $sLang = $this->getName()."=". $iLang;
00852 }
00853 return $sLang;
00854 }
00855
00868 public function processUrl( $sUrl, $iLang = null )
00869 {
00870 $iLang = isset( $iLang ) ? $iLang : $this->getBaseLanguage();
00871 $oStr = getStr();
00872
00873 if ( !$this->isAdmin() ) {
00874 $sParam = $this->getUrlLang( $iLang );
00875 if ( !$oStr->preg_match('/(\?|&(amp;)?)lang=[0-9]+/', $sUrl) && ($iLang != oxConfig::getInstance()->getConfigParam( 'sDefaultLang' ))) {
00876 if ( $sUrl ) {
00877 if ($oStr->strpos( $sUrl, '?') === false) {
00878 $sUrl .= "?";
00879 } elseif ( !$oStr->preg_match('/(\?|&(amp;)?)$/', $sUrl ) ) {
00880 $sUrl .= "&";
00881 }
00882 }
00883 $sUrl .= $sParam."&";
00884 } else {
00885 $sUrl = getStr()->preg_replace('/(\?|&(amp;)?)lang=[0-9]+/', '\1'.$sParam, $sUrl);
00886 }
00887 }
00888
00889 return $sUrl;
00890 }
00891
00898 public function detectLanguageByBrowser()
00899 {
00900 $sBrowserLang = strtolower( substr( $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2 ) );
00901
00902 if ( !$sBrowserLang ) {
00903 return;
00904 }
00905
00906 $aLangs = $this->getLanguageArray(null, true );
00907
00908 foreach ( $aLangs as $oLang ) {
00909 if ( $oLang->abbr == $sBrowserLang ) {
00910 return (int) $oLang->id;
00911 }
00912 }
00913 }
00914 }