Files
webmail-client/backend/tests/api/test_admin_translation.py
T
lukasandClaude Opus 5.5 972e10876b Translation on Firefox Translations models; new logo
- Email translation moves from LibreTranslate to our own translator
  service (translator/): Mozilla's Firefox Translations models on the
  Bergamot engine, fastText language detection (176 languages). Polish,
  English, German, French, Spanish and Italian on first start (~350 MB
  instead of ~10 GB); Admin panel > Email translation installs and
  removes languages. Built and pushed as the `translator` image.
- Every message is translated paragraph by paragraph as plain text;
  names travel with their sentence and are kept only where the model
  changed them; a sentence start the model copied ("Enclosed") is tried
  again in lower case; list markers are not sent
- The Translate button shows only for installed languages
- New logo: favicon, app/maskable/iPhone icons, notification badge,
  email logo and calendar copy regenerated; BIMI logo rebuilt in SVG
  Tiny PS with its gradients; masks render in browsers
- Launch screen background is the app's dark grey

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:04:04 +02:00

82 lines
2.9 KiB
Python

"""Email translation's languages in the admin panel (app/api/admin.py), with
the translator service replaced by a stand-in."""
from __future__ import annotations
import pytest
from app import translation
from tests.api.test_admin_users import World, world # noqa: F401 — the fixture
@pytest.fixture
def service(monkeypatch: pytest.MonkeyPatch) -> dict[str, list[str]]:
state: dict[str, list[str]] = {"installed": ["en", "pl"], "calls": []}
async def status() -> dict[str, object]:
return {
"installed": list(state["installed"]),
"installing": {"de": {"done": 10, "total": 40}} if "de" in state["calls"] else {},
"available": ["en", "pl", "de", "hu"],
"errors": {},
}
async def install(code: str) -> None:
state["calls"].append(code)
async def remove(code: str) -> None:
state["installed"].remove(code)
monkeypatch.setattr(translation, "enabled", lambda: True)
monkeypatch.setattr(translation, "status", status)
monkeypatch.setattr(translation, "install", install)
monkeypatch.setattr(translation, "remove", remove)
return state
async def test_admin_installs_and_removes_languages(
world: World, # noqa: F811
service: dict[str, list[str]],
) -> None:
async with await world.client(await world.user(admin=True)) as c:
got = (await c.get("/api/admin/translation")).json()
assert got["reachable"] and got["installed"] == ["en", "pl"]
assert got["available"] == ["en", "pl", "de", "hu"]
got = (await c.post("/api/admin/translation/languages/de")).json()
assert service["calls"] == ["de"]
assert got["installing"] == {"de": {"done": 10, "total": 40}}
got = (await c.delete("/api/admin/translation/languages/pl")).json()
assert got["installed"] == ["en"]
assert (await c.post("/api/admin/translation/languages/x;rm")).status_code == 422
async def test_only_admins(world: World, service: dict[str, list[str]]) -> None: # noqa: F811
async with await world.client(await world.user()) as c:
assert (await c.get("/api/admin/translation")).status_code == 403
assert (await c.post("/api/admin/translation/languages/de")).status_code == 403
assert service["calls"] == []
async def test_unreachable_service_is_reported(
world: World, # noqa: F811
monkeypatch: pytest.MonkeyPatch,
) -> None:
async def down() -> dict[str, object]:
raise translation.TranslationError("down")
monkeypatch.setattr(translation, "enabled", lambda: True)
monkeypatch.setattr(translation, "status", down)
async with await world.client(await world.user(admin=True)) as c:
got = (await c.get("/api/admin/translation")).json()
assert got == {
"enabled": True,
"reachable": False,
"installed": [],
"installing": {},
"available": [],
"errors": {},
}