diff --git a/README.md b/README.md
index fcdfcd2..a0ed6b6 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
| **آدرسِ زنده** | `https://api.math.tadrisino2.ir` · [سلامت](https://api.math.tadrisino2.ir/api/health) |
| **استک** | Python 3.11+ · Django 5.2 · DRF · SQLite · Qdrant (RAG) |
| **API** | ۵۶ اندپوینت · مستنداتِ زنده در `/api/docs/` |
-| **تست** | ۴۸۱ تست، همه سبز (`python manage.py test`) |
+| **تست** | ۴۸۳ تست، همه سبز (`python manage.py test`) |
| **محتوا** | ۸ پایه · ۵۸ فصل · ۲۶۳ نود · ۲٬۶۱۷ درس · ۲٬۴۶۳ سوال |
---
diff --git a/config/settings.py b/config/settings.py
index a9648fb..7526e61 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -237,7 +237,9 @@ ROOT_URLCONF = 'config.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [],
+ # قالبهای سطحِ پروژه (که به هیچ اپی تعلق ندارند) — فعلاً فقط
+ # پوستهی راستبهچپِ صفحههای مستنداتِ API.
+ 'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
diff --git a/config/tests.py b/config/tests.py
index 083a296..4e73c87 100644
--- a/config/tests.py
+++ b/config/tests.py
@@ -450,3 +450,27 @@ class CorsDevPortTests(TestCase):
# و پذیرشِ هر پورتِ localhost را واقعاً خطرناک میکرد.
from django.conf import settings
self.assertFalse(settings.CORS_ALLOW_CREDENTIALS)
+
+
+class ApiDocsRtlShellTests(TestCase):
+ """
+ صفحههای مستنداتِ API باید پوستهی راستبهچپِ خودمان را داشته باشند.
+
+ بدونِ آن، Swagger متنِ فارسی را در یک بلوکِ چپبهراست میچیند و نتیجهاش
+ پریدنِ نقطهی جمله به ابتدای خط و برعکس شدنِ ستونهای جدول است. این تست
+ هست چون خرابیاش فقط با چشم دیده میشود: هیچ خطایی نمیدهد و هیچ تستِ
+ دیگری نمیگیردش.
+ """
+
+ def test_swagger_ui_carries_the_rtl_shell(self):
+ html = self.client.get('/api/docs/').content.decode()
+ self.assertIn('direction: rtl', html)
+ # کد باید صریحاً چپبهراست بماند، وگرنه «Authorization: Bearer ...»
+ # در بلوکِ RTL جابهجا میشود.
+ self.assertIn('direction: ltr', html)
+ # قالبِ اصلیِ drf-spectacular باید دستنخورده زیرش باشد.
+ self.assertIn('swagger-ui-bundle', html)
+
+ def test_redoc_carries_the_rtl_shell(self):
+ html = self.client.get('/api/redoc/').content.decode()
+ self.assertIn('direction: rtl', html)
diff --git a/config/urls.py b/config/urls.py
index 5d78161..569e0b3 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -68,8 +68,13 @@ urlpatterns = [
# OpenAPI schema + Swagger UI + Redoc
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
- path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
- path('api/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
+ # قالبِ خودمان فقط یک پوستهی راستبهچپ روی قالبِ drf-spectacular است؛
+ # بدونش متنِ فارسی در یک بلوکِ LTR رندر میشود و نقطهی جمله و ترتیبِ
+ # ستونهای جدول جابهجا میشوند. توضیح در خودِ قالب.
+ path('api/docs/', SpectacularSwaggerView.as_view(
+ url_name='schema', template_name='tadrisino/swagger_ui.html'), name='swagger-ui'),
+ path('api/redoc/', SpectacularRedocView.as_view(
+ url_name='schema', template_name='tadrisino/redoc.html'), name='redoc'),
# همه زیرِ /api/ جمع میشوند؛ هر اپ مسیرهای خودش را نگه میدارد، پس
# ترتیبِ این فهرست اهمیتی ندارد و تداخلی بینشان نیست.
diff --git a/templates/tadrisino/redoc.html b/templates/tadrisino/redoc.html
new file mode 100644
index 0000000..39198ee
--- /dev/null
+++ b/templates/tadrisino/redoc.html
@@ -0,0 +1,36 @@
+{% extends "drf_spectacular/redoc.html" %}
+
+{# همان مشکلِ راستبهچپِ swagger_ui.html، این بار در Redoc. توضیحِ کامل آنجاست. #}
+
+{% block head %}
+{{ block.super }}
+
+{% endblock head %}
diff --git a/templates/tadrisino/swagger_ui.html b/templates/tadrisino/swagger_ui.html
new file mode 100644
index 0000000..a392afb
--- /dev/null
+++ b/templates/tadrisino/swagger_ui.html
@@ -0,0 +1,69 @@
+{% extends "drf_spectacular/swagger_ui.html" %}
+
+{# Swagger UI هر متنی را چپبهراست میچیند، چون برای انگلیسی نوشته شده. متنِ
+ ما فارسی است، و در یک بلوکِ LTR نتیجهاش این میشود که نقطهی پایانِ جمله
+ به ابتدای خط میپرد، ترتیبِ ستونهای جدول برعکس میشود، و هر کلمهی
+ انگلیسیِ وسطِ جمله جای خودش را گم میکند.
+
+ راهِ حل، تغییرِ *متن* نیست — جهتِ خودِ بلوک باید راستبهچپ شود. اینجا فقط
+ بخشهایی که Markdown فارسی رندر میکنند RTL میشوند؛ ساختارِ خودِ Swagger
+ (مسیرها، متدها، نامِ فیلدها) دستنخورده میماند چون همه انگلیسیاند.
+
+ قالبِ اصلی دست نمیخورد: این فایل با {{ block.super }} رویش سوار میشود،
+ پس بهروزرسانیِ drf-spectacular چیزی را خراب نمیکند. #}
+
+{% block head %}
+{{ block.super }}
+
+{% endblock head %}