<?php

/**
 * Ahead WebSoft Technologies Pvt Ltd.
 * @copyright  Copyright 2006-2026 Ahead WebSoft Technologies Pvt Ltd.
 * @license    https://www.socialengine.com/policies
 */
class Core_AdminLanguageController extends Core_Controller_Action_Admin
{
	protected $_languagePath;

	public function init()
	{
		$this->_languagePath = APPLICATION_PATH . '/application/languages';
	}

	public function indexAction()
	{

		// Prepare default langauge
		$this->view->defaultLanguage = $defaultLanguage = Engine_Api::_()->getApi('settings', 'core')->getSetting('core.locale.locale', 'en');
		if ($defaultLanguage == 'auto') {
			$this->view->defaultLanguage = $defaultLanguage = 'en';
		}

		$languageTable = Engine_Api::_()->getDbTable('languages', 'core');
		// Init default locale
		$localeObject = Zend_Registry::get('Locale');
		$languages = Zend_Locale::getTranslationList('language', $localeObject);
		$territories = Zend_Locale::getTranslationList('territory', $localeObject);

		//Create in table
		$languagesDir = [];
		$items = scandir($this->_languagePath);
		foreach ($items as $item) {
			if ($item == '..' || $item == '.' || $item == 'index.html')
				continue;
			if (is_dir($this->_languagePath . '/' . $item))
				$languagesDir[] = $item;
		}

		foreach ($languagesDir as $language) {
			$isLanguageExist = Engine_Api::_()->getDbTable('languages', 'core')->isLanguageExist($language);
			if (empty($isLanguageExist)) {
				try {
					if (isset($languages[$language]) && $languages[$language]) {
						$languageName = $languages[$language];
					} else {
						$languageArray = explode('_', $language);
						if (isset($languageArray[1])) {
							$languageName = $territories[$languageArray[1]];
						}
					}
					$row = $languageTable->createRow();
					$values['code'] = $language;
					$values['name'] = $languageName;
					$values['fallback'] = $language;
					$row->setFromArray($values);
					$row->save();
					$row->order = $row->language_id;
					$row->save();
				} catch (Exception $e) {
					//silence
				}
			}
		}

		$this->view->languageNameList = $localeMultiOptions = Engine_Api::_()->getApi('languages', 'core')->getLanguages(array('admin' => 1));
	}

	public function createAction()
	{
		$translate = Zend_Registry::get('Zend_Translate');
		$form = $this->view->form = new Core_Form_Admin_Language_Create();
		$this->view->languageList = $languageList = $translate->getList();

		if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {
			$localeCode = $this->_getParam('language');

			$defaultLanguage = Engine_Api::_()->getApi('settings', 'core')->getSetting('core.locale.locale', 'en');
			if (!engine_in_array($defaultLanguage, $languageList)) {
				if ($defaultLanguage == 'auto' && isset($languageList['en'])) {
					$defaultLanguage = 'en';
				} else {
					$defaultLanguage = null;
				}
			}

			if (!engine_in_array($localeCode, $translate->getList())) {
				$filename = APPLICATION_PATH . "/application/languages/$localeCode/custom.csv";
				mkdir(dirname($filename));
				chmod(dirname($filename), 0777);
				touch($filename);
				chmod($filename, 0777);
				$csv = new Engine_Translate_Writer_Csv($filename);
				// each language pack must have at least one line written to it to be recognized
				$csv->setTranslation($localeCode, $localeCode);
				$csv->write();

				$adapter = Engine_Api::_()->getApi('settings', 'core')->getSetting('core.translate.adapter', 'array');

				if ($adapter == 'array') {
					//create array file
					$folder = APPLICATION_PATH . "/application/languages/$localeCode";
					$this->csv_folder_to_array($folder, $localeCode);
				}


				//Create in table
				$languageName = Zend_Locale_Data::getList($localeCode, 'language');
				$languageTable = Engine_Api::_()->getDbTable('languages', 'core');
				$language = $languageTable->createRow();
				$values['code'] = $localeCode;
				$values['name'] = $languageName[$localeCode];
				$values['fallback'] = $localeCode;
				$language->setFromArray($values);
				$language->save();
				$language->order = $language->language_id;
				$language->save();
			}
			$this->_helper->redirector->gotoRoute(array('action' => 'index'));
		}
	}

	public function uploadAction()
	{
		$form = $this->view->form = new Core_Form_Admin_Language_Upload();
		if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {
			$localeCode = $this->_getParam('locale', null);
			if (!empty($localeCode)) {
				$filename = APPLICATION_PATH . "/application/languages/$localeCode/custom.csv";
				@mkdir(dirname($filename));
				@chmod(dirname($filename), 0777);

				if (move_uploaded_file($_FILES['file']['tmp_name'], $filename)) {
					@chmod($filename, 0777);
					$adapter = Engine_Api::_()->getApi('settings', 'core')->getSetting('core.translate.adapter', 'array');

					if ($adapter == 'array') {
						$folder = APPLICATION_PATH . "/application/languages/$localeCode";
						$this->csv_folder_to_array($folder, $localeCode);
					}

					$this->_forward(
						'success',
						'utility',
						'core',
						array(
							'parentRefresh' => 2000,
							'messages' => array(Zend_Registry::get('Zend_Translate')->_('Language file has been uploaded.')),
							'redirect' => Zend_Controller_Front::getInstance()->getRouter()->assemble(array('action' => 'index')),
						)
					);
				} else {
					$form->addError('Unable to import language file to this language.  Please CHMOD 777 the "/application/languages" directory an all directories and files inside it, then try again.');
				}
			} else {
				$form->addError('Unknown language');
			}
		}
	}

	public function defaultAction()
	{
		if ($this->getRequest()->isPost()) {
			$locale = $this->_getParam('locale', 'en');

			$languageNameList = Engine_Api::_()->getApi('languages', 'core')->getLanguages(array('admin' => 1));

			if (engine_in_array($locale, array_keys($languageNameList))) {
				Engine_Api::_()->getApi('settings', 'core')->core_locale_locale = $locale;
				if ($locale == 'en') {
					$dbGetInsert = Engine_Db_Table::getDefaultAdapter();
					$dbGetInsert->update('engine4_core_languages', array('enabled' => 1), array('code =?' => $locale));
				}
			}
		}
	}

