A single-page web app that translates English text into eight target languages in parallel through an OpenAI-compatible chat completions endpoint.
The app was built for tencent/Hy-MT2-1.8B, but it works with any endpoint that accepts OpenAI-style /v1/chat/completions requests and returns choices[0].message.content.
- 3x3 responsive translation grid.
- English source input plus eight live output tiles.
- Debounced input, with all translation requests sent concurrently.
- Previous translations stay visible while replacement translations are loading.
- Per-tile loading, ready, and quiet error states.
- Server-side proxy keeps API keys out of the browser.
- No frontend build step and no runtime dependencies.
The default target tiles are:
- Chinese (Simplified)
- Spanish
- Hindi
- Arabic
- French
- Portuguese
- Japanese
- Korean
Set LLM_TRANSLATE_LANGUAGES in .env to change the target tiles without editing code:
LLM_TRANSLATE_LANGUAGES=chinese,spanish,hindi,arabic,french,portuguese,japanese,koreanEntries can use built-in keys, display names, prompt names, or language codes from public/languages.js. The first eight valid entries are used.
For a language that is not in the built-in catalog, use:
LLM_TRANSLATE_LANGUAGES=chinese,custom-key|Display Name|Prompt Name|lang|ltrUse rtl as the final field for right-to-left languages. Restart the server after changing .env.
- Node.js 20 or newer.
- A running OpenAI-compatible chat completions endpoint for Hy-MT2 or another translation-capable model.
Create a local .env from the example:
cp .env.example .envSet either an exact chat completions URL:
LLM_TRANSLATE_ENDPOINT=http://127.0.0.1:8000/v1/chat/completionsor a base URL:
OPENAI_BASE_URL=http://127.0.0.1:8000/v1Then set the model id or serving alias exposed by your endpoint:
LLM_TRANSLATE_MODEL=tencent/Hy-MT2-1.8BIf your endpoint requires bearer auth:
LLM_TRANSLATE_API_KEY=your_api_keyOPENAI_API_KEY, OPENAI_MODEL, and OPENAI_BASE_URL are also accepted for compatibility.
| Name | Required | Default | Notes |
|---|---|---|---|
PORT |
No | 3000 |
Local server port. |
LLM_TRANSLATE_ENDPOINT |
One endpoint setting required | Exact /v1/chat/completions URL. |
|
OPENAI_BASE_URL |
One endpoint setting required | Base URL; /chat/completions is appended when needed. |
|
LLM_TRANSLATE_API_KEY |
No | Bearer token for the translation endpoint. | |
OPENAI_API_KEY |
No | Fallback bearer token name. | |
LLM_TRANSLATE_MODEL |
No | tencent/Hy-MT2-1.8B |
Model id or serving alias. |
LLM_TRANSLATE_LANGUAGES |
No | Built-in eight-language demo set | Comma-separated target language list. Uses the first eight valid entries. |
LLM_TRANSLATE_TEMPERATURE |
No | 0.7 |
Inference setting from the Hy-MT2 docs. |
LLM_TRANSLATE_TOP_P |
No | 0.6 |
Inference setting from the Hy-MT2 docs. |
LLM_TRANSLATE_TOP_K |
No | 20 |
Inference setting from the Hy-MT2 docs. |
LLM_TRANSLATE_REPETITION_PENALTY |
No | 1.05 |
Inference setting from the Hy-MT2 docs. |
LLM_TRANSLATE_MAX_TOKENS |
No | 4096 |
Maximum output tokens per request. |
npm run devOpen http://localhost:3000.
For production-style local serving:
npm startPOST /api/translate
{
"sourceText": "Good morning.",
"targetLanguage": "French"
}The server sends this prompt to the configured model:
Translate the following text into {target_language}. Note that you should only output the translated result without any additional explanation:
{source_text}
Do not commit .env. It is ignored by default. Only .env.example should be published.
The browser talks to the local server, and the local server talks to the model endpoint. This keeps provider keys and private endpoint details out of client-side code.
MIT