WebOrbiton
v3.0.0.2

FlatlyPage

198 lines · 7.2 KB
  1. <?php
  2. header('Content-Type: application/json; charset=utf-8');
  3. ​
  4. if (isset($_SERVER['HTTP_ORIGIN'])) {
  5. ​
  6. $originHost = parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST);
  7. $serverHost = $_SERVER['HTTP_HOST'];
  8. $serverParts = explode('.', $serverHost);
  9. $baseDomain = implode('.', array_slice($serverParts, -2));
  10. ​
  11. if (
  12. $originHost === $baseDomain ||
  13. str_ends_with($originHost, '.' . $baseDomain)
  14. ) {
  15. header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
  16. header('Access-Control-Allow-Credentials: true');
  17. header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
  18. header('Access-Control-Allow-Headers: Content-Type, Authorization');
  19. }
  20. }
  21. ​
  22. if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
  23. http_response_code(200);
  24. exit;
  25. }
  26. ​
  27. function logDebug($msg) {
  28. file_put_contents(__DIR__.'/translate_debug.log', date('Y-m-d H:i:s').' - '.$msg."\n", FILE_APPEND);
  29. }
  30. ​
  31. $xmlPath = __DIR__.'/../data/translate-api.xml';
  32. if (!file_exists($xmlPath)) {
  33. logDebug("ERROR: XML not found");
  34. http_response_code(500);
  35. die(json_encode(['error'=>'Config not found', 'path'=>$xmlPath]));
  36. }
  37. ​
  38. $xml = simplexml_load_file($xmlPath);
  39. $apis = [];
  40. foreach ($xml->apis->api as $api) {
  41. $apis[(string)$api->id] = [
  42. 'endpoint' => (string)$api->endpoint,
  43. 'apiKey' => (string)$api->apiKey,
  44. 'requiresKey' => ((string)$api->requiresKey==='true')
  45. ];
  46. }
  47. ​
  48. $systemFile = __DIR__.'/../data/system.php';
  49. $system = is_file($systemFile) ? include $systemFile : [];
  50. if (is_array($system) && !empty($system['translator_api_key']) && isset($apis[$system['translator_provider'] ?? ''])) {
  51. $apis[$system['translator_provider']]['apiKey'] = (string) $system['translator_api_key'];
  52. }
  53. ​
  54. $input = json_decode(file_get_contents('php://input'), true);
  55. $text = trim($input['text'] ?? '');
  56. $source = $input['source'] ?? 'auto';
  57. $target = $input['target'] ?? 'en';
  58. $provider = $input['provider'] ?? 'mymemory';
  59. ​
  60. if ($text === '') {
  61. http_response_code(400);
  62. die(json_encode(['error'=>'No text provided']));
  63. }
  64. ​
  65. if (!isset($apis[$provider])) {
  66. http_response_code(400);
  67. die(json_encode(['error'=>"Invalid provider: $provider"]));
  68. }
  69. ​
  70. $config = $apis[$provider];
  71. $translatedText = null;
  72. ​
  73. try {
  74. switch($provider) {
  75. ​
  76. case 'mymemory':
  77. $url = $config['endpoint'].'?q='.urlencode($text).'&langpair='.$source.'|'.$target;
  78. $resp = @file_get_contents($url);
  79. if (!$resp) throw new Exception('MyMemory connection failed');
  80. $data = json_decode($resp,true);
  81. $translatedText = $data['responseData']['translatedText'] ?? null;
  82. break;
  83. ​
  84. case 'google':
  85. if (empty($config['apiKey'])) throw new Exception('Google API key missing');
  86. $url = $config['endpoint'].'?key='.$config['apiKey'];
  87. $post = json_encode(['q'=>$text,'source'=>$source,'target'=>$target,'format'=>'text']);
  88. $opts = ['http'=>['method'=>'POST','header'=>'Content-Type: application/json','content'=>$post,'ignore_errors'=>true]];
  89. $resp = file_get_contents($url,false,stream_context_create($opts));
  90. $data = json_decode($resp,true);
  91. if (isset($data['error'])) throw new Exception($data['error']['message']);
  92. $translatedText = $data['data']['translations'][0]['translatedText'] ?? null;
  93. break;
  94. ​
  95. case 'deepl':
  96. if (empty($config['apiKey'])) throw new Exception('DeepL API key missing');
  97. ​
  98. $text = mb_substr($text, 0, 5000);
  99. $text = str_replace(["\0","\x1a"], '', $text);
  100. ​
  101. $postData = json_encode([
  102. 'text' => [$text],
  103. 'source_lang' => strtoupper($source),
  104. 'target_lang' => strtoupper($target)
  105. ]);
  106. ​
  107. $options = [
  108. 'http'=>[
  109. 'method'=>'POST',
  110. 'header'=>"Content-Type: application/json\r\n".
  111. "Authorization: DeepL-Auth-Key ".$config['apiKey'],
  112. 'content'=>$postData,
  113. 'timeout'=>30,
  114. 'ignore_errors'=>true
  115. ]
  116. ];
  117. ​
  118. $response = file_get_contents($config['endpoint'], false, stream_context_create($options));
  119. if ($response === false) throw new Exception('DeepL connection failed');
  120. $data = json_decode($response,true);
  121. if (isset($data['message'])) throw new Exception('DeepL error: '.$data['message']);
  122. $translatedText = $data['translations'][0]['text'] ?? null;
  123. break;
  124. ​
  125. case 'hf-marian':
  126. if (empty($config['apiKey'])) throw new Exception('HF API key missing');
  127. ​
  128. $modelPair = "{$source}-{$target}";
  129. $modelName = "Helsinki-NLP/opus-mt-" . $modelPair;
  130. $dynamicUrl = "https://router.huggingface.co/hf-inference/models/" . $modelName;
  131. ​
  132. $postData = json_encode(['inputs' => $text]);
  133. $options = [
  134. 'http' => [
  135. 'method' => 'POST',
  136. 'header' => "Content-Type: application/json\r\n" .
  137. "Authorization: Bearer " . $config['apiKey'] . "\r\n" .
  138. "X-Wait-For-Model: true\r\n",
  139. 'content' => $postData,
  140. 'timeout' => 60,
  141. 'ignore_errors' => true
  142. ]
  143. ];
  144. ​
  145. $response = @file_get_contents($dynamicUrl, false, stream_context_create($options));
  146. if ($response === false) {
  147. throw new Exception("Connection to model failed: $modelName");
  148. }
  149. ​
  150. $data = json_decode($response, true);
  151. ​
  152. if (isset($data['error'])) {
  153. if (strpos($data['error'], 'not found') !== false || strpos($data['error'], 'Model not found') !== false) {
  154. echo "[Error: The language pair $source to $target is not supported by this model]";
  155. exit;
  156. }
  157. if (isset($data['estimated_time'])) {
  158. throw new Exception("Model is loading. Try again in " . round($data['estimated_time']) . "s.");
  159. }
  160. throw new Exception('HF Error: ' . $data['error']);
  161. }
  162. ​
  163. $result = is_array($data) ? ($data[0] ?? $data) : $data;
  164. ​
  165. if (isset($result['translation_text'])) {
  166. $translatedText = $result['translation_text'];
  167. } elseif (isset($result['generated_text'])) {
  168. $translatedText = $result['generated_text'];
  169. } else {
  170. throw new Exception('HF translation failed: unexpected response format');
  171. }
  172. break;
  173. ​
  174. ​
  175. default:
  176. throw new Exception("Unknown provider: $provider");
  177. }
  178. ​
  179. if (!$translatedText) throw new Exception('No translation returned');
  180. ​
  181. echo json_encode([
  182. 'success'=>true,
  183. 'translatedText'=>$translatedText,
  184. 'provider'=>$provider,
  185. 'source'=>$source,
  186. 'target'=>$target
  187. ]);
  188. ​
  189. } catch(Exception $e) {
  190. logDebug("EXCEPTION: ".$e->getMessage());
  191. http_response_code(500);
  192. echo json_encode(['error'=>$e->getMessage()]);
  193. }
  194. ​