PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/dev/translation/langAutoParser.class.php

https://github.com/asterix14/dolibarr
PHP | 323 lines | 189 code | 42 blank | 92 comment | 40 complexity | 719b0be8ec03dc774c2a0b9e0f45f90a MD5 | raw file
Possible License(s): LGPL-2.0
  1. <?php
  2. /**
  3. * This software is licensed under GPL license agreement
  4. * This is a language automatic translator parser for Dolibarr
  5. * This script uses google language ajax api as the translator engine
  6. * The main translator function can be found at:
  7. *
  8. * http://www.plentyofcode.com/2008/10/google-translation-api-translate-on.html
  9. * Hope you make a good use of it :)
  10. *
  11. * http://code.google.com/intl/fr/apis/ajaxlanguage/documentation/#SupportedPairs
  12. */
  13. /**
  14. * Class to parse language files and translate them
  15. */
  16. class langAutoParser
  17. {
  18. private $translatedFiles = array();
  19. private $destLang = '';
  20. private $refLang = '';
  21. private $langDir = '';
  22. private $limittofile = '';
  23. private $time;
  24. private $time_end;
  25. private $outputpagecode = 'UTF-8';
  26. //private $outputpagecode = 'ISO-8859-1';
  27. const DIR_SEPARATOR = '/';
  28. function __construct($destLang,$refLang,$langDir,$limittofile){
  29. // Set enviorment variables
  30. $this->destLang = $destLang;
  31. $this->refLang = $refLang;
  32. $this->langDir = $langDir.self::DIR_SEPARATOR;
  33. $this->time = date('Y-m-d H:i:s');
  34. $this->limittofile = $limittofile;
  35. // Translate
  36. //ini_set('default_charset','UTF-8');
  37. ini_set('default_charset',$this->outputpagecode);
  38. $this->parseRefLangTranslationFiles();
  39. }
  40. /**
  41. * Parse file
  42. *
  43. * @return void
  44. */
  45. private function parseRefLangTranslationFiles()
  46. {
  47. $files = $this->getTranslationFilesArray($this->refLang);
  48. $counter = 1;
  49. foreach($files as $file)
  50. {
  51. if ($this->limittofile && $this->limittofile != $file) continue;
  52. $counter++;
  53. $fileContent = null;
  54. $refPath = $this->langDir.$this->refLang.self::DIR_SEPARATOR.$file;
  55. $fileContent = file($refPath,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
  56. print "Processing file " . $file . ", with ".count($fileContent)." lines<br>\n";
  57. // Define target dirs
  58. $targetlangs=array($this->destLang);
  59. if ($this->destLang == 'all')
  60. {
  61. $targetlangs=array();
  62. // If we must process all languages
  63. $arraytmp=dol_dir_list($this->langDir,'directories',0);
  64. foreach($arraytmp as $dirtmp)
  65. {
  66. if ($dirtmp['name'] === $this->refLang) continue; // We discard source language
  67. $tmppart=explode('_',$dirtmp['name']);
  68. if (preg_match('/^en/i',$dirtmp['name'])) continue; // We discard en_* languages
  69. if (preg_match('/^fr/i',$dirtmp['name'])) continue; // We discard fr_* languages
  70. if (preg_match('/^es/i',$dirtmp['name'])) continue; // We discard es_* languages
  71. if (preg_match('/ca_ES/i',$dirtmp['name'])) continue; // We discard es_CA language
  72. if (preg_match('/pt_BR/i',$dirtmp['name'])) continue; // We discard pt_BR language
  73. if (preg_match('/nl_BE/i',$dirtmp['name'])) continue; // We discard nl_BE language
  74. if (preg_match('/^\./i',$dirtmp['name'])) continue; // We discard files .*
  75. if (preg_match('/^CVS/i',$dirtmp['name'])) continue; // We discard CVS
  76. $targetlangs[]=$dirtmp['name'];
  77. }
  78. //var_dump($targetlangs);
  79. }
  80. // Process translation of source file for each target languages
  81. foreach($targetlangs as $mydestLang)
  82. {
  83. $this->translatedFiles = array();
  84. $destPath = $this->langDir.$mydestLang.self::DIR_SEPARATOR.$file;
  85. // Check destination file presence
  86. if (! file_exists($destPath))
  87. {
  88. // No file present, we generate file
  89. echo "File not found: " . $destPath . ". We generate it.<br>\n";
  90. $this->createTranslationFile($destPath,$mydestLang);
  91. }
  92. else
  93. {
  94. echo "Updating file: " . $destPath . "<br>\n";
  95. }
  96. // Translate lines
  97. $fileContentDest = file($destPath,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
  98. $newlines=0;
  99. foreach($fileContent as $line){
  100. $key = $this->getLineKey($line);
  101. $value = $this->getLineValue($line);
  102. if ($key && $value)
  103. {
  104. $newlines+=$this->translateFileLine($fileContentDest,$file,$key,$value,$mydestLang);
  105. }
  106. }
  107. $this->updateTranslationFile($destPath,$file,$mydestLang);
  108. echo "New translated lines: " . $newlines . "<br>\n";
  109. //if ($counter ==3) die('fim');
  110. }
  111. }
  112. }
  113. /**
  114. * Update file with new translations
  115. *
  116. * @param string $destPath Target path
  117. * @param string $file File
  118. * @param string $mydestLang Target language code
  119. * @return void
  120. */
  121. private function updateTranslationFile($destPath,$file,$mydestLang)
  122. {
  123. $this->time_end = date('Y-m-d H:i:s');
  124. if (count($this->translatedFiles[$file])>0)
  125. {
  126. $fp = fopen($destPath, 'a');
  127. fwrite($fp, "\r\n");
  128. fwrite($fp, "\r\n");
  129. fwrite($fp, "// START - Lines generated via autotranslator.php tool (".$this->time.").\r\n");
  130. fwrite($fp, "// Reference language: ".$this->refLang." -> ".$mydestLang."\r\n");
  131. foreach( $this->translatedFiles[$file] as $line) {
  132. fwrite($fp, $line . "\r\n");
  133. }
  134. fwrite($fp, "// STOP - Lines generated via autotranslator.php tool (".$this->time_end.").\r\n");
  135. fclose($fp);
  136. }
  137. return;
  138. }
  139. /**
  140. * Create a new translation file
  141. *
  142. * @param string $path Path
  143. * @param string $mydestlang Target language code
  144. * @return void
  145. */
  146. private function createTranslationFile($path,$mydestlang)
  147. {
  148. $fp = fopen($path, 'w+');
  149. fwrite($fp, "/*\r\n");
  150. fwrite($fp, " * Language code: {$mydestlang}\r\n");
  151. fwrite($fp, " * Automatic generated via autotranslator.php tool\r\n");
  152. fwrite($fp, " * Generation date " . $this->time. "\r\n");
  153. fwrite($fp, " */\r\n");
  154. fclose($fp);
  155. return;
  156. }
  157. /**
  158. * Put in array translatedFiles[$file], line of a new tranlated pair
  159. *
  160. * @param string $content Existing content of dest file
  161. * @param string $file Target file name translated (xxxx.lang)
  162. * @param string $key Key to translate
  163. * @param string $value Existing value in source file
  164. * @param string $mydestLang Language code (ie: fr_FR)
  165. * @return int 0=Nothing translated, 1=Record translated
  166. */
  167. private function translateFileLine($content,$file,$key,$value,$mydestLang)
  168. {
  169. //print "key =".$key."\n";
  170. foreach( $content as $line ) {
  171. $destKey = $this->getLineKey($line);
  172. $destValue = $this->getLineValue($line);
  173. // If translated return
  174. //print "destKey=".$destKey."\n";
  175. if ( trim($destKey) == trim($key) )
  176. { // Found already existing translation (key already exits in dest file)
  177. return 0;
  178. }
  179. }
  180. if ($key == 'CHARSET') $val=$this->outputpagecode;
  181. else if (preg_match('/^Format/',$key)) $val=$value;
  182. else if ($value=='-') $val=$value;
  183. else
  184. {
  185. // If not translated then translate
  186. if ($this->outputpagecode == 'UTF-8') $val=$this->translateTexts(array($value),substr($this->refLang,0,2),substr($mydestLang,0,2));
  187. else $val=utf8_decode($this->translateTexts(array($value),substr($this->refLang,0,2),substr($mydestLang,0,2)));
  188. }
  189. $val=trim($val);
  190. if (empty($val)) return 0;
  191. $this->translatedFiles[$file][] = $key . '=' . $val ;
  192. return 1;
  193. }
  194. /**
  195. *
  196. * @param string $line Line found into file
  197. * @return string Key
  198. */
  199. private function getLineKey($line)
  200. {
  201. $arraykey = explode('=',$line,2);
  202. return trim($arraykey[0]);
  203. }
  204. /**
  205. *
  206. * @param string $line Line found into file
  207. * @return string Value
  208. */
  209. private function getLineValue($line)
  210. {
  211. $arraykey = explode('=',$line,2);
  212. return trim($arraykey[1]);
  213. }
  214. /**
  215. *
  216. * @param string $lang Language code
  217. * @return array Array
  218. */
  219. private function getTranslationFilesArray($lang)
  220. {
  221. $dir = new DirectoryIterator($this->langDir.$lang);
  222. while($dir->valid()) {
  223. if(!$dir->isDot() && $dir->isFile() && ! preg_match('/^\./',$dir->getFilename())) {
  224. $files[] = $dir->getFilename();
  225. }
  226. $dir->next();
  227. }
  228. return $files;
  229. }
  230. /**
  231. * Return translation of a value
  232. *
  233. * @param array $src_texts Array with one value
  234. * @param string $src_lang Language code source
  235. * @param string $dest_lang Language code target
  236. * @return string Value translated
  237. */
  238. private function translateTexts($src_texts, $src_lang, $dest_lang)
  239. {
  240. $tmp=explode('_',$src_lang);
  241. if ($tmp[0] == $tmp[1]) $src_lang=$tmp[0];
  242. $tmp=explode('_',$dest_lang);
  243. if ($tmp[0] == $tmp[1]) $dest_lang=$tmp[0];
  244. //setting language pair
  245. $lang_pair = $src_lang.'|'.$dest_lang;
  246. $src_texts_query = "";
  247. $src_text_to_translate=preg_replace('/%s/','SSSSS',join('',$src_texts));
  248. $src_text_to_translate=preg_replace('/'.preg_quote('\n\n').'/',' NNNNN ',$src_text_to_translate);
  249. $src_texts_query .= "&q=".urlencode($src_text_to_translate);
  250. $url = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0".$src_texts_query."&langpair=".urlencode($lang_pair);
  251. // sendRequest
  252. // note how referer is set manually
  253. //print "Url to translate: ".$url."\n";
  254. if (! function_exists("curl_init"))
  255. {
  256. print "Error, your PHP does not support curl functions.\n";
  257. die();
  258. }
  259. $ch = curl_init();
  260. curl_setopt($ch, CURLOPT_URL, $url);
  261. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  262. curl_setopt($ch, CURLOPT_REFERER, "Mozilla");
  263. $body = curl_exec($ch);
  264. curl_close($ch);
  265. sleep(6); // This is to avoid to overload server. Best value is 6.
  266. // now, process the JSON string
  267. $json = json_decode($body, true);
  268. if ($json['responseStatus'] != 200)
  269. {
  270. print "Error: ".$json['responseStatus']." ".$url."\n";
  271. return false;
  272. }
  273. $rep=$json['responseData']['translatedText'];
  274. $rep=preg_replace('/SSSSS/i','%s',$rep);
  275. $rep=preg_replace('/NNNNN/i','\n\n',$rep);
  276. $rep=preg_replace('/&#39;/i','\'',$rep);
  277. //print "OK ".join('',$src_texts).' => '.$rep."\n";
  278. return $rep;
  279. }
  280. }
  281. ?>