Managing translations for multilingual software can be tedious. You maintain a POT template with all your strings, and then need to keep multiple (gettext) PO files synchronized and translated. I wrote a small command-line tool in Go called “potranslate” to automate the translation part using Google Translate.
Use it from the command line:
# Scans for default.pot and PO files in ./locales
potranslate --source-lang en ./locales
Point it at a directory with POT and PO files, and it will:
- Sync missing entries from POT to PO files
- Translate empty strings using Google Translate
It takes about one second per tanslated string, but it is non-interactive.
How it works
The tool is written in Go and uses three main components:
File parsing: Uses github.com/leonelquinteros/gotext to parse the gettext
format. POT and PO files follow the same structure, so reading them is
straightforward.
Translation: Uses github.com/Conight/go-googletrans to call Google
Translate. It’s a simple HTTP wrapper around Google’s translation service.
Progress tracking: Uses github.com/schollz/progressbar/v3 for the terminal
progress bar, since translations can take a while.
The workflow is simple:
- Scan directory for POT and PO files (e.g.,
default.potanddefault_es.po,default_fr.po) - Parse POT to get all source strings
- Add any missing entries from POT to each PO file
- Find empty translation strings in PO files
- Translate them one by one
- Write back to disk
Syncing entries
Before translating, the tool syncs the PO files with the POT template. If
default.pot has 100 entries and default_es.po only has 95 The tool adds those 5
missing entries with empty translations and then translates them. It also copies
the source comments from POT entries (like #: file.py:123) so you know where
each string comes from.
Rewrite mode
Sometimes PO files accumulate obsolete entries. The --rewrite flag rebuilds
the entire file from the POT template:
# Removes entries from the PO files that don't exist in the POT.
potranslate --rewrite ./locales
This preserves existing translations but removes entries that no longer exist in the POT. It strips old translator comments but keeps source location comments from the POT.
Adding new languages
You can create a new PO file for a language from scratch:
# Adds default_es.po from default.pot and translates everything
potranslate --add-lang es --source-lang en ./locales
The tool will updates the metadata headers (language code, revision date) and translates all entries.
Rate limiting
Google Translate will throttle you if you send too many requests. The tool waits 1 second between translations by default:
# Default: 1 second between requests
potranslate ./locales
# Fast mode: 0.1 seconds
potranslate --fast ./locales
For a file with 50 untranslated strings, that’s 50 seconds at normal speed, or 5
seconds with --fast.
Multiple domains
Larger projects often split translations into domains:
# Translates admin.pot and admin_*.po files
potranslate --domain admin ./locales
File naming follows the pattern <domain>_<lang>.po. The tool uses underscores,
not hyphens or dots.
Language detection
The tool reads the source language from POT metadata:
"Language: en\n"
If it’s not there, you need to specify it:
potranslate --source-lang en ./locales
When provided via command line, it writes the source language back to the POT metadata. Target languages are read from each PO file’s metadata or filename.
Interrupting
Press Ctrl-C to stop. The tool saves completed translations before exiting, so you can resume later. The progress bar shows how far along you are.
Limitations
The tool doesn’t validate translation quality. Google Translate makes mistakes, especially with context-dependent strings or technical terminology. You should review the translations. It also does not handle plural forms specially (translates them as separate strings) nor does it support translation memory or glossaries.
Example output
$ potranslate --source-lang en ./locales
Processing domain: default
POT file: ./locales/default.pot
Source language: en
Found 2 PO file(s)
Processing: default_es.po (target: es)
Added 3 missing entry/entries from POT file
[████████████████████████] 25/25 (100%)
Translated 25 string(s)
Processing: default_fr.po (target: fr)
No missing entries to add
[████████████████████████] 18/18 (100%)
Translated 18 string(s)
Complete! Translated 43 string(s) total
I wrote this because I needed it for a project and couldn’t find a simple command-line tool that did both syncing and translating. The code is small and does one thing.
See: https://github.com/mevdschee/potranslate
Enjoy!