	public function enabledAction()
	{
		if ($this->getRequest()->isPost()) {
			$locale = $this->_getParam('locale', 'en');
			$disableLocale = $this->_getParam('disableLocale', 1);
			$dbGetInsert = Engine_Db_Table::getDefaultAdapter();
			if (!empty($disableLocale)) {
				$dbGetInsert->update('engine4_core_languages', array('enabled' => 0), array('code =?' => $locale));
			} else {
				$dbGetInsert->update('engine4_core_languages', array('enabled' => 1), array('code =?' => $locale));
			}
		}
	}

	public function editIconAction()
	{

		$this->_helper->layout->setLayout('admin-simple');
		$locale = $this->_getParam('locale', null);
		$this->view->form = $form = new Core_Form_Admin_Language_EditIcon();
		$isLanguageExist = Engine_Api::_()->getDbTable('languages', 'core')->isLanguageExist($locale);
		$language = Engine_Api::_()->getItem('core_language', $isLanguageExist);
		$form->icon->setValue($language->icon);
		if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {
			$language->icon = $_POST['icon'];
			$language->save();

			$this->_forward(
				'success',
				'utility',
				'core',
				array(
					'smoothboxClose' => 10,
					'parentRefresh' => 10,
					'messages' => array('Icon has been upoaded successfully.')
				)
			);
		}
	}

	public function deleteAction()
	{
		$form = $this->view->form = new Core_Form_Admin_Language_Delete();

		$languageList = Zend_Locale_Data::getList('en', 'language');
		$territoryList = Zend_Locale_Data::getList('en', 'territory');
		$localeCode = $this->_getParam('locale', null);
		if (empty($localeCode)) {
			return;
		}
		if (false !== strpos($localeCode, '_')) {
			list($locale, $territory) = explode('_', $localeCode);
		} else {
			$locale = $localeCode;
			$territory = null;
		}


		$languagePack = $languageList[$locale];
		if ($territory && !empty($territoryList[$territory])) {
			$languagePack .= " ({$territoryList[$territory]})";
		}
		$languagePack .= "  [$localeCode]";

		$form->setDescription(sprintf($form->getDescription(), $languagePack));


		if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {
			$lang_dir = APPLICATION_PATH . '/application/languages/' . $localeCode;
			try {
				@Engine_Package_Utilities::fsRmdirRecursive($lang_dir, true);

				Engine_Api::_()->getDbTable('languages', 'core')->delete(array('code =?' => $localeCode, "fallback =?" => $localeCode));

				$this->_forward(
					'success',
					'utility',
					'core',
					array(
						'smoothboxClose' => 2000,
						'parentRefresh' => 2000,
						'format' => 'smoothbox',
						'messages' => array(Zend_Registry::get('Zend_Translate')->_('Language has been deleted.')),
					)
				);
			} catch (Exception $e) {
				$form->addError('Unable to delete language files.  Please log in through FTP and delete the directory "/application/languages/' . $localeCode . '/ and all of the files inside.');
			}
		}
	}

	public function editAction()
	{
		$this->view->locale = $locale = $this->_getParam('locale');
		$this->view->page = $page = $this->_getParam('page');

		$translate = new Zend_Translate(
			'Engine_Translate_Adapter_Csv',
			APPLICATION_PATH . '/application/languages/' . $locale,
			null,
			array(),
		);

		try {
			if (!$locale || !Zend_Locale::findLocale($locale)) {
				throw new Exception('missing locale ' . $locale);
			}
		} catch (Exception $e) {
			return $this->_helper->redirector->gotoRoute(array('action' => 'index', 'controller' => 'language'), 'admin_default', true);
		}

		// Process filter form
		$this->view->filterForm = $filterForm = new Core_Form_Admin_Language_Filter();
		$filterForm->isValid($this->_getAllParams());
		$filterValues = $filterForm->getValues();
		extract($filterValues); // search, show

		// Make query
		$filterValues = array_filter($filterValues);
		$this->view->values = $filterValues;
		$this->view->query = (empty($filterValues) ? '' : '?' . http_build_query($filterValues));

		// Assign basic locale info
		$this->view->localeObject = $localeObject = new Zend_Locale($locale);
		$this->view->locale = $locale = $localeObject->toString();

		// Get locale translation info
		$localeLanguage = $localeObject->getLanguage();
		$localeRegion = $localeObject->getRegion();
		$this->view->localeLanguageTranslation = $localeLanguageTranslation
			= Zend_Locale::getTranslation($localeLanguage, 'language', Zend_Registry::get('Locale'));
		$this->view->localeRegionTranslation = $localeRegionTranslation
			= Zend_Locale::getTranslation($localeRegion, 'territory', Zend_Registry::get('Locale'));

		$translate1 = Zend_Registry::get('Zend_Translate');

		if ($localeLanguageTranslation && $localeRegionTranslation) {
			$this->view->localeTranslation = $localeLanguageTranslation . ' '
				. sprintf($translate->translate('(%s)'), $localeRegionTranslation) . ' '
				. sprintf($translate->translate('[%s]'), $locale);
		} elseif ($localeLanguageTranslation) {
			$this->view->localeTranslation = $localeLanguageTranslation . ' '
				. sprintf($translate->translate('[%s]'), $locale);
		} else {
			$this->view->localeTranslation = sprintf($translate->translate('[%s]'), $locale);
		}

		// Query plural system for max and sample space
		$sample = array();
		$max = 0;
		for ($i = 0; $i <= 1000; $i++) {
			$form = Zend_Translate_Plural::getPlural($i, $locale);
			$max = max($max, $form);
			if (@engine_count($sample[$form]) < 3) {
				$sample[$form][] = $i;
			}
		}
		$this->view->pluralFormCount = ($max + 1);
		$this->view->pluralFormSample = $sample;

		// Get initial and default values
		$baseMessages = $this->_getLanguageMessagesForInstalledModules('en');
		if ($translate->isAvailable($locale)) {
			$currentMessages = $this->_getLanguageMessagesForInstalledModules($locale);
		} else {
			$currentMessages = array(); // @todo this should redirect or smth
		}

		// Get phrases that are not in the english pack?
		if (!empty($currentMessages) && $locale != 'en') {
			$missingBasePhrases = array_diff_key($currentMessages, $baseMessages);
			$missingBasePhrases = array_combine(array_keys($missingBasePhrases), array_keys($missingBasePhrases));
			$baseMessages = array_merge($baseMessages, $missingBasePhrases);
		}

		// Build the fancy array
		$resultantMessages = array();
		$missing = 0;
		$index = 0;
		foreach ($baseMessages as $key => $value) {
			// Build
			$composite = array(
				'uid' => ++$index,
				'key' => $key,
				'original' => $value,
				'plural' => (bool) is_array($value),
			);

			// filters, plurals, and missing, oh my.
			if (!$this->_isTranslationMissing($key, $currentMessages, $value)) {
				if ('missing' == $show) {
					continue;
				}
				if (is_array($value) && !is_array($currentMessages[$key])) {
					$composite['current'] = array($currentMessages[$key]);
				} elseif (!is_array($value) && is_array($currentMessages[$key])) {
					$composite['current'] = current($currentMessages[$key]);
				} else {
					$composite['current'] = $currentMessages[$key];
				}
			} else {
				if ('translated' == $show) {
					continue;
				}
				if (is_array($value)) {
					$composite['current'] = array();
				} else {
					$composite['current'] = '';
				}
				$missing++;
			}

			// Do search
			if ($search && !$this->_searchArrayRecursive($search, $composite)) {
				continue;
			}
			// Add
			$resultantMessages[] = $composite;
		}

		// Build the paginator
		$this->view->paginator = $paginator = Zend_Paginator::factory($resultantMessages);
		$paginator->setItemCountPerPage(50);
		$paginator->setCurrentPageNumber($page);


		// Process form POST
		if ($this->getRequest()->isPost()) {
			$keys = $this->_getParam('keys');
			$values = $this->_getParam('values');

			// Try to combine the values and keys arrays
			$combined = array();
			foreach ($values as $index => $value) {
				if (is_string($value)) {
					if (empty($value)) {
						continue;
					}
					$key = $keys[$index];
					$combined[$key] = $value;
				} elseif (is_array($value)) {
					if (empty($value) || array_filter($value) === array()) {
						continue;
					}
					$key = $keys[$index][0];
					if (engine_count($value) == 1)
						$combined[$key] = array_merge($value, array($value[0]));
					else
						$combined[$key] = $value;
				}
			}

			// Try to write to a file
			$targetFile = APPLICATION_PATH . '/application/languages/' . $locale . '/custom.csv';
			if (!file_exists($targetFile)) {
				touch($targetFile);
				chmod($targetFile, 0777);
			}

			$writer = new Engine_Translate_Writer_Csv($targetFile);
			$writer->setTranslations($combined);
			$writer->write();

			// flush cached language vars
			@Zend_Registry::get('Zend_Cache')->clean();

			// redirect to this same page to get the new values
			return $this->_redirect($_SERVER['REQUEST_URI'], array('prependBase' => false));
		}
	}

