End-to-end pipeline that:
- Accepts an English phrase.
- Calls Google Cloud Translation (v3) to translate it into the requested language.
- Immediately runs the translated phrase through the G2P service to obtain IPA/ARPAbet phonetics.
- Stores (or returns cached) rows in SurrealDB so each
(input_en, lang)pair is only processed once.
The stack is fully containerized and brought up via docker compose.
- Docker + Docker Compose.
- A Google Cloud project with Cloud Translation API v3 enabled.
- A service-account JSON key with permissions to call that API (stored under
.creds/– Git ignores it). - SSH access to
[email protected]:bigmark222/Phonix.git(already configured).
Edit .env (already committed, but with placeholders) and set:
SURREAL_USER=root
SURREAL_PASS=root
SURREAL_NS=app
SURREAL_DB=phonix
GOOGLE_TRANSLATE_PROJECT_ID=your-project-id
GOOGLE_TRANSLATE_LOCATION=global # or regional endpoint
GOOGLE_TRANSLATE_DEBUG=true # optional, for verbose logging
GOOGLE_TRANSLATE_CREDENTIALS_PATH=/run/creds/google-translate-service-account.json
Then drop your service-account JSON into .creds/google-translate-service-account.json. This folder is already ignored by Git and gets mounted read-only into the orchestrator container (/run/creds/...).
From the repo root:
docker compose up -d --buildThis launches:
- Redis (
localhost:6379) - SurrealDB (
localhost:8000) phonix-g2p(FastAPI) (localhost:8001)phonix-orchestrator(Axum) (localhost:3000)
Check status with:
docker compose psIf NordVPN or another firewall blocks localhost, either disable it or issue curl commands from inside a container (see step 4).
Translate + store (default / route):
curl -X POST http://localhost:3000/ \
-H 'Content-Type: application/json' \
-d '{"text":"secret phrase","target_lang":"es"}'Response:
{
"record_id": "stealth:...",
"input_en": "secret phrase",
"target_phrase": "frase secreta",
"target_ipa": "fɾase sekɾeta",
"lang": "es",
"cached": false,
"has_english_phrase": false,
"english_hint": null
}Repeat the same request and cached becomes true (SurrealDB hit).
Raw g2p (if you only want pronunciation):
curl -X POST http://localhost:3000/g2p \
-H 'Content-Type: application/json' \
-d '{"text":"hola","lang":"es"}'We switched to Surreal’s JSON-RPC endpoint, so use:
curl -u root:root \
-H 'Surreal-NS: app' \
-H 'Surreal-DB: phonix' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json; charset=utf-8' \
-d '{"method":"query","params":["SELECT * FROM stealth"],"id":1}' \
http://localhost:8000/rpcExample output:
{
"result": [
{
"result": [
{
"id": "stealth:z5k4y71a63ylpmq3xjeu",
"input_en": "secret phrase",
"target_phrase": "frase secreta",
"target_ipa": "fɾase sekɾeta",
"lang": "es",
"stealth_output": "frase secreta",
"has_english_phrase": false,
"english_hint": null,
"created_at": "2025-11-13T13:14:18.477664259Z"
}
],
"status": "OK",
"time": "280.042µs"
}
]
}If you need to run SQL manually (e.g., to reset the table), use the CLI:
docker compose exec -T surrealdb /surreal sql --conn http://localhost:8000 \
--user root --pass root --ns app --db phonix < migrations/001_init.surqlThen reapply migrations/002_stealth_phonetics.surql. (We had to drop/recreate the table once during development to fix duplicated stealth.* field definitions.)
-
Google auth: With
GOOGLE_TRANSLATE_DEBUG=true, logs showservice_account=…, token type, project, and location for each call. This proved handy when we swapped from API keys to OAuth2 JWTs (the v3 API only accepts service-account tokens). -
Surreal errors: When the DB rejects a query, the orchestrator logs the
detailand rawresultto help trace schema issues. -
VPN/firewalls: If
curl http://localhost:3000fails with “Operation not permitted”, disable the VPN or tunnel inside Docker:docker compose exec phonix-g2p python - <<'PY' import requests print(requests.post('http://phonix-orchestrator:3000/', json={ "text": "secret phrase", "target_lang": "es" }).text) PY
-
Resetting
stealth: To wipe cached rows and reapply the schema:docker compose exec -T surrealdb /surreal sql --conn http://localhost:8000 \ --user root --pass root --ns app --db phonix <<'EOF' REMOVE TABLE stealth; EOF docker compose exec -T surrealdb /surreal sql --conn http://localhost:8000 \ --user root --pass root --ns app --db phonix < migrations/001_init.surql docker compose exec -T surrealdb /surreal sql --conn http://localhost:8000 \ --user root --pass root --ns app --db phonix < migrations/002_stealth_phonetics.surql
Launch the Ratatui client to drive the workflow without typing curl commands:
Host (if localhost:3000 reaches Docker):
export TUI_API_URL=http://host.docker.internal:3000 # optional override
cargo run --bin tui-
Docker (bypasses macOS loopback/firewall issues):
script -q /dev/null docker run --rm -it \ --network phonix_default \ -e TUI_API_URL=http://phonix-orchestrator:3000 \ -v "$PWD/phonix-orchestrator":/app \ -w /app \ rust:1.84 bash -lc 'export PATH="/usr/local/cargo/bin:$PATH"; cargo run --bin tui'
-
Tabtoggles between editing the input phrase and selecting languages. -
Spacetoggles the highlighted language; Up/Down/PageUp/PageDown move the cursor. -
Enter(orS) runs the batch, issuing one request per selected language. -
Escclears the selection,Qquits.
The TUI talks to http://localhost:3000 by default; override with TUI_API_URL (as shown above) if you need another base URL.
The repo is already linked to GitHub via SSH:
git remote add origin [email protected]:bigmark222/Phonix.git
git pull --rebase origin main
git push -u origin mainBefore pushing, double-check that .creds/ remains ignored and .env only carries non-sensitive values (the actual JSON stays local; CI/CD environments should mount secrets another way).
- Add a write API (or admin UI) that lets you set
english_hintand togglehas_english_phrasedirectly from the app instead of Surrealist. - Wire up CI to run
cargo check+ Python lint/tests on each PR. - Add health/status endpoints for SurrealDB and Redis to surface in Compose logs.