* * 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 . */ /** * \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
\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.
\n"; $this->createTranslationFile($destPath, $my_destlang); } else { echo "Updating file: " . $destPath . "
\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 . "
\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('/'/i', '\'', $rep); //print "OK ".join('',$src_texts).' => '.$rep."\n"; return $rep; } }