	public function addPhraseAction()
	{

		$form = $this->view->form = new Core_Form_Admin_Language_AddPhrase();

		if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {
			$phrase = $this->_getParam('phrase');

			$locale = $this->_getParam('locale');

			if ($phrase && $locale) {
				$targetFile = APPLICATION_PATH . '/application/languages/' . $locale . '/custom.csv';
				if (!file_exists($targetFile)) {
					touch($targetFile);
					chmod($targetFile, 0777);
				}
				if (file_exists($targetFile)) {
					$writer = new Engine_Translate_Writer_Csv($targetFile);
					$writer->setTranslations(
						array(
							$phrase => $phrase,
						)
					);
					$writer->write();
					@Zend_Registry::get('Zend_Cache')->clean();
				}
			}
			$this->_forward('success', 'utility', 'core', array(
				'parentRedirect' => Zend_Controller_Front::getInstance()->getRouter()->assemble(array(
					'module' => 'core',
					'controller' => 'language',
					'action' => 'edit',
					'locale' => $locale,
				), 'admin_default', true) . '?search=' . urlencode($phrase)
			));
		}
	}

	public function translateAction()
	{
		// Prepare form
		$this->view->form = $form = new Core_Form_Admin_Language_Translate();

		// Check method/valid
		if (!$this->getRequest()->isPost()) {
			return;
		}
		if (!$form->isValid($this->getRequest()->getPost())) {
			return;
		}

		$this->view->form = null;
		$this->view->values = $form->getValues();
	}

