**Introduction**
I have built a fully automated translation management system for Enigma2 plugins. It is integrated into a GitHub workflow and handles extraction, translation, and compilation of language files without any manual intervention.
Works with any Enigma2 plugin that follows the standard `locale/` structure and uses `gettext`.
---
### Main Components
1. **`update_translations.py`**
– Python script that:
- Extracts translatable strings from `.py` files and `setup.xml`
- Generates/updates the `.pot` master template
- Creates/updates `.po` files for over 90 languages
- Compiles `.mo` files (binary format for Enigma2)
- Auto‑translates empty strings using Google Translate API
- Uses a cache (`translation_cache.json`) to avoid repeated requests
2. **GitHub Actions workflow** (`.github/workflows/update-translations.yml`)
– triggers on push, runs the script, commits changes.
---
### File Structure and Placement
Assuming your plugin is located at:
`/usr/lib/enigma2/python/Plugins/Extensions/YourPlugin/`
Place the files as follows:
```
YourPlugin/
├── __init__.py # must define PluginLanguageDomain and call localeInit()
├── plugin.py # your main plugin code
├── setup.xml # (optional) if you have an XML setup screen
├── update_translations.py # <-- copy this script here
├── translate_utils.py # <-- (optional) if you want separate translation utilities
├── locale/ # created automatically by the script
│ └── ...
└── translation_cache.json # auto-generated cache file (do not edit)
```
- **`update_translations.py`** must be placed **directly inside your plugin folder** (same level as `__init__.py`).
- **`translate_utils.py`** (if used) goes in the **same folder** – it contains the Google Translate logic.
- The script automatically creates the `locale/` directory and all language subfolders.
- The GitHub workflow file (`.github/workflows/update-translations.yml`) goes in the **root of your GitHub repository**, not inside the plugin folder.
---
### Plugin’s `__init__.py` Requirements
Make sure your `__init__.py` contains these lines (or similar):
PluginLanguageDomain = "YourPlugin"
PluginLanguagePath = "Extensions/YourPlugin/locale"
def localeInit():
gettext.bindtextdomain(PluginLanguageDomain, resolveFilename(SCOPE_PLUGINS, PluginLanguagePath))
localeInit()
language.addCallback(localeInit)
The script will read `PluginLanguageDomain` from `__init__.py` automatically.
---
### GitHub Workflow File
Save this as `.github/workflows/update-translations.yml` in your repository root:
name: Update Translations by Lululla
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
update-translations:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
# with:
# persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install gettext (msgmerge, msgfmt)
run: |
sudo apt-get update
sudo apt-get install -y gettext
- name: Run translation updaters
run: |
for pyfile in $(find . -type f -name "update_translations.py"); do
plugin_dir=$(dirname "$pyfile")
echo "Running translation updater in $plugin_dir"
cd "$plugin_dir"
python3 update_translations.py
# Forza l'aggiunta dei file locale generati (ignora .gitignore)
if [ -d locale ]; then
git add -f locale/
fi
cd - > /dev/null
done
- name: Commit and push changes
run: |
git config user.name "github-actions"
git config user.email "actions@github.com"
git add .
if ! git diff --cached --quiet; then
git commit -m "Update translations via workflow"
git pull --rebase origin main
git push origin main
else
echo "No changes to commit"
fi
Display More
---
### How It Works (Summary)
1. You push code changes to GitHub.
2. The workflow runs `update_translations.py` in every plugin folder that contains it.
3. The script extracts all `_("...")` strings from `.py` and `setup.xml`.
4. It updates the `.pot` file and all `.po` files for 90+ languages.
5. For any empty `msgstr`, it calls Google Translate API (cached) to auto‑translate.
6. It compiles `.mo` files.
7. The workflow commits and pushes the updated `locale/` folder back to your repo.
No manual translation work needed ever again.
---
### Benefits
- Supports **over 90 languages** out of the box.
- **Cache** prevents repeated API calls – respects rate limits.
- **RTL languages** (Arabic, Hebrew, etc.) are automatically detected and left untranslated (preserves correct script).
- **Continuous integration** – every code change updates translations automatically.
- **Ready for Enigma2** – the `.mo` files are exactly what the plugin loads.
---
### Links / Attachments
- `update_translations.py` (attached)
- `translate_utils.py` (attached – optional, but recommended)
Tested on **CommandCenter** plugin. Works perfectly.
and on all my plugins on my Git.
Feedback and suggestions welcome!
---
## Italian Version (for your understanding)
Sistema automatico di gestione traduzioni per plugin Enigma2 – Integrazione GitHub Workflow
**Introduzione**
Ho realizzato un sistema completamente automatico per la gestione delle traduzioni dei plugin Enigma2. È integrato in un workflow GitHub e si occupa di estrarre, tradurre e compilare i file lingua senza intervento manuale.
Funziona con qualsiasi plugin Enigma2 che usi la struttura standard `locale/` e `gettext`.
---
### Dove mettere i file
Supponiamo che il tuo plugin sia in:
`/usr/lib/enigma2/python/Plugins/Extensions/TuoPlugin/`
La struttura diventa:
```
TuoPlugin/
├── __init__.py # deve definire PluginLanguageDomain e chiamare localeInit()
├── plugin.py # il tuo codice principale
├── setup.xml # (opzionale) schermata di setup
├── update_translations.py # <-- metti qui questo script
├── translate_utils.py # <-- (opzionale) metti qui se lo usi
├── locale/ # creato automaticamente dallo script
│ └── ...
└── translation_cache.json # file cache auto-generato (non modificare)
```
- **`update_translations.py`** va **direttamente nella cartella del plugin** (stesso livello di `__init__.py`).
- **`translate_utils.py`** (se usato) va nella **stessa cartella** – contiene la logica di Google Translate.
- Lo script crea automaticamente la cartella `locale/` e tutte le sottocartelle per lingua.
- Il file workflow di GitHub (`.github/workflows/update-translations.yml`) va nella **radice del repository GitHub**, non dentro la cartella del plugin.
---
### Requisiti del `__init__.py`
Il tuo `__init__.py` deve contenere qualcosa come:
PluginLanguageDomain = "TuoPlugin"
PluginLanguagePath = "Extensions/TuoPlugin/locale"
def localeInit():
gettext.bindtextdomain(PluginLanguageDomain, resolveFilename(SCOPE_PLUGINS, PluginLanguagePath))
localeInit()
language.addCallback(localeInit)
Lo script legge automaticamente `PluginLanguageDomain` dal file `__init__.py`.
---
### Workflow GitHub
Salva come `.github/workflows/update-translations.yml` (nella radice del repo). Il codice YAML è quello che ho scritto sopra in inglese (uguale).
---
### Come funziona (riassunto)
1. Fai push delle modifiche su GitHub.
2. Il workflow esegue `update_translations.py` in ogni cartella plugin che lo contiene.
3. Lo script estrae tutte le stringhe `_("...")` dai `.py` e da `setup.xml`.
4. Aggiorna il file `.pot` e tutti i file `.po` per oltre 90 lingue.
5. Per ogni `msgstr` vuoto, chiama l'API Google Translate (con cache) per tradurlo.
6. Compila i file `.mo`.
7. Il workflow committa e pusha la cartella `locale/` aggiornata sul tuo repo.
Mai più traduzioni manuali.
---
### Vantaggi
- Supporto **oltre 90 lingue** già pronte.
- **Cache** evita chiamate API ripetute – rispetta i limiti.
- **Lingue RTL** (arabo, ebraico…) rilevate automaticamente e non tradotte (per preservare la scrittura corretta).
- **Integrazione continua** – ogni modifica al codice aggiorna automaticamente le traduzioni.
- **Pronto per Enigma2** – i file `.mo` sono esattamente quelli che il plugin carica.
---
### Allegati
- `update_translations.py`
- `translate_utils.py` (opzionale ma consigliato)
Testato sul plugin **CommandCenter**. Funziona perfettamente.
Feedback e suggerimenti sono benvenuti!
![]()
