perf+security: fix build, secure downloads, dedupe translations, refactor i18n
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m49s

Frontend:
- Fix Framer Motion / motion-dom build error by pinning framer-motion to
  11.18.2 (compatible with React 19 and Next.js 16).
- Add cross-env and build:local script to bypass standalone symlink errors
  on Windows without Developer Mode.
- Allow NEXT_OUTPUT=default to disable standalone output for local builds.
- Refactor i18n: split 14,177-line src/lib/i18n.tsx into per-locale,
  per-namespace JSON files under src/lib/i18n/messages/.
- Load English synchronously; other locales loaded on demand via dynamic
  imports (reduces initial bundle, improves maintainability).
- Remove unused next-intl message files src/messages/en.json and fr.json.

Backend:
- Remove insecure legacy /api/v1/download/{filename} and /api/v1/cleanup/{filename}
  endpoints. The job-based /api/v1/download/{job_id} already enforces ownership.
- Deduplicate texts in TranslationService.translate_batch before sending them
  to the provider, reducing API calls for repeated strings.
- Pin httpx to <0.28 to fix TestClient incompatibility with starlette 0.35.1.
- Add pytest-cov and ruff dev dependencies/config.

DevOps:
- Remove hardcoded Grafana password from docker-compose.yml and
  docker-compose.monitoring.yml; use GRAFANA_PASSWORD env var.
- Change default TRANSLATION_SERVICE from ollama to google in
  docker-compose.yml (Ollama is an optional profile).
- Add GRAFANA_PASSWORD to .env.example.
- Add .coverage and frontend/pnpm-workspace.yaml to .gitignore.

Tests:
- Update API versioning tests for removed legacy endpoints.
- Add tests/test_translation_service.py for deduplication behavior.