	public function translateRemoteAction()
	{
		set_time_limit(0);

		// Get params
		$this->view->source = $source = $this->_getParam('source');
		$this->view->target = $target = $this->_getParam('target');
		$this->view->batchCount = $batchCount = $this->_getParam('batchCount', 50);
		$this->view->retranslate = $retranslate = $this->_getParam('retranslate');
		$this->view->file = $file = $this->_getParam('file');
		$this->view->offset = $offset = $this->_getParam('offset', 0);

		// Check params

		// Check source
		if (empty($source) || !is_string($source)) {
			throw new Engine_Exception('Invalid source data type');
		}
		if (!Zend_Locale::isLocale($source)) {
			$this->view->status = false;
			$this->view->error = 'The source language does not appear to be a valid locale.';
			return;
		}
		if (!Engine_Service_GTranslate::isAvailableLanguage($source)) {
			$this->view->status = false;
			$this->view->error = 'The source language does not appear to be a available for translation.';
			return;
		}

		// Check source dir
		$sourceDir = $this->_languagePath . '/' . $source;
		if (!is_dir($sourceDir)) {
			$this->view->status = false;
			$this->view->error = 'The source language does not appear to exist.';
			return;
		}

		// Check target
		if (empty($target) || !is_string($target)) {
			$this->view->status = false;
			$this->view->error = 'Invalid target data type.';
			return;
		}

		// See if we need to expand target
		if (engine_in_array($target, array('all', 'all-translated', 'all-untranslated'))) {
			$form = new Core_Form_Admin_Language_Translate();
			$targetMultiOptions = $form->target->options;
			if ($target == 'all-translated') {
				$targets = $targetMultiOptions['Translated'];
			} elseif ($target == 'all-untranslated') {
				$targets = $targetMultiOptions['Untranslated'];
			} else {
				$targets = array_merge($targetMultiOptions['Untranslated'], $targetMultiOptions['Translated']);
			}

			// Meh
			$this->view->status = true;
			$this->view->state = 'listTargets';
			$this->view->targets = $targets;
			return;
		}

		// Check target
		if (!Zend_Locale::isLocale($source)) {
			$this->view->status = false;
			$this->view->error = 'The target language does not appear to be a valid locale.';
			return;
		}
		if (!Engine_Service_GTranslate::isAvailableLanguage($source)) {
			$this->view->status = false;
			$this->view->error = 'The target language does not appear to be a available for translation.';
			return;
		}

		// Check target dir
		$targetDir = $this->_languagePath . '/' . $target;
		if (!is_dir($targetDir)) {
			// try to create
			if (!@mkdir($targetDir, 0777, true)) {
				$this->view->status = false;
				$this->view->error = 'The target language pack does not exist and it was not possible to create it.';
				return;
			}
		}


		// Check files
		$sourceFiles = array();
		$it = new DirectoryIterator($sourceDir);
		foreach ($it as $file) {
			// Ignore dirs (duh)
			if (!$file->isFile()) {
				continue;
			}
			if (strtolower(substr($file->getFilename(), -4)) !== '.csv') {
				continue;
			}
			// Ignore files that have already been translated (at least for now)
			//if( file_exists($targetDir . '/' . $file->getFilename()) ) continue;
			$files[] = basename($file->getPathName());
		}

		if (empty($files)) {
			$this->view->status = false;
			$this->view->error = 'No source files.';
			return;
		}

		// See if we need to expand file
		if (empty($file)) {
			$this->view->status = true;
			$this->view->state = 'listFiles';
			$this->view->files = $files;
			return;
		} elseif (!engine_in_array($file, $files)) {
			$this->view->status = false;
			$this->view->error = 'Not a valid file.';
			return;
		}

		$sourceFile = $sourceDir . '/' . $file;
		$targetFile = $targetDir . '/' . $file;

		// Init translate API
		$languageApi = new Engine_Service_GTranslate();
		$languageApi->setRequestType('curl');

		// Init reader and writer
		$reader = new Engine_Translate_Writer_Csv($sourceFile);
		$writer = new Engine_Translate_Writer_Csv($targetFile);

		// Get messages and diff
		$sourceMessages = $reader->getTranslations();
		$targetMessages = $writer->getTranslations();
		$deltaMessages = array_diff_key($sourceMessages, $targetMessages);

		// Take the batchCount of messages
		// In retranslate mode, we need to go by offset
		$currentMessages = array_slice($deltaMessages, ($retranslate ? $offset : 0), $batchCount);
		if ($retranslate) {
			$this->view->newOffset = $offset = ($offset + engine_count($currentMessages));
		}

		// If it's empty, we're done with the file
		if ((!$retranslate && empty($deltaMessages)) || empty($currentMessages)) {
			$this->view->status = true;
			$this->view->state = 'fileComplete';
			return;
		}

		// Process plurals into normal variables temporarily
		$currentKeys = array();
		$currentValues = array();

		foreach ($currentMessages as $key => $value) {
			if (is_array($value)) {
				foreach ($value as $val) {
					$currentKeys[] = $key;
					$currentValues[] = $this->_escape($val);
				}
			} else {
				$currentKeys[] = $key;
				$currentValues[] = $this->_escape($value);
			}
		}

		// Send to google
		$response = (array) $languageApi->query($source, $target, $currentValues);
		if (!$response || engine_count($response) !== engine_count($currentValues)) {
			$this->view->status = false;
			$this->view->error = 'Translation failed';
			return;
		}

		// Process response back into plurals
		$resultantMessages = array();
		foreach ($currentKeys as $index => $key) {
			//$previousValue = $currentValues[$index];
			$value = $this->_unescape($response[$index]);

			if (isset($resultant[$key])) {
				if (!is_array($resultant[$key])) {
					$resultant[$key] = array($resultant[$key]);
				}
				$resultant[$key][] = $value;
			} else {
				$resultant[$key] = $value;
			}
		}


		// Write to file
		$writer->setTranslations($resultantMessages);
		$writer->write();


		// Send back statistics
		$this->view->status = true;
		$this->view->sourceCount = engine_count($sourceMessages);
		$this->view->targetCount = engine_count($targetMessages);
		$this->view->untranslatedCount = engine_count($deltaMessages);
		$this->view->translatedCount = engine_count($resultantMessages);
	}

	public function translatePhraseAction()
	{
		// Make sure source is valid
		$this->view->source = $source = $this->_getParam('source');
		if (!Zend_Locale::isLocale($source)) {
			$this->view->status = false;
			$this->view->error = 'Source is not a valid Zend locale';
			return;
		}
		if (!Engine_Service_GTranslate::isAvailableLanguage($source)) {
			$this->view->status = false;
			$this->view->error = 'Source is not a valid Google locale';
			return;
		}

		// Make sure target is valid
		$this->view->target = $target = $this->_getParam('target');
		if (!Zend_Locale::isLocale($target)) {
			$this->view->status = false;
			$this->view->error = 'Target is not a valid Zend locale';
			return;
		}
		if (!Engine_Service_GTranslate::isAvailableLanguage($target)) {
			$this->view->status = false;
			$this->view->error = 'Target is not a valid Google locale';
			return;
		}

		// Make sure we have a phrase
		$text = $this->_getParam('text');
		if (!$text) {
			$this->view->status = false;
			$this->view->error = 'No text was given';
			return;
		}

		// Check for escape param
		$escape = (bool) $this->_getParam('escape', true);

		// Send query
		$languageApi = new Engine_Service_GTranslate();
		$languageApi->setRequestType('curl');

		if ($escape) {
			$this->view->sourcePhraseUnescaped = $text;
			$text = $this->_escape($text);
		}

		$response = $languageApi->query($source, $target, $text);

		if ($escape) {
			$this->view->targetPhraseEscaped = $response;
			$response = $this->_unescape($response);
		}


		// Assign response
		$this->view->sourcePhrase = $text;
		$this->view->targetPhrase = $response;
	}

