Rujukan API
Dokumen ini memadankan tingkah laku aplikasi Express dalam api/app.js dan pengendali laluan di bawah api/routes/.
Had dan tingkah laku
| Item | Nilai |
|---|---|
| Saiz badan JSON | Sehingga 2 MB (express.json({ limit: '2mb' })) |
| Sasaran setiap permintaan | 1–36 kod bahasa |
| Item kelompok | 1–100 item setiap permintaan kelompok |
| Model | standard (lalai) atau advanced (hanya untuk tahap berbayar; lihat di bawah) |
Peruntukan token bulanan (peringkat percuma): Sebelum memanggil model, API menganggarkan token secara kasar sebagai ceil(content_length / 4) × (number_of_targets + 1) dan, untuk peringkat free sahaja, menolak permintaan dengan 429 / token_limit_reached jika anggaran melebihi baki peruntukan bulanan (FREE_TIER_MONTHLY_TOKENS, lalai 100000). Tahap berbayar tidak disekat oleh pemeriksaan awal ini dalam enforceTokenCap; penggunaan masih direkod.
Had kadar: Apabila Upstash Redis dikonfigurasikan (UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN, dan URL tidak mengandungi tempat letak your-instance), had per minit dikenakan mengikut tahap: percuma 5, permulaan 30, pertumbuhan 60, skala 120, perusahaan tanpa had. Apabila had dicapai, respons adalah 429 dengan error: "rate_limit_reached". Jika Redis tidak dikonfigurasikan, had kadar diabaikan (lihat rateLimit.js).
Respons had kadar yang berjaya mungkin termasuk X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
GET /health
Tiada pengesahan.
Respons 200
{
"status": "ok",
"timestamp": "2025-03-23T12:00:00.000Z"
}
GET /languages
Tiada pengesahan.
Mengembalikan senarai kanonik bahasa yang disokong (kod, nama paparan, bendera RTL). Terdapat 36 entri; kod adalah satu-satunya nilai yang diterima dalam targets pada titik akhir terjemahan.
Respons 200
{
"languages": [
{ "code": "en", "name": "English", "rtl": false },
{ "code": "ar", "name": "Arabic", "rtl": true }
]
}
Sumber: api/utils/languages.js.
POST /translate
Memerlukan Authorization: Bearer <api_key>.
Menterjemah satu rentetan content ke setiap bahasa yang disenaraikan dalam targets. Model mengembalikan objek JSON tunggal yang kunci-kuncinya adalah tepat kod bahasa yang diminta dan nilainya adalah rentetan yang diterjemah (lihat formatPrompts.js).
Badan permintaan
| Medan | Jenis | Wajib | Penerangan |
|---|---|---|---|
content | string | Ya | Rentetan tidak kosong untuk diterjemah |
targets | string[] | Ya | Tatasusunan kod bahasa yang sah dan tidak kosong (maksimum 36) |
format | string | Tidak | Salah satu daripada plain, markdown, json, html. Jika diabaikan, format dikesan secara automatik daripada content. |
source | string | Tidak | Petunjuk bahasa sumber untuk model; pilihan |
model | string | Tidak | standard (lalai) atau advanced. advanced memerlukan tahap berbayar (403 pada percuma). |
Respons 200
{
"translations": {
"es": "...",
"fr": "..."
},
"usage": {
"input_tokens": 120,
"output_tokens": 340,
"total_tokens": 460,
"model": "standard",
"detected_format": "markdown",
"detection_confidence": 0.95
}
}
detected_format dan detection_confidence hanya muncul apabila format diabaikan dan pengesanan automatik dijalankan.
Contoh (cURL)
curl -sS -X POST "https://api.usepolylingo.com/v1/translate" \
-H "Authorization: Bearer $POLYLINGO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "{\"title\":\"Hello\"}",
"format": "json",
"targets": ["fr", "de"]
}'
Contoh (Python 3)
pip install requests
import os, requests
url = "https://api.usepolylingo.com/v1/translate"
headers = {
"Authorization": f"Bearer {os.environ['POLYLINGO_API_KEY']}",
"Content-Type": "application/json",
}
r = requests.post(url, json={
"content": "<p>Hello <strong>world</strong></p>",
"format": "html",
"targets": ["es"],
}, timeout=120)
r.raise_for_status()
print(r.json()["translations"]["es"])
POST /translate/batch
Memerlukan Authorization: Bearer <api_key>.
Memproses setiap item secara berurutan (satu panggilan model setiap item). Jika mana-mana item gagal, API mengembalikan 500 dan tidak mengembalikan keputusan separa untuk permintaan itu.
Badan permintaan
| Medan | Jenis | Wajib | Penerangan |
|---|---|---|---|
items | array | Ya | Setiap elemen: id (string), content (string), format pilihan. |
targets | string[] | Ya | Peraturan sama seperti /translate. |
source | string | Tidak | Petunjuk bahasa sumber pilihan. |
model | string | Tidak | standard atau advanced (peraturan sama seperti /translate). |
Respons 200
{
"results": [
{ "id": "welcome", "translations": { "fr": "...", "de": "..." } },
{ "id": "goodbye", "translations": { "fr": "...", "de": "..." } }
],
"usage": {
"total_tokens": 900,
"input_tokens": 400,
"output_tokens": 500,
"model": "standard"
}
}
Contoh
curl -sS -X POST "https://api.usepolylingo.com/v1/translate/batch" \
-H "Authorization: Bearer $POLYLINGO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "id": "a", "content": "Hello", "format": "plain" },
{ "id": "b", "content": "## Title", "format": "markdown" }
],
"targets": ["es", "it"]
}'
POST /jobs
Memerlukan Authorization: Bearer <api_key>.
Menyusun kerja terjemahan dan mengembalikan segera dengan job_id. Terjemahan dijalankan di latar belakang — tiada risiko tamat masa HTTP tanpa mengira saiz kandungan. Poll GET /jobs/:id untuk keputusan.
Gunakan titik akhir ini sebagai ganti POST /translate apabila menterjemah dokumen besar (Markdown panjang, banyak bahasa sasaran) di mana tempoh permintaan mungkin melebihi tamat masa klien HTTP atau proksi anda.
Badan permintaan
| Medan | Jenis | Wajib | Penerangan |
|---|---|---|---|
content | string | Ya | Rentetan tidak kosong untuk diterjemah |
targets | string[] | Ya | Tatasusunan kod bahasa yang sah dan tidak kosong (maksimum 36) |
format | string | Tidak | Salah satu daripada plain, markdown, json, html. Dikesan secara automatik jika diabaikan. |
source | string | Tidak | Petunjuk bahasa sumber; pilihan. |
model | string | Tidak | standard (lalai) atau advanced. |
Respons 202
{
"job_id": "a1b2c3d4-...",
"status": "pending",
"created_at": "2025-03-23T12:00:00.000Z"
}
GET /jobs/:id
Memerlukan Authorization: Bearer <api_key>.
Memantau status kerja yang dihantar melalui POST /jobs. Poll setiap 5–10 saat. Kerja dimiliki oleh pengguna yang menghantar — pengguna lain menerima 404.
Respons (pending / processing)
{
"job_id": "a1b2c3d4-...",
"status": "pending",
"created_at": "2025-03-23T12:00:00.000Z",
"updated_at": "2025-03-23T12:00:00.000Z",
"completed_at": null,
"queue_position": 3
}
status adalah pending (menunggu pekerja) atau processing (pekerja telah mengambilnya). queue_position (bermula dari 1) adalah berapa banyak kerja pending atau processing yang dibuat sebelum ini — gunakan untuk UI kemajuan. Diabaikan apabila pertanyaan kiraan gagal.
Respons (selesai)
{
"job_id": "a1b2c3d4-...",
"status": "completed",
"created_at": "2025-03-23T12:00:00.000Z",
"updated_at": "2025-03-23T12:00:02.000Z",
"completed_at": "2025-03-23T12:00:02.000Z",
"translations": {
"es": "...",
"fr": "..."
},
"usage": {
"input_tokens": 120,
"output_tokens": 340,
"total_tokens": 460,
"model": "standard"
}
}
Respons (gagal)
{
"job_id": "a1b2c3d4-...",
"status": "failed",
"error": "Model returned invalid JSON"
}
Contoh (JavaScript)
const API = 'https://api.usepolylingo.com/v1'
const headers = {
'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
'Content-Type': 'application/json',
}
// 1. Hantar
const submit = await fetch(`${API}/jobs`, {
method: 'POST',
headers,
body: JSON.stringify({ content: longMarkdown, format: 'markdown', targets: ['de', 'fr'] }),
})
const { job_id } = await submit.json()
// 2. Poll
while (true) {
await new Promise(r => setTimeout(r, 10_000))
const poll = await fetch(`${API}/jobs/${job_id}`, { headers })
const job = await poll.json()
if (job.status === 'completed') { console.log(job.translations); break }
if (job.status === 'failed') { throw new Error(job.error) }
// Pilihan: tunjukkan kemajuan (queue_position bermula dari 1, diabaikan jika tidak beratur)
if (job.queue_position != null) console.log(`Queue position: ${job.queue_position}`)
}
GET /usage
Memerlukan Authorization: Bearer <api_key> (carian kunci standard — bukan laluan hanya bypass dalaman).
Mengembalikan penggunaan token untuk bulan kalendar semasa bagi pengguna yang disahkan.
Respons 200
{
"period_start": "2025-03-01T00:00:00.000Z",
"period_end": "2025-03-31T23:59:59.000Z",
"tokens_used": 12000,
"tokens_included": 100000,
"tokens_remaining": 88000,
"overage_tokens": 0,
"tier": "free"
}
tokens_included dan tokens_remaining adalah null untuk enterprise (peruntukan tanpa had dalam laporan).
Format kandungan
Nilai format yang disokong: plain, markdown, json, html.
| Format | Dipelihara | Diterjemah |
|---|---|---|
plain | Pemisah baris / perenggan | Semua teks yang kelihatan |
markdown | Sintaks, pautan (URL tidak berubah), kod berpagar (verbatim) | Prosa dan teks pautan |
json | Kekunci, struktur, jenis bukan rentetan | Nilai rentetan sahaja |
html | Tag dan atribut | Nod teks dan atribut yang sesuai (lihat arahan) |
RTL dan arah dalam aplikasi anda
Untuk output plain dan markdown, API hanya mengembalikan teks yang diterjemah — ia tidak menambah dir="rtl" atau elemen pembungkus. Tetapkan arah teks dalam UI anda (CSS direction, atribut dir elemen induk, atau susun atur i18n rangka kerja anda) apabila memaparkan bahasa Arab, Ibrani, atau Parsi.
Untuk format html, markup terjemahan mungkin termasuk dir="rtl" apabila sesuai untuk sasaran RTL; lihat formatPrompts.js dan ujian HTML dalam scripts/test-translation.js.
Respons ralat
Ralat adalah JSON apabila boleh:
{
"error": "invalid_request",
"message": "Perincian yang boleh dibaca manusia"
}
| HTTP | error | Bila |
|---|---|---|
| 400 | invalid_request | Medan badan hilang/tidak sah (contoh: content kosong, targets salah) |
| 400 | invalid_format | format tidak dalam set yang disokong |
| 400 | invalid_language | Kod tidak diketahui dalam targets |
| 401 | invalid_api_key | Authorization hilang/salah, kunci tidak diketahui, kunci dibatalkan |
| 403 | advanced_not_available | model: "advanced" pada peringkat percuma |
| 429 | token_limit_reached | Had bulanan peringkat percuma akan terlampau (pemeriksaan awal) |
| 429 | rate_limit_reached | Had RPM per minit (apabila Redis diaktifkan) |
| 500 | translation_error | Kegagalan model/rangkaian; selamat untuk cuba semula |
| 404 | not_found | GET /jobs/:id — kerja tidak wujud atau milik pengguna lain |
| 500 | server_error | POST /jobs — gagal memasukkan ke dalam barisan; selamat untuk cuba semula |
GET /usage mungkin mengembalikan 500 dengan mesej generik jika pertanyaan Supabase gagal.
Model asas (maklumat)
API hanya mendedahkan standard dan advanced. ID model OpenAI sebenar dikonfigurasikan dalam api/utils/modelRouter.js dan tidak dikembalikan dalam respons API.