<?php
/* Copyright (C) 2009-2012 Laurent Destailleur  <eldy@users.sourceforge.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

/**
 *      \file       dev/translation/langAutoParser.class.php
 *		\ingroup    dev
 *      \brief      This file is an example for a command line script
 */

/**
 * Class to parse language files and translate them
 * This is a language automatic translator parser for Dolibarr
 */
class autoTranslator
{
	private $_translatedFiles = array();
	private $_destlang = '';
	private $_refLang = '';
	private $_langDir = '';
	private $_limittofile = '';
	private $_time;
	private $_time_end;
	private $_outputpagecode = 'UTF-8';
	private $_apikey;
	//private $_outputpagecode = 'ISO-8859-1';
	const DIR_SEPARATOR = '/';


	/**
	 * Constructor
	 *
	 * @param   string $_destlang       Destination lang
	 * @param   string $_refLang        Ref lang
	 * @param   string $_langDir        Dir lang
	 * @param   string $_limittofile    Limit to file
	 * @param   string $_apikey         Api key
	 * @return void
	 */
	public function __construct($_destlang, $_refLang, $_langDir, $_limittofile, $_apikey)
	{

		// Set enviorment variables
		$this->_destlang = $_destlang;
		$this->_refLang = $_refLang;
		$this->_langDir = $_langDir.self::DIR_SEPARATOR;
		$this->_time = date('Y-m-d H:i:s');
		$this->_limittofile = $_limittofile;
		$this->_apikey = $_apikey;

		// Translate
		//ini_set('default_charset','UTF-8');
		ini_set('default_charset', $this->_outputpagecode);
		$this->parseRefLangTranslationFiles();
	}