	public function exportAction()
	{
		$locale = $this->_getParam('locale', 'en');  // e.g., 'ar'
		$translationDir = APPLICATION_PATH . DIRECTORY_SEPARATOR . 'application' . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . $locale;
		$output = [];

		if (!is_dir($translationDir)) {
			throw new Exception("Translation directory not found: " . $translationDir);
		}

		$csvFiles = glob($translationDir . '/*.csv');
		if (empty($csvFiles)) {
			throw new Exception("No CSV files found in translation directory.");
		}

		foreach ($csvFiles as $csvFile) {
			$handle = fopen($csvFile, 'r');
			if (!$handle) continue;

			while (($data = fgetcsv($handle, 0, ';')) !== false) {
				if (count($data) >= 2) {
					$key = trim($data[0]);
					$value = trim($data[1]);

					if (!isset($output[$key])) {
						$output[$key] = $value;
					}
				}
			}
			fclose($handle);
		}

		ksort($output); // Optional: sort keys alphabetically

		if (empty($output)) {
			throw new Exception("No translations found after merging.");
		}

		$tmpFile = APPLICATION_PATH . "/temporary/merged_{$locale}.csv";
		$fp = fopen($tmpFile, 'w');
		if (!$fp) {
			throw new Exception("Cannot write to file: $tmpFile");
		}

		// Write using semicolon as delimiter
		foreach ($output as $key => $value) {
			// Skip empty keys to prevent leading semicolon
			if ($key === '') continue;
			fputcsv($fp, [$key, $value], ';');
		}

		fclose($fp);

		// Force download
		header("Content-Disposition: attachment; filename=\"{$locale}.csv\"");
		header("Content-Type: text/csv; charset=utf-8");
		header("Content-Length: " . filesize($tmpFile));
		readfile($tmpFile);
		unlink($tmpFile);
		exit;
	}

	protected function _getLanguageMessagesForInstalledModules($locale)
	{
		$languageDir = APPLICATION_PATH . '/application/languages/' . $locale;
		if (!is_dir($languageDir)) {
			return array();
		}

		$moduleTable = Engine_Api::_()->getDbtable('modules', 'core');
		$enabledModuleNames = $moduleTable->getEnabledModuleNames();
		$messages = array();
		$files = glob($languageDir . DIRECTORY_SEPARATOR . '*.csv');
		if (empty($files)) {
			return $messages;
		}

		foreach ($files as $file) {
			$fileName = basename($file, '.csv');
			$shouldInclude = ($fileName === 'core' || $fileName === 'custom');
			if (!$shouldInclude && !engine_in_array($fileName, $enabledModuleNames)) {
				continue;
			}

			$parsedMessages = Engine_Translate_Parser_Csv::parse($file, $locale, array(
				'delimiter' => ';',
				'enclosure' => '"',
			));

			if (!empty($parsedMessages[$locale])) {
				$messages = array_merge($messages, $parsedMessages[$locale]);
			}
		}

		return $messages;
	}

	protected function _isTranslationMissing($key, $currentMessages, $value = null)
	{
		if (!array_key_exists($key, $currentMessages)) {
			return true;
		}

		$currentValue = $currentMessages[$key];
		if (is_array($currentValue)) {
			$filteredValues = array_filter($currentValue, function ($item) {
				return $item !== null && $item !== '';
			});
			return empty($filteredValues);
		}

		if (is_string($currentValue)) {
			return trim($currentValue) === '';
		}

		return $currentValue === null || $currentValue === '';
	}

	protected function _searchArrayRecursive($searchStr, $searchValue)
	{
		$found = false;
		if (is_array($searchValue)) {
			foreach ($searchValue as $key => $value) {
				if (is_string($value) && stripos($value, $searchStr) !== false) {
					$found = true;
					break;
				} elseif (is_array($value)) {
					if ($this->_searchArrayRecursive($searchStr, $value)) {
						$found = true;
						break;
					}
				}
			}
		}

		return $found;
	}

	protected function _escape($string)
	{
		// <![CDATA[
		// ]]>

		// Cdata
		// Format: {}
		//$cdataChar = "\x10";
		//$cdataData = null;
		//$string = $this->_replaceAll('/' . preg_quote('<![CDATA[', '/') . '.+?' . preg_quote(']]>', '/') . '/iu', $string, $cdataChar, $cdataData);

		// Just strip cdata for now
		$string = str_replace(array('<![CDATA[', ']]>'), array('', ''), $string);

		// Sprintf
		// Format: php.net
		$sprintfChar = "\x14";
		$sprintfData = null;
		$string = $this->_replaceAll('/\%([0-9]\$)?[ds]/iu', $string, $sprintfChar, $sprintfData);

		// Activity
		// Format: {}
		$activityChar = "\x11";
		$activityData = null;
		$string = $this->_replaceAll('/\{[^{}\x11\x12\x13\x14]+?\}/iu', $string, $activityChar, $activityData);

		// Substitution
		// Format: %%
		$substitutionChar = "\x12";
		$substitutionData = null;
		$string = $this->_replaceAll('/\%[^%\x11\x12\x13\x14]+?\%/iu', $string, $substitutionChar, $substitutionData);

		// Mail
		// Format: []
		$mailChar = "\x13";
		$mailData = null;
		$string = $this->_replaceAll('/\[[^\[\]\x11\x12\x13\x14]+?\]/iu', $string, $mailChar, $mailData);


		// Line breaks
		$lineChar = "\x15";
		$lineData = null;
		$string = $this->_replaceAll('/[\r\n]+/iu', $string, $lineChar, $lineData);


		// Restore everything
		$string = $this->_restoreAll($activityChar, $activityData, $string);
		$string = $this->_restoreAll($substitutionChar, $substitutionData, $string);
		$string = $this->_restoreAll($mailChar, $mailData, $string);
		$string = $this->_restoreAll($sprintfChar, $sprintfData, $string);
		$string = $this->_restoreAll($lineChar, $lineData, $string);

		return $string;
	}

	protected function _unescape($string)
	{
		// Decode
		$string = htmlspecialchars_decode($string, ENT_QUOTES);

		// Remove
		$string = preg_replace('/' . preg_quote('<![CDATA[', '/') . '(.*?)' . preg_quote(']]>', '/') . '/ius', '$1', $string);

		/*
        // Mail
        $string = preg_replace('/\<\?\{{3}([^\[\]]+?)\}{3}\?\>/iu', '[$1]', $string);

        // Substitution
        $string = preg_replace('/\<\?\{{2}([^%]+?)\}{2}\?\>/iu', '%$1%', $string);

        // Activity
        $string = preg_replace('/\<\?\{([^%]+?)\}\?\>/iu', '{$1}', $string);

        // Sprintf
        $string = preg_replace('/\<\?(\%([0-9]\$)?[ds])\?\>/iu', '$1', $string);
        */

		return $string;
	}

