"""What is sent to the translation service (app/translation.py).""" from __future__ import annotations import pytest from app import translation from app.translation import detect, languages_of, protect_addresses, translate_html def test_addresses_in_text_are_kept_from_translation() -> None: html = ( '

My reel: https://vimeo.com/1, ' "write to anna@x.example or see www.example.com today.

" ) out = protect_addresses(html) assert 'https://vimeo.com/1' in out assert 'anna@x.example' in out assert 'www.example.com' in out assert '' in out # attributes untouched def test_style_blocks_are_left_alone() -> None: html = "

Hi

" assert protect_addresses(html) == html async def test_names_go_with_their_sentence_unless_the_model_changes_them( monkeypatch: pytest.MonkeyPatch, ) -> None: sent: list[list[str]] = [] model = { "I came across Imaginary Pixels today.": "Natknąłem się dziś na Imaginary Pixels.", "Dear Lukas,": "Drogi Lukasie,", # an ending: still the name "Regards, Milan": "Pozdrawiam, Mediolan", # changed: done again around it "Regards,": "Pozdrawiam,", } async def post(path: str, payload: dict[str, object]) -> object: q = payload["q"] assert isinstance(q, list) sent.append(list(q)) return {"translatedText": [model.get(x, x) for x in q]} async def installed() -> list[translation.Language]: return [translation.Language(c, c) for c in ("en", "pl")] monkeypatch.setattr(translation, "_post", post) monkeypatch.setattr(translation, "languages", installed) html = "

I came across Imaginary Pixels today.

Dear Lukas,

Regards, Milan

" out = await translate_html(html, "en", "pl", names=["Imaginary Pixels", "Lukas", "Milan"]) assert out == ( "

Natknąłem się dziś na Imaginary Pixels.

Drogi Lukasie,

" "

Pozdrawiam, Milan

" ) assert sent[1:] == [["Regards,"]] # only the piece that lost a name went again def _fake_detector(monkeypatch: pytest.MonkeyPatch) -> list[str]: """A detector that knows Chinese signs, Polish letters, else English.""" asked: list[str] = [] def one(text: str) -> str: asked.append(text) if any("\u4e00" <= c <= "\u9fff" for c in text): return "zh-Hans" return "pl" if any(c in "ąćęłńóśźż" for c in text.lower()) else "en" async def detect_many(texts: list[str]) -> list[str]: return [one(t) for t in texts] async def installed() -> list[translation.Language]: return [translation.Language(c, c) for c in ("en", "pl", "zh-Hans")] monkeypatch.setattr(translation, "_detect_many", detect_many) monkeypatch.setattr(translation, "languages", installed) return asked async def test_short_parts_take_the_next_language(monkeypatch: pytest.MonkeyPatch) -> None: asked = _fake_detector(monkeypatch) parts = [ "您好!", "Szanowny Kliencie,", # short: goes with the Polish that follows "Widzę, że złożyłeś wniosek o otwarcie sklepu na platformie.", "-----", "Hello, my name is Jacqueline, the manager for Europe.", "Jacqueline Lian", # short, last: goes with the one before ] assert await languages_of(parts) == ["zh-Hans", "pl", "pl", "", "en", "en"] assert "Jacqueline Lian" not in asked # too short to ask about async def test_a_message_in_three_languages(monkeypatch: pytest.MonkeyPatch) -> None: _fake_detector(monkeypatch) text = ( "尊敬的客户,我是速卖通的官方客户经理,我从后台看到您申请入驻速卖通平台开店。\n" "Szanowny Kliencie,\n" "Widzę, że złożyłeś wniosek o otwarcie sklepu na platformie AliExpress.\n" "Dears,\nI noticed from the backend that you have applied to join the platform.\n" ) assert set((await detect(text)).split(",")) == {"zh-Hans", "pl", "en"} # One language: one code. assert await detect("I noticed from the backend that you applied, thanks a lot.") == "en" async def test_each_paragraph_from_its_own_language(monkeypatch: pytest.MonkeyPatch) -> None: _fake_detector(monkeypatch) calls: list[tuple[str, list[str]]] = [] async def post(path: str, payload: dict[str, object]) -> object: q = payload["q"] if path == "/translate" and isinstance(q, list) and payload.get("source") != "auto": calls.append((str(payload["source"]), list(q))) return {"translatedText": [f"PL({x.upper()})" for x in q]} return {"translatedText": list(q) if isinstance(q, list) else q} # names: unchanged monkeypatch.setattr(translation, "_post", post) html = ( "
我是速卖通的官方客户经理奎琳,我从后台看到您申请入驻速卖通平台开店。
" "
Widzę, że złożyłeś wniosek o otwarcie sklepu & więcej.
" "
I noticed that you applied to join the platform & more.
" "
WhatsApp: +48 780 549 877
" ) out = await translate_html(html, "zh-Hans,pl,en", "pl") assert [c[0] for c in calls] == ["zh-Hans", "en"] # the Polish is left alone assert "
Widzę, że złożyłeś wniosek o otwarcie sklepu & więcej.
" in out # Two pieces of one Chinese sentence get a space between them. assert "PL(我是速卖通的官方客户经理奎琳,) PL(" in out assert "PL(I NOTICED THAT YOU APPLIED TO JOIN THE PLATFORM & MORE.)" in out.replace( "&", "&" ) assert '+48 780 549 877' in out async def test_one_language_needs_no_detector_and_skips_what_is_missing( monkeypatch: pytest.MonkeyPatch, ) -> None: asked = _fake_detector(monkeypatch) calls: list[tuple[str, list[str]]] = [] async def post(path: str, payload: dict[str, object]) -> object: q = payload["q"] if path == "/translate" and isinstance(q, list) and payload.get("source") == "en": calls.append(("en", list(q))) return {"translatedText": [f"PL({x.upper()})" for x in q]} return {"translatedText": list(q) if isinstance(q, list) else q} monkeypatch.setattr(translation, "_post", post) html = "

Hello there, how are you?

Short one.

1. Thursday 2nd July

" out = await translate_html(html, "en", "pl") assert out == ( "

PL(HELLO THERE, HOW ARE YOU?)

PL(SHORT ONE.)

" "

1. PL(THURSDAY 2ND JULY)

" # the list marker is not sent ) assert asked == [] # the message's one language is known: no detection # Hungarian is not installed: left as it is, nothing sent. calls.clear() assert await translate_html("

Jó napot kívánok

", "hu", "pl") == "

Jó napot kívánok

" assert calls == [] async def test_a_sentence_start_the_model_copied_is_tried_lower_case( monkeypatch: pytest.MonkeyPatch, ) -> None: model = { "Enclosed is a summary. Natalia wrote it.": ( "Enclosed jest podsumowaniem. Natalia to napisała." ), "enclosed is a summary. natalia wrote it.": ( "załączone jest podsumowanie. Natalia to napisała." ), "Natalia wrote it.": "Natalia to napisała.", "natalia wrote it.": "Natalia to napisała.", } sent: list[str] = [] async def post(path: str, payload: dict[str, object]) -> object: q = payload["q"] assert isinstance(q, list) sent.extend(q) return {"translatedText": [model[x] for x in q]} async def installed() -> list[translation.Language]: return [translation.Language(c, c) for c in ("en", "pl")] monkeypatch.setattr(translation, "_post", post) monkeypatch.setattr(translation, "languages", installed) out = await translate_html("

Enclosed is a summary. Natalia wrote it.

", "en", "pl") assert out == "

Załączone jest podsumowanie. Natalia to napisała.

" # A name comes back the same lower-case too: the first try stands. sent.clear() assert await translate_html("

Natalia wrote it.

", "en", "pl") == ( "

Natalia to napisała.

" ) assert sent == ["Natalia wrote it.", "natalia wrote it."] def test_capitalised_again_but_not_after_abbreviations() -> None: assert translation._capitalised("załączony na lipiec 2026 r., od 13 lipca. dalej np. tak") == ( "Załączony na lipiec 2026 r., od 13 lipca. Dalej np. tak" ) def test_a_comma_word_keeps_the_first_try_case() -> None: first = "Enclosed jest podsumowaniem na lipiec 2026, od 13 lipca." again = "Załączony jest podsumowanie na lipiec 2026 r., Od 13 lipca, Anna wie." assert translation._as_before(again, first) == ( "Załączony jest podsumowanie na lipiec 2026 r., od 13 lipca, Anna wie." )