German Translation (complete i18n): - Full DE translation block (146 keys matching FR/EN/UA coverage) - All 37 categories with German name and description - 228 country names in country.json (country_DE field) - 10 inline fallback countries with country_DE - getCountryName() and all ternary expressions handle DE - 399 country briefs with DE field - 16 preset labels made translatable via data-i18n - Browser language auto-detection (navigator.language) with FR fallback - DE language button in UI Self-Hostable Daily API: - Node.js server (api/server.js) converted from Cloudflare Worker - In-memory KV store with TTL, SHA-256 IP hashing - Configurable PORT and CORS_ORIGINS via environment variables - Docker-ready with api/Dockerfile (node:22-alpine) - docker-compose.yml for easy self-hosting (nginx + api) - config.example.js for API URL override - Default DAILY_API falls back to original Cloudflare Worker (no breaking change) UX Improvements: - Replaced single "Play again" button with two: "Back to menu" + "Play again" - Added replayGame() for instant same-mode replay - Hardcoded French alert() strings replaced with t() translations - Added favicon (globe emoji SVG) Repo Cleanup: - Removed 12 unused numbered HTML snapshots - Removed archive/, .DS_Store files, Cloudflare Worker source - Removed .docx and .xlsx dev documents - Added .gitignore - Rewrote README.md with game description and self-hosting guide
16 lines
290 B
YAML
16 lines
290 B
YAML
services:
|
|
web:
|
|
image: nginx:alpine
|
|
restart: unless-stopped
|
|
ports:
|
|
- "8080:80"
|
|
volumes:
|
|
- .:/usr/share/nginx/html:ro
|
|
|
|
api:
|
|
build: ./api
|
|
restart: unless-stopped
|
|
ports:
|
|
- "3000:3000"
|
|
environment:
|
|
- CORS_ORIGINS=http://localhost:8080
|