trl is a small Unix-friendly command-line translator. It wraps a few
translation providers behind one CLI and reads text from flags, files, stdin,
or a local editor.
The built-in fallback/"default" provider is DeepL, which at the time of writing
is free up to 500,000 monthly characters translated.
You can override that default with TRL_DEFAULT_PROVIDER or a command-line
option --provider/-p (see documentation below).
Self-hosted providers such as LibreTranslate and Ollama are also supported.
- A Unix-like shell environment
- Python 3.9 or newer
- The Python package
requests
Download the standalone script somewhere on your PATH:
mkdir -p ~/.local/bin # and append the directory to your $PATH
curl -fsSL https://raw.githubusercontent.com/lmerz1/trl/main/trl -o ~/.local/bin/trl
chmod +x ~/.local/bin/trlIf you already use uv, this is the least
surprising way to satisfy the requests dependency for a single-file script
without touching your system Python:
uv run --with requests ~/.local/bin/trl -hIf you want to invoke trl this way regularly, add a shell alias:
alias trl='uv run --quiet --with requests ~/.local/bin/trl'This remains the easiest option for new macOS users even when python3
already exists on the system, because it avoids modifying that interpreter.
If you prefer to run the script directly through its shebang, install
requests for the same python3 that /usr/bin/env python3 will resolve to:
python3 -m pip install --user requests
trl -hThis works with any python3 that is Python 3.9 or newer, including older
macOS system installations that still resolve python3 to Python 3.9.
uv run is still the cleaner default if you do not want to manage packages in
that interpreter.
If you want a persistent isolated environment without using uv run on every
invocation:
uv venv ~/.local/share/trl-venv
~/.local/share/trl-venv/bin/python -m pip install requests
~/.local/share/trl-venv/bin/python ~/.local/bin/trl -hThis is also a good fit on macOS when your shell's python3 points to an
older system interpreter, because uv venv can provision its own Python.
DeepL is the default backend. It requires an API key.
Create a free API key with DeepL and export it:
export TRL_API_KEY='your-api-key-here'Then run:
trl -t ES -c "Hallo Welt! Wie geht's?"Ollama does not require an API key, but it does require a model name and a reachable Ollama server:
trl --provider ollama --model qwen3.5:4b -t DE -c "Please translate this."A self-hosted LibreTranslate instance usually does not require an API key. By
default trl expects it on http://localhost:5000:
trl -p libretranslate -t FR -c "Hello world"These are the provider values currently accepted by --provider/-p as well as
the corresponding environment variable ($TRL_DEFAULT_PROVIDER):
| Provider value | Aliases for convenience | Backend | API key | Default connection |
|---|---|---|---|---|
deepl |
d |
DeepL Free API | Required | DeepL-hosted API |
libretranslate |
local_libre, libre, lt |
Self-hosted LibreTranslate | Optional* | http://localhost:5000 |
ollama |
local_ollama, o |
Ollama HTTP API | Not required | http://localhost:11434 |
*Depending on how your instance is set up
Notes:
--modelis required forollamaunlessTRL_OLLAMA_MODELis set.--portand--base-urlmay matter for self-hosted providers. If both are set,--base-urlwins.- When using DeepL,
--port,--base-url, and--modelare ignored. - When using LibreTranslate,
--modelis ignored.
All environment variables are optional:
trl will work even when none are set, however in this case, you may have to
use the corresponding option if a required argument is missing.
TRL_API_KEY: API key for DeepL, or optionally for a LibreTranslate instance that requires oneTRL_DEFAULT_TARGET_LANG: default target language, so you can omit-tTRL_DEFAULT_PROVIDER: default provider, so you can omit-pwhen using a provider other than DeepLTRL_OLLAMA_MODEL: default model for theollamaprovider
Option precedence is: command-line flag, then environment variable, then the built-in default.
Examples:
export TRL_API_KEY="your-api-key-here"
export TRL_DEFAULT_TARGET_LANG="en"
export TRL_DEFAULT_PROVIDER="ollama"
export TRL_OLLAMA_MODEL="translategemma:4b"If you rotate between multiple keys, keep them in separate shell variables and assign the active one only when needed:
export DEEPL_API_KEY_1="your-api-key-here:fx"
TRL_API_KEY="$DEEPL_API_KEY_1" trl -t EN -c "test"You may also store a key in a text file and pass it via -f / --file.
The file should contain a line like:
TRL_API_KEY your-api-key-here
Then invoke:
trl -f /path/to/API_KEYS.txt -t EN -c "test"Authentication precedence is:
--key--fileTRL_API_KEY
You can provide content in any one of these ways:
-c,--content: text directly on the command line-i,--input-file: read from a file-i -: read from stdin explicitly--edit: compose text in a local editor- stdin without
-i -:trlwill also read piped input automatically
--edit is Unix-only. trl checks VISUAL and EDITOR first, then falls
back to common editors such as nano, vim, hx, code, codium,
cursor, and zed.
trl -h
trl -t ES -c "Hallo Welt! Wie geht's?"
trl -c "What does Hungarian look like again..." -t HU
echo "hello world" | trl -t FR
trl -t EN < query.txt > output.txt
trl -t EN --input-file query.txt > output.txt
trl -t EN --input-file -
trl -t EN --edit
trl -p ollama --model qwen3.5:4b -t DE -c "Please translate this."
trl -p ollama --base-url https://remote-host.example:11434 --model translategemma:4b -t FR -c "Remote inference works too."
trl -t JA <<'EOF'
Can my terminal display "special" shell characters like `'"!? safely?
EOFExample output:
$ trl -c "Can my terminal display a Japanese script?" -t JA
端末に日本語を表示できますか?
With -m / --more-output:
$ trl -c "What does Hungarian look like again? I forgot..." -t HU -m
Request:
Target language: HU
>>> 'What does Hungarian look like again? I forgot...'
Answer:
Detected source language: EN
>>> 'Hogy is néz ki a magyar? Elfelejtettem...'
-t,--target: target language code-c,--content: content to translate-i,--input-file: read content from a file; use-for stdin-e,--edit: compose content in a local editor-s,--source: source language, if you want to override auto-detection-m,--more-output,--more_output: include request and language info in the output-f,--file: path to a file containingTRL_API_KEY ...-k,--key: pass an API key directly on the command line-p,--provider: choose the backend provider--port: override the default port for a self-hosted provider--base-url: full base URL for a self-hosted or remote provider--model: model name for providers that require one, such asollama
trldoes not validate that the selected API key matches the selected provider.- Supported languages depend on the provider you use.
- Short or ambiguous input may translate differently depending on whether you
specify
--source.
Example:
$ trl -t EN -c "haine"
haine
$ trl -t EN -c "haine" -s FR
hate
- ISO 639-1 language codes in use by DeepL's API. You may also be able to use full written-out language names with language models in the Ollama provider.
- DeepL API documentation.
They also offer a CLI API client with
more features than this project has, however
trlhas existed for longer. 🙂 - LibreTranslate documentation
- Ollama
- Open a new issue
The author is not affiliated with DeepL SE or any of the other translation providers.