Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/localization/ |
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/localization/translation.php |
<?php namespace Bitrix\Main\Localization; use Bitrix\Main; use Bitrix\Main\IO\Path; use Bitrix\Main\Context; use Bitrix\Main\Config\Configuration; class Translation { /** @var boolean */ private static $allowConvertEncoding = null; /** @var boolean */ private static $useTranslationRepository = null; /** @var string */ private static $translationRepositoryPath = null; /** @var string */ private static $currentEncoding = null; /** @var bool[] */ private static $needConvertEncoding = array(); /** @var array */ private static $map = array(); const CACHE_ID = 'TranslationLoadMapCache'; const CACHE_TTL = 3600; /** * Returns true if language translation is one of the default translation. * * @param string $lang Language code to check. * @return bool */ public static function isDefaultTranslationLang($lang) { return ($lang === 'ru') || ($lang === 'en') || ($lang === 'de'); } /** * Returns encoding of source lang file in the translation repository. * * @param string $lang Language code to retrieve encoding. * @return string */ public static function getDefaultTranslationEncoding($lang) { static $sourceEncoding = [ 'ru' => 'windows-1251', 'en' => 'iso-8859-1', 'de' => 'iso-8859-15', ]; if (isset($sourceEncoding[$lang])) { return $sourceEncoding[$lang]; } return 'utf-8'; } /** * Returns encoding of source lang file in the translation repository. * * @param string $lang Language code to retrieve encoding. * @return string */ public static function getSourceEncoding($lang) { $encoding = ''; if (self::useTranslationRepository() || self::allowConvertEncoding()) { if (self::isDefaultTranslationLang($lang)) { $encoding = self::getDefaultTranslationEncoding($lang); } else { $encoding = 'utf-8'; } } elseif (Main\Application::isUtfMode() || defined('BX_UTF')) { $encoding = 'utf-8'; } if (empty($encoding)) { $culture = Main\Localization\CultureTable::getRow(array('filter' => array('=CODE' => $lang))); if ($culture) { $encoding = $culture['CHARSET']; } } if (empty($encoding)) { $encoding = self::getCurrentEncoding(); } return $encoding; } /** * Sets current encoding. * * @param string $encoding Charset encoding. * @return void */ public static function setCurrentEncoding($encoding) { self::$currentEncoding = $encoding; } /** * Returns current encoding. * * @return string */ public static function getCurrentEncoding() { if (self::$currentEncoding === null) { $encoding = null; // site settings if (Main\Application::isUtfMode() || defined('BX_UTF')) { $encoding = 'utf-8'; } elseif (defined('SITE_CHARSET') && (SITE_CHARSET <> '')) { $encoding = SITE_CHARSET; } elseif (defined('LANG_CHARSET') && (LANG_CHARSET <> '')) { $encoding = LANG_CHARSET; } else { $context = Context::getCurrent(); if ($context instanceof Main\Context) { $culture = $context->getCulture(); if ($culture instanceof Context\Culture) { $encoding = $culture->getCharset(); } } } // default settings if ($encoding === null) { if (Configuration::getValue('default_charset') !== null) { $encoding = Configuration::getValue('default_charset'); } elseif (defined('BX_DEFAULT_CHARSET') && (BX_DEFAULT_CHARSET <> '')) { $encoding = BX_DEFAULT_CHARSET; } else { $encoding = 'windows-1251'; } } self::$currentEncoding = mb_strtolower($encoding); } return self::$currentEncoding; } /** * Tells if need to convert encoding. * * @param string $language Language code. * @param string $targetEncoding Target encoding. * * @return bool */ public static function needConvertEncoding($language, $targetEncoding = null) { if (!isset(self::$needConvertEncoding[$language]) || self::$needConvertEncoding[$language] === null) { self::$needConvertEncoding[$language] = false; if (self::allowConvertEncoding()) { if ($targetEncoding === null) { $targetEncoding = self::getCurrentEncoding(); } $sourceEncoding = self::getSourceEncoding($language); self::$needConvertEncoding[$language] = ($targetEncoding != $sourceEncoding); } } return self::$needConvertEncoding[$language]; } /** * Tells if need to convert encoding for certain file. * * @param string $langFile Language file path. * * @return bool */ public static function checkPathRestrictionConvertEncoding($langFile) { $needConvert = false; if (self::allowConvertEncoding()) { if (self::getDeveloperRepositoryPath() !== null) { $needConvert = (stripos($langFile, self::getDeveloperRepositoryPath()) === 0); } if (!$needConvert && self::useTranslationRepository()) { $needConvert = (stripos($langFile, self::getTranslationRepositoryPath()) === 0); } } return $needConvert; } /** * Tells if need to use translation repository. * * @return bool */ public static function useTranslationRepository() { if (self::$useTranslationRepository === null) { self::$useTranslationRepository = false; if(self::getTranslationRepositoryPath() !== null) { self::$useTranslationRepository = true; } } return self::$useTranslationRepository; } /** * Returns path to translation repository. * * @return string */ public static function getTranslationRepositoryPath() { if(self::$translationRepositoryPath === null) { $config = Configuration::getValue('translation'); if ($config !== null && !empty($config['translation_repository'])) { $translationRepositoryPath = realpath($config['translation_repository']); if (file_exists($translationRepositoryPath)) { self::$translationRepositoryPath = Path::normalize($translationRepositoryPath); } } } return self::$translationRepositoryPath; } /** * Tells true if configuration allows to convert encodings. * * @return bool */ public static function allowConvertEncoding() { if(self::$allowConvertEncoding === null) { self::$allowConvertEncoding = false; $config = Configuration::getValue('translation'); if ($config !== null && !empty($config['convert_encoding'])) { self::$allowConvertEncoding = ($config['convert_encoding'] === true); } } return self::$allowConvertEncoding; } /** * Returns path to developer repository. * * @return string */ public static function getDeveloperRepositoryPath() { static $developerRepositoryPath, $wasChecked; if($wasChecked === null) { $wasChecked = true; $config = Configuration::getValue('translation'); if ($config !== null && !empty($config['developer_repository'])) { $developerRepositoryPath = realpath($config['developer_repository']); if (file_exists($developerRepositoryPath)) { $developerRepositoryPath = Path::normalize($developerRepositoryPath); } } } return $developerRepositoryPath; } /** * Converts lang file to translation repository path. * * @param string $langFile Language file path. * @param string $language Language code to retrieve translation. * @return string */ public static function convertLangPath($langFile, $language) { if (empty($language) || !(self::useTranslationRepository() || self::getDeveloperRepositoryPath() !== null)) { return $langFile; } static $documentRoot; if ($documentRoot === null) { $documentRoot = Path::normalize(Main\Application::getDocumentRoot()); } if (self::useTranslationRepository() && !self::isDefaultTranslationLang($language)) { $modulePath = self::getTranslationRepositoryPath().'/'.$language.'/'; } elseif (self::getDeveloperRepositoryPath() !== null) { $modulePath = self::getDeveloperRepositoryPath(). '/'; } elseif (self::isDefaultTranslationLang($language)) { $modulePath = $documentRoot. '/bitrix/modules/'; } else { return $langFile; } if (strpos($langFile, '\\') !== false) { $langFile = str_replace('\\', '/', $langFile); } if (strpos($langFile, '//') !== false) { $langFile = str_replace('//', '/', $langFile); } // linked if (self::getDeveloperRepositoryPath() !== null) { if (mb_strpos($langFile, self::getDeveloperRepositoryPath()) === 0) { $langFile = str_replace( self::getDeveloperRepositoryPath(). '/', $modulePath, $langFile ); return $langFile; } } // module lang if (strpos($langFile, $documentRoot. '/bitrix/modules/') === 0) { $langFile = str_replace( $documentRoot.'/bitrix/modules/', $modulePath, $langFile ); return $langFile; } self::loadMap(); $langPathParts = preg_split('#[/]+#', trim(str_replace($documentRoot, '', $langFile), '/'), 6); if ( empty($langPathParts) || $langPathParts[0] !== 'bitrix' || empty($langPathParts[1]) || empty($langPathParts[2]) || empty($langPathParts[3]) ) { return $langFile; } $testEntry = $langPathParts[1]; switch ($testEntry) { // bitrix/mobileapp/[moduleName] -> [moduleName]/install/mobileapp/[moduleName] case 'mobileapp': $moduleName = $langPathParts[2]; if (isset(self::$map[$moduleName][$testEntry], self::$map[$moduleName][$testEntry][$moduleName])) { $testEntry = 'mobileapp/'. $moduleName; $langFile = str_replace( $documentRoot.'/bitrix/mobileapp/'. $moduleName. '/', $modulePath.''.$moduleName.'/install/mobileapp/'. $moduleName. '/', $langFile ); } break; // bitrix/templates/[templateName] -> [moduleName]/install/templates/[templateName] case 'templates': $templateName = $langPathParts[2]; foreach (self::$map as $moduleName => $moduleEntries) { if (isset(self::$map[$moduleName][$testEntry], self::$map[$moduleName][$testEntry][$templateName])) { $langFile = str_replace( $documentRoot.'/bitrix/templates/'.$templateName.'/', $modulePath.''.$moduleName.'/install/templates/'. $templateName .'/', $langFile ); break; } } break; // bitrix/components/bitrix/[componentName] -> [moduleName]/install/components/bitrix/[componentName] // bitrix/activities/bitrix/[activityName] -> [moduleName]/install/activities/bitrix/[activityName] // bitrix/wizards/bitrix/[wizardsName] -> [moduleName]/install/wizards/bitrix/[wizardsName] // bitrix/gadgets/bitrix/[gadgetName] -> [moduleName]/install/gadgets/bitrix/[gadgetName] case 'components': case 'activities': case 'wizards': case 'gadgets': case 'blocks': if ($langPathParts[2] !== 'bitrix') { break; } $searchEntryName = $langPathParts[3]; foreach (self::$map as $moduleName => $moduleEntries) { if (isset(self::$map[$moduleName][$testEntry], self::$map[$moduleName][$testEntry][$searchEntryName])) { $langFile = str_replace( $documentRoot.'/bitrix/'.$testEntry.'/bitrix/'.$searchEntryName.'/', $modulePath.''.$moduleName.'/install/'.$testEntry.'/bitrix/'. $searchEntryName. '/', $langFile ); break; } } break; // bitrix/js/[moduleName]/[smth] -> [moduleName]/install/js/[moduleName]/[smth] // bitrix/js/[moduleName]/[smth] -> [moduleName]/install/public/js/[moduleName]/[smth] case 'js': $libraryNamespace = $langPathParts[2]. '/'. $langPathParts[3]; foreach (self::$map as $moduleName => $moduleEntries) { if (isset(self::$map[$moduleName][$testEntry], self::$map[$moduleName][$testEntry][$libraryNamespace])) { $langFile = str_replace( $documentRoot.'/bitrix/'.$testEntry.'/'.$libraryNamespace.'/', $modulePath.''.$moduleName.'/install/'.$testEntry.'/'.$libraryNamespace.'/', $langFile ); break; } if (isset(self::$map[$moduleName]["public/{$testEntry}"], self::$map[$moduleName]["public/{$testEntry}"][$libraryNamespace])) { $langFile = str_replace( $documentRoot.'/bitrix/'.$testEntry.'/'.$libraryNamespace.'/', $modulePath.''.$moduleName.'/install/public/'.$testEntry.'/'.$libraryNamespace.'/', $langFile ); break; } } break; // bitrix/[moduleName]/payment/[paymentHandler] -> [moduleName]/payment/[paymentHandler] case 'payment': $searchEntryName = $langPathParts[3]; foreach (self::$map as $moduleName => $moduleEntries) { if (isset(self::$map[$moduleName][$testEntry], self::$map[$moduleName][$testEntry][$searchEntryName])) { $langFile = str_replace( $documentRoot.'/bitrix/modules/'.$moduleName.'/'.$testEntry.'/', $modulePath.''.$moduleName.'/'.$testEntry.'/', $langFile ); break; } } break; } return $langFile; } /** * Restore project map structure from file structure. * * @return array */ public static function loadMap() { if (empty(self::$map)) { $cacheManager = Main\Application::getInstance()->getManagedCache(); if ($cacheManager->read(static::CACHE_TTL, static::CACHE_ID)) { self::$map = $cacheManager->get(static::CACHE_ID); } } if (empty(self::$map)) { $testForExistence = array( 'templates', 'components', 'activities', 'wizards', 'gadgets', 'js', 'public/js', 'blocks', 'payment', 'mobileapp', ); $bxRoot = Main\Application::getDocumentRoot(). '/bitrix/modules/'; $modulesList = new Main\IO\Directory($bxRoot); foreach ($modulesList->getChildren() as $moduleDirectory) { if ($moduleDirectory->isDirectory()) { $moduleName = $moduleDirectory->getName(); if (strpos($moduleName, '.') === false || strpos($moduleName, 'bitrix.') === 0) { self::$map[$moduleName] = array(); foreach ($testForExistence as $testEntry) { $testPath = $bxRoot. '/'. $moduleName. '/install/'. $testEntry; if ($testEntry === 'templates' || $testEntry === 'mobileapp') { $testPath .= '/'; } elseif ($testEntry === 'js' || $testEntry === 'public/js') { $testPath .= '/'. $moduleName. '/'; } elseif ($testEntry === 'payment') { $testPath = $bxRoot. '/'. $moduleName. '/'. $testEntry; } else { $testPath .= '/bitrix/'; } $testDirectory = new Main\IO\Directory($testPath); if ($testDirectory->isExists()) { self::$map[$moduleName][$testEntry] = array(); foreach ($testDirectory->getChildren() as $testDirectoryEntry) { if ($testDirectoryEntry->isDirectory()) { if ($testEntry === 'js' || $testEntry === 'public/js') { self::$map[$moduleName][$testEntry][$moduleName.'/'.$testDirectoryEntry->getName()] = 1; } else { self::$map[$moduleName][$testEntry][$testDirectoryEntry->getName()] = 1; } } } } } } } } $cacheManager->set(static::CACHE_ID, static::$map); } return self::$map; } /** * @param $language * @param $langFile * @return array */ public static function getEncodings($language, $langFile) { static $encodingCache = array(); if(isset($encodingCache[$language])) { list($convertEncoding, $targetEncoding, $sourceEncoding) = $encodingCache[$language]; } else { $convertEncoding = self::needConvertEncoding($language); $targetEncoding = $sourceEncoding = ''; if($convertEncoding) { $targetEncoding = self::getCurrentEncoding(); $sourceEncoding = self::getSourceEncoding($language); } $encodingCache[$language] = array($convertEncoding, $targetEncoding, $sourceEncoding); } if($convertEncoding) { $convertEncoding = self::checkPathRestrictionConvertEncoding($langFile); } return array($convertEncoding, $targetEncoding, $sourceEncoding); } }