transLATER
Scrivi ora, traduci DOPO.
Un servizio che traduce da solo la documentazione dei tuoi progetti su GitLab, con un modello di lingua che gira a casa tua: niente servizi esterni, niente costi a parola. Scrivi nella tua lingua, fai push, e qualche minuto dopo nel repository ci sono le traduzioni. Il nome gioca con l’inglese later, «dopo»: tu scrivi adesso, la traduzione arriva poco più tardi.
Traduce:
- le pagine Markdown: README, documenti, pagine di un sito Hugo (anche il front matter), e nei
blocchi di codice i commenti (
# …,// …) e le scritte degli schemi disegnati a caratteri; - i disegni SVG: solo le scritte, il resto del file resta identico; se una scritta tradotta non ci sta, il carattere si rimpicciolisce quanto basta;
frontend.yml(le schede di un sito vetrina) e le scritte di un sito (i18n/it.toml);- i file di configurazione d’esempio (
.env.example,*.yaml,*.toml,*.conf,*.ini…): solo i commenti, chiavi e valori restano identici.
Le traduzioni finiscono accanto agli originali, nello stesso repository:
| Originale | Traduzione |
|---|---|
README.md | README.en.md |
docs/img/schema.svg | docs/img/schema.en.svg |
content/guide/x/index.md (Hugo) | content/guide/x/index.en.md |
frontend.yml | frontend.en.yml |
i18n/it.toml | i18n/en.toml |
.env.example, conf.yaml (i commenti) | .env.en.example, conf.en.yaml |
In testa a ogni Markdown, originale compreso, c’è la barra delle lingue disponibili:
🌐 **Italiano** · [English](https://git.eandgcode.com/egprojects/translater/-/blob/main/README.en.md). Si scrive guardando i file che ci sono davvero, quindi
una lingua aggiunta compare da sola; nelle traduzioni i link agli altri documenti e alle immagini
puntano alle loro traduzioni.
GitLab ──push──► webhook ──► translater (coda, un giro alla volta) ──► commit «Traduzioni automatiche»
│
└──► translater-ollama (modello di lingua sulla scheda video)
Requisiti
- Un server con Docker e il plugin
docker compose(Linux). - Una scheda video NVIDIA con il supporto per Docker (NVIDIA Container Toolkit): consigliata. Con 12 GB di memoria video il modello di serie sta per l'80% sulla scheda e scrive circa 43 token al secondo. Senza scheda video gira sul processore, molto più lento, e vuole circa 20 GB di RAM liberi.
- Disco: circa 31 GB (18,7 GB il modello, 9,4 GB l’immagine di Ollama, 2,2 GB quella del translater con Chromium dentro).
- Un GitLab (anche self-hosted) raggiungibile dal server, e il servizio raggiungibile da GitLab per il webhook. GitHub per ora no.
Mentre lavora il modello prende quasi tutta la scheda video e qualche GB di RAM; dopo 5 minuti senza lavoro si scarica da solo, e fra un giro e l’altro restano solo i due programmi (un centinaio di MB). Se un altro programma sta usando la scheda video, il modello va un po’ più sul processore: più lento, ma va.
Installazione
- L’utente di GitLab (vedi sotto): un utente normale, Maintainer dei progetti da tradurre, e un suo token.
- Sul PC, in questa cartella:
./setup-translater.sh. Al primo lancio crea.envdal modello.env.example: compila dove sta il server (SERVER_SSH,SERVER_KEY),GITLAB_URLeGITLAB_TOKEN, e rilancia. Lo script si copia sul server, costruisce l’immagine, avvia i due container e scarica il modello (una volta sola). Si può anche lanciare direttamente sul server: lì le righeSERVER_*restano vuote. - In ogni progetto da tradurre, un
translations.yml. Al giro successivo il servizio lo trova, crea il webhook del progetto e traduce tutto; poi riparte a ogni push.
La pagina di stato è su http://IP-DEL-SERVER:8790/ (utente translater, password in .env sul
server: STATO_PASSWORD): coda, ultimi giri, anteprime PNG dei disegni tradotti, tasto «Traduci ora».
L’utente di GitLab
- Un utente normale (non amministratore), per esempio
translater, membro Maintainer dei progetti da tradurre (Manage → Members): serve per il push sul ramo principale e per creare il webhook. - Un suo token personale con gli scopi
apiewrite_repository: va inGITLAB_TOKEN. - Se GitLab e transLATER stanno nella stessa rete di casa, GitLab di serie non chiama indirizzi
locali: in Admin → Settings → Network → Outbound requests aggiungi alla allowlist
IP-DEL-SERVER:8790(per esempio192.168.1.20:8790).
I commit di transLATER portano l’indirizzo «noreply» di quell’utente, e il webhook li riconosce: un commit di traduzioni non fa partire un altro giro.
Il modello
Di serie gemma4:26b-a4b (Google Gemma 4, a esperti: 26 miliardi di parametri, 4 attivi per volta), scelto con una gara sugli stessi testi: sezioni con elenchi, un paragrafo con codice, il front matter di una pagina, le 36 scritte di uno schema SVG e qualche frase difficile.
| Modello | Velocità (RTX 4070 12 GB + Xeon 22 core) | Com’è andata |
|---|---|---|
| gemma4:26b-a4b (18,7 GB) | 43 token/s | ottima: glossario rispettato, grassetti e codice intatti, nel disegno sposta le parole fra le righe spezzate perché si leggano ancora |
| qwen3.6:35b-a3b (22,6 GB) | 48 token/s | buona, ma traduce anche dentro il codice (sensors/<stanza>/… → <room>) e applica male il glossario |
| gemma4:31b (densa, 20,4 GB) | 9 token/s | come la 26b, cinque volte più lenta, e anche lei tocca il codice |
| translategemma:12b | 6,5 token/s (solo processore) | buona ma senza contesto: «si toglie tensione» → «we are relieving stress» |
| translategemma:27b | 5,3 token/s | non meglio della 12b |
Si cambia con --model <nome> (qualunque modello di Ollama): la
cache è per modello, quindi con un modello nuovo si ritraduce tutto. Su macchine più piccole
gemma4:12b (8 GB) o gemma4:e4b (6,6 GB) sono più leggeri; la loro qualità non è stata provata.
Come traduce
- Markdown a sezioni: ogni richiesta è una sezione intera (un titolo e i suoi paragrafi), con il titolo del documento e l’ultima parte già tradotta come contesto, e il glossario del progetto. Codice fra backtick, indirizzi e shortcode non si toccano.
- Blocchi di codice: nei blocchi con un linguaggio (
bash,yaml,ini,cpp…) si traducono solo i commenti; comandi, codice e stringhe fra virgolette restano come sono. Nei blocchi senza linguaggio, di solito schemi disegnati con─ │ ┌ ▶, si traducono le scritte fra un tratto e l’altro, e quello che segue sulla stessa riga resta nella sua colonna: una scritta più lunga usa gli spazi che la seguono o accorcia la linea di collegamento, e se non ci sta resta com’era. - File di configurazione: la copia tradotta (
.env.en.example) ha i commenti nella lingua nuova e per il resto è identica all’originale; i Markdown tradotti la linkano al posto dell’originale. - Controllo: una traduzione si accetta solo se ha la stessa struttura riga per riga (titoli, voci di elenco, righe di tabella) e gli stessi codici e indirizzi. Se no si riprova, poi blocco per blocco, poi con i segnaposto; solo alla fine un pezzo resta nella lingua di partenza (il log dice perché) e il giro dopo ci riprova.
- Disegni SVG: le scritte di un disegno si traducono insieme (il modello sa che due righe di fila possono essere una frase spezzata). Poi Chromium misura ogni scritta e lo spazio che ha: il riquadro che la contiene nel disegno originale (con lo stesso margine dal bordo) o, se non c’è, la riga più lunga della sua colonna. Solo se la traduzione non ci sta il carattere si rimpicciolisce, fino al 70%.
- Link fra i documenti: nei file tradotti i link agli altri file tradotti portano alle traduzioni
(
docs/guida.md→docs/guida.en.md, anche con l’ancora); se il testo del link è il nome del file, cambia anche quello. Un testo vero («la guida») resta tradotto com’è. - Cache: ogni sezione tradotta resta in
dati/cache.sqlitesul server; un documento cambiato costa solo le sezioni cambiate. - Correggere a mano: scrivi tu il file tradotto (es.
README.en.md) senza la prima riga<!-- traduzione automatica … -->: il tuo vince, transLATER non lo tocca più. - Siti Hugo: nelle pagine tradotte i link alle sezioni del sito (
/guide/x/) diventano quelli della lingua (/en/guide/x/); i disegni tradotti di una pagina (schema.en.svg) Hugo li sceglie da solo per la pagina inglese.
Quando parte
- A ogni push sul ramo principale di un progetto con
translations.yml(webhook). - Comunque ogni
SCOPERTA_MINUTI(di serie un’ora): cerca i progetti nuovi e quelli con commit non ancora tradotti, se un webhook si è perso. - A mano:
./setup-translater.sh --translate gruppo/progetto(oall), oppure dalla pagina di stato.
Lo script: setup-translater.sh
| Comando | Cosa fa |
|---|---|
(niente) o --install | .env, immagine, avvio, download del modello |
--translate <gruppo/progetto|all> | mette in coda subito |
--count <gruppo/progetto> | quanti file e pezzi ci sono da tradurre, senza tradurre |
--test <file.md|file.svg> [lingua] | dal PC: traduce un file e lo riporta accanto (con le anteprime PNG per gli SVG) |
--status · --logs | coda e ultimi giri · segue il log |
--model <nome> | cambia modello |
--start · --stop · --restart · --update · --uninstall | i container |
Licenza
MIT, vedi LICENSE. Il modello di serie ha la sua licenza (Gemma Terms of Use).
Il tuo parere
Commenti scelti
Una selezione dei commenti ricevuti, pubblicati con il permesso di chi li ha scritti. La media conta tutti i voti.