The Problem

Organizations that need a self‑hosted, offline‑capable translation service often encounter code that is hard to maintain, lacks reproducible builds, and exposes a wildcard CORS policy. These friction points increase operational risk and slow down secure deployments.

What This Does

LibreTranslate is a free, open‑source Machine Translation API powered by the Argos Translate library. The repository contains 214 files organised into two projects: libretranslate/ (172 files) and scripts/ (8 files). Core translation logic lives in libretranslate/app.py (the primary API handler), while supporting modules such as storage.py, api_keys.py, cache.py, secret.py, detect.py, language.py, and locales.py provide backend services, key management, caching, language detection, and i18n handling.

Execution starts at the main entry point in libretranslate/main.py:268, which calls create_app to initialise the framework (Flask/Django/Express‑style) and then runs the server. The translation pipeline flows through translateiso2model → language‑model lookup, with get_storage (called from 12 places) and get_req_api_key (called from 5 places) as the most‑touched functions. A secondary entry point spec at libretranslate/app.py:1330 generates the OpenAPI specification, reaching 22 functions.

The internal call graph resolves 164 self‑call edges; notable hubs are get_storage (12 callers), get_str (6 callers), and get_json_dict (5 callers). Three modules (libretranslate/__init__.py, libretranslate/main.py, libretranslate/app.py) participate in a circular import dependency, and app.py contains 1171 lines of code, creating high cognitive load and deep nesting (max indentation depth 8).

How It Is Wired

  • Entry points: main (libretranslate/main.py:268) reaches 24 functions; spec (libretranslate/app.py:1330) reaches 22 functions; translate_file (libretranslate/app.py:883) reaches 16 functions.
  • Outbound effects: 16 functions make network calls (e.g., spec → lazy_swag → swag_eval → func → lookup via requests.post). File system touches occur via main → create_app [os.mkdir], translate_file → get_upload_dir [os.mkdir], and database reads/writes are performed by api_keys.py (reads/writes a DB) and cache.py (cryptographic secret generation).
  • Responsibility map (functions per file, callers, and effects):
  • libretranslate/app.py – 43 functions, called from 4 files, calls into 10, reads/writes files, defines get_version, get_upload_dir, get_req_api_key, get_req_secret, get_json_dict.
  • libretranslate/storage.py – 43 functions/3 types, called from 5 files, defines get_storage, exists, set_bool, get_bool, set_int.
  • libretranslate/api_keys.py – 7 functions/2 types, called from 2 files, reads/writes files and a DB, makes an outbound network call for key lookup.
  • libretranslate/cache.py – 6 functions/1 class, called from 2 files, performs a cryptographic secret‑generating operation.
  • libretranslate/secret.py – 14 functions, called from 2 files, defines to_base, obfuscate, generate_secret, rotate_secrets, secret_match.
  • libretranslate/detect.py – 6 functions/2 classes, called from 2 files.
  • libretranslate/language.py – 7 functions, called from 2 files, defines iso2model, model2iso, load_languages, load_lang_codes, get_language_with_fallback.
  • libretranslate/main.py – 4 functions, called from 2 files, defines get_parser, get_args, main, redirect.
  • libretranslate/locales.py – 7 functions, called from 1 file.
  • Module graph: libretranslate/app imports from libretranslate/__init__ and libretranslate/main; libretranslate/main imports from libretranslate/app, creating a cycle that inflates instability (instability 0.7 for app, 0.29 for __init__ and main).

How To Use It

Setup

  • Install the Python package: pip install -e . (pyproject.toml present).
  • Or build and run via Docker: docker compose up -d (docker‑compose.yml and docker/Dockerfile exist).

Configuration

  • The API reads environment variables and a .env‑style config; see libretranslate/app.py for the exact variables it references (e.g., LIBRETRANSLATE_SECRET, LIBRETRANSLATE_API_KEY).
  • CORS is currently set to "*" in libretranslate/app.py – replace with an explicit allow list for production.

Running it

  • Start the server from the CLI: python -m libretranslate.main (entry point main.py:268).
  • For HTTPS behind a reverse proxy, use the provided Docker Compose files or the k8s.yaml manifest.

Real‑World Use

A CI pipeline fetches translated subtitles for a multilingual video platform. The backend calls POST /translate with { "q": "text", "source": "en", "target": "fr" }. The request is authenticated via an API key stored in api_keys.py, routed through storage.py for request‑rate limits, and cached by cache.py to avoid repeated model loads. If the key is missing, api_keys.lookup returns a 401, and the caller retries with a fallback key.

import requests
resp = requests.post(
    "http://localhost:5000/translate",
    json={"q": "Hello world", "source": "en", "target": "es"},
    headers={"X-Api-Key": "my-secret-key"}
)
print(resp.json()["translatedText"])

Code Health & Issues

  • High: Pin third‑party GitHub Actions to commit SHAs – .github/workflows currently uses @v2, @v4 tags for pierotofy/issuewhiz, docker/setup-qemu-action, docker/setup-buildx-action, docker/login-action; a tag can move and bring new code with secrets.
  • High: Commit a lockfile beside pyproject.toml – no lockfile is present, so transitive dependencies may differ between test and production builds.
  • High: Replace the wildcard CORS origin with an explicit allow list – libretranslate/app.py sets Access-Control-Allow-Origin: *"; pairing with credentials is disallowed by browsers.
  • Medium: Declare least‑privilege permissions for GITHUB_TOKEN – 3 workflows have no permissions block; add contents: read at the top and widen per job.
  • Medium: Enable Dependabot or Renovate – no update bot configured; add .github/dependabot.yml for Python and GitHub‑Actions ecosystems.
  • Medium: Pin container base image by digest – docker/Dockerfile uses python:3.11.14-slim-bookworm without a digest; pin via python:3.11.14-slim-bookworm@sha256<digest> and enable Dependabot Docker monitoring.
  • Medium: Gate pull requests on a dependency vulnerability scan – CI lacks dependency review; add dependency-review-action on pull_request or osv-scanner on push.
  • Medium: Set persist-credentials: false on checkout – publish-package.yml keeps the token; add with: persist-credentials: false and pass explicit tokens only to the push step.
  • Low: Set timeout-minutes on workflow jobs – 4 jobs have no timeout; add realistic bounds to prevent overlapping runs.

The Bottom Line

LibreTranslate delivers a capable, self‑hosted translation API with solid i18n support and Docker/Kubernetes deployment options. However, the codebase suffers from circular imports, an oversized app.py, missing dependency lockfile, and a permissive CORS policy that together raise operational risk. Teams comfortable with Docker and willing to tighten security posture (pin actions, add lockfile, restrict CORS) can operate it safely; others may need to invest in refactoring the import graph and cleaning up CI configuration before production use.