Install LibreTranslate and configure Mastodon to take advantage of it.

This is a minimal viable product for testing alongside Mastodon instance installed from the source code, bare-metal only. See additional notes at the end of this document.

Install dependencies.

$ sudo apt install python3 python3-pip python3-setuptools python3-dev

Create libretranslate user.

$ sudo useradd --create-home --home-dir /opt/libretranslate libretranslate

Install libretranslate locally, preferring binary packages.

$ sudo -u libretranslate pip3 install --user --prefer-binary libretranslate

Inspect how to manage language packages.

$ sudo -u libretranslate /opt/libretranslate/.local/bin/argospm -h
usage: argospm [-h] {update,search,install,list,remove} ...

positional arguments:
  {update,search,install,list,remove}
                        Available commands.
    update              Downloads remote package index.
    search              Search package from remote index.
    install             Install package.
    list                List installed packages.
    remove              Remove installed package.

options:
  -h, --help            show this help message and exit

Update package index.

$ sudo -u libretranslate /opt/libretranslate/.local/bin/argospm update

List available language packages.

$ sudo -u libretranslate /opt/libretranslate/.local/bin/argospm search
translate-ar_en: ar -> en
translate-az_en: az -> en
translate-zh_en: zh -> en
translate-cs_en: cs -> en
translate-da_en: da -> en
translate-nl_en: nl -> en
translate-en_ar: en -> ar
translate-en_az: en -> az
translate-en_zh: en -> zh
translate-en_cs: en -> cs
translate-en_da: en -> da
translate-en_nl: en -> nl
translate-en_eo: en -> eo
translate-en_fi: en -> fi
translate-en_fr: en -> fr
translate-en_de: en -> de
translate-en_el: en -> el
translate-en_he: en -> he
translate-en_hi: en -> hi
translate-en_hu: en -> hu
translate-en_id: en -> id
translate-en_ga: en -> ga
translate-en_it: en -> it
translate-en_ja: en -> ja
translate-en_ko: en -> ko
translate-en_fa: en -> fa
translate-en_pl: en -> pl
translate-en_pt: en -> pt
translate-en_ru: en -> ru
translate-en_sk: en -> sk
translate-en_es: en -> es
translate-en_sv: en -> sv
translate-en_tr: en -> tr
translate-en_uk: en -> uk
translate-eo_en: eo -> en
translate-fi_en: fi -> en
translate-fr_en: fr -> en
translate-de_en: de -> en
translate-el_en: el -> en
translate-he_en: he -> en
translate-hi_en: hi -> en
translate-hu_en: hu -> en
translate-id_en: id -> en
translate-ga_en: ga -> en
translate-it_en: it -> en
translate-ja_en: ja -> en
translate-ko_en: ko -> en
translate-fa_en: fa -> en
translate-pl_en: pl -> en
translate-pt_en: pt -> en
translate-ru_en: ru -> en
translate-sk_en: sk -> en
translate-es_en: es -> en
translate-sv_en: sv -> en
translate-tr_en: tr -> en
translate-uk_en: uk -> en

Install desired language packages.

$ sudo -u libretranslate /opt/libretranslate/.local/bin/argospm install translate-pl_en
Downloaded package /opt/libretranslate/.local/cache/argos-translate/downloads/translate-pl_en.argosmodel
Installed package to /opt/libretranslate/.local/share/argos-translate/packages
$ sudo -u libretranslate /opt/libretranslate/.local/bin/argospm install translate-en_pl
Downloaded package /opt/libretranslate/.local/cache/argos-translate/downloads/translate-en_pl.argosmodel
Installed package to /opt/libretranslate/.local/share/argos-translate/packages

List installed language packages.

$ sudo -u libretranslate /opt/libretranslate/.local/bin/argospm list
translate-en_pl
translate-pl_en

Inspect libretranslate parameters.

$ sudo -u libretranslate /opt/libretranslate/.local/bin/libretranslate --help
usage: libretranslate [-h] [--host HOST] [--port PORT] [--char-limit <number of characters>] [--req-limit <number>] [--req-limit-storage <Storage URI>]
                      [--daily-req-limit <number>] [--req-flood-threshold <number>] [--batch-limit <number of texts>] [--ga-id <GA ID>] [--debug] [--ssl]
                      [--frontend-language-source <language code>] [--frontend-language-target <language code>] [--frontend-timeout <milliseconds>] [--api-keys]
                      [--api-keys-db-path API_KEYS_DB_PATH] [--api-keys-remote API_KEYS_REMOTE] [--get-api-key-link GET_API_KEY_LINK]
                      [--require-api-key-origin REQUIRE_API_KEY_ORIGIN] [--load-only <comma-separated language codes>] [--threads <number of threads>] [--suggestions]
                      [--disable-files-translation] [--disable-web-ui]

LibreTranslate - Free and Open Source Translation API

