app/ ├── core/ # shared game logic - knows nothing about HTTP │ ├── combat.py │ ├── dungeon.py │ ├── progression.py │ └── translation.py │ ├── api/ # FastAPI - thin layer, calls core │ └── routes/ │ ├── dungeon.py # calls core.dungeon │ └── combat.py # calls core.combat │ └── workers/ # also calls core, not the API └── handlers/ └── loot.py # calls core.progression
TRANSLATION LAYER: at launch for every user, depending on language, the phrases are either being all translated or not.
- backend/services/translator/translation_service.py.translate does not write to Redis; it only resolves text.
- backend/services/cache_warm.py.warm_cache generates precomputed strings for non-dynamic phrase values and stores cache
/translate endpoint in backend/api/main.py:
- Query params:
text,to_language(defaulten) - Uses
backend.services.translator.translation_service.translate - Reads and writes cache in Redis using
translation:{lang}:{hash(text)} - TTL controlled by
backend/services/translator/config.py(cache_time)
New test: tests/services/test_translator_api.py