API مرجع
این سند رفتار برنامه Express در api/app.js و هندلرهای مسیر زیر api/routes/ را مطابقت میدهد.
محدودیتها و رفتار
| مورد | مقدار |
|---|---|
| اندازه بدنه JSON | تا 2 مگابایت (express.json({ limit: '2mb' })) |
| اهداف در هر درخواست | 1–36 کد زبان |
| آیتمهای دستهای | 1–100 آیتم در هر درخواست دستهای |
| مدلها | standard (پیشفرض) یا advanced (فقط در سطوح پرداختی؛ در زیر ببینید) |
محدودیت ماهانه توکن (سطح رایگان): قبل از فراخوانی مدل، API توکنها را تقریباً به صورت ceil(content_length / 4) × (number_of_targets + 1) تخمین میزند و فقط برای سطح free، اگر تخمین از باقیمانده سهمیه ماهانه (FREE_TIER_MONTHLY_TOKENS، پیشفرض 100000) بیشتر باشد، درخواست را با 429 / token_limit_reached رد میکند. سطوح پرداختی توسط این پیشبررسی در enforceTokenCap مسدود نمیشوند؛ استفاده همچنان ثبت میشود.
محدودیت نرخ: وقتی Upstash Redis پیکربندی شده باشد (UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN، و URL شامل جایگزین your-instance نباشد)، محدودیتهای دقیقهای بر اساس سطح اعمال میشود: رایگان 5، شروعکننده 30، رشد 60، مقیاس 120، سازمانی نامحدود. در صورت رسیدن به حد، پاسخ 429 با error: "rate_limit_reached" است. اگر Redis پیکربندی نشده باشد، محدودیت نرخ نادیده گرفته میشود (ببینید rateLimit.js).
پاسخهای موفق با محدودیت نرخ ممکن است شامل X-RateLimit-Limit، X-RateLimit-Remaining، X-RateLimit-Reset باشند.
GET /health
بدون احراز هویت.
پاسخ 200
{
"status": "ok",
"timestamp": "2025-03-23T12:00:00.000Z"
}
GET /languages
بدون احراز هویت.
فهرست رسمی زبانهای پشتیبانی شده (کد، نام نمایشی، پرچم RTL) را برمیگرداند. 36 ورودی وجود دارد؛ کدها تنها مقادیری هستند که در targets در نقاط انتهایی ترجمه پذیرفته میشوند.
پاسخ 200
{
"languages": [
{ "code": "en", "name": "English", "rtl": false },
{ "code": "ar", "name": "Arabic", "rtl": true }
]
}
منبع: api/utils/languages.js.
POST /translate
نیازمند Authorization: Bearer <api_key>.
یک رشته content واحد را به هر زبانی که در targets فهرست شده است ترجمه میکند. مدل یک شیء JSON واحد بازمیگرداند که کلیدهای آن دقیقاً کدهای زبان درخواست شده هستند و مقادیر رشتههای ترجمه شدهاند (ببینید formatPrompts.js).
بدنه درخواست
| فیلد | نوع | اجباری | توضیح |
|---|---|---|---|
content | string | بله | رشته غیرخالی برای ترجمه. |
targets | string[] | بله | آرایه غیرخالی از کدهای زبان معتبر (حداکثر 36). |
format | string | خیر | یکی از plain، markdown، json، html. اگر حذف شود، فرمت به صورت خودکار از content تشخیص داده میشود. |
source | string | خیر | نشانه زبان منبع برای مدل؛ اختیاری. |
model | string | خیر | standard (پیشفرض) یا advanced. advanced نیازمند سطح پرداختی است (403 در رایگان). |
پاسخ 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 و detection_confidence فقط زمانی ظاهر میشوند که format حذف شده باشد و تشخیص خودکار اجرا شده باشد.
مثال (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"]
}'
مثال (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
نیازمند Authorization: Bearer <api_key>.
هر آیتم را به ترتیب پردازش میکند (یک فراخوانی مدل برای هر آیتم). اگر هر آیتمی شکست بخورد، API با 500 پاسخ میدهد و نتایج جزئی برای آن درخواست بازنمیگرداند.
بدنه درخواست
| فیلد | نوع | اجباری | توضیح |
|---|---|---|---|
items | array | بله | هر عنصر: id (رشته)، content (رشته)، format اختیاری. |
targets | string[] | بله | قوانین مشابه /translate. |
source | string | خیر | نشانه زبان منبع اختیاری. |
model | string | خیر | standard یا advanced (قوانین مشابه /translate). |
پاسخ 200
{
"results": [
{ "id": "welcome", "translations": { "fr": "...", "de": "..." } },
{ "id": "goodbye", "translations": { "fr": "...", "de": "..." } }
],
"usage": {
"total_tokens": 900,
"input_tokens": 400,
"output_tokens": 500,
"model": "standard"
}
}
مثال
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
نیازمند Authorization: Bearer <api_key>.
یک کار ترجمه را در صف قرار میدهد و بلافاصله با job_id پاسخ میدهد. ترجمه در پسزمینه اجرا میشود — بدون خطر تایماوت HTTP صرفنظر از اندازه محتوا. برای نتیجه، GET /jobs/:id را نظرسنجی کنید.
این endpoint را به جای POST /translate هنگام ترجمه اسناد بزرگ (Markdown طولانی، زبانهای هدف متعدد) استفاده کنید که ممکن است مدت زمان درخواست از تایماوت کلاینت HTTP یا پراکسی شما بیشتر شود.
بدنه درخواست
| فیلد | نوع | اجباری | توضیح |
|---|---|---|---|
content | string | بله | رشته غیرخالی برای ترجمه. |
targets | string[] | بله | آرایه غیرخالی از کدهای زبان معتبر (حداکثر 36). |
format | string | خیر | یکی از plain، markdown، json، html. اگر حذف شود، به صورت خودکار تشخیص داده میشود. |
source | string | خیر | نشانه زبان منبع؛ اختیاری. |
model | string | خیر | standard (پیشفرض) یا advanced. |
پاسخ 202
{
"job_id": "a1b2c3d4-...",
"status": "pending",
"created_at": "2025-03-23T12:00:00.000Z"
}
GET /jobs/:id
نیازمند Authorization: Bearer <api_key>.
وضعیت کاری که از طریق POST /jobs ارسال شده را نظرسنجی میکند. هر 5–10 ثانیه نظرسنجی کنید. کارها متعلق به کاربری هستند که آنها را ارسال کرده است — کاربران دیگر 404 دریافت میکنند.
پاسخ (در انتظار / در حال پردازش)
{
"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 میتواند pending (در انتظار کارگر) یا processing (کارگر آن را گرفته است) باشد. queue_position (مبنای 1) تعداد کارهای در انتظار یا در حال پردازش است که دقیقاً قبل از این ایجاد شدهاند — برای UI پیشرفت استفاده کنید. اگر پرسوجوی شمارش شکست بخورد، حذف میشود.
پاسخ (تکمیل شده)
{
"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"
}
}
پاسخ (ناموفق)
{
"job_id": "a1b2c3d4-...",
"status": "failed",
"error": "Model returned invalid JSON"
}
مثال (JavaScript)
const API = 'https://api.usepolylingo.com/v1'
const headers = {
'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
'Content-Type': 'application/json',
}
// 1. ارسال
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. نظرسنجی
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) }
// اختیاری: نمایش پیشرفت (queue_position مبنای 1 است، وقتی در صف نیست حذف میشود)
if (job.queue_position != null) console.log(`Queue position: ${job.queue_position}`)
}
GET /usage
نیازمند Authorization: Bearer <api_key> (جستجوی کلید استاندارد — نه مسیر داخلی فقط برای دور زدن).
استفاده توکن را برای ماه تقویمی جاری برای کاربر احراز هویت شده برمیگرداند.
پاسخ 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 و tokens_remaining برای enterprise مقدار null دارند (سهمیه نامحدود در گزارشدهی).
فرمتهای محتوا
مقادیر پشتیبانی شده format: plain، markdown، json، html.
| فرمت | حفظ شده | ترجمه شده |
|---|---|---|
plain | شکست خطوط / پاراگرافها | تمام متن قابل مشاهده |
markdown | نحو، لینکها (URL بدون تغییر)، کد محصور (کلمه به کلمه) | نثر و متن لینک |
json | کلیدها، ساختار، انواع غیررشتهای | فقط مقادیر رشتهای |
html | تگها و ویژگیها | گرههای متنی و ویژگیهای مناسب (ببینید prompts) |
RTL و جهت در برنامه شما
برای خروجی plain و markdown، API فقط متن ترجمه شده را برمیگرداند — dir="rtl" یا عناصر پوششی اضافه نمیکند. هنگام نمایش عربی، عبری یا فارسی، جهت متن را در UI خود تنظیم کنید (CSS direction، ویژگی dir عنصر والد یا طرحبندی i18n فریمورک شما).
برای فرمت html، نشانهگذاری ترجمه شده ممکن است شامل dir="rtl" باشد در صورت مناسب بودن برای اهداف RTL؛ ببینید formatPrompts.js و تستهای HTML در scripts/test-translation.js.
پاسخهای خطا
خطاها در صورت امکان JSON هستند:
{
"error": "invalid_request",
"message": "جزئیات قابل خواندن برای انسان"
}
| HTTP | error | چه زمانی |
|---|---|---|
| 400 | invalid_request | فیلدهای بدنه گمشده/نامعتبر (مثلاً content خالی، targets نامناسب) |
| 400 | invalid_format | format در مجموعه پشتیبانی شده نیست |
| 400 | invalid_language | کد ناشناخته در targets |
| 401 | invalid_api_key | Authorization گمشده/ناقص، کلید ناشناخته، کلید لغو شده |
| 403 | advanced_not_available | model: "advanced" در سطح رایگان |
| 429 | token_limit_reached | سقف ماهانه سطح رایگان پیش از فراخوانی رد شده (پیشبررسی) |
| 429 | rate_limit_reached | محدودیت RPM دقیقهای (وقتی Redis فعال است) |
| 500 | translation_error | خطای مدل/شبکه؛ ایمن برای تلاش مجدد |
| 404 | not_found | GET /jobs/:id — کار وجود ندارد یا متعلق به کاربر دیگر است |
| 500 | server_error | POST /jobs — خطا در صفبندی؛ ایمن برای تلاش مجدد |
GET /usage ممکن است با پیام عمومی 500 بازگردد اگر پرسوجوی Supabase شکست بخورد.
مدلهای زیرساختی (اطلاعاتی)
API فقط standard و advanced را ارائه میدهد. شناسههای واقعی مدل OpenAI در api/utils/modelRouter.js پیکربندی شدهاند و در پاسخهای API بازگردانده نمیشوند.