options:
  -h, --help            show this help message and exit
  --host HOST           Hostname (127.0.0.1)
  --port PORT           Port (5000)
  --char-limit <number of characters>
                        Set character limit (-1)
  --req-limit <number>  Set the default maximum number of requests per minute per client (-1)
  --req-limit-storage <Storage URI>
                        Storage URI to use for request limit data storage. See https://flask-limiter.readthedocs.io/en/stable/configuration.html. (memory://)
  --daily-req-limit <number>
                        Set the default maximum number of requests per day per client, in addition to req-limit. (-1)
  --req-flood-threshold <number>
                        Set the maximum number of request limit offences that a client can exceed before being banned. (-1)
  --batch-limit <number of texts>
                        Set maximum number of texts to translate in a batch request (-1)
  --ga-id <GA ID>       Enable Google Analytics on the API client page by providing an ID (None)
  --debug               Enable debug environment
  --ssl                 Whether to enable SSL
  --frontend-language-source <language code>
                        Set frontend default language - source (en)
  --frontend-language-target <language code>
                        Set frontend default language - target (es)
  --frontend-timeout <milliseconds>
                        Set frontend translation timeout (500)
  --api-keys            Enable API keys database for per-user rate limits lookup
  --api-keys-db-path API_KEYS_DB_PATH
                        Use a specific path inside the container for the local database. Can be absolute or relative (api_keys.db)
  --api-keys-remote API_KEYS_REMOTE
                        Use this remote endpoint to query for valid API keys instead of using the local database
  --get-api-key-link GET_API_KEY_LINK
                        Show a link in the UI where to direct users to get an API key
  --require-api-key-origin REQUIRE_API_KEY_ORIGIN
                        Require use of an API key for programmatic access to the API, unless the request origin matches this domain
  --load-only <comma-separated language codes>
                        Set available languages (ar,de,en,es,fr,ga,hi,it,ja,ko,pt,ru,zh)
  --threads <number of threads>
                        Set number of threads (4)
  --suggestions         Allow user suggestions
  --disable-files-translation
                        Disable files translation
  --disable-web-ui      Disable web ui

Define systemd service.

$ sudo tee /etc/systemd/system/libretranslate.service <<EOF
[Unit]
Description=LibreTranslate
After=network.target

[Service]
User=libretranslate
Group=libretranslate
WorkingDirectory=/opt/libretranslate/
ExecStart=/opt/libretranslate/.local/bin/libretranslate --host 127.0.0.1 --port 5000 --disable-files-translation
Restart=always
#CPUQuota=50%

[Install]
WantedBy=multi-user.target
EOF
[Unit]
Description=LibreTranslate
After=network.target

[Service]
User=libretranslate
Group=libretranslate
WorkingDirectory=/opt/libretranslate/
ExecStart=/opt/libretranslate/.local/bin/libretranslate --host 127.0.0.1 --port 5000 --disable-files-translation
Restart=always
#CPUQuota=50%

[Install]
WantedBy=multi-user.target

Reload systemd configuration.

$ sudo systemctl daemon-reload

Enable and start service.

$ sudo systemctl enable --now libretranslate

Inspect service status.

$ sudo systemctl status libretranslate
● libretranslate.service - LibreTranslate
     Loaded: loaded (/etc/systemd/system/libretranslate.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-11-16 22:44:11 UTC; 19s ago
   Main PID: 130836 (libretranslate)
      Tasks: 8 (limit: 19660)
     Memory: 143.5M
     CGroup: /system.slice/libretranslate.service
             └─130836 /usr/bin/python3 /opt/libretranslate/.local/bin/libretranslate --host 127.0.0.1 --port 5000 --disable-files-translation

Nov 16 22:44:11 mastodon systemd[1]: Started LibreTranslate.

Perform initial service test.

$ curl --request POST \
       --header "Content-type: application/json" \
       --data '{ "q": "Dzisiaj jest Czwartek, 17 listopada 2022", "source": "pl", "target": "en"}' 
       http://localhost:5000/translate
{"translatedText":"Today it is Thursday, November 17, 2022"}

Update Mastodon configuration to allow requests to localhost and define LibreTranslate endpoint.

$ sudo -u mastodon vim /home/mastodon/live/.env.production
[...]
# locale
DEFAULT_LOCALE=en

# translate
ALLOWED_PRIVATE_ADDRESSES=127.0.0.1
LIBRE_TRANSLATE_ENDPOINT=http://127.0.0.1:5000

Restart mastodon-web service.

$ sudo systemctl restart mastodon-web

You should see Translate link.

That is all.

Additional notes

Translation is a very resource intensive operation.

Inspect project documentation, dockerfile and libretranslate-init for more details, so you can run it with WSGI and Gunicorn.

Error 422 Mastodon::PrivateNetworkAddressError means that ALLOWED_PRIVATE_ADDRESSES configuration variable is not defined.

503 response can indicate missing language file, so I strongly suggest to install every available language.