Come tradurre un file HTML senza rompere tag, attributi o link
Cosa tradurre in un file HTML, cosa lasciare invariato e come verificarlo. Con una pagina di esempio, un checker gratuito e un test su 9 esecuzioni con un LLM locale.

Per tradurre un file HTML, traduci il testo che le persone leggono e gli attributi che contengono parole destinate al lettore, come alt, title, placeholder, aria-label e la meta description della pagina. Lascia invariato il markup: nomi dei tag, href, src, id, class, script, stili e qualsiasi elemento contrassegnato con translate="no". Poi modifica un valore che è facile dimenticare, l'attributo lang sull'elemento <html>, in modo che browser, screen reader e motori di ricerca sappiano in quale lingua è ora la pagina.
Mantenere intatti i tag si è rivelato la parte facile. Abbiamo tradotto una pagina di aiuto HTML di 59 righe in cinese semplificato nove volte con un modello locale, usando tre metodi, e abbiamo verificato ogni output con uno script. Ogni esecuzione ha mantenuto tutti i tag, i link e gli ID. Ciò che è andato storto è stato più silenzioso: il modello ha tradotto una riga all'interno di un blocco di codice <pre> in tutte e sei le esecuzioni che inviavano l'intero file, ha lasciato l'aria-label della navigazione in inglese in tutte e sei, e il metodo che per design mantiene il markup più al sicuro, traducendo i pezzi di testo uno per uno, ha prodotto una frase che diceva al lettore di fare la cosa sbagliata in tutte e tre le sue esecuzioni.
Risposta rapida: cosa tradurre e cosa lasciare invariato
| Parte del file | Esempio dal nostro campione | Tradurlo? |
|---|---|---|
| Testo visibile | titoli, paragrafi, celle di tabella, testo dei link, <label> | Sì |
<title> e meta description | <title>Export Your Library | Shelfmark Help</title> | Sì. Entrambi compaiono nei risultati di ricerca e nelle schede del browser. |
og:title e altri meta tag social | <meta property="og:title" content="Export Your Library"> | Sì, solo il valore di content |
alt, title, placeholder, aria-label | alt="The Export dialog with EPUB selected", aria-label="Breadcrumb" | Sì |
lang su <html> | <html lang="en"> | Cambialo nella lingua di destinazione, ad esempio zh-Hans |
| Nomi dei tag e degli attributi | <a>, <img>, width, aria-label stesso | No |
href, src, id, class, for, name, type, data-* | href="#choose-format", id="q" | No |
<code>, <pre>, <script>, <style> | shelfmark export --format epub | No. Decidi separatamente per i commenti al codice e l'output di esempio. |
| Testo impostato tramite CSS | .note::before { content: "Note: "; } | Sì, ma risiede nel foglio di stile, quindi pianificalo |
| Dati strutturati JSON-LD | "name": "Export your Shelfmark library" | Traduci i valori di name e description; mantieni le chiavi e il JSON valido |
Elementi con translate="no" | <span translate="no">Shelfmark</span> | No |
| Commenti HTML | <!-- Generated by the help-center build... --> | Facoltativo. I lettori non li vedono mai. |
| Riferimenti a caratteri | <library>, , © | Mantieni i caratteri di escape. < non deve diventare un vero <. |
Questo elenco non è una nostra invenzione. La sezione dello standard HTML sull'attributo translate definisce gli "attributi traducibili": title su ogni elemento, alt sulle immagini, placeholder sugli input, content sugli elementi meta il cui nome è noto per essere traducibile, e lang, che secondo lo standard deve essere modificato per corrispondere alla nuova lingua. Indica inoltre aria-label di ARIA come esempio di un attributo che altre specifiche possono aggiungere, e afferma che in un elemento translate="no", il testo e i valori degli attributi "devono essere lasciati così come sono quando la pagina viene localizzata".
Cosa abbiamo testato
Abbiamo scritto sample-source.html, una pagina di un centro assistenza per la stessa app di lettura immaginaria, Shelfmark, che abbiamo usato nel nostro test di traduzione Markdown. Contiene un esempio per ogni riga della tabella sopra, più alcune trappole:
- una frase spezzata da tag inline: "Prima di esportare, esegui il backup delle tue note. Un'esportazione copia i tuoi libri, ma non elimina nulla da Shelfmark," con il nome del prodotto all'interno di
translate="no"; - una frase con due elementi inline
<code>il cui ordine è importante: "Digita il percorso della cartella<library>dopo--out"; - un blocco
<pre><code>con un comando e una riga di output di esempio,# Export finished: 128 books; - una regola CSS che inserisce la parola "Nota:" prima di un paragrafo;
- un link interno a
#choose-format, un linkmailto:, un modulo di ricerca e un blocco JSON-LD.
Poi abbiamo chiesto a un modello locale di tradurlo in cinese semplificato in tre modi:
- File intero. Incolla l'intero file e chiedi indietro il file tradotto.
- Con istruzioni. Lo stesso, più otto regole: mantieni ogni nome di tag e attributo, non modificare
href,src,id,classe valori simili, traduci gli attributi di testo e i meta tag elencati, lascia stare<code>,<pre>,<script>e<style>tranne che pernameedescriptiondel JSON-LD, rispettatranslate="no", mantieni i riferimenti a caratteri e i commenti, e impostalangsuzh-Hans. - Segmenti. L'approccio degli strumenti che estraggono il testo dall'HTML: uno script divide il file in tag e testo, salta
<code>,<pre>,<script>,<style>e gli elementitranslate="no", invia al modello i frammenti di testo rimanenti e gli attributi di testo come un elenco JSON numerato, e riscrive le traduzioni nel markup intatto. Imposta anchelang="zh-Hans"da solo.
Il modello era Qwen 3.6 27B (Q4_K_M) in LM Studio, con il thinking disattivato e temperatura 0,3, su un Apple M4 Max con 64 GB di memoria. Abbiamo eseguito ogni metodo tre volte, nove esecuzioni in totale, il 27 ottobre 2026. Lo script è run_llm_html_test.py, e tutti e nove gli output sono pubblicati senza modifiche; il README elenca ogni file. Se non hai mai configurato un modello locale, la nostra guida alla traduzione con LLM locale copre le impostazioni.
Questo è stato un piccolo test su un modello, una coppia di lingue e una pagina. Mostra quali problemi si verificano e come individuarli. Non classifica modelli o strumenti.
Risultato: il markup è sopravvissuto; tre decisioni no
Abbiamo verificato ogni output con check_html_translation.py, un checker che utilizza solo la libreria standard di Python. L'output completo è in check-results.txt, e results.csv contiene una riga per ogni esecuzione.
| Controllo | File intero (3 esecuzioni) | Con istruzioni (3 esecuzioni) | Segmenti (3 esecuzioni) |
|---|---|---|---|
Gli stessi 58 tag nello stesso ordine; ogni href, src, id, class invariato | 3 su 3 | 3 su 3 | 3 su 3 |
Testo con translate="no" mantenuto, il link interno funziona ancora, <library> ancora con escape | 3 su 3 | 3 su 3 | 3 su 3 |
Riga di output di esempio all'interno di <pre> tradotta | 3 su 3 | 3 su 3 | 0 su 3 (saltato per design) |
CSS content: "Note: " tradotto | 3 su 3 | 0 su 3 | 0 su 3 (saltato per design) |
JSON-LD name e description tradotti | 3 su 3 | 3 su 3 | 0 su 3 (saltato per scelta) |
aria-label="Breadcrumb" tradotto | 0 su 3 | 0 su 3 | 3 su 3 |
La frase con due elementi inline <code> dice la cosa giusta | 3 su 3 | 3 su 3 | 0 su 3 |
| Spazi tra testo cinese attraverso un tag inline | nessuno | 0, 5 e 4 | 6 in ogni esecuzione |
lang su <html> | zh-CN (non richiesto) | zh-Hans | zh-Hans (impostato dallo script) |
Ognuna delle nove esecuzioni ha mantenuto gli stessi 58 tag nello stesso ordine, ogni href, src, id e class, la destinazione del link interno alla pagina, il commento, il <library> con escape e il nome del prodotto dentro translate="no". Se temevate che un modello potesse rovinare il markup di una pagina semplice, non è successo. I problemi riguardavano tutti cosa tradurre.
1. L'output di esempio dentro <pre> è stato tradotto
Il blocco di codice nel nostro esempio termina con una riga di output del programma:
<pre><code>shelfmark export --format epub --covers --out ~/Books/export
# Export finished: 128 books</code></pre>
In tutte e sei le esecuzioni complete e con istruzioni, il modello ha restituito # 导出完成:128 本书 su quella riga, comprese le tre esecuzioni in cui il prompt diceva di non modificare nulla dentro <pre>. Il comando stesso non è mai stato toccato. Il modello ha trattato la riga come un commento, e tradurre i commenti è una scelta ragionevole in un tutorial. Ma questa riga è ciò che il programma stampa, e un lettore che la confronta con il proprio terminale vedrà l'inglese. Decidete prima di tradurre se l'output di esempio e i commenti del codice vanno tradotti, e ditelo allo strumento, oppure proteggete completamente i blocchi <pre>.
Le esecuzioni complete hanno anche tradotto il content: "Note: " CSS nel blocco <style>, mentre le esecuzioni con istruzioni, a cui era stato detto di lasciare stare <style>, lo hanno mantenuto in inglese. Nessuna delle due è sbagliata di per sé. Tradurre il foglio di stile è corretto per una pagina in cui il CSS è inline, e sbagliato per un sito in cui un unico foglio di stile condiviso serve tutte le lingue. In ogni caso, è una decisione che qualcuno deve prendere, non un dettaglio che un modello dovrebbe indovinare.
2. Le etichette di accessibilità sono state saltate
La navigazione breadcrumb è <nav aria-label="Breadcrumb">. Uno screen reader annuncia quell'etichetta; i lettori vedenti non la vedono mai. In tutte e sei le esecuzioni complete e con istruzioni, è rimasta in inglese, anche se il prompt con istruzioni elencava aria-label tra gli attributi da tradurre. In un'esecuzione con istruzioni, anche l'aria-label="Search" del pulsante di ricerca è rimasto in inglese.
Il metodo a segmenti lo ha tradotto ogni volta, perché il suo script raccoglieva ogni valore di aria-label, alt, title e placeholder e li richiedeva esplicitamente uno per uno. Questo è l'argomento più forte a favore dell'estrazione intenzionale degli attributi di testo, invece di sperare che il modello se ne accorga.
3. Tradurre i frammenti ha preservato i tag ma ha spezzato la frase
Il metodo a segmenti è sicuro per il markup per costruzione: il modello non vede mai un tag, quindi non può danneggiarlo. Ha superato ogni controllo strutturale in tutte e tre le esecuzioni. Ha anche prodotto l'unica traduzione del test che ha dato al lettore istruzioni sbagliate.
La frase inglese è "Type the path to the <library> folder after --out." Il codice inline <code> la divide in tre frammenti: "Type the path to the", "folder after" e un punto. Il cinese dispone queste parole in un ordine diverso, quindi un traduttore deve spostare i due elementi di codice. Il metodo a segmenti non può spostarli. Tutte e tre le esecuzioni hanno invertito l'istruzione. L'esecuzione 2 ha prodotto questo (le esecuzioni 1 e 3 dicono 后 invece di 之后, con lo stesso significato):
在 <code><library></code> 之后输入 <code>--out</code>文件夹的路径。
Si legge "dopo <library>, digita il percorso della cartella --out", l'inverso dell'istruzione. Tutte e sei le esecuzioni a file intero e con istruzioni hanno spostato gli elementi di codice e hanno fatto la cosa giusta:
在 <code>--out</code> 后面输入 <code><library></code> 文件夹的路径。
La stessa suddivisione ha lasciato spazi indesiderati dove un tag incontra il testo cinese, come 前往 <b>设置</b> e <b>书库</b> ,, in tutte e tre le esecuzioni a segmenti, sei punti per esecuzione. Un browser li mostra come spazi visibili, anche prima della punteggiatura cinese. Le esecuzioni a file intero non ne avevano; due delle tre esecuzioni con istruzioni ne avevano quattro o cinque.
Un controllo strutturale non può individuare la frase invertita, perché ogni tag è esattamente dove era. Il nostro controllo segnala quando il codice inline cambia ordine, cosa normale per molte lingue, ma quell'avviso non distingue giusto da sbagliato. In questo test è scattato su tutte e sei le traduzioni corrette ed è rimasto silenzioso sulle tre sbagliate, perché quelle sbagliate mantenevano l'ordine inglese. Solo una persona che legge la frase può capirlo. La soluzione è inviare al traduttore frasi intere, con i loro tag inline, come hanno fatto le esecuzioni a file intero, e controllare la struttura dopo.
Differenze minori
lang: le esecuzioni a file intero l'hanno cambiato inzh-CNda sole. Le esecuzioni con istruzioni hanno usatozh-Hans, come richiesto. Entrambi sono tag di lingua validi;zh-Hansindica la scrittura (cinese semplificato),zh-CNindica una regione. La guida sulle dichiarazioni di lingua del W3C raccomanda di dichiarare la lingua sull'elemento<html>e non con un meta tagContent-Language.- JSON-LD: le esecuzioni a file intero e con istruzioni hanno tradotto i valori
nameedescriptione mantenuto il JSON valido. Il nostro script a segmenti ha saltato il contenuto di<script>, quindi i suoi dati strutturati sono rimasti in inglese, che è anche il comportamento di uno strumento che ignora gli script. - Riferimenti a caratteri: le esecuzioni a file intero e con istruzioni hanno mantenuto
›, ,©e il riferimento all'emoji così come scritti. Cinque di quelle sei esecuzioni hanno riscritto l'intervallo2–5in parole cinesi (2 到 5 o 2 至 5); un'esecuzione con istruzioni ha scritto un trattino semplice invece del riferimento, anche se il suo prompt diceva di mantenere i riferimenti. Il nostro script a segmenti li ha decodificati tutti e ha riscritto i caratteri, il che si visualizza allo stesso modo. Quello che conta,<library>dentro<code>, è rimasto con escape in tutte e nove le esecuzioni.
Prima di tradurre: preparare il file
- Contrassegna ciò che non deve cambiare. Metti
translate="no"sui nomi di prodotto, i numeri di modello, le stringhe simili a codice nel testo e qualsiasi altra cosa che deve restare com'è. Fa parte di HTML, non costa nulla e il modello l'ha rispettato in tutte e sei le esecuzioni che gli hanno inviato il file intero. Gli strumenti a segmenti che lo leggono, come il nostro script, saltano del tutto quegli elementi. La nostra guida su cosa non tradurre spiega come decidere cosa mettere in quella lista. - Decidi la politica per il codice. I commenti al codice vanno tradotti? L'output di esempio? Il foglio di stile è condiviso tra le lingue? Scrivi la risposta, insieme ai nomi che non devono cambiare, in un glossario di traduzione e dallo a chi o a ciò che traduce.
- Mantieni gli ID nella lingua di origine. I link interni alla pagina puntano a valori
id. Se qualcuno traduce unid, ogni link a esso si rompe. Nessuna delle nostre esecuzioni l'ha fatto, ma un traduttore che localizza "per aiutare" le ancore lo farà. - Raccogli il testo nascosto. Elenca gli attributi che contengono parole,
alt,title,placeholder,aria-label,valuesui pulsanti, i meta tag e JSON-LD, così vengono controllati e non dimenticati. - Non tradurre le stringhe JavaScript sul posto. I messaggi impostati da uno script, come un avviso o l'etichetta di un pulsante creata nel codice, richiedono un passaggio di localizzazione separato nel codice. Nessuna delle sei esecuzioni a file intero o con istruzioni ha modificato il nostro blocco script, il che è corretto, ma significa che quelle stringhe restano in inglese.
Dopo aver tradotto: controllare
-
Esegui il controllo strutturale.
python3 check_html_translation.py source.html translated.html --lang zh-Hans --keep ShelfmarkConfronta i tag e il loro ordine, ogni attributo che non è testo rivolto al lettore, il contenuto di
<pre>,<script>e<style>, il codice inline, le chiavi JSON-LD, il testo contranslate="no", i commenti e i link interni alla pagina. Avverte degli attributi di testo ancora in inglese, di un valorelangdiverso da quello atteso, di testo visibile che sembra non tradotto, di codice inline che ha cambiato ordine e di spazi tra testo cinese, giapponese o coreano attraverso un tag inline. Non giudica la qualità della traduzione. -
Leggi ogni frase che contiene un tag inline. È qui che il significato si è rotto nel nostro test. Non affidarti all'avviso "codice inline riordinato" del controllo per trovare queste frasi: nel nostro test, le traduzioni sbagliate erano quelle che mantenevano l'ordine originale.
-
Apri la pagina in un browser. Clicca i link interni alla pagina, passa tra i campi del modulo con un lettore di schermo se puoi e cerca spazi vuoti attorno al testo in grassetto e ai link.
-
Per le lingue da destra a sinistra, imposta anche
dir="rtl"sull'elemento<html>. La nostra guida alla traduzione di libri RTL spiega cos'altro cambia. -
Per XHTML, come i file dei capitoli dentro un EPUB, conferma anche che il file sia ancora XML ben formato, per esempio con
xmllint --noout chapter.xhtml. Un browser perdona un tag non chiuso; un e-reader potrebbe non farlo. La nostra checklist di QA per la traduzione EPUB copre il resto di un ebook.
Dove si inserisce BookTranslator
La pagina di caricamento di BookTranslator accetta file .html, .htm e .xhtml insieme a libri e documenti, quindi puoi caricare una pagina salvata o un articolo di aiuto statico come file unico. Non abbiamo eseguito questo esempio tramite BookTranslator per questo articolo e non abbiamo testato come gestisce l'ordine del codice inline, il contenuto CSS o JSON-LD, quindi controlla il suo output allo stesso modo in cui controlleresti quello di qualsiasi altro strumento. Vedi il prezzo prima di pagare.
Qualunque strumento tu usi, esegui i passaggi di preparazione prima di tradurre e i controlli dopo. Una pagina con tutti i tag intatti può comunque dire al lettore di digitare la cosa sbagliata. Se il tuo HTML è in realtà documentazione scritta in Markdown, la nostra guida alla traduzione Markdown tratta il formato di origine.
Ottieni i file di test
Tutto ciò che riguarda questo test è liberamente riutilizzabile:
- sample-source.html: il campione inglese di 59 righe;
- check_html_translation.py: il verificatore strutturale (solo libreria standard Python);
- run_llm_html_test.py: i tre metodi, per qualsiasi server locale compatibile con OpenAI;
- i nove output nella cartella outputs, con check-results.txt e results.csv.
Post Correlati





