API переводчика
Офлайн-переводчик HomServer. Два движка:
fast— LibreTranslate (Argos/OPUS-MT): доли секунды, качество среднее. По умолчанию.quality— LLM TranslateGemma 4B: заметно лучше и естественнее, но медленно (≈10–60 с на абзац) и по одному запросу за раз (очередь).
Адреса: в локальной сети http://192.168.3.2:12010, снаружи https://translate.cybercidor.keenetic.link.
Авторизация
Ключ создаётся в веб-интерфейсе на вкладке «API-ключи». Передать можно любым способом:
заголовок Authorization: Bearer tr_…, заголовок X-API-Key: tr_… или поле api_key
в теле запроса (как в LibreTranslate). Лимит — запросов в минуту на ключ (по умолчанию 120), при превышении — 429.
Ошибки возвращаются в формате LibreTranslate: {"error": "текст"} с кодом 400/401/413/429/503.
Совместимость с LibreTranslate
Эндпоинты /translate, /detect, /languages, /translate_file принимают
те же параметры, что LibreTranslate, поэтому подходят готовые клиенты и плагины (в т.ч. интеграция Nextcloud с LibreTranslate):
указываете адрес сервиса и ключ. Дополнительный параметр engine=quality включает LLM.
| Метод | Путь | Описание |
|---|---|---|
| POST | /translate | q (строка или массив), source (код или auto), target, format (text|html), engine |
| POST | /detect | q → [{"language":"ru","confidence":90}] |
| GET | /languages | языки движка fast (?engine=quality — языки LLM), без ключа |
| POST | /translate_file | multipart file, source, target, engine → ждёт окончания, {"translatedFileUrl": "…"} |
API v1
| Метод | Путь | Описание |
|---|---|---|
| POST | /api/v1/translate | JSON {"text", "source", "target", "engine", "format"} → {"translatedText", "source", "detectedLanguage", "engine", "seconds"}. text может быть массивом. |
| POST | /api/v1/translate/stream | то же, ответ — Server-Sent Events: meta, delta ({"t": "кусок"}), done или error |
| GET | /api/v1/languages | языки обоих движков, форматы файлов, лимиты (без ключа) |
| POST | /api/v1/files | multipart file, target, source, engine → задача {"id", "status", …} |
| GET | /api/v1/jobs/{id} | статус: queued/running/done/error, progress (%), download_url |
| GET | /api/v1/jobs/{id}/download | скачать результат (ключ не нужен, ссылка случайная; хранится 24 ч) |
| GET | /api/v1/jobs | задачи этого ключа |
| DELETE | /api/v1/jobs/{id} | удалить завершённую задачу |
| GET | /api/v1/status | доступность движков, занятость LLM, очередь |
| GET | /health | проверка живости (без ключа) |
Форматы файлов: txt, md, srt, vtt, html, xhtml, docx, pptx, xlsx, odt, odp, ods, epub, pdf (PDF → текст без вёрстки, сканы не поддерживаются). До 25 МБ.
Длинные запросы к quality: если ответ готовится дольше 15 с, сервер начинает слать пробелы перед JSON,
чтобы прокси роутера не оборвал соединение (JSON-парсеры их игнорируют). Ставьте таймаут клиента от 5 минут или используйте файлы/стрим.
Машиночитаемая схема: /api/openapi.json.
Примеры
curl
curl -s http://192.168.3.2:12010/api/v1/translate \
-H "Authorization: Bearer tr_ВАШ_КЛЮЧ" -H "Content-Type: application/json" \
-d '{"text": "Привет, мир!", "source": "ru", "target": "en"}'
# качественный перевод
curl -s http://192.168.3.2:12010/api/v1/translate -H "Authorization: Bearer tr_ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" --max-time 600 \
-d '{"text": "Замена ремня ГРМ на Ford Focus 2", "target": "en", "engine": "quality"}'
# файл
curl -s http://192.168.3.2:12010/api/v1/files -H "Authorization: Bearer tr_ВАШ_КЛЮЧ" \
-F file=@doc.docx -F target=en -F engine=fast
curl -s http://192.168.3.2:12010/api/v1/jobs/ID -H "Authorization: Bearer tr_ВАШ_КЛЮЧ"
curl -sOJ http://192.168.3.2:12010/api/v1/jobs/ID/download
PHP
function translate(string $text, string $target = 'en', string $engine = 'fast'): string {
$ch = curl_init('http://192.168.3.2:12010/api/v1/translate');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $engine === 'quality' ? 600 : 30,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . getenv('TRANSLATOR_KEY')],
CURLOPT_POSTFIELDS => json_encode(['text' => $text, 'target' => $target, 'engine' => $engine]),
]);
$res = json_decode(curl_exec($ch), true);
if (!empty($res['error'])) throw new RuntimeException($res['error']);
return $res['translatedText'];
}
Python
import httpx
r = httpx.post("http://192.168.3.2:12010/api/v1/translate",
headers={"Authorization": "Bearer tr_ВАШ_КЛЮЧ"},
json={"text": ["Первая строка", "Вторая"], "target": "en"}, timeout=600)
print(r.json()["translatedText"])
JavaScript (стрим)
const r = await fetch(BASE + "/api/v1/translate/stream", {
method: "POST",
headers: {"Content-Type": "application/json", "Authorization": "Bearer " + KEY},
body: JSON.stringify({text, target: "en", engine: "quality"}),
});
// читать r.body построчно: события "event: delta\ndata: {"t": "..."}"