	protected function _replaceAll($pattern, $subject, $replace, &$replaceData)
	{
		preg_match_all($pattern, $subject, $matches, PREG_OFFSET_CAPTURE);
		if (empty($matches)) {
			return array();
		}

		$replaceData = array();
		$delta = 0;
		foreach ($matches[0] as $match) {
			$subString = $match[0];
			$start = $match[1] - $delta;
			$length = strlen($subString);
			$replaceData[] = $subString;
			$subject = substr($subject, 0, $start)
				. $replace
				. substr($subject, $start + $length);
			$delta += $length - 1;
		}

		return $subject;
	}

	protected function _restoreAll($char, $data, $string)
	{
		// <![CDATA[
		// ]]>
		if (is_array($data) && engine_count($data) > 0) {
			$string = str_replace($char, '<![CDATA[' . $char . ']]>', $string);
			foreach ($data as $datum) {
				$pos = strpos($string, $char);
				if (false !== $pos) {
					$string = substr($string, 0, $pos)
						. $datum
						. substr($string, $pos + strlen($char));
				}
			}
		}
		return $string;
	}

	public function apiAction()
	{

		$this->view->form = $form = new Core_Form_Admin_Language_Api();

		$this->_helper->layout->setLayout('admin-simple');

		if (!$this->getRequest()->isPost()) {
			return;
		}

		if (!$form->isValid($this->getRequest()->getPost())) {
			return;
		}

		try {
			$values = $form->getValues();
			Engine_Api::_()->getApi('settings', 'core')->setSetting('core_googletranslatorapi', $values['core_googletranslatorapi']);

			$this->_forward('success', 'utility', 'core', array(
				'smoothboxClose' => true,
				'parentRefresh' => true,
				'messages' => array('Google translation api key saved successfully.')
			));
		} catch (Exception $e) {
		}
	}

	public function autotranslateAction()
	{

		$this->view->locale = $this->_getParam('locale', null);

		$this->view->form = $form = new Core_Form_Admin_Language_Autotranslate();

		$this->_helper->layout->setLayout('admin-simple');

		if (!$this->getRequest()->isPost()) {
			return;
		}

		if (!$form->isValid($this->getRequest()->getPost())) {
			return;
		}
	}

	public function addnewpackAction()
	{

		$phrases_translate = $this->_getParam('phrases_translate', 'all');

		$enFolderFilePath = APPLICATION_PATH . DIRECTORY_SEPARATOR . 'application' . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'en';

		if (file_exists(@$enFolderFilePath)) {

			$file = $this->_getParam('langs', null);
			$file_type = strtolower(end(explode('.', @$file)));
			$convert_languages = $this->_getParam('convert_languages', null);

			ini_set('max_execution_time', 0);
			set_time_limit(0);

			if (($file !== '.') && ($file !== '..') && (engine_in_array($file_type, array('csv')))) {

				$tmp = Engine_Translate_Parser_Csv::parse(APPLICATION_PATH . '/application/languages/en/' . $file, 'null', array('delimiter' => ';', 'enclosure' => '"'));

				if (!empty($tmp['null']) && is_array($tmp['null']))
					$phrases = $tmp['null'];
				else
					$phrases = array();

				$specialValues = $this->specialValuesArray();

				// Collect all texts to translate
				$textsToTranslate = array();
				$textIndexMap = array();
				$index = 0;

				foreach ($phrases as $key => $phrase) {
					if (is_array($phrase)) {
						foreach ($phrase as $idx => $phraseT) {
							$phraseT = strtr((string) $phraseT, $specialValues);
							$textsToTranslate[$index] = $phraseT;
							$textIndexMap[$index] = array('type' => 'array', 'key' => $key, 'subIdx' => $idx);
							$index++;
						}
					} else {
						$phrase = strtr((string) $phrase, $specialValues);
						$textsToTranslate[$index] = $phrase;
						$textIndexMap[$index] = array('type' => 'string', 'key' => $key);
						$index++;
					}
				}

				$api = Engine_Api::_()->getApi('languages', 'core');
				$translations = $api->batchTranslate($textsToTranslate, 'en', $convert_languages);

				$translateTextArray = array();
				$replace = array_keys($specialValues);
				$find = array_values($specialValues);

				foreach ($translations as $idx => $translatedText) {
					if (isset($textIndexMap[$idx])) {
						$mapping = $textIndexMap[$idx];
						$translatedText = str_ireplace($find, $replace, $translatedText);

						if ($mapping['type'] === 'array') {
							if (!isset($translateTextArray[$mapping['key']])) {
								$translateTextArray[$mapping['key']] = array();
							}
							$translateTextArray[$mapping['key']][$mapping['subIdx']] = htmlspecialchars_decode($translatedText, ENT_QUOTES);
						} else {
							$translateTextArray[$mapping['key']] = htmlspecialchars_decode($translatedText, ENT_QUOTES);
						}
					}
				}

				if ($translateTextArray) {
					$targetFolder = APPLICATION_PATH . DIRECTORY_SEPARATOR . 'application' . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . $convert_languages;
					if (!is_dir($targetFolder)) {
						mkdir($targetFolder, 0777, true);
					}

					$targetFilePath = $targetFolder . DIRECTORY_SEPARATOR . $file;
					if (!file_exists($targetFilePath)) {
						touch($targetFilePath);
						chmod($targetFilePath, 0777);
					} else {
						chmod($targetFilePath, 0777);
					}

					$writer = new Engine_Translate_Writer_Csv($targetFilePath);
					$writer->setTranslations($translateTextArray);
					$writer->write();
				}
			}
		}
		echo json_encode(array('status' => 1));
		die;
	}

