TranslateHub is a self-hosted translation management platform for teams that want to manage application copy outside the main codebase and fetch translations at runtime through an API.
It includes a browser-based admin dashboard, per-project locale management, runtime translation delivery, project locking, admin user management, themes, and Docker support.
- Features
- Tech Stack
- How It Works
- Getting Started
- First-Time Setup
- Seeding Demo Data
- Available Scripts
- API Overview
- Project Security Model
- Frontend Highlights
- Project Structure
- Testing
- Deployment Notes
- Roadmap Ideas
- Contributing
- License
- Manage translation projects with custom locale codes like
en,en-US,fr-FR, orzh-Hans - Store locale metadata as
{ code, name }for cleaner UI and API responses - Create pages inside each project, then create page-local keys with automatic prefixed full keys like
dashboard.greet - Create, edit, bulk import, and delete translation keys inside each page
- Runtime translation delivery through API key-protected public endpoints
- Source-locale fallback when a translation is missing
- Per-project password protection
- Lock and unlock projects to prevent accidental edits or deletion
- Password-confirmed project deletion flow
- Admin and super-admin roles
- Theme switching with local persistence
- Sidebar project navigation for fast switching between projects
- Mobile-friendly dashboard UI
- Docker Compose support for one-command startup
- Backend: Node.js, Express
- Database: MongoDB, Mongoose
- Auth: JWT
- Password hashing: bcryptjs
- Frontend: Vanilla JavaScript, HTML, CSS
- Icons: Font Awesome
- Containers: Docker, Docker Compose
TranslateHub has two main surfaces:
-
Dashboard API and UI for admins
- manage projects
- manage locales
- manage translation keys
- manage admin users
-
Public runtime API for client apps
- fetch translations using an
X-API-Keyheader - retrieve one locale or all locales
- use source-locale fallback automatically
- fetch translations using an
Typical flow:
- Create a project
- Add source and target locales
- Create one or more pages like
dashboardorsettings - Add page-local translation keys and values
- Copy the project API key
- Fetch translations for a specific page at runtime
For local development you need:
- Node.js 20+
- npm
- MongoDB
If you prefer containers, Docker Desktop or Docker Engine is enough.
- Install dependencies:
npm install- Create an environment file:
cp .env.example .env-
Start MongoDB locally
-
Start the app:
npm start- Open:
http://localhost:3000
Example values are available in .env.example.
| Variable | Required | Default | Description |
|---|---|---|---|
PORT |
No | 3000 |
Express server port |
MONGODB_URI |
No | mongodb://localhost:27017/translate-hub |
MongoDB connection string |
JWT_SECRET |
Yes | - | Secret used to sign dashboard auth tokens |
NODE_ENV |
No | development |
Runtime environment |
Example:
PORT=3000
MONGODB_URI=mongodb://localhost:27017/translate-hub
JWT_SECRET=change-this-to-a-long-random-string
NODE_ENV=developmentThe easiest way to run the full stack is:
docker compose up -dThis starts:
- the Express app on
http://localhost:3000 - MongoDB on
mongodb://localhost:27017
Useful commands:
docker compose logs -f
docker compose down
docker compose down -vNotes:
- MongoDB data is stored in the
mongo-datavolume - the compose file already wires
MONGODB_URIto the MongoDB service - update
JWT_SECRETindocker-compose.ymlbefore using it anywhere beyond local development
On a fresh database, the app shows a setup screen instead of a login screen.
You will create the first super_admin account through the UI.
After setup:
- the app stores a JWT token in local storage
- the dashboard becomes available
- additional admins can be created from the Admins page
You can load demo content with:
npm run seedThis creates:
- a demo project
- sample pages
- sample locale data
- sample translation keys
- an initial super admin if needed
Current demo project password:
demo1234
| Command | Description |
|---|---|
npm start |
Start the production server |
npm run dev |
Start the server with nodemon |
npm run seed |
Seed demo data |
npm run test:frontend |
Run lightweight frontend helper/router tests |
Base path: /api/auth
| Method | Endpoint | Description |
|---|---|---|
GET |
/status |
Check whether first-time setup is needed |
POST |
/setup |
Create the initial super admin |
POST |
/login |
Sign in with username and password |
GET |
/me |
Get current authenticated user |
PUT |
/password |
Change current user password |
Base path: /api/admins
Requires authenticated super_admin access.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
List admins |
POST |
/ |
Create admin or super admin |
PUT |
/:id |
Update admin profile, role, status, or password |
DELETE |
/:id |
Delete admin |
Base path: /api/projects
Requires authenticated dashboard access.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
List projects |
POST |
/ |
Create project |
GET |
/:id |
Get project details and stats |
PUT |
/:id |
Update project metadata, locales, and password |
DELETE |
/:id |
Delete project with password confirmation |
POST |
/:id/regenerate-key |
Regenerate public API key |
POST |
/:id/lock |
Lock project using project password |
POST |
/:id/unlock |
Unlock project using project password |
Translation key management:
| Method | Endpoint | Description |
|---|---|---|
GET |
/:projectId/pages |
List project pages |
POST |
/:projectId/pages |
Create one page |
PUT |
/:projectId/pages/:pageId |
Update one page |
DELETE |
/:projectId/pages/:pageId |
Delete one page |
GET |
/:projectId/pages/:pageId/keys |
List page translation keys |
POST |
/:projectId/pages/:pageId/keys |
Create one page-local key |
POST |
/:projectId/pages/:pageId/keys/bulk |
Bulk import page-local keys |
PUT |
/:projectId/pages/:pageId/keys/:keyId |
Update a key |
PATCH |
/:projectId/pages/:pageId/keys/:keyId/translate |
Update one locale value |
DELETE |
/:projectId/pages/:pageId/keys/:keyId |
Delete a key |
Base path: /api/v1
Requires the X-API-Key header.
| Method | Endpoint | Description |
|---|---|---|
GET |
/pages |
Get project pages |
GET |
/pages/:pageKey/translations/:locale |
Get one page for one locale |
GET |
/pages/:pageKey/translations |
Get one page for all locales |
GET |
/locales |
Get project locale metadata |
Example:
curl -H "X-API-Key: th_your_project_api_key" \
http://localhost:3000/api/v1/pages/dashboard/translations/en-USExample response:
{
"locale": "en-US",
"localeName": "English (United States)",
"projectId": "...",
"pageKey": "dashboard",
"translations": {
"welcome": "Welcome to our app!",
"home": "Home"
}
}Notes:
- each page has a required
pageKeylikedashboard - users create local keys like
greet, and the system stores the full key asdashboard.greet - duplicate local keys are blocked within the same page
- changing a
pageKeyis blocked after that page already contains translation keys
TranslateHub protects projects in two layers:
- users authenticate with JWT
- admins can manage projects and translations
- super admins can also manage admin accounts
Each project can be protected by its own password.
Supported behavior:
- project lock and unlock requires project password
- deleting a project requires project password and explicit confirmation
- when a project is locked, translation keys cannot be added, edited, bulk imported, or deleted
- changing an existing project password requires the current project password
- legacy projects without a password can add one in settings
- vanilla JS single-page dashboard
- hash-based routing for refresh persistence and back/forward support
- local theme persistence
- fast sidebar project switching
- responsive layout for desktop and mobile
- improved large-screen layout usage
.
├── config/ # Database connection
├── middleware/ # Auth and API key middleware
├── models/ # Mongoose models
├── public/ # Frontend assets
│ ├── css/
│ └── js/
│ └── modules/
├── routes/
│ └── api/ # Express API routes
├── scripts/ # Seed utilities
├── tests/ # Lightweight frontend tests
├── Dockerfile
├── docker-compose.yml
├── package.json
└── server.js
Run the included frontend module tests:
npm run test:frontendThis currently validates helper and router behavior used by the dashboard.
- set a strong
JWT_SECRET - keep project API keys private in client environment configuration, not hard-coded in repos
- use a managed MongoDB instance or persistent Docker volume
- prefer HTTPS in production
- consider putting a reverse proxy like Nginx or Caddy in front of the app
- search and filtering for large project lists
- export/import translation files by format
- audit log for sensitive actions like unlock/delete/password changes
- end-to-end UI tests
- production deployment examples for Nginx or Traefik
- role expansion beyond
adminandsuper_admin
Contributions are welcome.
Suggested flow:
- Fork the repository
- Create a feature branch
- Make your changes
- Run relevant checks
- Open a pull request
If you are extending the frontend, keep the current goal in mind: improve the product while avoiding unnecessary architectural complexity.
This project is licensed under the MIT License. See LICENSE for details.
