i18n: add translate() helper backed by call_llm

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Giorgio Gilestro 2026-05-27 16:48:32 +02:00
parent 5730aad73c
commit 7683f82820
2 changed files with 157 additions and 0 deletions

View file

@ -42,3 +42,78 @@ def test_respond_in_clause_unknown_lang_falls_back_to_english():
prompt assembly. Unknown codes map to no-suffix (English default)."""
from app.services.i18n import respond_in_clause
assert respond_in_clause("xx") == ""
@pytest.mark.asyncio
async def test_translate_happy_path(monkeypatch):
from unittest.mock import AsyncMock, MagicMock
from app.services import translation as mod
from app.services.openrouter import LogResult
monkeypatch.setattr(mod, "call_llm", AsyncMock(return_value=LogResult(
content="# Apertura\n\nIl mercato è in calo dello 0,4%.",
model="deepseek/deepseek-v4-flash",
prompt_tokens=300, completion_tokens=80, cost_usd=0.00002,
)))
client = MagicMock()
translated, llm_log = await mod.translate(
client, "# Open\n\nThe market is down 0.4%.", "it",
)
assert "Apertura" in translated
assert llm_log.model == "deepseek/deepseek-v4-flash"
assert llm_log.cost_usd == pytest.approx(0.00002)
@pytest.mark.asyncio
async def test_translate_strips_code_fences(monkeypatch):
"""If the LLM wraps the output in ```markdown ... ```, strip it."""
from unittest.mock import AsyncMock, MagicMock
from app.services import translation as mod
from app.services.openrouter import LogResult
fenced = "```markdown\n# Titolo\n\nCorpo.\n```"
monkeypatch.setattr(mod, "call_llm", AsyncMock(return_value=LogResult(
content=fenced, model="m", prompt_tokens=10, completion_tokens=20, cost_usd=0.0,
)))
client = MagicMock()
translated, _ = await mod.translate(client, "# Title\n\nBody.", "it")
assert "```" not in translated
assert translated.startswith("# Titolo")
@pytest.mark.asyncio
async def test_translate_provider_failure_propagates(monkeypatch):
from unittest.mock import AsyncMock, MagicMock
from app.services import translation as mod
monkeypatch.setattr(mod, "call_llm", AsyncMock(side_effect=RuntimeError("upstream down")))
client = MagicMock()
with pytest.raises(RuntimeError, match="upstream down"):
await mod.translate(client, "# Title\n\nBody.", "it")
@pytest.mark.asyncio
async def test_translate_unknown_lang_returns_source_unchanged(monkeypatch):
"""Defensive: an unknown lang code (or 'en') short-circuits without
calling the LLM. Callers shouldn't have to gate the call themselves."""
from unittest.mock import AsyncMock, MagicMock
from app.services import translation as mod
from app.services.openrouter import LogResult
call_mock = AsyncMock(return_value=LogResult(
content="should not be returned",
model="m", prompt_tokens=0, completion_tokens=0, cost_usd=0.0,
))
monkeypatch.setattr(mod, "call_llm", call_mock)
client = MagicMock()
out, _ = await mod.translate(client, "Hello world.", "en")
assert out == "Hello world."
call_mock.assert_not_awaited()