	public function convertmisssinglangAction()
	{

		$mainLanguagePhrase = $this->_getParam('main_language_phrase', null);
		$langs = $this->_getParam('langs', null);
		$phrasesTranslate = $this->_getParam('phrases_translate', 'missing');
		$translateOnlyMissing = ($phrasesTranslate !== 'all');

		$targetFile = APPLICATION_PATH . '/application/languages/' . $langs . '/custom.csv';
		$targetFolder = dirname($targetFile);
		if (!is_dir($targetFolder)) {
			@mkdir($targetFolder, 0777, true);
		}
		if (!file_exists($targetFile)) {
			touch($targetFile);
			chmod($targetFile, 0777);
		}

		$specialValues = $this->specialValuesArray();
		ini_set('max_execution_time', 0);
		set_time_limit(0);

		$textsToTranslate = array();
		$textIndexMap = array();
		$selectedMissingKeys = array();
		$index = 0;

		if (!empty($mainLanguagePhrase)) {
			$mainLanguagePhrase = strip_tags($mainLanguagePhrase);
			$mainLanguagePhrases = explode('||||', $mainLanguagePhrase);
			foreach ($mainLanguagePhrases as $mainPhrase) {
				$mainPhrase = trim($mainPhrase);
				if ($mainPhrase === '') {
					continue;
				}

				if (preg_match('/^"(.*)";"(.*)"$/s', $mainPhrase, $matches)) {
					$key = $matches[1];
				} else {
					$langArray = explode('";"', trim($mainPhrase, '"'));
					$key = isset($langArray[0]) ? trim($langArray[0], '"') : '';
				}

				if ($key !== '') {
					$selectedMissingKeys[$key] = true;
				}
			}
		}

		$translate = Zend_Registry::get('Zend_Translate');
		$baseMessages = $this->_getLanguageMessagesForInstalledModules('en');
		if ($translate->isAvailable($langs)) {
			$currentMessages = $this->_getLanguageMessagesForInstalledModules($langs);
		} else {
			$currentMessages = array();
		}

		if (!empty($currentMessages) && $langs != 'en') {
			$missingBasePhrases = array_diff_key($currentMessages, $baseMessages);
			$missingBasePhrases = array_combine(array_keys($missingBasePhrases), array_keys($missingBasePhrases));
			$baseMessages = array_merge($baseMessages, $missingBasePhrases);
		}

		foreach ($baseMessages as $key => $value) {
			if ($translateOnlyMissing && !$this->_isTranslationMissing($key, $currentMessages, $value)) {
				continue;
			}

			if (!empty($selectedMissingKeys) && !isset($selectedMissingKeys[$key])) {
				continue;
			}

			if (is_array($value)) {
				foreach ($value as $subIdx => $subValue) {
					$textsToTranslate[$index] = strtr((string) $subValue, $specialValues);
					$textIndexMap[$index] = array('type' => 'array', 'key' => $key, 'subIdx' => $subIdx);
					$index++;
				}
			} else {
				if ($value === '') {
					continue;
				}
				$textsToTranslate[$index] = strtr((string) $value, $specialValues);
				$textIndexMap[$index] = array('type' => 'string', 'key' => $key);
				$index++;
			}
		}

		if (empty($textsToTranslate)) {
			echo json_encode(array('status' => 1));
			die;
		}

		$api = Engine_Api::_()->getApi('languages', 'core');
		$translations = $api->batchTranslate($textsToTranslate, 'en', $langs);

		if (empty($translations)) {
			echo json_encode(array('status' => 0, 'error' => 'Translation failed.'));
			die;
		}

		$replace = array_keys($specialValues);
		$find = array_values($specialValues);
		$translateTextArray = array();

		foreach ($translations as $idx => $translatedText) {
			if (!isset($textIndexMap[$idx])) {
				continue;
			}

			$mapping = $textIndexMap[$idx];
			$translatedText = str_ireplace($find, $replace, $translatedText);
			$translatedText = htmlspecialchars_decode($translatedText, ENT_QUOTES);

			if ($mapping['type'] === 'array') {
				if (!isset($translateTextArray[$mapping['key']])) {
					$translateTextArray[$mapping['key']] = array();
				}
				$translateTextArray[$mapping['key']][$mapping['subIdx']] = $translatedText;
			} else {
				$translateTextArray[$mapping['key']] = $translatedText;
			}
		}

		if (!empty($translateTextArray)) {
			$writer = new Engine_Translate_Writer_Csv($targetFile);
			$writer->setTranslations($translateTextArray);
			$writer->write();
			@Zend_Registry::get('Zend_Cache')->clean();
		}

		echo json_encode(array('status' => 1));
		die;
	}

	private function _translateCSV($file, $targetLanguage)
	{

		ini_set('max_execution_time', 0);
		set_time_limit(0);

		$enFolderFilePath = APPLICATION_PATH . '/application/languages/en/' . $file;
		if (!file_exists($enFolderFilePath)) {
			return false;
		}

		$tmp = Engine_Translate_Parser_Csv::parse($enFolderFilePath, 'null', array('delimiter' => ';', 'enclosure' => '"'));
		$phrases = !empty($tmp['null']) && is_array($tmp['null']) ? $tmp['null'] : array();

		if (empty($phrases)) {
			return false;
		}

		// Collect all texts to translate
		$specialValues = $this->specialValuesArray();
		$textsToTranslate = array();
		$textIndexMap = array();
		$index = 0;

		foreach ($phrases as $key => $phrase) {
			if (is_array($phrase)) {
				foreach ($phrase as $idx => $phraseT) {
					$phraseT = strtr((string) $phraseT, $specialValues);
					$textsToTranslate[$index] = $phraseT;
					$textIndexMap[$index] = array('type' => 'array', 'key' => $key, 'subIdx' => $idx);
					$index++;
				}
			} else {
				$phrase = strtr((string) $phrase, $specialValues);
				$textsToTranslate[$index] = $phrase;
				$textIndexMap[$index] = array('type' => 'string', 'key' => $key);
				$index++;
			}
		}

		$api = Engine_Api::_()->getApi('languages', 'core');
		$translations = $api->batchTranslate($textsToTranslate, 'en', $targetLanguage);

		if (empty($translations)) {
			return false;
		}

		$translateTextArray = array();
		$replace = array_keys($specialValues);
		$find = array_values($specialValues);

		foreach ($translations as $idx => $translatedText) {
			if (isset($textIndexMap[$idx])) {
				$mapping = $textIndexMap[$idx];
				$translatedText = str_ireplace($find, $replace, $translatedText);

				if ($mapping['type'] === 'array') {
					if (!isset($translateTextArray[$mapping['key']])) {
						$translateTextArray[$mapping['key']] = array();
					}
					$translateTextArray[$mapping['key']][$mapping['subIdx']] = htmlspecialchars_decode($translatedText, ENT_QUOTES);
				} else {
					$translateTextArray[$mapping['key']] = htmlspecialchars_decode($translatedText, ENT_QUOTES);
				}
			}
		}

		// Write to file
		if (empty($translateTextArray)) {
			return false;
		}

		$targetFolder = APPLICATION_PATH . DIRECTORY_SEPARATOR . 'application' . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . $targetLanguage;
		if (!is_dir($targetFolder)) {
			mkdir($targetFolder, 0777, true);
		}

		$targetFilePath = $targetFolder . DIRECTORY_SEPARATOR . $file;
		if (!file_exists($targetFilePath)) {
			touch($targetFilePath);
			chmod($targetFilePath, 0777);
		} else {
			chmod($targetFilePath, 0777);
		}

		$writer = new Engine_Translate_Writer_Csv($targetFilePath);
		$writer->setTranslations($translateTextArray);
		$writer->write();

		return true;
	}

