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 public static function getInstance()
00063 {
00064 if ( defined('OXID_PHP_UNIT')) {
00065 if ( ($oClassMod = modInstances::getMod(__CLASS__)) && is_object($oClassMod) ) {
00066 return $oClassMod;
00067 } else {
00068 $inst = oxNew( 'oxLang' );
00069 modInstances::addMod( __CLASS__, $inst );
00070 return $inst;
00071 }
00072 }
00073
00074 if ( !self::$_instance instanceof oxLang ) {
00075
00076 self::$_instance = oxNew( 'oxLang');
00077 }
00078 return self::$_instance;
00079 }
00080
00087 public function resetBaseLanguage()
00088 {
00089 $this->_iBaseLanguageId = null;
00090 }
00091
00097 public function getBaseLanguage()
00098 {
00099 $myConfig = $this->getConfig();
00100
00101
00102 if ( $this->_iBaseLanguageId !== null ) {
00103 return $this->_iBaseLanguageId;
00104 }
00105
00106 $blAdmin = $this->isAdmin();
00107
00108
00109 if ( $blAdmin && ( ( $iSeLang = oxConfig::getParameter( 'changelang' ) ) !== null ) ) {
00110 $this->_iBaseLanguageId = $iSeLang;
00111 }
00112
00113 if ( is_null( $this->_iBaseLanguageId ) ) {
00114 $this->_iBaseLanguageId = oxConfig::getParameter( 'lang' );
00115 }
00116
00117
00118 $aLanguageUrls = $myConfig->getConfigParam( 'aLanguageURLs' );
00119
00120 if ( !$blAdmin && is_array( $aLanguageUrls ) ) {
00121 foreach ( $aLanguageUrls as $iId => $sUrl ) {
00122 if ( $myConfig->isCurrentUrl( $sUrl ) ) {
00123 $this->_iBaseLanguageId = $iId;
00124 break;
00125 }
00126 }
00127 }
00128
00129 if ( is_null( $this->_iBaseLanguageId ) ) {
00130 $this->_iBaseLanguageId = oxConfig::getParameter( 'language' );
00131 }
00132
00133
00134
00135 if ( is_null( $this->_iBaseLanguageId ) && !$blAdmin && !oxUtils::getInstance()->isSearchEngine() ) {
00136
00137
00138 $this->_iBaseLanguageId = oxUtilsServer::getInstance()->getOxCookie( 'language' );
00139
00140
00141 if ( is_null( $this->_iBaseLanguageId ) ) {
00142 $this->_iBaseLanguageId = $this->detectLanguageByBrowser();
00143 }
00144 }
00145
00146 if ( is_null( $this->_iBaseLanguageId ) ) {
00147 $this->_iBaseLanguageId = $myConfig->getConfigParam( 'sDefaultLang' );
00148 }
00149
00150 $this->_iBaseLanguageId = (int) $this->_iBaseLanguageId;
00151
00152
00153 $this->_iBaseLanguageId = $this->validateLanguage( $this->_iBaseLanguageId );
00154
00155
00156 oxUtilsServer::getInstance()->setOxCookie( 'language', $this->_iBaseLanguageId );
00157
00158 return $this->_iBaseLanguageId;
00159 }
00160
00168 public function getTplLanguage()
00169 {
00170 if ( $this->_iTplLanguageId === null ) {
00171 if ( !$this->isAdmin() ) {
00172 $this->_iTplLanguageId = $this->getBaseLanguage();
00173 } else {
00174
00175
00176 if ( is_null( $this->_iTplLanguageId ) ) {
00177 $this->_iTplLanguageId = oxSession::getVar( 'tpllanguage' );
00178 }
00179
00180 if ( is_null( $this->_iTplLanguageId ) ) {
00181 $this->_iTplLanguageId = $this->getBaseLanguage();
00182 }
00183 }
00184
00185
00186 $this->_iTplLanguageId = $this->validateLanguage( $this->_iTplLanguageId );
00187 }
00188 return $this->_iTplLanguageId;
00189 }
00190
00196 public function getEditLanguage()
00197 {
00198 if ( $this->_iEditLanguageId !== null ) {
00199 return $this->_iEditLanguageId;
00200 }
00201
00202 if ( !$this->isAdmin() ) {
00203 $this->_iEditLanguageId = $this->getBaseLanguage();
00204 } else {
00205
00206 $this->_iEditLanguageId = oxConfig::getParameter( 'editlanguage' );
00207
00208
00209 if ( "saveinnlang" == $this->getConfig()->getActiveView()->getFncName() ) {
00210 $iNewLanguage = oxConfig::getParameter( "new_lang");
00211 }
00212
00213 if ( isset( $iNewLanguage ) ) {
00214 $this->_iEditLanguageId = $iNewLanguage;
00215 oxSession::deleteVar( "new_lang" );
00216 }
00217
00218 if ( is_null( $this->_iEditLanguageId ) ) {
00219
00220 $this->_iEditLanguageId = $this->getBaseLanguage();
00221 }
00222 }
00223
00224
00225 $this->_iEditLanguageId = $this->validateLanguage( $this->_iEditLanguageId );
00226
00227 return $this->_iEditLanguageId;
00228 }
00229
00239 public function getLanguageArray( $iLanguage = null, $blOnlyActive = false, $blSort = false )
00240 {
00241 $myConfig = $this->getConfig();
00242
00243 if ( is_null($iLanguage) ) {
00244 $iLanguage = $this->_iBaseLanguageId;
00245 }
00246
00247 $aLanguages = array();
00248 $aConfLanguages = $myConfig->getConfigParam( 'aLanguages' );
00249 $aLangParams = $myConfig->getConfigParam( 'aLanguageParams' );
00250
00251 if ( is_array( $aConfLanguages ) ) {
00252 $i = 0;
00253 reset( $aConfLanguages );
00254 while ( list( $key, $val ) = each( $aConfLanguages ) ) {
00255
00256 if ( $blOnlyActive && is_array($aLangParams) ) {
00257
00258 if ( !$aLangParams[$key]['active'] ) {
00259 $i++;
00260 continue;
00261 }
00262 }
00263
00264 if ( $val) {
00265 $oLang = new oxStdClass();
00266 if ( isset($aLangParams[$key]['baseId']) ) {
00267 $oLang->id = $aLangParams[$key]['baseId'];
00268 } else {
00269 $oLang->id = $i;
00270 }
00271 $oLang->oxid = $key;
00272 $oLang->abbr = $key;
00273 $oLang->name = $val;
00274
00275 if ( is_array($aLangParams) ) {
00276 $oLang->active = $aLangParams[$key]['active'];
00277 $oLang->sort = $aLangParams[$key]['sort'];
00278 }
00279
00280 if ( isset( $iLanguage ) && $oLang->id == $iLanguage ) {
00281 $oLang->selected = 1;
00282 } else {
00283 $oLang->selected = 0;
00284 }
00285 $aLanguages[$oLang->id] = $oLang;
00286 }
00287 ++$i;
00288 }
00289 }
00290
00291 if ( $blSort && is_array($aLangParams) ) {
00292 uasort( $aLanguages, array($this, '_sortLanguagesCallback') );
00293 }
00294
00295 return $aLanguages;
00296 }
00297
00306 public function getLanguageAbbr( $iLanguage = null)
00307 {
00308 $myConfig = $this->getConfig();
00309
00310 if ( !isset($iLanguage) ) {
00311 $iLanguage = $this->_iBaseLanguageId;
00312 }
00313
00314 $aLangAbbr = $this->getLanguageIds();
00315
00316 if ( isset($iLanguage,$aLangAbbr[$iLanguage]) ) {
00317 return $aLangAbbr[$iLanguage];
00318 }
00319
00320 return $iLanguage;
00321 }
00322
00329 public function getLanguageNames()
00330 {
00331
00332 $aConfLanguages = $this->getConfig()->getConfigParam( 'aLanguages' );
00333 $aLangIds = $this->getLanguageIds();
00334 $aLanguages = array();
00335 foreach ( $aLangIds as $iId => $sValue ) {
00336 $aLanguages[$iId] = $aConfLanguages[$sValue];
00337 }
00338 return $aLanguages;
00339 }
00340
00346 public function getLanguageIds()
00347 {
00348 $aLangParams = $this->getConfig()->getConfigParam( 'aLanguageParams' );
00349
00350
00351 if ( is_array($aLangParams) ) {
00352
00353 $aIds = array();
00354
00355 foreach ( $aLangParams as $sAbbr => $aValue ) {
00356 $iBaseId = (int) $aValue['baseId'];
00357 $aIds[$iBaseId] = $sAbbr;
00358 }
00359 return $aIds;
00360 }
00361
00362 return array_keys( $this->getConfig()->getConfigParam( 'aLanguages' ));
00363 }
00364
00377 public function translateString( $sStringToTranslate, $iLang = null, $blAdminMode = null )
00378 {
00379 $aLangCache = $this->_getLangTranslationArray( $iLang, $blAdminMode );
00380 $sText = isset( $aLangCache[$sStringToTranslate] ) ? $aLangCache[$sStringToTranslate] : $sStringToTranslate;
00381
00382 $blIsAdmin = isset( $blAdminMode ) ? $blAdminMode : $this->isAdmin();
00383 if ( !$blIsAdmin && $sText === $sStringToTranslate ) {
00384 $sText = $this->_readTranslateStrFromTextFile( $sStringToTranslate, $iLang, $blIsAdmin );
00385 }
00386
00387 return $sText;
00388 }
00389
00398 public function formatCurrency( $dValue, $oActCur = null )
00399 {
00400 if ( !$oActCur ) {
00401 $oActCur = $this->getConfig()->getActShopCurrencyObject();
00402 }
00403 return number_format( $dValue, $oActCur->decimal, $oActCur->dec, $oActCur->thousand );
00404 }
00405
00414 public function formatVat( $dValue, $oActCur = null )
00415 {
00416 $iDecPos = 0;
00417 $sValue = ( string ) $dValue;
00418 $oStr = getStr();
00419 if ( ( $iDotPos = $oStr->strpos( $sValue, '.' ) ) !== false ) {
00420 $iDecPos = $oStr->strlen( $oStr->substr( $sValue, $iDotPos + 1 ) );
00421 }
00422
00423 $oActCur = $oActCur ? $oActCur : $this->getConfig()->getActShopCurrencyObject();
00424 $iDecPos = ( $iDecPos < $oActCur->decimal ) ? $iDecPos : $oActCur->decimal;
00425 return number_format( $dValue, $iDecPos, $oActCur->dec, $oActCur->thousand );
00426 }
00427
00435 public function getLanguageTag( $iLanguage = null)
00436 {
00437 if ( !isset( $iLanguage ) ) {
00438 $iLanguage = $this->getBaseLanguage();
00439 }
00440
00441 $iLanguage = (int) $iLanguage;
00442
00443 return ( ( $iLanguage )?"_$iLanguage":"" );
00444 }
00445
00453 public function validateLanguage( $iLang = null )
00454 {
00455 $iLang = (int) $iLang;
00456
00457
00458 $aLanguages = $this->getLanguageArray();
00459
00460 if ( !isset( $aLanguages[$iLang] ) && is_array( $aLanguages ) ) {
00461 $oLang = current( $aLanguages );
00462 $iLang = $oLang->id;
00463 }
00464
00465 return $iLang;
00466 }
00467
00475 public function setBaseLanguage( $iLang = null )
00476 {
00477 if ( is_null($iLang) ) {
00478 $iLang = $this->getBaseLanguage();
00479 } else {
00480 $this->_iBaseLanguageId = (int) $iLang;
00481 }
00482
00483 if ( defined( 'OXID_PHP_UNIT' ) ) {
00484 modSession::getInstance();
00485 }
00486
00487 oxSession::setVar( 'language', $iLang );
00488 }
00489
00497 public function setTplLanguage( $iLang = null )
00498 {
00499 if ( is_null($iLang) ) {
00500 $iLang = $this->getTplLanguage();
00501 } else {
00502 $this->_iTplLanguageId = (int) $iLang;
00503 }
00504
00505 if ( defined( 'OXID_PHP_UNIT' ) ) {
00506 modSession::getInstance();
00507 }
00508
00509 oxSession::setVar( 'tpllanguage', $iLang );
00510 }
00511
00520 protected function _recodeLangArray( $aLangArray, $sCharset )
00521 {
00522 foreach ( $aLangArray as $sKey => $sValue ) {
00523 $aLangArray[$sKey] = iconv( $sCharset, 'UTF-8', $sValue );
00524 }
00525
00526 return $aLangArray;
00527 }
00528
00537 protected function _getLangFilesPathArray( $blAdmin, $iLang )
00538 {
00539 $myConfig = $this->getConfig();
00540 $aLangFiles = array();
00541
00542
00543 $sStdPath = $myConfig->getStdLanguagePath( "", $blAdmin, $iLang );
00544 if ( $sStdPath ) {
00545 $aLangFiles[] = $sStdPath . "lang.php";
00546 $aLangFiles = array_merge( $aLangFiles, glob( $sStdPath."*_lang.php" ) );
00547 }
00548
00549 $sCustPath = $myConfig->getLanguagePath( "", $blAdmin, $iLang );
00550 if ( $sCustPath && $sCustPath != $sStdPath ) {
00551 if ( is_readable( $sCustPath . "lang.php" ) ) {
00552 $aLangFiles[] = $sCustPath . "lang.php";
00553 }
00554 $aLangFiles = array_merge( $aLangFiles, glob( $sCustPath."*_lang.php" ) );
00555 }
00556
00557 return count( $aLangFiles ) ? $aLangFiles : false;
00558 }
00559
00568 protected function _getLangFileCacheName( $blAdmin, $iLang )
00569 {
00570 $myConfig = $this->getConfig();
00571 return "langcache_" . ( (int) $blAdmin ) . "_{$iLang}_" . $myConfig->getShopId() . "_" . $myConfig->getConfigParam( 'sTheme' );
00572 }
00573
00582 protected function _getLanguageFileData( $blAdmin = false, $iLang = 0 )
00583 {
00584 $myConfig = $this->getConfig();
00585 $myUtils = oxUtils::getInstance();
00586
00587 $sCacheName = $this->_getLangFileCacheName( $blAdmin, $iLang );
00588 $aLangCache = $myUtils->getLangCache( $sCacheName );
00589 if ( !$aLangCache && ( $aLangFiles = $this->_getLangFilesPathArray( $blAdmin, $iLang ) ) ) {
00590 $aLangCache[$iLang] = array();
00591 $sBaseCharset = false;
00592 foreach ( $aLangFiles as $sLangFile ) {
00593
00594 if (!file_exists($sLangFile)) {
00595 continue;
00596 }
00597
00598 include $sLangFile;
00599
00600
00601 if ( isset( $aLang['charset'] ) ) {
00602
00603
00604 if ( $myConfig->isUtf() ) {
00605 $aLang = $this->_recodeLangArray( $aLang, $aLang['charset'] );
00606
00607
00608 $aLang['charset'] = 'UTF-8';
00609 }
00610
00611 if ( !$sBaseCharset ) {
00612 $sBaseCharset = $aLang['charset'];
00613 }
00614
00615 $aLangCache[$iLang] = array_merge( $aLangCache[$iLang], $aLang );
00616 }
00617 }
00618
00619
00620 if ( $sBaseCharset ) {
00621 $aLangCache[$iLang]['charset'] = $sBaseCharset;
00622 }
00623
00624
00625 $myUtils->setLangCache( $sCacheName, $aLangCache );
00626 }
00627
00628 return $aLangCache;
00629 }
00630
00639 protected function _getCacheLanguageId( $blAdmin, $iLang = null )
00640 {
00641 $iLang = ( $iLang === null && $blAdmin ) ? $this->getTplLanguage() : $iLang;
00642 if ( !isset( $iLang ) ) {
00643 $iLang = $this->getBaseLanguage();
00644 if ( !isset( $iLang ) ) {
00645 $iLang = 0;
00646 }
00647 }
00648
00649 return (int) $iLang;
00650 }
00651
00660 protected function _getLangTranslationArray( $iLang = null, $blAdmin = null )
00661 {
00662 startProfile("<b>_getLangTranslationArray</b>");
00663
00664 $blAdmin = isset( $blAdmin ) ? $blAdmin : $this->isAdmin();
00665 $iLang = $this->_getCacheLanguageId( $blAdmin, $iLang );
00666
00667 $aLangCache = $blAdmin ? $this->_aAdminLangCache : $this->_aLangCache;
00668
00669 if ( !isset( $aLangCache[$iLang] ) ) {
00670
00671
00672 $aLangCache = $this->_getLanguageFileData( $blAdmin, $iLang );
00673 if ( $blAdmin ) {
00674 $this->_aAdminLangCache = $aLangCache;
00675 } else {
00676 $this->_aLangCache = $aLangCache;
00677 }
00678 }
00679
00680 stopProfile("<b>_getLangTranslationArray</b>");
00681
00682
00683 return ( isset( $aLangCache[$iLang] ) ? $aLangCache[$iLang] : array() );
00684 }
00685
00695 protected function _readTranslateStrFromTextFile( $sStringToTranslate, $iLang = null, $blIsAdmin = null )
00696 {
00697 $blIsAdmin = isset( $blIsAdmin ) ? $blIsAdmin : $this->isAdmin();
00698 $iLang = ( $iLang === null && $blIsAdmin)?$this->getTplLanguage():$iLang;
00699 if ( !isset( $iLang ) ) {
00700 $iLang = $this->getBaseLanguage();
00701 if ( !isset( $iLang ) ) {
00702 $iLang = 0;
00703 }
00704 }
00705
00706 $sFileName = $this->getConfig()->getLanguagePath('lang.txt', $blIsAdmin, $iLang);
00707
00708 if ( is_file ( $sFileName ) ) {
00709
00710 static $aUserLangCache = array();
00711
00712 if ( !isset( $aUserLangCache[$sFileName] ) ) {
00713 $handle = @fopen( $sFileName, "r" );
00714 if ( $handle === false ) {
00715 return $sStringToTranslate;
00716 }
00717
00718 $contents = fread( $handle, filesize ( $sFileName ) );
00719 fclose( $handle );
00720 $fileArray = explode( "\n", $contents );
00721 $aUserLangCache[$sFileName] = array();
00722 $aLang = &$aUserLangCache[$sFileName];
00723 $oStr = getStr();
00724
00725 while ( list( $nr,$line ) = each( $fileArray ) ) {
00726 $line = ltrim( $line );
00727 if ( $line[0]!="#" && $oStr->strpos( $line, "=" ) > 0 ) {
00728 $index = trim( $oStr->substr( $line, 0, $oStr->strpos($line, "=" ) ) );
00729 $value = trim( $oStr->substr( $line, $oStr->strpos( $line, "=" ) + 1, $oStr->strlen( $line ) ) );
00730 $aLang[trim($index)] = trim($value);
00731 }
00732 }
00733 }
00734
00735 if ( !isset( $aLang ) && isset( $aUserLangCache[$sFileName] ) ) {
00736 $aLang = &$aUserLangCache[$sFileName];
00737 }
00738
00739 if ( isset( $aLang[$sStringToTranslate] ) ) {
00740 return $aLang[$sStringToTranslate];
00741 }
00742 }
00743
00744 return $sStringToTranslate;
00745 }
00746
00755 protected function _sortLanguagesCallback( $a1, $a2 )
00756 {
00757 return ($a1->sort > $a2->sort);
00758 }
00759
00765 public function getName()
00766 {
00767 return $this->_sName;
00768 }
00769
00775 public function getFormLang()
00776 {
00777 if ( !$this->isAdmin()) {
00778 return "<input type=\"hidden\" name=\"".$this->getName()."\" value=\"". $this->getBaseLanguage() . "\">";
00779 }
00780 }
00781
00789 public function getUrlLang( $iLang = null )
00790 {
00791 if ( !$this->isAdmin()) {
00792 $iLang = isset( $iLang ) ? $iLang : $this->getBaseLanguage();
00793 return $this->getName()."=". $iLang;
00794 }
00795 }
00796
00809 public function processUrl( $sUrl, $iLang = null )
00810 {
00811 $iLang = isset( $iLang ) ? $iLang : $this->getBaseLanguage();
00812 $oStr = getStr();
00813
00814 if ( !$this->isAdmin() ) {
00815 $sParam = $this->getUrlLang( $iLang );
00816 if (!preg_match('/(\?|&(amp;)?)lang=[0-9]+/', $sUrl) && ($iLang != oxConfig::getInstance()->getConfigParam( 'sDefaultLang' ))) {
00817 if ( $sUrl ) {
00818 if ($oStr->strpos( $sUrl, '?') === false) {
00819 $sUrl .= "?";
00820 } elseif (!preg_match('/(\?|&(amp;)?)$/', $sUrl)) {
00821 $sUrl .= "&";
00822 }
00823 }
00824 $sUrl .= $sParam."&";
00825 } else {
00826 $sUrl = preg_replace('/(\?|&(amp;)?)lang=[0-9]+/', '\1'.$sParam, $sUrl);
00827 }
00828 }
00829
00830 return $sUrl;
00831 }
00832
00839 public function detectLanguageByBrowser()
00840 {
00841 $sBrowserLang = strtolower( substr( $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2 ) );
00842
00843 if ( !$sBrowserLang ) {
00844 return;
00845 }
00846
00847 $aLangs = $this->getLanguageArray(null, true );
00848
00849 foreach ( $aLangs as $oLang ) {
00850 if ( $oLang->abbr == $sBrowserLang ) {
00851 return (int) $oLang->id;
00852 }
00853 }
00854 }
00855 }