Adventures with LibreTranslate
- 8 minutes read - 1546 words(Updated 11 Jun 2024 with corrections on calling LibreTranslate)
Now if you’ve spent any time on my site, or you know me at all, you know I like playing around with computers, installing stuff, whatever the case may be. I’ve particularly enjoyed running a server the past nearly 3 (!) years, since I can install things that I, and in turn others (friends, loved ones, the world at large), will find useful. I am happy to run this server on my own dime and pay for the VPS and hosting, because it is not only a private but a public good, and that is how it should be. I have not only myself but family and friends set up on Vaultwarden and NextCloud, and it’s just really nice.
That said, again, I like being able to offer services that will hopefully help make people’s lives easier, or at least more enjoyable. That is why, when I found out about LibreTranslate, I immediately wanted to be able to use it on my server. LibreTranslate is meant to be a self-hosted Google Translate replacement. I remember using Google Translate a ton over the years for various purposes, but I’ve tried to cut as many Google things out of my life as possible, and have really intentionally avoided using it for years. So again, I was very happy to see that I could potentially self-host a replacement for it.
One problem is that LibreTranslate didn’t have a YunoHost package, and I didn’t see an easy way of installing it otherwise. The site offers Docker packages, which are supposed to be easy, but I can’t wrap my head around how to use them. I tried doing a bespoke (if you will) installation of LibreTranslate, and it failed miserably. I couldn’t get it to work at all. So I got rid of the subdomain, removed the files, and thought, “OK, I’ll wait until there is an official package.”
Imagine my glee when, just for fun, I searched the YunoHost apps catalogue and found that someone had indeed made an app package! Finally! I set up a subdomain (DNS and all), added it to YunoHost, and installed LibreTranslate on the subdomain. I navigated to the page and looked, and found it working, but only offering two languages: English<->French. That makes sense, since the YunoHost devs are mostly French. OK. Fine. But there had to be a way to enable more languages than just those two.
Like a number of FOSS projects (IMHO, YMMV), LibreTranslate’s documentation is spotty at best, at least for a relatively casual user like myself. I know that sounds ridiculous, since I am running this on my own server, but hey, I don’t have the knowledge to get my hands too dirty. Or do I?
I looked through the documentation and zeroed in on how to update the “language models.” That sounded like what I was looking for. I poke around in my installation, which is buried in a Python venv (“virtual environment”) directory tree, and finally found the libretranslate binary (in my installation, the scripts/install_models.py script doesn’t exist). So I thought, OK, let’s run the binary and pass the parameter –update-models as directed.
When I ran that command, the program started, after downloading a bunch of language model files, and said it was listening on localhost, awaiting visitors. Cool! But nope, that didn’t do it. Something was missing.
I dug in a little more, and did a “locate” operation to find files for “libretranslate.” I found files in /etc/yunohost/apps/libretranslate, which seemed promising. As with most things, LibreTranslate is, at least in YunoHost, hooked into systemd, so /etc/yunohost/apps/libretranslate/conf/systemd.service was the relevant file. I opened the file and found that this is the call to start the binary: __INSTALL_DIR__/.venv/bin/libretranslate --host 127.0.0.1 --port __PORT__ --load-only en,fr --frontend-language-target en
(updated 11 Jun 2024; you may have to check this on your own installation)
However, I look a little closer and realize that this is the “prototype,” so to speak, for the package to create the conf files based on the individual setup of the YunoHost system (hence the placeholders INSTALL_DIR &c.). So modifying this file didn’t do anything (I found that out the hard way). The actual systemd service file is, on my system, at /etc/systemd/system/libretranslate.service. So I open that file up and find something much more readable, or at least filled out, since the port is filled in and such. But note that, per the switches, it’s by default telling the program to load only En(glish) and Fr(ench). And that won’t do, since I want all languages (available) to be enabled.
So I removed “–load-only en,fr” and replaced it with “–update-models.” This was another mistake.
We don’t want to update the language models every time the server runs. That would be wasteful in terms of CPU time and probably cause a crash. And let’s be honest, it didn’t work very well when I changed that up. But not for the reason that I expected, however. I decided to try a little experiment and call the binary, using that exact same command-line, but with –update-models, as root. Why not? I run the program like that, and it starts downloading the models. However, the operation stops. Why? Because it says my hard disk is full. Cue terrified face! The language models can’t be that big, can they?
My root partition doesn’t have a whole ton of space on it, since it’s mostly just intended for the OS and its files, nothing super fancy. It’s maybe 30Gb or so, and adequate for my purposes. Most of my files live in /home which has plenty of space. So there’s got to be a way to run the program as it was intended, and download all the language model files. I realized that the systemd service is running the libretranslate binary as the user libretranslate; otherwise it won’t work properly and won’t put the language model files in the proper place.
The language models live in /.local/share/argos-translate/packages, but again, this is off of /, which is going to have space issues, at least in my installation. At time of writing, the language models are about 6.7Gb. Not huge, and doable, but you need to have enough space for them, of course, and a root partition won’t always have a lot to play around with unless you have more forethought than I did. I had to think a bit outside the box to get this to work. I had to find a way to trick the program into installing the files elsewhere. A lot of this is written in Python which makes zero sense to me, so I thought hey, it would be easier to work with the hardcoded path than to modify the program itself – especially since those changes likely wouldn’t survive an upgrade of the package.
My solution, whether elegant, or not, was the following:
- Create a directory “packages” off the homedir of the LibreTranslate user (on my system, /home/libretranslate/packages)
- Make sure to
chown
(= change owner) to user libretranslate and group libretranslate, so it is writable by the script. Assuming you’re in the LibreTranslate user’s homedir:chown libretranslate:libretranslate packages
- Open a root shell:
sudo su
- Remove the /.local/share/argos-translate/packages directory, and create a symlink (= symbolic link) to the “packages” directory we’ve created in the LibreTranslate user’s homedir:
cd <LibreTranslate root>/.local/share/argos-translate
rm packages
ln -s /home/libretranslate/packages ./packages
- Now that we have set up the symlink to fool the program into putting files where we want, do the following:
- If you don’t still have the root shell, type
sudo su
to start one - “Kill” the LibreTranslate binary so we start fresh:
pkill -9 libretranslate
(orpgrep libretranslate
and thenkill -9 <pid>
from there) - Become the LibreTranslate user:
su libretranslate
- If you’re not still there,
cd
to the LibreTranslate root directory - Run the following command (adjusting as needed based on your systemd service’s parameters, particularly the “host” and “port” values):
<LibreTranslate directory>/venv/bin/libretranslate --host 127.0.0.1 --port <port> --frontend-language-target en --update-models
- If you don’t still have the root shell, type
If you’ve done everything correctly up to this point, it should download the language models and will keep running LibreTranslate. Go ahead and Ctrl-C, exit out of the LibreTranslate “su” shell, and exit out of the root shell, and you’re done. almost. For good measure, I’d recommend rebooting your VPS/server entirely.
Once you’ve rebooted, you should be able to navigate to LibreTranslate’s domain or subdomain and you’ll have all the languages, not just French and English! Keep in mind that there will likely be updates to the language models and you may want to rm -rf
the contents of the “packages” directory and run the last set of commands once in awhile. I looked and thought there would be an easier way to update the models, but there are just links here to download individual models. I can’t find a Github or other thing that I can just pull everything at once like the script does, so I’d recommend using the script for updates.
In any case, if this post helped at all, I am happy to hear it, and of course, if any issues arise or you have a better suggestion for steps, please let me know. Above all I hope you are able to get a working instance up and share it with others!