	public function specialValuesArray()
	{

		return array(
			'{item:$subject}' => 'SES_SES_1',
			'{others:$otherItems}' => 'SES_SES_2',
			'%s' => 'SES_SES_3',
			'&nbsp;' => 'SES_SES_4',
			'(subject)' => 'SES_SES_5',
			'(object)' => 'SES_SES_6',
			'<br /><br />' => 'SES_SES_8',
			'</a>' => 'SES_SES_9',
			'(%d)' => 'SES_SES_10',
			'{translate:$label}' => 'SES_SES_tr_la',
			'{var:$value}' => 'SES_SES_var_val',
			'{item:$object}' => 'SES_SES_itm_obj',
			'{actors:$subject:$object}:' => 'SES_SES_actr_sub_obj',
			'{body:$body}' => 'SES_SES_bo_bo',
			'{var:$label}' => 'SES_SES_va_la',
			'{var:$type}' => 'SES_SES_va_tpe',
			'{item:$object:$label}' => 'SES_SES_it_ob_la',
			'[sender_title]' => 'SES_SES_se_ti',
			'[header]' => 'SES_SES_header',
			'http://[host][object_link]' => 'SES_SES_htt_link',
			'[footer]' => 'SES_SES_ft',
			'%1$s' => 'SES_23_SES',
			'%2$s' => 'SES24SES',
			'{var:$count}' => 'SES_SES_vr_cnt',
			'(s)' => 'SES26SES',
			'{item:$owner}' => 'SES_SES_it_onr',
			'{item:$object:album}' => 'SES_SES_it_ob_al',
			'{item:$object:photo}' => 'SES_SES_it_ob_poto',
			'{item:$action:new photos}' => 'SES_SES_it_ac_nw_pots',
			'\r\n' => 'SES_per_s_SES',
			"<a href='%s'>" => 'SES_a_SES',
			'%d' => 'SESSES',
			'{item:$object:blog entry}' => 'SES_blg_etry_SES',
			'[object_title]' => 'SES__ojt_tle_SES',
			'&#187' => 'SES__187_SES',
			'{item:$object:classified listing}' => 'SES_cl_lit_SES',
			'<span>' => 'SES_op_spn_SES',
			'</span>' => 'SES_cl_spn_SES',
			'http://www.yoursite.com/pages/[url]' => 'SES_pgs_url_SES',
			'%1$d' => 'SES_41SES',
			'{name}' => 'SES_nme_SES',
			'{fileListMax}' => 'SES_file_mx_SES',
			'{fileListSizeMax}' => 'SES_fle_li_mx_SES',
			'<code>' => 'SES_op_cd_SES',
			'</code>' => 'SES__cd_SES',
			'{text}' => 'SES_txt_SES',
			'%max%' => 'SES_mx_SES',
			'%value%' => 'SES_vle_SES',
			'%hostname%' => 'SES_ht_nme_SES',
			'%localPart%' => 'SES_lo_prt_SES',
			'[recipient_title]' => 'SES_rcpt_tle_SES',
			'[sender_email]' => 'SES_se_eml_SES',
			'[message]' => 'SES_msg_SES',
			'[error_report]' => 'SES_eor_rpt_SES',
			'[password]' => 'SES_pwds_SES',
			'[date]' => 'SES_dte_SES',
			'{item:$object:posted}' => 'SES__postd_SES',
			'{itemParent:$object::event topic}' => 'SES_prnt_SES',
			'{itemParent:$object:event}' => 'SES_60SES',
			'{item:$object:topic}' => 'SES_61SES',
			'[object_parent_title]' => 'SES_62SES',
			'{itemParent:$object:forum}' => 'SES_63SES',
			'{item:$postGuid:posted}' => 'SES_64SES',
			'{itemParent:$object::group topic}' => 'SES_65SES',
			'{itemParent:$object:group}:' => 'SES_66SES',
			'<style>' => 'SES_67SES',
			'</style>' => 'SES_68SES',
			'http://[host][message_link]' => 'SES_69SES',
			'{item:$object:video}' => 'SES_70SES',
			'[object_type_name]' => 'SES_71SES',
			'%3$s' => 'SES_72SES',
			'{item:$object:poll}' => 'SES_em_ct_ll_SES',
			'[object_link]' => 'SES_oct_lnk_SES',
			'[subscription_title]' => 'SES_subf_tle_SES',
			'[subscription_description]' => 'SES_subs_desptn_SES',
			'[subscription_terms]' => 'SES_subs_trms_SES',
			'{item:$object:playlist}' => 'SES_it_plst_SES',
			'[object_description]' => 'SES_SES_ojt_des',
			'{item:$object:message}' => 'SES_SES_itm_msg',
			'&quot;' => 'SES81_SES',
			'[category_name]' => 'SES82_SES',
			'{var:$commentLink}' => 'SES83_SES',
			'<i>' => 'SES84_SES',
			'</i>' => 'SES85_SES',
			'<b>' => 'SES86_SES',
			'</b>' => 'SES87_SES',
			'[invoice_body]' => 'SES88SES',
			'[event_title]' => 'SES89SES',
			'[ticket_body]' => 'SES_90_SES',
			'[description]' => 'SES_91_SES',
			'[site_title]' => 'SES_92_SES',
			'[questionreply]' => 'SES_93_SES',
			'[event_description]' => 'SES_94_SES',
			'http://[host]' => 'SES_95_SES',
			'[birthday_content]' => 'SES_96_SES',
			'[birthday_subject]' => 'SES_97_SES',
			'{item:$object:photos}' => 'SES_SES_it_ob_potos',
			'<strong>' => 'SES_SES_op_strng',
			'</strong>' => 'SES_SES_strng',
			'{var:$pokedPageLink}' => 'SES_SES_vr_pkd_lnk',
			'{item:$playlist}' => 'SES_SES_it_plst',
			'[sender_name]' => 'SES_SES_se_nme',
			'[content]' => 'SES_SES_connt'
		);
	}
}