	/**
	 * 	Parse file
	 *
	 * 	@return	void
	 */
	private function parseRefLangTranslationFiles()
	{

		$files = $this->getTranslationFilesArray($this->_refLang);
		$counter = 1;
		foreach ($files as $file) {
			if ($this->_limittofile && $this->_limittofile != $file) {
				continue;
			}
			$counter++;
			$fileContent = null;
			$refPath = $this->_langDir.$this->_refLang.self::DIR_SEPARATOR.$file;
			$fileContent = file($refPath, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
			print "Processing file " . $file . ", with ".count($fileContent)." lines<br>\n";

			// Define target dirs
			$targetlangs=array($this->_destlang);
			if ($this->_destlang == 'all') {
				$targetlangs=array();

				// If we must process all languages
				$arraytmp=dol_dir_list($this->_langDir, 'directories', 0);
				foreach ($arraytmp as $dirtmp) {
					if ($dirtmp['name'] === $this->_refLang) {
						continue;	// We discard source language
					}
					$tmppart=explode('_', $dirtmp['name']);
					if (preg_match('/^en/i', $dirtmp['name'])) {
						continue;	// We discard en_* languages
					}
					if (preg_match('/^fr/i', $dirtmp['name'])) {
						continue;	// We discard fr_* languages
					}
					if (preg_match('/^es/i', $dirtmp['name'])) {
						continue;	// We discard es_* languages
					}
					if (preg_match('/ca_ES/i', $dirtmp['name'])) {
						continue;	// We discard es_CA language
					}
					if (preg_match('/pt_BR/i', $dirtmp['name'])) {
						continue;	// We discard pt_BR language
					}
					if (preg_match('/nl_BE/i', $dirtmp['name'])) {
						continue;  // We discard nl_BE language
					}
					if (preg_match('/^\./i', $dirtmp['name'])) {
						continue;	// We discard files .*
					}
					if (preg_match('/^CVS/i', $dirtmp['name'])) {
						continue;	// We discard CVS
					}
					$targetlangs[]=$dirtmp['name'];
				}
				//var_dump($targetlangs);
			}

			// Process translation of source file for each target languages
			foreach ($targetlangs as $my_destlang) {
				$this->_translatedFiles = array();

				$destPath = $this->_langDir.$my_destlang.self::DIR_SEPARATOR.$file;
				// Check destination file presence
				if (! file_exists($destPath)) {
					// No file present, we generate file
					echo "File not found: " . $destPath . ". We generate it.<br>\n";
					$this->createTranslationFile($destPath, $my_destlang);
				} else {
					echo "Updating file: " . $destPath . "<br>\n";
				}

				// Translate lines
				$fileContentDest = file($destPath, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
				$newlines=0;
				foreach ($fileContent as $line) {
					$key = $this->getLineKey($line);
					$value = $this->getLineValue($line);
					if ($key && $value) {
						$newlines+=$this->translateFileLine($fileContentDest, $file, $key, $value, $my_destlang);
					}
				}

				$this->updateTranslationFile($destPath, $file, $my_destlang);
				echo "New translated lines: " . $newlines . "<br>\n";
				//if ($counter ==3) die('fim');
			}
		}
	}

	/**
	 * Update file with new translations
	 *
	 * @param 	string	$destPath		Target path
	 * @param 	string	$file			File
	 * @param 	string	$my_destlang		Target language code
	 * @return	void
	 */
	private function updateTranslationFile($destPath, $file, $my_destlang)
	{
		$this->_time_end = date('Y-m-d H:i:s');

		if (isset($this->_translatedFiles[$file]) && count($this->_translatedFiles[$file])>0) {
			$fp = fopen($destPath, 'a');
			fwrite($fp, "\n");
			fwrite($fp, "\n");
			fwrite($fp, "// START - Lines generated via autotranslator.php tool (".$this->_time.").\n");
			fwrite($fp, "// Reference language: ".$this->_refLang." -> ".$my_destlang."\n");
			foreach ($this->_translatedFiles[$file] as $line) {
				fwrite($fp, $line . "\n");
			}
			fwrite($fp, "// STOP - Lines generated via autotranslator.php tool (".$this->_time_end.").\n");
			fclose($fp);
		}
		return;
	}

	/**
	 * Create a new translation file
	 *
	 * @param 	string	$path			Path
	 * @param 	string	$my_destlang		Target language code
	 * @return	void
	 */
	private function createTranslationFile($path, $my_destlang)
	{
		$fp = fopen($path, 'w+');
		fwrite($fp, "/*\n");
		fwrite($fp, " * Language code: {$my_destlang}\n");
		fwrite($fp, " * Automatic generated via autotranslator.php tool\n");
		fwrite($fp, " * Generation date " . $this->_time. "\n");
		fwrite($fp, " */\n");
		fclose($fp);
		return;
	}

	/**
	 * Put in array _translatedFiles[$file], line of a new tranlated pair
	 *
	 * @param 	string	$content		Existing content of dest file
	 * @param 	string	$file			Target file name translated (xxxx.lang)
	 * @param 	string	$key			Key to translate
	 * @param 	string	$value			Existing value in source file
	 * @param	string	$my_destlang	Language code (ie: fr_FR)
	 * @return	int						0=Nothing translated, 1=Record translated
	 */
	private function translateFileLine($content, $file, $key, $value, $my_destlang)
	{

		//print "key    =".$key."\n";
		foreach ($content as $line) {
			$destKey = $this->getLineKey($line);
			$destValue = $this->getLineValue($line);
			// If translated return
			//print "destKey=".$destKey."\n";
			if (trim($destKey) == trim($key)) {	// Found already existing translation (key already exits in dest file)
				return 0;
			}
		}

		if ($key == 'CHARSET') {
			$val=$this->_outputpagecode;
		} elseif (preg_match('/^Format/', $key)) {
			$val=$value;
		} elseif ($value=='-') {
			$val=$value;
		} else {
			// If not translated then translate
			if ($this->_outputpagecode == 'UTF-8') {
				$val=$this->translateTexts(array($value), substr($this->_refLang, 0, 2), substr($my_destlang, 0, 2));
			} else {
				$val=utf8_decode($this->translateTexts(array($value), substr($this->_refLang, 0, 2), substr($my_destlang, 0, 2)));
			}
		}

		$val=trim($val);

		if (empty($val)) {
			return 0;
		}

		$this->_translatedFiles[$file][] = $key . '=' . $val ;
		return 1;
	}

	/**
	 * getLineKey
	 *
	 * @param 	string 	$line	Line found into file
	 * @return	string	Key
	 */
	private function getLineKey($line)
	{
		$arraykey = explode('=', $line, 2);
		return trim($arraykey[0]);
	}

	/**
	 * getLineValue
	 *
	 * @param 	string 	$line	Line found into file
	 * @return	string	Value
	 */
	private function getLineValue($line)
	{
		$arraykey = explode('=', $line, 2);
		return trim(isset($arraykey[1])?$arraykey[1]:'');
	}

	/**
	 * getTranslationFilesArray
	 *
	 * @param 	string 	$lang	Language code
	 * @return	array	Array
	 */
	private function getTranslationFilesArray($lang)
	{
		$dir = new DirectoryIterator($this->_langDir.$lang);
		while ($dir->valid()) {
			if (!$dir->isDot() && $dir->isFile() && ! preg_match('/^\./', $dir->getFilename())) {
				$files[] =  $dir->getFilename();
			}
			$dir->next();
		}
		return $files;
	}

	/**
	 * Return translation of a value
	 *
	 * @param 	array	$src_texts		Array with one value
	 * @param 	string	$src_lang		Language code source (us, fr, it, ...)
	 * @param 	string	$dest_lang		Language code target (es, de, ...)
	 * @return 	string					Value translated
	 */
	private function translateTexts($src_texts, $src_lang, $dest_lang)
	{
		// We want to be sure that src_lang and dest_lang are using 2 chars only
		$tmp=explode('_', $src_lang);
		if (! empty($tmp[1]) && $tmp[0] == $tmp[1]) {
			$src_lang=$tmp[0];
		}
		$tmp=explode('_', $dest_lang);
		if (! empty($tmp[1]) && $tmp[0] == $tmp[1]) {
			$dest_lang=$tmp[0];
		}

		//setting language pair
		$lang_pair = $src_lang.'|'.$dest_lang;

		$src_text_to_translate=preg_replace('/%s/', 'SSSSS', implode('', $src_texts));
		$src_text_to_translate=preg_replace('/'.preg_quote('\n\n').'/', ' NNNNN ', $src_text_to_translate);

		// Define GET URL v1
		//$url = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=".urlencode($src_text_to_translate)."&langpair=".urlencode($lang_pair);
		// Example: http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=Setup%20area&langpair=en_US|fr_FR
		// Define GET URL v2
		$url = "https://www.googleapis.com/language/translate/v2?key=".$this->_apikey."&q=".urlencode($src_text_to_translate)."&source=".urlencode($src_lang)."&target=".urlencode($dest_lang);
		// Example: https://www.googleapis.com/language/translate/v2?key=_apikey&q=Setup%20area&source=en_US&target=fr_FR

		// Send request
		//print "Url to translate: ".$url."\n";

		if (! function_exists("curl_init")) {
			  print "Error, your PHP does not support curl functions.\n";
			  die();
		}

		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_REFERER, "Mozilla");
		$body = curl_exec($ch);
		curl_close($ch);
		//sleep(1);	// This is to avoid to overload server.

		// now, process the JSON string
		$json = json_decode($body, true);

		if ((! empty($json['responseStatus']) && $json['responseStatus'] != 200)
		|| count($json['data']['translations']) == 0) {
			print "Error: ".$json['responseStatus']." ".$url."\n";
			return false;
		}

		$rep=$json['data']['translations'][0]['translatedText'];
		$rep=preg_replace('/SSSSS/i', '%s', $rep);
		$rep=preg_replace('/NNNNN/i', '\n\n', $rep);
		$rep=preg_replace('/&#39;/i', '\'', $rep);

		//print "OK ".join('',$src_texts).' => '.$rep."\n";

		return $rep;
	}
}
