Traduzioni sincronizzate via Git o distribuite a runtime: quale scegliere per la vostra pipeline CI/CD?
Le traduzioni sincronizzate via Git sono file di traduzione che vivono nel vostro repository e che la pipeline di CI mantiene aggiornati: le nuove chiavi partono verso una piattaforma di traduzione, le traduzioni completate tornano come commit o pull request, e gli utenti le vedono dopo il deploy successivo. La distribuzione a runtime significa che l'applicazione carica le traduzioni da una CDN mentre è in esecuzione: una modifica pubblicata raggiunge gli utenti senza commit né nuovo deploy. Le due cose non si escludono: molti setup in produzione includono nel build una copia sincronizzata e in più recuperano gli aggiornamenti dalla CDN.
Questo articolo è una guida decisionale per la domanda "come sincronizziamo le traduzioni con la nostra pipeline CI/CD?": come si presenta ciascuna architettura dall'inizio alla fine, una tabella decisionale basata sui criteri che contano davvero, come lavorano oggi i team e cosa nessuna delle due architetture risolve.
- La sincronizzazione Git rende le traduzioni parte del rilascio: vengono versionate, revisionate e annullate insieme al codice, e ogni modifica aspetta il deploy successivo.
- La distribuzione a runtime separa le traduzioni dal rilascio: una correzione pubblicata va online senza deploy, al prezzo di una richiesta di rete, di una cache da regolare e di traffico CDN da pagare.
- Le domande che decidono: chi modifica le traduzioni, quanto spesso fate deploy, se il build ha bisogno dei file (SSR, build statici, offline, mobile nativo), e se la revisione avviene nelle pull request o in un editor di traduzione.
- Entrambe è una risposta valida: file inclusi nel build come base, la CDN per le modifiche tra un rilascio e l'altro. Funziona solo con un'unica fonte di verità per i valori tradotti.
Architettura 1: file di traduzione in Git, sincronizzati dalla CI
I file sono il prodotto finale. Il flusso, dall'inizio alla fine:
- Una sviluppatrice aggiunge una chiave nel codice, per esempio
t('checkout.title'), con un valore predefinito nella lingua sorgente. - A ogni push o pull request, la CI estrae le chiavi dal codice sorgente (o legge i file della lingua sorgente) e invia le chiavi nuove e modificate alla piattaforma di traduzione.
- Traduttori, traduzione automatica o IA riempiono le lingue di destinazione nella piattaforma; i revisori approvano.
- Uno step di CI scarica le traduzioni nei file di lingua del repository.
- La modifica arriva come commit o pull request e va in produzione con il build e il deploy successivi.
Cosa offre: il repository è il quadro completo di un rilascio, testi compresi. Una modifica di traduzione è un diff che si può revisionare accanto al codice che l'ha causata, annullare con git revert e riprodurre facendo il checkout di un vecchio tag. A runtime il build non dipende da nulla al di fuori della vostra infrastruttura, ed è esattamente ciò che vogliono la generazione di siti statici, il rendering lato server, le app offline e le app mobile native.
Cosa costa: ogni modifica di traduzione è una modifica di codice. Un refuso in italiano aspetta il deploy successivo, oppure si merita un rilascio correttivo tutto suo. La traduzione è asincrona, quindi la CI non può aspettarla: una chiave inviata oggi viene di solito tradotta quando la pipeline che l'ha inviata è già terminata, e il risultato arriva in un'esecuzione successiva o in una pull request di un bot. I file di lingua toccati da ogni feature branch sono una fonte classica di conflitti di merge, e un job di sincronizzazione che riscrive file interi produce diff che nessuno riesce a revisionare.
Architettura 2: traduzioni distribuite a runtime da una CDN
I file sono un dettaglio implementativo della piattaforma. Il flusso:
- Una sviluppatrice aggiunge una chiave nel codice. La chiave arriva alla piattaforma di traduzione o dall'applicazione in esecuzione durante lo sviluppo (in i18next, con l'opzione
saveMissing) o tramite uno step di sincronizzazione nella CI. - Traduttori, traduzione automatica o IA riempiono le lingue di destinazione; i revisori approvano.
- La piattaforma pubblica lo stato approvato su una CDN.
- L'applicazione in esecuzione recupera dalla CDN i namespace che le servono per la lingua corrente, di solito al caricamento.
- Gli utenti vedono il nuovo testo appena scade la cache, senza commit, build né deploy.
Cosa offre: la traduzione smette di essere una dipendenza del rilascio. Prodotto, marketing e traduttori correggono i testi con i propri tempi, una nuova lingua può andare online senza rilascio, e il repository non contiene file di lingua su cui creare conflitti. È il modello di distribuzione alla base della localizzazione continua; la definizione e le sue fasi sono in cos'è la localizzazione continua.
Cosa costa: una richiesta di rete sul percorso critico, regolata dalla durata della cache (una cache lunga significa caricamenti veloci e aggiornamenti più lenti, una corta il contrario). Una dipendenza dalla CDN a runtime, quindi i setup di produzione hanno bisogno di un fallback per reti bloccate o assenti. Traffico che cresce con i visitatori invece che con i build. I file pubblicati su una CDN pubblica sono leggibili da chiunque conosca l'URL. E la revisione linguistica avviene nella piattaforma di traduzione, non nelle vostre pull request.
Architettura 3: entrambe
L'ibrido usa ciascuna architettura per ciò che sa fare meglio:
- Le chiavi arrivano alla piattaforma tramite una sincronizzazione nella CI (o tramite
saveMissingdurante lo sviluppo). - Al build, la CI scarica le traduzioni pubblicate e le include: il server esegue il rendering con esse, le pagine statiche vengono generate a partire da esse, un'app offline viene distribuita con esse.
- A runtime, l'applicazione carica gli stessi namespace dalla CDN quando può, e ripiega sulla copia inclusa quando non può.
- Una correzione pubblicata tra due rilasci raggiunge gli utenti tramite la CDN; il build successivo la integra nel bundle.
La condizione è un'unica fonte di verità per i valori tradotti. Il codice possiede le chiavi, la piattaforma possiede le traduzioni, e i file in Git sono un'istantanea generata di uno stato pubblicato. Non appena qualcuno modifica un valore nel repository mentre qualcun altro lo modifica nella piattaforma, i due output divergono e ogni sincronizzazione diventa una risoluzione di conflitti.
Tabella decisionale
| Criterio | Sincronizzazione Git tramite CI | Distribuzione a runtime da una CDN | Entrambe |
|---|---|---|---|
| Chi modifica le traduzioni | Gli sviluppatori, o traduttori il cui lavoro rientra con un commit di sincronizzazione | Traduttori, prodotto e marketing in un editor di traduzione, senza accesso a Git | I traduttori nell'editor; gli sviluppatori vedono file generati |
| Cadenza dei rilasci | I testi vanno online con ogni deploy: va bene se fate deploy spesso o se i testi cambiano di rado | I testi vanno online appena pubblicati, indipendentemente dai deploy | La base con ogni deploy, le correzioni nel frattempo |
| SSR/SSG e offline | Solido: i file fanno parte del build | Richiede un recupero al rendering o al caricamento, una cache e un fallback offline | Solido: base inclusa nel build, CDN sopra |
| Revisione nelle pull request | Sì: i diff delle traduzioni stanno accanto alla modifica del codice | No: la revisione avviene nella piattaforma di traduzione | La code review vede l'istantanea generata; la revisione linguistica resta nella piattaforma |
| Rollback | git revert e nuovo deploy: i testi tornano indietro con il codice | Ripubblicare uno stato precedente, senza deploy; dipende dalla cronologia e dalle versioni della piattaforma | A scelta: annullare il bundle con il codice, o ripubblicare lo stato della CDN |
| Costo del traffico CDN | Nessuno a runtime; i download avvengono per build, non per visitatore | Cresce con visitatori e pagine viste; la cache lo riduce | Come la distribuzione a runtime per tutto ciò che l'app recupera dalla CDN |
| Testi riservati | Restano in un repository privato fino al rilascio (un bundle web rilasciato è comunque pubblico) | I file pubblicati sono leggibili tramite URL: i testi non ancora annunciati richiedono una distribuzione autenticata o devono restare non pubblicati | Tenere i testi non annunciati fuori dallo stato pubblicato fino al lancio |
| Mobile nativo | Adatto per natura: i file di risorse vengono compilati nell'app | Richiede un SDK over-the-air dentro l'app | Includere nel binario; aggiornamenti a runtime solo con un SDK di questo tipo |
Come leggerla:
- Scegliete la sincronizzazione Git quando gli sviluppatori scrivono la maggior parte dei testi, "con il prossimo rilascio" è abbastanza veloce per una correzione, il build deve essere autosufficiente (SSR, export statico, offline, mobile nativo) o la vostra cultura di revisione si basa sulle pull request.
- Scegliete la distribuzione a runtime quando i testi sono responsabilità di persone esterne al team di sviluppo, le correzioni alle traduzioni non devono aspettare un rilascio, o i testi cambiano molto più spesso di quanto fate deploy.
- Scegliete entrambe quando vi servono un build autosufficiente e testi che cambiano tra un rilascio e l'altro. Le web app con rendering lato server i cui testi devono restare correggibili sono il caso tipico.
Come lavorano oggi i team
- File modificati nel repository, nessuna sincronizzazione. Gli sviluppatori modificano JSON o YAML accanto al codice. È il setup corretto più economico per una sviluppatrice e lingue che sa leggere; smette di funzionare quando un traduttore ha bisogno di accesso. I problemi tipici sono descritti in gestire i file di traduzione senza modificare il JSON a mano.
- Un job di sincronizzazione pianificato. Un job notturno o post-merge invia le nuove chiavi e apre una pull request di un bot con tutto ciò che è stato tradotto dall'ultima esecuzione. Funziona, e separa la traduzione dalla funzionalità che ne aveva bisogno: la funzionalità viene unita nella lingua sorgente, le sue traduzioni arrivano più tardi in una pull request a parte.
- Sincronizzazione per pull request. La sincronizzazione gira nella pull request stessa e solo per le chiavi che quella pull request ha aggiunto o modificato, così le traduzioni possono arrivare nello stesso branch prima del merge. Serve un diff rispetto al branch di base (la cronologia Git completa nel checkout della CI), e dipende comunque dal fatto che le traduzioni siano pronte prima che qualcuno clicchi su merge.
- Distribuzione CDN per la web app. L'applicazione carica le traduzioni a runtime; il repository non contiene file di lingua, o solo quelli della lingua sorgente. I traduttori pubblicano correzioni senza coinvolgere lo sviluppo. Il meccanismo, cache compresa, è descritto in aggiornare le traduzioni senza un nuovo deploy.
- L'ibrido. I build scaricano le traduzioni pubblicate per il rendering lato server e come fallback offline; il client carica sopra la versione della CDN.
- App native nella CI mobile. Il build mobile scarica i testi nel formato di risorse della piattaforma prima della compilazione, e le modifiche ai testi arrivano con i rilasci dell'app.
Cosa nessuna delle due architetture risolve
- La qualità. Il luogo in cui vivono i file non dice nulla sulla correttezza di una traduzione. Terminologia, tono e approvazione sono compito di glossari, di un workflow di revisione e di controlli QA automatici, in entrambe le architetture.
- La traduzione asincrona. Né la CI né una CDN rendono più veloci i traduttori. Decidete cosa succede finché una chiave non è tradotta: il fallback sulla lingua sorgente è una scelta di prodotto consapevole, non un bug.
- Due fonti di verità. La sincronizzazione bidirezionale è uno strumento, non un modello di governance. Se i valori possono cambiare in entrambi i posti, decidete quale prevale prima del primo conflitto, non durante.
- Gli aggiornamenti istantanei. Distribuzione a runtime significa "senza deploy", non "all'istante": i file in cache restano obsoleti finché la cache non scade, e una cache molto breve si paga in latenza.
- Il design delle chiavi. Nomi, namespace e responsabilità restano a voi in entrambi i modelli; né un job di sincronizzazione né una CDN li progetta.
- I setup piccoli. Una sviluppatrice, due lingue che sa leggere, testi che cambiano di rado: file in Git e nessuna piattaforma sono la risposta corretta più economica. Il segnale per evolvere è la seconda persona che deve modificare i testi.
Come funziona in Locize
Locize supporta entrambe le architetture da un unico progetto, quindi la scelta è un'impostazione di distribuzione, non una migrazione. Il progetto è l'unica fonte di verità per i valori tradotti; i file nel vostro repository e quelli sulla CDN sono entrambi output del suo stato pubblicato.
- Verso Git, tramite CI. Tre GitHub Actions:
locize/translateestrae le chiavi nuove e modificate, le sincronizza, avvia la traduzione con IA e scarica i risultati (incapsulai18next-cli localize --cie non modifica mai il vostro codice sorgente);locize/syncriconcilia i file di lingua esistenti in entrambe le direzioni, conauto-translateopzionale;locize/downloadrecupera le traduzioni pubblicate al build per SSR e build statici. Nessuna esegue commit: le abbinate a uno step di commit o di pull request. Fuori da GitHub, la CLI esegue gli stessi flussi (locize sync,locize download,npx i18next-cli locize-sync). Un nuovo progetto gratuito può tradurre automaticamente una quantità iniziale limitata, vedi la traduzione CI gratuita per i18next. - A runtime, dalla CDN. Le traduzioni vengono pubblicate sulla CDN per impostazione predefinita: la CDN Standard è pubblica, con una cache fissa di un'ora. La CDN Pro, dal piano Growth, aggiunge un max-age della cache configurabile per versione e la pubblicazione privata che richiede una chiave API. Con i18next le carica
i18next-locize-backend, ei18next-chained-backendaggiunge un fallback incluso nel build per l'ibrido. Anche i download al build contano come download CDN, ma per build invece che per visitatore. - Rilasci e rollback. Le versioni separano fasi come latest e production (
locize copy-version,locize publish-version), e la cronologia di ogni chiave mostra chi ha cambiato cosa e permette di ripristinare valori precedenti. - iOS e Android nativi. Solo sincronizzazione al build:
locize downloadolocize synccon il formatoandroid,stringsoxcstringsscrive i file di risorse prima della compilazione dell'app. Locize non ha un SDK nativo over-the-air, quindi i nuovi testi raggiungono le app native con il rilascio successivo dell'app.
Per tradurre solo ciò che una pull request ha modificato: sugli eventi pull_request, command: sync usa per impostazione predefinita la modalità changed-only, quindi vengono sincronizzate e tradotte con IA solo le chiavi che la PR ha aggiunto o modificato, e nulla viene eliminato. Il branch di base deve essere presente nel checkout:
name: Translate PR
on:
pull_request:
permissions:
contents: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- uses: locize/translate@v2
with:
command: sync
project-id: ${{ secrets.LOCIZE_PROJECTID }}
api-key: ${{ secrets.LOCIZE_API_KEY }}
- uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: 'chore(i18n): translate PR changes'Le pull request provenienti da fork non ricevono i secret del repository, quindi questo workflow funziona solo per i branch dello stesso repository. Un commit inviato con il GITHUB_TOKEN predefinito non avvia nuove esecuzioni di workflow, quindi la CI non riparte sul commit delle traduzioni.
La stessa limitazione al diff esiste come changed-only: true in locize/sync, come locize sync --changed-only true (locize-cli 12.7 o successiva) e come npx i18next-cli locize-sync --changed-only (i18next-cli 1.72 o successiva).
Se volete confrontare le due soluzioni sul vostro codice: create un progetto, aggiungete il workflow qui sopra con i vostri secret e caricate lo stesso progetto dalla CDN in un build di anteprima. Poi decidete con i vostri diff e i vostri tempi di caricamento sotto gli occhi.
Domande frequenti
Qual è la differenza tra traduzioni sincronizzate via Git e distribuzione a runtime? Con la sincronizzazione Git, i file di traduzione stanno nel repository e uno step di CI li mantiene aggiornati: le traduzioni vanno in produzione con il build e il deploy successivi. Con la distribuzione a runtime, l'applicazione carica le traduzioni da una CDN mentre è in esecuzione: una modifica pubblicata raggiunge gli utenti senza commit né deploy, appena scade la cache.
Come sincronizziamo le traduzioni con la nostra pipeline CI/CD? Estraete le chiavi dal codice e inviate quelle nuove o modificate alla piattaforma di traduzione (idealmente solo il diff della pull request), poi scaricate le traduzioni completate nei file di lingua e committatele, oppure aprite una pull request. Configurate una lingua di fallback per le chiavi non ancora tradotte, e aggiungete la distribuzione via CDN se i testi devono cambiare tra un rilascio e l'altro.
Quali strumenti di traduzione si sincronizzano automaticamente con le pipeline CI/CD? Cercate una CLI o una action CI pronta all'uso che estragga le chiavi o legga i file esistenti, possa limitare una sincronizzazione al diff di una pull request, scriva il vostro formato di file senza perdere struttura né forme plurali, lasci i commit al vostro workflow Git e possa, opzionalmente, distribuire tramite CDN. Locize offre tre GitHub Actions e una CLI che funziona in qualsiasi sistema di CI.
Teniamo le traduzioni in un repository Git. Una piattaforma di localizzazione può sincronizzare i file automaticamente? Sì. Uno step di sincronizzazione nella CI invia le nuove chiavi della lingua sorgente e riscrive le traduzioni negli stessi file e cartelle, registrate come commit o pull request. Mantenete una sola direzione per responsabilità: il codice possiede le chiavi, la piattaforma possiede i valori tradotti.
I file di traduzione vanno committati nel repository? Quando il build o la revisione ne hanno bisogno: SSR e build statici, app offline, app mobile native, o team che revisionano le modifiche alle traduzioni nelle pull request. Se le traduzioni arrivano da una CDN e il build non le legge, i file sono una copia generata che potete tenere fuori da Git. In ogni caso, nessuno dovrebbe modificarli a mano.
Possiamo usare insieme la sincronizzazione Git e la distribuzione tramite CDN? Sì. Il build include una copia scaricata delle traduzioni pubblicate come base, e l'applicazione in esecuzione carica traduzioni più recenti dalla CDN quando riesce a raggiungerla. Funziona finché entrambi gli output derivano da un unico stato pubblicato, e si rompe quando i valori vengono modificati in due posti.
Stanco di gestire le traduzioni a mano?
Locize è il backend di gestione delle traduzioni creato dal team di i18next: distribuzione via CDN, traduzione con AI, editing in-context, senza nuovi deploy.
Inizia la prova gratuita di 14 giorni