[DEVELOPERS] Automated Translation Management System for Enigma2 Plugins – GitHub Workflow Integration

    • Official Post

    **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):


    Code
    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:


    ---


    ### 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.


    OwnerPlugins repositories


    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:


    Code
    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!


    :clinking beer mugs:

Chat about everything else!

A friendly forum for off-topic discussions, random questions, and community bonding. Your space for conversations outside our main categories. Discuss hobbies, news, games, or anything else with the wider community.