feat: add multilingual glossary support (backend + frontend types)
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 1m31s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 1m31s
Backend: - Add source_language column to glossaries table - Add translations JSON column to glossary_terms table - Alembic migration for schema changes - format_glossary_for_prompt now language-aware: extracts correct translation per target language, falls back to EN reference for templates with only FR→EN data - CRUD routes accept/return source_language and translations - Pydantic schemas updated Frontend: - Types updated: GlossaryTerm now has translations: Record<string, string> - Glossary/GlossaryListItem now have source_language - Added SUPPORTED_LANGUAGES constant (13 languages) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,7 @@ def _format_term(term: GlossaryTerm) -> dict:
|
||||
"id": term.id,
|
||||
"source": term.source,
|
||||
"target": term.target,
|
||||
"translations": term.translations or {},
|
||||
"created_at": term.created_at.isoformat() if term.created_at else None,
|
||||
}
|
||||
|
||||
@@ -55,6 +56,7 @@ def _format_glossary(glossary: Glossary) -> dict:
|
||||
return {
|
||||
"id": glossary.id,
|
||||
"name": glossary.name,
|
||||
"source_language": glossary.source_language,
|
||||
"terms": [_format_term(t) for t in glossary.terms] if glossary.terms else [],
|
||||
"created_at": glossary.created_at.isoformat() if glossary.created_at else None,
|
||||
"updated_at": glossary.updated_at.isoformat() if glossary.updated_at else None,
|
||||
@@ -103,6 +105,7 @@ async def create_glossary(
|
||||
glossary = Glossary(
|
||||
user_id=user.id,
|
||||
name=body.name,
|
||||
source_language=body.source_language,
|
||||
created_at=datetime.now(timezone.utc),
|
||||
updated_at=datetime.now(timezone.utc),
|
||||
)
|
||||
@@ -112,6 +115,7 @@ async def create_glossary(
|
||||
glossary=glossary,
|
||||
source=term_data.source,
|
||||
target=term_data.target,
|
||||
translations=term_data.translations or {},
|
||||
created_at=datetime.now(timezone.utc),
|
||||
)
|
||||
session.add(term)
|
||||
@@ -180,6 +184,7 @@ async def list_glossaries(
|
||||
GlossaryListItem(
|
||||
id=g.id,
|
||||
name=g.name,
|
||||
source_language=g.source_language or "fr",
|
||||
terms_count=len(g.terms) if g.terms else 0,
|
||||
created_at=g.created_at,
|
||||
)
|
||||
@@ -331,6 +336,9 @@ async def update_glossary(
|
||||
if body.name is not None:
|
||||
glossary.name = body.name
|
||||
|
||||
if body.source_language is not None:
|
||||
glossary.source_language = body.source_language
|
||||
|
||||
if body.terms is not None:
|
||||
# Delete existing terms
|
||||
session.query(GlossaryTerm).filter(
|
||||
@@ -343,6 +351,7 @@ async def update_glossary(
|
||||
glossary_id=glossary.id,
|
||||
source=term_data.source,
|
||||
target=term_data.target,
|
||||
translations=term_data.translations or {},
|
||||
created_at=datetime.now(timezone.utc),
|
||||
)
|
||||
session.add(term)
|
||||
|
||||
@@ -915,10 +915,13 @@ async def _run_translation_job(
|
||||
|
||||
# Story 3.10: Retrieve and format glossary terms for LLM prompt
|
||||
glossary_terms = None
|
||||
glossary_source_lang = "fr"
|
||||
if glossary_id and user_id:
|
||||
try:
|
||||
glossary_terms = get_glossary_terms(glossary_id, user_id)
|
||||
logger.info(f"Job {job_id}: Loaded {len(glossary_terms)} glossary terms")
|
||||
glossary_data = get_glossary_terms(glossary_id, user_id)
|
||||
glossary_terms = glossary_data["terms"]
|
||||
glossary_source_lang = glossary_data.get("source_language", "fr")
|
||||
logger.info(f"Job {job_id}: Loaded {len(glossary_terms)} glossary terms (source: {glossary_source_lang})")
|
||||
except GlossaryNotFoundError as e:
|
||||
tracker.set_error(str(e))
|
||||
logger.error(f"Job {job_id}: Glossary error - {e}")
|
||||
@@ -940,7 +943,10 @@ async def _run_translation_job(
|
||||
effective_prompt = custom_prompt
|
||||
|
||||
# Build the full prompt combining effective prompt and glossary
|
||||
full_prompt = build_full_prompt(effective_prompt, glossary_terms)
|
||||
full_prompt = build_full_prompt(
|
||||
effective_prompt, glossary_terms,
|
||||
source_lang=glossary_source_lang, target_lang=target_lang,
|
||||
)
|
||||
|
||||
translation_provider = None
|
||||
_p = provider.lower()
|
||||
|
||||
Reference in New Issue
Block a user