Model or dataset
LanceMoe/openai-translator avatar
LanceMoe/openai-translator

openai-translator is a thin front end over one chat endpoint

A translator built using OpenAI.

397 stars59 forksTypeScriptGPL-3.0

At a glance

What is it?
OpenAI Translator is a React PWA that calls whatever OpenAI-compatible /v1/chat/completions endpoint you point it at, keeps history in the browser, and ships as a static build on nginx. The interesting decisions are what it leaves out: no backend, no bundled key, no release history.
Who is it for?
openai-translator fits anyone who already has an OpenAI-compatible endpoint and wants a self-hosted, installable UI over it, and it fits learners, since the author presents it as a technique demo. Check three things before relying on it: which provider your key actually points at, whether local browser history meets your data policy, and that your nginx config replaces the shipped default.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 29 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

You bring the base URL and the key, or nothing works

There is no account to create and no key that ships with the app. What you supply is a base URL for an OpenAI-compatible provider and an API key for that provider, and the transport underneath is the plain `/v1/chat/completions` route. Anything that speaks that shape can sit behind it, which is the project's central design decision.

The tradeoff is that the app cannot tell you what you are talking to. Model availability depends on the API provider and credentials you configure, so the same dropdown can be full on one account and half empty on another. If you paste a key for the wrong provider, the failure surfaces as an ordinary HTTP error from that endpoint rather than as a configuration warning from the UI.

The dependency list explains part of the shape. `axios` handles the plain request path, and `@microsoft/fetch-event-source` is there for the optional streaming mode. Streaming is a toggle on the same endpoint, not a different API, so a provider with partial or non-streaming support still works, just without incremental output.

The default is gpt-5.6-luna and the rest is a suggestion list

The default model is `gpt-5.6-luna`. The configuration page also offers `gpt-4o-mini`, `gpt-4o`, `gpt-5.4-mini`, `gpt-5.4-nano`, `gpt-4.5-preview`, `gpt-5.5`, `gpt-5.6-sol`, `gpt-5.6-terra`, `o3-mini`, `o1`, plus the open weights pair `gpt-oss-120b` and `gpt-oss-20b`.

The list is a convenience, not a contract. The alternative to picking from it is typing any chat model identifier your configured provider supports, so a model released after this build still works if your endpoint routes it. That matters for the open weights entries, which exist in the suggestion list because self-hosted OpenAI-compatible servers can serve them, and it matters for anything else behind the same API shape.

Streaming, history and model choice are independent settings. Nothing in the way the app is wired forces the smallest model or forces streaming on, so a cheap model for routine sentences and a larger one for prose is a matter of what you select, not of what the UI permits.

History lives in the browser, and that is the whole privacy story

Translation history is saved locally. There is no account system, no sync service and no server component in the repository layout: `src/` holds the app, and the build output is static files handed to nginx or any web server.

Local storage means the trade is explicit. Nothing about your source text leaves your machine except the request you send to the endpoint you configured, so the privacy boundary is that provider rather than this app. It also means history is per browser and per device, and clearing site data takes the history with it.

The installable behaviour comes from the PWA layer rather than a native shell. `workbox-build` handles service worker generation, and Cloudflare Pages is the stated hosting target for the hosted demo at translator.lance.moe. Voice input is present through `react-speech-recognition`, alongside `react-textarea-autosize` for the input box and `zustand` for client state.

The docs do not describe an export or import path for that history, so plan on it being disposable.

The Docker image is a static build behind nginx on port 80

The container path is a two stage Dockerfile. The builder stage is `node:22-slim`, installs pnpm globally, copies the manifests ahead of the source so dependency installation can use the lockfile, then runs the production build. The runtime stage is `nginx:alpine`, and it copies the finished `dist` directory into `/usr/share/nginx/html` along with the repository's own `nginx/default.conf`.

The install command for the dependencies uses `--frozen-lockfile` and `--ignore-scripts`, which means the image build fails loudly if `pnpm-lock.yaml` and `package.json` have drifted, and it skips lifecycle scripts including husky's prepare hook.

Build and run are two separate steps:

bash
docker build -t openai-translator-web .
docker run -p 3000:80 openai-translator-web

The image exposes port 80 and the run command maps it to 3000 on the host, so the app answers at `http://localhost:3000/`. Because a stock nginx config is copied over the default, you are shipping a web server config too, and any headers, caching or SPA fallback rules you need have to be edited there rather than in application code.

pnpm dev binds vite --host, which is what makes the phone test possible

Local development is three commands once pnpm exists. Dependencies come down with:

