Skip to content

translating

Alexander Herling edited this page Oct 11, 2026 · 2 revisions

Translating rDownloader

rDownloader ships in English, German, French and Spanish. Adding another language needs no programming: one entry in a list and the translated text. You can start small — every string a language does not have yet shows in English, never as a technical key — and the language picker marks the language (in progress) until it is complete.

This page is for translators. It assumes you can edit JSON files and open a pull request; Building from source covers the tools the checks need.

Where the text lives

Each part of rDownloader keeps its own text, one file or folder per language. <code> is the language's two-letter ISO 639-1 code in lower case — it, nl, pl.

Part Where What is in it
Web interface web/src/locales/<code>/*.json Every label, message and help text, one file per area (downloads.json, settings.json, …)
Browser extension extension/_locales/<code>/messages.json The menu entries, the popup and the options page
Plugins plugins/<plugin>/locales/<code>.json A plugin's name, description, account labels and error messages
Website rdownloader.net, a separate repository Open an issue; the maintainer adds the language there

The list of languages itself is web/src/locales/languages.json. Everything — the language picker, the tests, the helper script — reads it from there.

Adding a language

  1. Add it to the list. In web/src/locales/languages.json, add an entry under the language's code with the name the language uses for itself and the status in-progress:

    "it": {
      "name": "Italiano",
      "status": "in-progress"
    }

    The entries' order is the order of the language picker.

  2. Translate the web interface. Create web/src/locales/<code>/ and put translated copies of the files in web/src/locales/en/ there. Translate as much as you like; a key you leave out shows in English. Keep the English key names and nesting exactly — only the text after the colon changes. A key English does not have makes the tests fail, because nothing would ever show it.

  3. Optionally, the extension and the plugins. extension/_locales/<code>/messages.json and plugins/<plugin>/locales/<code>.json work the same way: copy the English file, translate what you can. Both may be partial or missing. The extension follows the browser's language, not the one chosen in rDownloader.

  4. Finish. Once every catalogue of the language is complete, change its status to required. From then on the tests hold it to every key English has, like the four languages that ship today, and every new feature arrives in it too.

When the interface starts, it uses the browser's language only if that language is complete. An in-progress language has to be chosen in the footer or under Settings → Interface → This browser.

Placeholders

Words in braces are filled in by the program and must stay exactly as English has them:

"download_failed": "{name} could not be downloaded"
"download_failed": "Impossibile scaricare {name}"

The extension writes them as $1 or $HOST$; again, keep them as they are. The tests compare every translation's placeholders with English and name the key that differs.

Plurals

A text that depends on a number holds its forms in one string, separated by |, in English's order:

  • two forms: one, then more — "{count} file | {count} files";
  • three forms: none, one, then more — "no requests | {count} request | {count} requests".

The interface chooses between the forms the way English does. A language that needs more forms than that (Polish, Russian, Czech, …) needs a plural rule in the code; please say so in an issue instead of squeezing its forms into two.

Terms

  • Form of address. German says du, French vous, Spanish tú. A new language picks what its open-source tools usually use and keeps it everywhere.
  • Technical terms stay English where the language's IT usage keeps them — Stream, Plugin, Token, Proxy, Cookie, Hoster, Webhook. Ordinary words are translated.
  • Names are never translated: products, protocols and formats such as Newznab, SABnzbd, yt-dlp, PAR2, WebDAV, S3, NZB, JSON.
  • One concept, one word. Whichever word you choose for queue or download, use it on every page.

design.md in the repository records the words chosen for the existing languages.

Checking your work

From the repository root:

pnpm --dir web install
pnpm --dir web test src/i18n           # web catalogues: keys, placeholders, the language list
pnpm --dir web run typecheck:full
scripts/build-extension.sh --test-only # extension catalogues
cargo nextest run -p rd-plugin-host --test bundled_locales  # plugin catalogues

To add a single new key to several languages at once, scripts/i18n-key.sh takes the languages by name:

scripts/i18n-key.sh common actions.retry de=Wiederholen en=Retry es=Reintentar fr=Réessayer it=Riprova

Every required language must be named; an in-progress one may be.

Submitting

Open one pull request per language. Say which parts you translated and whether a native speaker read it. As CONTRIBUTING.md explains, the maintainer applies an accepted pull request by hand and credits you, and raises the version of every plugin whose catalogue changed.

Clone this wiki locally