Auto-sync enabled

FlatlyPage

Version 1.0.1 • 59 files • 798.19 KB
api/translate.php
<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

function logDebug($msg) {
    file_put_contents(__DIR__.'/translate_debug.log', date('Y-m-d H:i:s').' - '.$msg."\n", FILE_APPEND);
}

$xmlPath = __DIR__.'/../data/translate-api.xml';
if (!file_exists($xmlPath)) {
    logDebug("ERROR: XML not found");
    http_response_code(500);
    die(json_encode(['error'=>'Config not found', 'path'=>$xmlPath]));
}

$xml = simplexml_load_file($xmlPath);
$apis = [];
foreach ($xml->apis->api as $api) {
    $apis[(string)$api->id] = [
        'endpoint' => (string)$api->endpoint,
        'apiKey'   => (string)$api->apiKey,
        'requiresKey' => ((string)$api->requiresKey==='true')
    ];
}

$input = json_decode(file_get_contents('php://input'), true);
$text   = trim($input['text'] ?? '');
$source = $input['source'] ?? 'auto';
$target = $input['target'] ?? 'en';
$provider = $input['provider'] ?? 'mymemory';

if ($text === '') {
    http_response_code(400);
    die(json_encode(['error'=>'No text provided']));
}

if (!isset($apis[$provider])) {
    http_response_code(400);
    die(json_encode(['error'=>"Invalid provider: $provider"]));
}

$config = $apis[$provider];
$translatedText = null;

try {
    switch($provider) {

        case 'mymemory':
            $url = $config['endpoint'].'?q='.urlencode($text).'&langpair='.$source.'|'.$target;
            $resp = @file_get_contents($url);
            if (!$resp) throw new Exception('MyMemory connection failed');
            $data = json_decode($resp,true);
            $translatedText = $data['responseData']['translatedText'] ?? null;
            break;

        case 'google':
            if (empty($config['apiKey'])) throw new Exception('Google API key missing');
            $url = $config['endpoint'].'?key='.$config['apiKey'];
            $post = json_encode(['q'=>$text,'source'=>$source,'target'=>$target,'format'=>'text']);
            $opts = ['http'=>['method'=>'POST','header'=>'Content-Type: application/json','content'=>$post,'ignore_errors'=>true]];
            $resp = file_get_contents($url,false,stream_context_create($opts));
            $data = json_decode($resp,true);
            if (isset($data['error'])) throw new Exception($data['error']['message']);
            $translatedText = $data['data']['translations'][0]['translatedText'] ?? null;
            break;

        case 'deepl':
            if (empty($config['apiKey'])) throw new Exception('DeepL API key missing');

            $text = mb_substr($text, 0, 5000);
            $text = str_replace(["\0","\x1a"], '', $text);

            $postData = json_encode([
                'text' => [$text],
                'source_lang' => strtoupper($source),
                'target_lang' => strtoupper($target)
            ]);

            $options = [
                'http'=>[
                    'method'=>'POST',
                    'header'=>"Content-Type: application/json\r\n".
                              "Authorization: DeepL-Auth-Key ".$config['apiKey'],
                    'content'=>$postData,
                    'timeout'=>30,
                    'ignore_errors'=>true
                ]
            ];

            $response = file_get_contents($config['endpoint'], false, stream_context_create($options));
            if ($response === false) throw new Exception('DeepL connection failed');
            $data = json_decode($response,true);
            if (isset($data['message'])) throw new Exception('DeepL error: '.$data['message']);
            $translatedText = $data['translations'][0]['text'] ?? null;
            break;

        case 'hf-marian':
            if (empty($config['apiKey'])) throw new Exception('HF API key missing');

            $modelPair = "{$source}-{$target}";
            $modelName = "Helsinki-NLP/opus-mt-" . $modelPair;
            $dynamicUrl = "https://router.huggingface.co/hf-inference/models/" . $modelName;

            $postData = json_encode(['inputs' => $text]);
            $options = [
                'http' => [
                    'method'  => 'POST',
                    'header'  => "Content-Type: application/json\r\n" .
                                 "Authorization: Bearer " . $config['apiKey'] . "\r\n" .
                                 "X-Wait-For-Model: true\r\n",
                    'content' => $postData,
                    'timeout' => 60,
                    'ignore_errors' => true 
                ]
            ];

            $response = @file_get_contents($dynamicUrl, false, stream_context_create($options));
            
            if ($response === false) {
                throw new Exception("Connection to model failed: $modelName");
            }

            $data = json_decode($response, true);

            if (isset($data['error'])) {
                if (strpos($data['error'], 'not found') !== false || strpos($data['error'], 'Model not found') !== false) {
                    echo "[Error: The language pair $source to $target is not supported by this model]";
                    exit;
                }
                
                if (isset($data['estimated_time'])) {
                    throw new Exception("Model is loading. Try again in " . round($data['estimated_time']) . "s.");
                }
                
                throw new Exception('HF Error: ' . $data['error']);
            }

            $result = is_array($data) ? ($data[0] ?? $data) : $data;

            if (isset($result['translation_text'])) {
                $translatedText = $result['translation_text'];
            } elseif (isset($result['generated_text'])) {
                $translatedText = $result['generated_text'];
            } else {
                throw new Exception('HF translation failed: unexpected response format');
            }
            break;


        default:
            throw new Exception("Unknown provider: $provider");
    }

    if (!$translatedText) throw new Exception('No translation returned');

    echo json_encode([
        'success'=>true,
        'translatedText'=>$translatedText,
        'provider'=>$provider,
        'source'=>$source,
        'target'=>$target
    ]);

} catch(Exception $e) {
    logDebug("EXCEPTION: ".$e->getMessage());
    http_response_code(500);
    echo json_encode(['error'=>$e->getMessage()]);
}