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).

بدنه درخواست

فیلدنوعاجباریتوضیح
contentstringبلهرشته غیرخالی برای ترجمه.
targetsstring[]بلهآرایه غیرخالی از کدهای زبان معتبر (حداکثر 36).
formatstringخیریکی از plain، markdown، json، html. اگر حذف شود، فرمت به صورت خودکار از content تشخیص داده می‌شود.
sourcestringخیرنشانه زبان منبع برای مدل؛ اختیاری.
modelstringخیر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 پاسخ می‌دهد و نتایج جزئی برای آن درخواست بازنمی‌گرداند.

بدنه درخواست

فیلدنوعاجباریتوضیح
itemsarrayبلههر عنصر: id (رشته)، content (رشته)، format اختیاری.
targetsstring[]بلهقوانین مشابه /translate.
sourcestringخیرنشانه زبان منبع اختیاری.
modelstringخیر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 یا پراکسی شما بیشتر شود.

بدنه درخواست

فیلدنوعاجباریتوضیح
contentstringبلهرشته غیرخالی برای ترجمه.
targetsstring[]بلهآرایه غیرخالی از کدهای زبان معتبر (حداکثر 36).
formatstringخیریکی از plain، markdown، json، html. اگر حذف شود، به صورت خودکار تشخیص داده می‌شود.
sourcestringخیرنشانه زبان منبع؛ اختیاری.
modelstringخیر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": "جزئیات قابل خواندن برای انسان"
}
HTTPerrorچه زمانی
400invalid_requestفیلدهای بدنه گم‌شده/نامعتبر (مثلاً content خالی، targets نامناسب)
400invalid_formatformat در مجموعه پشتیبانی شده نیست
400invalid_languageکد ناشناخته در targets
401invalid_api_keyAuthorization گم‌شده/ناقص، کلید ناشناخته، کلید لغو شده
403advanced_not_availablemodel: "advanced" در سطح رایگان
429token_limit_reachedسقف ماهانه سطح رایگان پیش از فراخوانی رد شده (پیش‌بررسی)
429rate_limit_reachedمحدودیت RPM دقیقه‌ای (وقتی Redis فعال است)
500translation_errorخطای مدل/شبکه؛ ایمن برای تلاش مجدد
404not_foundGET /jobs/:id — کار وجود ندارد یا متعلق به کاربر دیگر است
500server_errorPOST /jobs — خطا در صف‌بندی؛ ایمن برای تلاش مجدد

GET /usage ممکن است با پیام عمومی 500 بازگردد اگر پرس‌وجوی Supabase شکست بخورد.


مدل‌های زیرساختی (اطلاعاتی)

API فقط standard و advanced را ارائه می‌دهد. شناسه‌های واقعی مدل OpenAI در api/utils/modelRouter.js پیکربندی شده‌اند و در پاسخ‌های API بازگردانده نمی‌شوند.

مرجع API | PolyLingo | PolyLingo