bash
pnpm install

then `pnpm dev` starts `vite --host`. The `--host` flag is the detail that matters on mobile, because Vite binds beyond loopback and the dev server becomes reachable from another device on the same network. Vite opens the browser on its own once it starts.

For a production-shaped check without Docker, `pnpm build` runs `tsc && vite build`, so a type error fails the build before Vite ever emits files, and the output lands in `dist` ready to be served as static content. Two other scripts exist for previewing and serving: `preview` runs `vite preview`, and `prod` chains the build with `pnpx serve -s dist`, where the `-s` flag makes that static server fall back to `index.html` for client side routes.

React Router 7 handles those routes, so the single page fallback is not optional. A static host without that rewrite will 404 on a deep link.

Version 0.3.0 with no GitHub releases and a GPL-3.0 licence

The package is published as `openai-translator-web` at version 0.3.0, declared as an ES module with a type field, and its build toolchain is Vite 8 with `@vitejs/plugin-react`, Tailwind CSS 4 through `@tailwindcss/vite`, and DaisyUI 5 for components. React 19 and Axios sit on the runtime side, with React Query 5 handling server state.

Maintenance is the part to read carefully. The last push was on 2026-09-04, which is inside the last six months, so the project is not stale. But the repository publishes no GitHub releases at all, so the version in `package.json` is the only number that moves and there is no changelog entry tied to a tag. Anyone tracking upgrades by release has nothing to track.

The licence is GPL-3.0, with the text in `LICENSE.md`. That choice matters for a self-hosted web app you might modify, since GPL obligations attach to derivative works you distribute.

Repository tooling is thorough for a project of this size: husky hooks, a Prettier config, ESLint flat config with import resolution, a `.hintrc`, a `pnpm-workspace.yaml`, and a `skills-lock.json`.

The author calls it a teaching project and credits bob-plugin-openai-translator

The stated purpose is pedagogical. The readme says the author thinks the project will help readers learn the techniques, and the stack list reads like a curriculum: React 19, Vite 8, Tailwind CSS 4, DaisyUI 5, Axios, React Router 7, React Query 5, PWA and Cloudflare Pages.

The origin is credited as inspired by yetone's `bob-plugin-openai-translator`. That lineage explains the shape. What began as a chat plugin has become a standalone installable web app with routing, internationalisation through i18next and react-i18next, and a production container.

There is an `.agents/` directory and a `skills-lock.json` at the repository root, which fits a project built with coding assistants in the loop rather than a team maintaining a service.

Reading the project as a teaching artifact also sets expectations about support. There are no GitHub releases, no published changelog tied to a tag, and the hosted demo at translator.lance.moe is provided as is. If you need a translator with a support contract behind it, this is the wrong shape.

Editorial conclusion

openai-translator fits anyone who already has an OpenAI-compatible endpoint and wants a self-hosted, installable UI over it, and it fits learners, since the author presents it as a technique demo. Check three things before relying on it: which provider your key actually points at, whether local browser history meets your data policy, and that your nginx config replaces the shipped default. The last push was on 2026-09-04, package version 0.3.0, and there are no GitHub releases, so the Docker tag tells you nothing about age.

Frequently asked questions

Does openai-translator need an OpenAI account to work?

You supply your own API base URL and API key for any OpenAI-compatible provider, and the app calls the /v1/chat/completions route with them. No key ships with the project, and model availability depends on the provider and credentials you configure.

How do I point openai-translator at a self-hosted model server?

Enter the server's base URL and a key in the configuration page, then type any chat model identifier that server supports instead of choosing from the suggestion list. The list includes gpt-oss-120b and gpt-oss-20b for that case.

Where does openai-translator keep past translations?

History is saved locally in the browser. There is no account or sync service in the project, so history is per device and clearing site data removes it, and no export path is documented.

How do I run openai-translator without Docker?

Run pnpm install, then pnpm dev for a Vite dev server bound with --host, or pnpm build for a static dist folder you can serve as a static website. A production-shaped local check is pnpm prod, which builds and serves dist with single page fallback.

What does the openai-translator Docker image actually contain?

A node:22-slim build stage produces dist, and an nginx:alpine runtime stage serves it on port 80 with the repository's own nginx/default.conf. Running docker run -p 3000:80 openai-translator-web serves the app at http://localhost:3000/.

Official sources

  1. Issues
  2. LanceMoe/openai-translator on GitHub
  3. License: GPL-3.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lancemoe-openai-translator.svg)](https://hysenlabs.com/projects/lancemoe-openai-translator)