All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m20s
Translation quality & format preservation: - Word: merge adjacent same-format runs into one unit (sentence-level coherence like inline-tag handling); translate comments/balloons; dedupe textbox collection (was translated twice); RTL no longer overrides center/justify alignment; CJK/Arabic font hints (eastAsia/cs) - PPTX: chart translations now actually reach the output file (ChartPart.blob is read-only — rewrite chart XML in the saved ZIP); CJK typeface hints (a:ea) - Excel: sheet renames no longer break references — rewrite cell formulas (3D/quoted), defined names, data validations, cond. formats - PDF: bold/italic honored (hebo/heit/hebi); table cells never merge; unchanged blocks left untouched (typography preserved, fixes duplicate hyperlinks); attempted/changed stats + route gate now cover PDF; CJK font paths; scanned PDFs via Mistral OCR (detection + admin settings) Features: - formality param (formal/informal) + automatic regional-variant prompts - output_mode=bilingual docx (source above translation) - per-user translation memory on Redis (falls back to LRU), context-hashed - QA report + 0-100 confidence score in job status; L0 on by default - OpenAI-compatible providers: whole chunk in ONE numbered-JSON request (~15x fewer calls) with per-item fallback; base prompt always present (custom prompt no longer replaces translation instructions) Infra & marketing alignment: - plan-based engine gating + vision gating (closes paid-engine leak); /providers/available filtered per plan; 107 languages exposed - zh-CN/zh-TW validation fixed; libmagic disabled on Windows (native crash) - admin: Mistral OCR settings + engine status dashboard; httpx<0.28 pin (TestClient breakage); Prometheus test fixture fixed - marketing docs aligned with code (PDF+OCR, retention, engines, pricing) - security: .env.ionos/.env.production/provider_settings.json removed Tests: 1173 passed / 0 failed (6 network tests deselected: free Google endpoint temporarily blocked from this machine)
244 lines
6.8 KiB
Python
244 lines
6.8 KiB
Python
"""
|
|
Pydantic models for translation endpoints
|
|
Story 3.6: Documentation OpenAPI (Swagger + ReDoc)
|
|
"""
|
|
|
|
from pydantic import BaseModel, Field
|
|
from typing import Optional, Literal, List, Dict, Any
|
|
from datetime import datetime
|
|
|
|
|
|
class TranslateResponseData(BaseModel):
|
|
"""Response data for translation request"""
|
|
|
|
id: str = Field(
|
|
...,
|
|
example="tr_abc123def456",
|
|
description="Identifiant unique du job de traduction"
|
|
)
|
|
status: Literal["processing"] = Field(
|
|
default="processing",
|
|
description="Statut du job (toujours 'processing' à la création)"
|
|
)
|
|
file_name: Optional[str] = Field(
|
|
None,
|
|
example="rapport_financier.xlsx",
|
|
description="Nom du fichier original"
|
|
)
|
|
source_lang: Optional[str] = Field(
|
|
None,
|
|
example="en",
|
|
description="Code langue source (ISO 639-1)"
|
|
)
|
|
target_lang: str = Field(
|
|
...,
|
|
example="fr",
|
|
description="Code langue cible (ISO 639-1)"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"id": "tr_abc123def456",
|
|
"status": "processing",
|
|
"file_name": "rapport_financier.xlsx",
|
|
"source_lang": "en",
|
|
"target_lang": "fr"
|
|
}
|
|
}
|
|
|
|
|
|
class TranslateResponseMeta(BaseModel):
|
|
"""Metadata for translation response"""
|
|
|
|
rate_limit_remaining: int = Field(
|
|
...,
|
|
description="Nombre de traductions restantes aujourd'hui",
|
|
example=4
|
|
)
|
|
estimated_time_seconds: Optional[int] = Field(
|
|
None,
|
|
description="Temps estimé pour la traduction en secondes",
|
|
example=15
|
|
)
|
|
|
|
|
|
class TranslateResponse(BaseModel):
|
|
"""Full response for translation request"""
|
|
|
|
data: TranslateResponseData
|
|
meta: TranslateResponseMeta
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"data": {
|
|
"id": "tr_abc123def456",
|
|
"status": "processing",
|
|
"file_name": "rapport_financier.xlsx",
|
|
"source_lang": "en",
|
|
"target_lang": "fr"
|
|
},
|
|
"meta": {
|
|
"rate_limit_remaining": 4,
|
|
"estimated_time_seconds": 15
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class TranslationStatusData(BaseModel):
|
|
"""Response data for translation status endpoint"""
|
|
|
|
id: str = Field(
|
|
...,
|
|
description="Identifiant unique du job de traduction",
|
|
example="tr_abc123def456"
|
|
)
|
|
status: Literal["queued", "processing", "completed", "failed"] = Field(
|
|
...,
|
|
description="Statut actuel du job"
|
|
)
|
|
progress_percent: int = Field(
|
|
default=0,
|
|
ge=0,
|
|
le=100,
|
|
description="Pourcentage de progression (0-100)",
|
|
example=65
|
|
)
|
|
current_step: str = Field(
|
|
default="Initializing",
|
|
description="Description de l'opération en cours",
|
|
example="Traduction de la diapositive 3/5"
|
|
)
|
|
file_name: Optional[str] = Field(
|
|
None,
|
|
description="Nom du fichier original",
|
|
example="presentation.pptx"
|
|
)
|
|
source_lang: Optional[str] = Field(
|
|
None,
|
|
description="Code langue source",
|
|
example="en"
|
|
)
|
|
target_lang: Optional[str] = Field(
|
|
None,
|
|
description="Code langue cible",
|
|
example="fr"
|
|
)
|
|
created_at: Optional[str] = Field(
|
|
None,
|
|
description="Date de création (ISO 8601)",
|
|
example="2024-01-15T10:30:00Z"
|
|
)
|
|
completed_at: Optional[str] = Field(
|
|
None,
|
|
description="Date de complétion (ISO 8601)",
|
|
example="2024-01-15T10:35:00Z"
|
|
)
|
|
failed_at: Optional[str] = Field(
|
|
None,
|
|
description="Date d'échec (ISO 8601)",
|
|
example=None
|
|
)
|
|
error_message: Optional[str] = Field(
|
|
None,
|
|
description="Message d'erreur si status='failed'",
|
|
example=None
|
|
)
|
|
quality: Optional[dict] = Field(
|
|
None,
|
|
description=(
|
|
"Rapport qualité post-traduction (job réussi) : "
|
|
"score 0-100, fidélité des nombres, ratio non traduit."
|
|
),
|
|
example={"score": 92, "numbers": {"source_numbers": 12, "preserved": 12, "fidelity": 1.0}, "untranslated_ratio": 0.02},
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"id": "tr_abc123def456",
|
|
"status": "processing",
|
|
"progress_percent": 65,
|
|
"current_step": "Traduction de la diapositive 3/5",
|
|
"file_name": "presentation.pptx",
|
|
"source_lang": "en",
|
|
"target_lang": "fr",
|
|
"created_at": "2024-01-15T10:30:00Z",
|
|
"completed_at": None,
|
|
"failed_at": None,
|
|
"error_message": None
|
|
}
|
|
}
|
|
|
|
|
|
class TranslationStatusMeta(BaseModel):
|
|
"""Metadata for translation status response"""
|
|
|
|
estimated_remaining_seconds: Optional[int] = Field(
|
|
default=None,
|
|
description="Temps restant estimé en secondes",
|
|
example=30
|
|
)
|
|
|
|
|
|
class TranslationStatusResponse(BaseModel):
|
|
"""Full response for translation status endpoint"""
|
|
|
|
data: TranslationStatusData
|
|
meta: Optional[TranslationStatusMeta] = None
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"data": {
|
|
"id": "tr_abc123def456",
|
|
"status": "processing",
|
|
"progress_percent": 65,
|
|
"current_step": "Traduction de la diapositive 3/5",
|
|
"file_name": "presentation.pptx",
|
|
"source_lang": "en",
|
|
"target_lang": "fr",
|
|
"created_at": "2024-01-15T10:30:00Z"
|
|
},
|
|
"meta": {
|
|
"estimated_remaining_seconds": 30
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class LanguageItem(BaseModel):
|
|
"""Single language entry"""
|
|
|
|
code: str = Field(
|
|
...,
|
|
description="Code langue ISO 639-1",
|
|
example="fr"
|
|
)
|
|
name: str = Field(
|
|
...,
|
|
description="Nom de la langue en français",
|
|
example="Français"
|
|
)
|
|
|
|
|
|
class LanguageResponse(BaseModel):
|
|
"""Response model for supported languages"""
|
|
|
|
supported_languages: Dict[str, str] = Field(
|
|
...,
|
|
description="Dictionnaire des langues supportées (code -> nom)",
|
|
example={
|
|
"fr": "French",
|
|
"de": "German",
|
|
"es": "Spanish",
|
|
"it": "Italian"
|
|
}
|
|
)
|
|
note: Optional[str] = Field(
|
|
None,
|
|
description="Note sur la disponibilité des langues",
|
|
example="Les langues supportées peuvent varier selon le service de traduction configuré"
|
|
) |