Your IP : 3.144.28.90


Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/localization/
Upload File :
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);
	}
}