PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/MultilingualLiquidThreads/MetaTranslator.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 338 lines | 196 code | 73 blank | 69 comment | 21 complexity | 5d7010b1cc8f1c8d968739b0ad60066b MD5 | raw file
  1. <?php
  2. require_once('HTMLTranslator.php');
  3. class MetaTranslator {
  4. /* Translation parameters */
  5. private $sourceLang;
  6. /* in MetaTranslation process */
  7. private $noTranslations;
  8. private $tags_begin=array();
  9. private $tags_end=array();
  10. /* Constant */
  11. private $TAG_BEGIN="<notranslate>";
  12. private $TAG_END="</notranslate>";
  13. private $TAG_RELAXED='__________';
  14. private $LANG_TAG_BEGIN='[';
  15. private $LANG_TAG_END=']';
  16. /**
  17. * Constructor
  18. * @param $sourceLang SourceLanguage
  19. */
  20. public function __construct($sourceLang) {
  21. $this->setSourceLanguage($sourceLang);
  22. }
  23. /**
  24. *
  25. */
  26. public function metaTranslate($func, $param, $order, $meta=true, $attach=true, $resultFunc, $statusFunc) {
  27. $sourceLang=$param[$order[0]];
  28. $targetLang=$param[$order[1]];
  29. $source=$param[$order[2]];
  30. $encode=$this->preTranslation($source, $meta);
  31. $trans=$this->doTranslate($func, $param, $order, $sourceLang, $targetLang, $encode, $resultFunc, $statusFunc);
  32. if($trans==null) {
  33. //error occured
  34. return null;
  35. }
  36. $newparam=$param;
  37. $newparam[$order[2]]=$trans;
  38. $decode=$this->postTranslation($func, $newparam, $order, $meta, $attach, $resultFunc, $statusFunc);
  39. return $decode;
  40. }
  41. /**
  42. * PreProcess
  43. * @param $source Translated sentence
  44. * @param $meta MetaTranslate or not
  45. * @return Encoded sentence
  46. */
  47. public function preTranslation($source, $meta=true) {
  48. $this->noTranslations=array();
  49. $escEncode='';
  50. /* no-MetaTranslate */
  51. if($meta) {
  52. $this->tags_begin[]='[relax]';
  53. $this->tags_begin[]=$this->TAG_BEGIN;
  54. $this->tags_end[]='[/relax]';
  55. $this->tags_end[]=$this->TAG_END;
  56. }
  57. /* LanguageTags */
  58. /* Encoding */
  59. $escEncode=$this->encodeEscapes_relaxed($source);
  60. return $escEncode;
  61. }
  62. /**
  63. * PostProcess
  64. * @param $func Translator
  65. * @param $param Parameters for $func
  66. * @param $order Parameter position : $param[$order[0]]=SourceLanguage, $param[$order[1]]=TargetLanguage, $param[$order[2]]=Source
  67. * @param $meta MetaTranslate or not
  68. * @param $attach Whether Description is necessary : Unnecessary->false
  69. * @param $resultFunc Such function that $resultFunc($func($param)) returns sentence
  70. * @return Sentence
  71. */
  72. public function postTranslation($func, $param, $order, $meta=true, $attach=true, $resultFunc=null, $statusFunc) {
  73. $source=$param[$order[2]];
  74. /* attach Descriptions */
  75. if($meta) {
  76. $this->attachDescriptions($func, $param, $order, $meta, $attach, $resultFunc, $statusFunc);
  77. }
  78. /* Decode */
  79. $result=$this->decodeEscapes($source);
  80. return $result;
  81. }
  82. /**
  83. * Replacing Intermediate Code into Escapes
  84. * @param $source Encoded sentence
  85. * @return Decoded sentence
  86. */
  87. private function decodeEscapes($source) {
  88. for($i=0; $i<count($this->noTranslations); $i++) {
  89. $source=str_ireplace($this->noTranslations[$i]['code'],
  90. $this->noTranslations[$i]['escape'], $source);
  91. }
  92. return $source;
  93. }
  94. /**
  95. * Attaching Descriptions
  96. */
  97. private function attachDescriptions($func, $param, $order, $meta, $attach, $resultFunc, $statusFunc) {
  98. $sourceLang=$param[$order[0]];
  99. $targetLang=$param[$order[1]];
  100. /* for all noTranslations */
  101. for($i=0; $i<count($this->noTranslations); $i++) {
  102. if($attach) {
  103. /* Recursive MetaTranslation */
  104. $meta=new MetaTranslator($sourceLang);
  105. $encode=$meta->preTranslation($this->noTranslations[$i]['escape']);
  106. $trans=$this->doTranslate($func, $param, $order, $sourceLang, $targetLang, $encode, $resultFunc, $statusFunc);
  107. $newparam=$param;
  108. $newparam[$order[2]]=$trans;
  109. $description=$meta->postTranslation($func, $newparam, $order, true, true, $resultFunc, $statusFunc);
  110. /* attaching */
  111. if($this->canAttach($this->noTranslations[$i]['escape'], $description)) {
  112. $this->noTranslations[$i]['escape'].='('.$description.')';
  113. }
  114. }
  115. $tagnum=$this->noTranslations[$i]['tag'];
  116. if($tagnum!=0) {
  117. $this->noTranslations[$i]['escape']=$this->tags_begin[$tagnum].
  118. $this->noTranslations[$i]['escape'].
  119. $this->tags_end[$tagnum];
  120. }else {
  121. $this->noTranslations[$i]['escape']=$this->TAG_RELAXED.
  122. $this->noTranslations[$i]['escape'].
  123. $this->TAG_RELAXED;
  124. }
  125. }
  126. }
  127. /**
  128. * Whether to Attach Descriptions
  129. */
  130. private function canAttach($escape, $description) {
  131. /* punctuations */
  132. $pattern='[\.| |.|,|,| |:|:|;|。|、|!|!|\?|?]';
  133. $comp1=@preg_replace($pattern, '', $escape);
  134. $comp2=@preg_replace($pattern, '', $description);
  135. return $comp1!==$comp2;
  136. }
  137. /**
  138. * Translate body
  139. */
  140. private function doTranslate($func, $param, $order, $sourceLang, $targetLang, $source, $resultFunc, $statusFunc) {
  141. $param[$order[0]]=$sourceLang;
  142. $param[$order[1]]=$targetLang;
  143. $param[$order[2]]=$source;
  144. $ht=new HTMLTranslator();
  145. $result = $ht->HTMLTranslate($func, $param, $order, $sourceLang, $targetLang, $source, $resultFunc, $statusFunc);
  146. return $result;
  147. }
  148. /**
  149. * Replacing Escapes into Intermediate Code : relaxed mode
  150. */
  151. private function encodeEscapes_relaxed($source) {
  152. $array=explode($this->TAG_RELAXED, $source);
  153. $relaxed='';
  154. for($i=0; $i<count($array)-1; $i++) {
  155. $relaxed.=$array[$i];
  156. if($i%2==0) {
  157. $relaxed.=$this->tags_begin[0];
  158. }else {
  159. $relaxed.=$this->tags_end[0];
  160. }
  161. }
  162. $relaxed.=$array[count($array)-1];
  163. return $this->encodeEscapes_strict($relaxed);
  164. }
  165. /**
  166. * Replacing Escapes into Intermediate Code : strict mode
  167. */
  168. private function encodeEscapes_strict($source) {
  169. $encode='';
  170. $escape='';
  171. $indent=0;
  172. $id=0;
  173. $tagStart=0;
  174. $tagEnd=0;
  175. $buf='';
  176. for($i=0; $i<mb_strlen($source); $i++) {
  177. $buf.=mb_substr($source, $i, 1);
  178. /* escape begins */
  179. $len=$this->startsWith($this->tags_begin, $buf);
  180. if($len!=-1) {
  181. /* before tag, do not escape */
  182. if($indent==0) {
  183. $encode.=mb_substr($buf, 0, mb_strlen($buf)-$len);
  184. $tagStart=$i;
  185. }else {
  186. $escape.=$buf;
  187. }
  188. $buf='';
  189. $indent++;
  190. continue;
  191. }
  192. /* escape ends */
  193. $len=$this->startsWith($this->tags_end, $buf, $tagNumber);
  194. if($len!=-1) {
  195. $indent--;
  196. $escape.=$buf;
  197. /* after tag, do not escape */
  198. if($indent==0) {
  199. $escape=mb_substr($escape, 0, mb_strlen($escape)-$len);
  200. $escape=$this->removeDescription($escape);
  201. $escape=trim($escape);
  202. $tagEnd=$i;
  203. $interCode=$this->getInterCode($tagStart, $tagEnd);
  204. $this->noTranslations[$id]=array('escape'=>$escape,
  205. 'code'=>$interCode,
  206. 'tag'=>$tagNumber);
  207. $id++;
  208. $encode.=' '.$interCode.' ';
  209. $escape='';
  210. }
  211. $buf='';
  212. continue;
  213. }
  214. }
  215. return $encode.$buf;
  216. }
  217. /**
  218. * if $str startsWith one of $array, return strlen($array[$i]), else -1
  219. */
  220. private function startsWith($array, $str, &$num=null) {
  221. for($i=0; $i<count($array); $i++) {
  222. if(strpos($str, $array[$i])!==false) {
  223. $num=$i;
  224. return mb_strlen($array[$i]);
  225. }
  226. }
  227. return -1;
  228. }
  229. /**
  230. * Removing Descriptions
  231. */
  232. private function removeDescription($source) {
  233. $ret='';
  234. $indent=0;
  235. for($i=0; $i<mb_strlen($source); $i++) {
  236. $buf=mb_substr($source, $i, 1);
  237. if($buf=='(') {
  238. $indent++;
  239. }
  240. if($indent==0) {
  241. $ret.=$buf;
  242. }
  243. if($buf==')') {
  244. $indent--;
  245. }
  246. }
  247. return $ret;
  248. }
  249. private function getInterCode($tagStart, $tagEnd) {
  250. $alt=dechex($tagStart).'x'.dechex($tagEnd);
  251. $search=array('0','1','2','3','4','5','6','7','8','9');
  252. $replace=array('g','h','i','j','k','l','m','n','o','p');
  253. $result=str_replace($search, $replace, $alt);
  254. return 'xxx'.$result.'xxx';
  255. }
  256. /**
  257. * Setter
  258. */
  259. public function setSourceLanguage($sourceLang) {
  260. $this->sourceLang=$sourceLang;
  261. }
  262. public function getSourceLanguage() {
  263. return $this->sourceLang;
  264. }
  265. }