مرجع 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 فقط، يرفض الطلب برمز 429 / token_limit_reached إذا تجاوز التقدير المنحة الشهرية المتبقية (FREE_TIER_MONTHLY_TOKENS، الافتراضي 100000). الطبقات المدفوعة غير محجوزة بواسطة هذا الفحص المسبق في 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 | سلسلة | نعم | سلسلة غير فارغة للترجمة. |
targets | مصفوفة من السلاسل | نعم | مصفوفة غير فارغة من رموز اللغات الصالحة (بحد أقصى 36). |
format | سلسلة | لا | واحد من plain، markdown، json، html. إذا تم حذفه، يتم الكشف التلقائي عن التنسيق من content. |
source | سلسلة | لا | تلميح لغة المصدر للنموذج؛ اختياري. |
model | سلسلة | لا | 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 | مصفوفة | نعم | كل عنصر: id (سلسلة)، content (سلسلة)، format اختياري. |
targets | مصفوفة من السلاسل | نعم | نفس قواعد /translate. |
source | سلسلة | لا | تلميح لغة المصدر اختياري. |
model | سلسلة | لا | 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 عن النتيجة.
استخدم هذه النقطة النهائية بدلًا من POST /translate عند ترجمة مستندات كبيرة (Markdown طويل، لغات هدف كثيرة) حيث قد تتجاوز مدة الطلب مهلة عميل HTTP أو البروكسي.
جسم الطلب
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
content | سلسلة | نعم | سلسلة غير فارغة للترجمة. |
targets | مصفوفة من السلاسل | نعم | مصفوفة غير فارغة من رموز اللغات الصالحة (بحد أقصى 36). |
format | سلسلة | لا | واحد من plain، markdown، json، html. يتم الكشف تلقائيًا إذا تم حذفه. |
source | سلسلة | لا | تلميح لغة المصدر؛ اختياري. |
model | سلسلة | لا | 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) هو عدد الوظائف المعلقة أو المعالجة التي تم إنشاؤها قبل هذه — استخدمه لواجهة المستخدم التقدمية. يحذف عند فشل استعلام العد.
الاستجابة (مكتملة)
{
"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 هما null للطبقة enterprise (منحة غير محدودة في التقارير).
تنسيقات المحتوى
القيم المدعومة لـ format: plain، markdown، json، html.
| التنسيق | محفوظ | مترجم |
|---|---|---|
plain | فواصل الأسطر / الفقرات | كل النص المرئي |
markdown | الصياغة، الروابط (URL بدون تغيير)، كود محاط (حرفي) | النثر ونص الرابط |
json | المفاتيح، الهيكل، الأنواع غير النصية | قيم النص فقط |
html | العلامات والسمات | عقد النص والسمات المناسبة (انظر المطالبات) |
RTL والاتجاه في تطبيقك
لـ plain و markdown، يعيد API النص المترجم فقط — لا يضيف dir="rtl" أو عناصر تغليف. اضبط اتجاه النص في واجهة المستخدم الخاصة بك (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.