fix: comprehensive glossary system audit — 6 critical fixes
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m27s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m27s
Full audit found 18 issues across backend, frontend, and data files. Root cause: target_language had no single source of truth — 'en' was hardcoded as default in 6+ places while templates are actually multilingual. Fixes applied: - routes/glossary_routes.py: list_glossaries() fallback 'en' → 'multi' - routes/glossary_routes.py: import reads target_lang from index.json (source of truth) instead of template file - data/glossaries/*.json: all 8 template files target_lang 'en' → 'multi' - services/glossary_service.py: get_glossary_terms() now returns target_language field (was missing entirely) - schemas/glossary_schemas.py: all defaults 'en' → 'multi' (GlossaryCreate, GlossaryResponse, GlossaryListItem) - useTranslationConfig.ts: only reset glossary on sourceLang change, not targetLang (multilingual glossaries work with any target) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
"name": "E-commerce & Vente - Français → Anglais",
|
||||
"description": "Terminologie e-commerce et vente française vers anglaise pour boutiques en ligne, catalogues et documents commerciaux",
|
||||
"source_lang": "fr",
|
||||
"target_lang": "en",
|
||||
"target_lang": "multi",
|
||||
"category": "ecommerce",
|
||||
"terms": [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "Finance & Comptabilité - Français → Anglais",
|
||||
"description": "Terminologie financière et comptable française vers anglaise pour rapports annuels, bilans et documents financiers",
|
||||
"source_lang": "fr",
|
||||
"target_lang": "en",
|
||||
"target_lang": "multi",
|
||||
"category": "finance",
|
||||
"terms": [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "RH & Ressources Humaines - Français → Anglais",
|
||||
"description": "Terminologie des ressources humaines française vers anglaise pour contrats, politiques et documents RH",
|
||||
"source_lang": "fr",
|
||||
"target_lang": "en",
|
||||
"target_lang": "multi",
|
||||
"category": "hr",
|
||||
"terms": [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "Juridique - Français → Anglais",
|
||||
"description": "Terminologie juridique française vers anglaise pour contrats, statuts et documents légaux",
|
||||
"source_lang": "fr",
|
||||
"target_lang": "en",
|
||||
"target_lang": "multi",
|
||||
"category": "legal",
|
||||
"terms": [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "Marketing & Communication - Français → Anglais",
|
||||
"description": "Terminologie marketing et communication française vers anglaise pour campagnes, stratégies et contenus marketing",
|
||||
"source_lang": "fr",
|
||||
"target_lang": "en",
|
||||
"target_lang": "multi",
|
||||
"category": "marketing",
|
||||
"terms": [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "Médical & Santé - Français → Anglais",
|
||||
"description": "Terminologie médicale française vers anglaise pour rapports médicaux, publications scientifiques et documents de santé",
|
||||
"source_lang": "fr",
|
||||
"target_lang": "en",
|
||||
"target_lang": "multi",
|
||||
"category": "medical",
|
||||
"terms": [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "Scientifique & Recherche - Français → Anglais",
|
||||
"description": "Terminologie scientifique française vers anglaise pour publications, articles de recherche et thèses",
|
||||
"source_lang": "fr",
|
||||
"target_lang": "en",
|
||||
"target_lang": "multi",
|
||||
"category": "scientific",
|
||||
"terms": [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "Technologie / IT - Français → Anglais",
|
||||
"description": "Terminologie technique et informatique française vers anglaise pour documentation, spécifications et rapports IT",
|
||||
"source_lang": "fr",
|
||||
"target_lang": "en",
|
||||
"target_lang": "multi",
|
||||
"category": "technology",
|
||||
"terms": [
|
||||
{
|
||||
|
||||
@@ -80,10 +80,11 @@ export function useTranslationConfig(hasFile: boolean): UseTranslationConfigRetu
|
||||
}
|
||||
}, [settings.defaultTargetLanguage]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Reset glossary selection when source or target language changes
|
||||
// Reset glossary selection when source language changes
|
||||
// (multilingual glossaries are compatible with any target language)
|
||||
useEffect(() => {
|
||||
setGlossaryId(null);
|
||||
}, [sourceLang, targetLang]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, [sourceLang]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Fetch available (admin-configured) providers
|
||||
useEffect(() => {
|
||||
|
||||
@@ -187,7 +187,7 @@ async def list_glossaries(
|
||||
id=g.id,
|
||||
name=g.name,
|
||||
source_language=g.source_language or "fr",
|
||||
target_language=getattr(g, "target_language", None) or "en",
|
||||
target_language=getattr(g, "target_language", None) or "multi",
|
||||
terms_count=len(g.terms) if g.terms else 0,
|
||||
created_at=g.created_at,
|
||||
)
|
||||
@@ -596,8 +596,8 @@ async def import_glossary_template(
|
||||
glossary = Glossary(
|
||||
user_id=user.id,
|
||||
name=glossary_name,
|
||||
source_language=template_data.get("source_lang", "fr"),
|
||||
target_language=template_data.get("target_lang", "en"),
|
||||
source_language=template_info.get("source_lang", template_data.get("source_lang", "fr")),
|
||||
target_language=template_info.get("target_lang", template_data.get("target_lang", "multi")),
|
||||
created_at=datetime.now(timezone.utc),
|
||||
updated_at=datetime.now(timezone.utc),
|
||||
)
|
||||
|
||||
@@ -47,7 +47,7 @@ class GlossaryCreate(BaseModel):
|
||||
default="fr", max_length=10, description="Langue source (ISO code)"
|
||||
)
|
||||
target_language: str = Field(
|
||||
default="en", max_length=10, description="Langue cible (ISO code)"
|
||||
default="multi", max_length=10, description="Langue cible (ISO code) ou 'multi' pour multilingue"
|
||||
)
|
||||
terms: list[GlossaryTermCreate] = Field(
|
||||
default_factory=list, description="Liste des termes"
|
||||
@@ -79,7 +79,7 @@ class GlossaryResponse(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
source_language: str = "fr"
|
||||
target_language: str = "en"
|
||||
target_language: str = "multi"
|
||||
terms: list[GlossaryTermResponse] = []
|
||||
created_at: Optional[datetime] = None
|
||||
updated_at: Optional[datetime] = None
|
||||
@@ -93,7 +93,7 @@ class GlossaryListItem(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
source_language: str = "fr"
|
||||
target_language: str = "en"
|
||||
target_language: str = "multi"
|
||||
terms_count: int = Field(
|
||||
default=0, description="Nombre de termes dans le glossaire"
|
||||
)
|
||||
|
||||
@@ -61,6 +61,7 @@ def get_glossary_terms(glossary_id: str, user_id: str) -> Dict[str, Any]:
|
||||
|
||||
return {
|
||||
"source_language": glossary.source_language or "fr",
|
||||
"target_language": getattr(glossary, "target_language", None) or "multi",
|
||||
"terms": result,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user