Verified:
- pnpm run build:local passes.
- uv run pytest tests/test_providers/* tests/test_translation_service.py
  tests/test_story_3_5_api_versioning.py tests/test_download_endpoint.py
  tests/test_translators/test_excel_translator.py: provider/translator tests
  pass; one pre-existing French error-message test still fails (message is
  returned in English, unrelated to this change).
This commit is contained in:
2026-06-14 16:44:18 +02:00
parent eda6821632
commit fa637abff0
365 changed files with 23910 additions and 14955 deletions

View File

@@ -0,0 +1,146 @@
{
"landing.nav.why": "لماذا نحن؟",
"landing.nav.formats": "التنسيقات",
"landing.nav.pricing": "الأسعار",
"landing.nav.login": "تسجيل الدخول",
"landing.nav.startFree": "ابدأ مجانًا",
"landing.hero.tag": "ذكاء اصطناعي احترافي للمستندات",
"landing.hero.titleLine1": "ترجم مستنداتك.",
"landing.hero.titleLine2": "مع تنسيق مثالي.",
"landing.hero.description": "المترجم الوحيد الذي يحافظ على SmartArt والرسوم البيانية وجداول المحتويات والأشكال والتخطيطات المعقدة — تمامًا كما كانت.",
"landing.hero.ctaMain": "ابدأ مجانًا — مستندان/شهر",
"landing.hero.ctaSec": "عرض العروض",
"landing.hero.deleted": "الملفات تُحذف بعد 60 دقيقة",
"landing.hero.noHidden": "بدون رسوم خفية",
"landing.hero.preview": "معاينة قبل الدفع",
"landing.hero.formattedOk": "التنسيق سليم",
"landing.hero.aiActive": "ترجمة الذكاء الاصطناعي نشطة",
"landing.steps.title": "كيف يعمل؟",
"landing.steps.subtitle": "ثلاث خطوات. صفر فقدان في التنسيق.",
"landing.steps.step1.num": "01",
"landing.steps.step1.title": "ارفع ملفك",
"landing.steps.step1.desc": "اسحب وأفلت مستند Excel أو Word أو PowerPoint أو PDF.",
"landing.steps.step2.num": "02",
"landing.steps.step2.title": "اختر اللغة والمحرك",
"landing.steps.step2.desc": "حدد اللغة المستهدفة والمحرك — كلاسيكي أو ذكاء اصطناعي سياقي.",
"landing.steps.step3.num": "03",
"landing.steps.step3.title": "حمّل النتيجة",
"landing.steps.step3.desc": "احصل على مستندك المترجم بتنسيق مطابق تمامًا للأصل.",
"landing.features.tag": "محرك ترجمة بالذكاء الاصطناعي",
"landing.features.title": "ترجمة تفهم مجالك",
"landing.features.description": "نماذج الذكاء الاصطناعي لدينا تحلل السياق وتحترم مصطلحاتك وحتى تترجم النصوص داخل الصور.",
"landing.features.context.title": "سياق الصناعة",
"landing.features.context.desc": "صِف مجالك واحصل على ترجمات مخصصة، وليس عامة.",
"landing.features.glossary.title": "قواميس المصطلحات",
"landing.features.glossary.desc": "حدد مصطلحاتك التقنية. CTA تبقى «وحدة معالجة الهواء»، وليس «الدعوة للإجراء».",
"landing.features.vision.title": "التعرف على الصور",
"landing.features.vision.desc": "النص المضمن في الصور والمخططات والرسوم البياني يتم اكتشافه وترجمته.",
"landing.features.demo.source": "المصدر (FR)",
"landing.features.demo.google": "Google Translate",
"landing.features.demo.ours": "ذكاؤنا الاصطناعي",
"landing.layout.title": "تنسيقك،",
"landing.layout.title2": "محفوظ بشكل مثالي",
"landing.layout.subtitle": "المترجمون الآخرون يدمرون تخطيطك. نحن لا.",
"landing.layout.p1.title": "SmartArt والمخططات",
"landing.layout.p1.desc": "الهياكل التنظيمية، المخططات الانسيابية، التسلسلات الهرمية — كلها مترجمة بشكل مطابق.",
"landing.layout.p2.title": "جداول المحتويات",
"landing.layout.p2.desc": "إدخالات جدول المحتويات وأرقام الصفحات والمراجع المتبادلة محدثة بشكل صحيح.",
"landing.layout.p3.title": "الرسوم والمخططات البيانية",
"landing.layout.p3.desc": "العناوين، تسميات المحاور، التسميات التوضيحية وأسماء السلاسل — كل شيء مترجم.",
"landing.layout.p4.title": "الأشكال ومربعات النص",
"landing.layout.p4.desc": "مستطيلات، كتل مستديرة، تعليقات توضيحية — محلية في كل مكان.",
"landing.layout.p5.title": "الرؤوس والتذييلات",
"landing.layout.p5.desc": "الرؤوس والتذييلات والحواشي لا تُفوت أبدًا.",
"landing.layout.p6.title": "130+ لغة",
"landing.layout.p6.desc": "Google Translate و DeepL ومحركات ذكاء اصطناعي احترافية.",
"landing.formats.title": "كل تنسيق،",
"landing.formats.title2": "كل عنصر",
"landing.formats.subtitle": "نترجم ما يفوته الآخرون. عملك يستحق توثيقًا لا تشوبه شائبة.",
"landing.formats.word.name": "Word",
"landing.formats.word.i1": "الفقرات والعناوين",
"landing.formats.word.i2": "الجداول والرسوم البيانية",
"landing.formats.word.i3": "مخططات SmartArt",
"landing.formats.word.i4": "جدول المحتويات",
"landing.formats.word.i5": "الرؤوس والتذييلات",
"landing.formats.word.i6": "الأشكال ومربعات النص",
"landing.formats.word.i7": "الحواشي والتعليقات الختامية",
"landing.formats.excel.name": "Excel",
"landing.formats.excel.i1": "قيم الخلايا",
"landing.formats.excel.i2": "أسماء الأوراق",
"landing.formats.excel.i3": "الرسوم والتسميات",
"landing.formats.excel.i4": "الرؤوس والتذييلات",
"landing.formats.excel.i5": "الخلايا المدمجة محفوظة",
"landing.formats.pptx.name": "PowerPoint",
"landing.formats.pptx.i1": "نص الشرائح والملاحظات",
"landing.formats.pptx.i2": "الرسوم والمخططات",
"landing.formats.pptx.i3": "الأشكال ومربعات النص",
"landing.formats.pptx.i4": "التخطيطات الرئيسية",
"landing.formats.pptx.i5": "الرسوم المتحركة محفوظة",
"landing.formats.pdf.name": "PDF",
"landing.formats.pdf.i1": "ملفات PDF النصية",
"landing.formats.pdf.i2": "التخطيط محفوظ",
"landing.formats.pdf.i3": "الصور في مكانها",
"landing.formats.pdf.i4": "الجداول محفوظة",
"landing.formats.pdf.i5": "الإخراج كـ DOCX أو PDF",
"landing.pricing.title": "أسعار بسيطة وشفافة",
"landing.pricing.subtitle": "ما تراه هو ما تدفعه. بدون رسوم خفية.",
"landing.pricing.monthly": "شهريًا",
"landing.pricing.annual": "سنويًا",
"landing.pricing.bestValue": "الأكثر شعبية",
"landing.pricing.month": "/شهر",
"landing.pricing.footer": "السعر المعروض هو السعر الذي تدفعه. بدون رسوم خفية بعد الترجمة.",
"landing.pricing.starter.name": "Starter",
"landing.pricing.starter.desc": "للأفراد والمشاريع الصغيرة",
"landing.pricing.starter.f1": "50 مستند / شهر",
"landing.pricing.starter.f2": "حتى 50 صفحة لكل مستند",
"landing.pricing.starter.f3": "Google Translate + DeepL",
"landing.pricing.starter.f4": "ملفات حتى 10 ميجابايت",
"landing.pricing.starter.cta": "ابدأ الآن",
"landing.pricing.pro.name": "Pro",
"landing.pricing.pro.desc": "للمحترفين المتميزين",
"landing.pricing.pro.f1": "200 مستند / شهر",
"landing.pricing.pro.f2": "حتى 200 صفحة لكل مستند",
"landing.pricing.pro.f3": "ترجمة بالذكاء الاصطناعي",
"landing.pricing.pro.f4": "Google + DeepL مشمولان",
"landing.pricing.pro.f5": "قواميس وأوامر مخصصة",
"landing.pricing.pro.f6": "دعم ذو أولوية",
"landing.pricing.pro.cta": "جرّب Pro",
"landing.pricing.business.name": "الأعمال",
"landing.pricing.business.desc": "للفرق ذات الاحتياجات الكبيرة",
"landing.pricing.business.f1": "1,000 مستند / شهر",
"landing.pricing.business.f2": "حتى 500 صفحة لكل مستند",
"landing.pricing.business.f3": "ذكاء اصطناعي متميز (Claude)",
"landing.pricing.business.f4": "جميع المزودين + واجهة برمجة التطبيقات",
"landing.pricing.business.f5": "خطاطف الويب والأتمتة",
"landing.pricing.business.f6": "5 مقاعد للفريق",
"landing.pricing.business.cta": "تواصل معنا",
"landing.cta.title": "ابدأ الترجمة في 30 ثانية",
"landing.cta.subtitle": "لا حاجة لبطاقة ائتمان. جرّب مجانًا الآن وأعد الحياة إلى مستنداتك متعددة اللغات.",
"landing.cta.button": "إنشاء حساب مجاني",
"landing.cta.secure": "محمي بتشفير AES-256",
"landing.footer.desc": "خبراء في الترجمة الذكية للمستندات. نمزج بين فن التنسيق وعلم الذكاء الاصطناعي السياقي.",
"landing.footer.product": "المنتج",
"landing.footer.resources": "الموارد",
"landing.footer.legal": "قانوني",
"landing.footer.rights": "© 2026 Wordly.art — جميع الحقوق محفوظة.",
"landing.hero.contextEngine": "ترجمة مكتشفة: مصطلح صيانة تقني لأنظمة التدفئة والتهوية...",
"landing.hero.liveAnalysis": "تحليل مباشر",
"landing.hero.termsDetected": "مصطلحات مكتشفة",
"landing.steps.process": "العملية",
"landing.translate.newProject": "مشروع جديد",
"landing.translate.title": "ترجمة مستند",
"landing.translate.subtitle": "استورد ملفًا واختر اللغة المستهدفة",
"landing.translate.sourceDocument": "المستند المصدر",
"landing.translate.configuration": "الإعدادات",
"landing.translate.sourceLang": "لغة المصدر",
"landing.translate.targetLang": "اللغة المستهدفة",
"landing.translate.provider": "المزود",
"landing.translate.startTranslation": "بدء الترجمة",
"landing.translate.zeroRetention": "صفر احتفاظ",
"landing.translate.filesDeleted": "الملفات محذوفة بعد المعالجة",
"landing.translate.dropHere": "اسحب وأفلت هنا",
"landing.translate.supportedFormats": "ملفات DOCX, XLSX, PPTX أو PDF مدعومة",
"landing.translate.aiAnalysis": "تحليل AI نشط",
"landing.translate.processing": "جاري المعالجة",
"landing.translate.preservingLayout": "جاري الحفاظ على التنسيق"
}