BookTranslator
BookTranslator

Come tradurre un file di lingua JSON senza rompere chiavi o segnaposto

Scopri quali valori in un file en.json vengono tradotti, cosa riscrive un traduttore di file (commenti, ordine delle chiavi, ID lunghi) e come verificare segnaposto, plurali ICU e chiavi con uno script gratuito e un file di test.

BookTranslator

BookTranslator Team

13 min di lettura

Per tradurre un file di lingua JSON come en.json, affida l'intero file a un traduttore che comprenda il JSON. Incollare il testo grezzo in una finestra di chat o in un traduttore web è il modo più rischioso. Un traduttore consapevole del JSON legge il file, traduce solo i valori testuali e riscrive le stesse chiavi, così la tua app può ancora caricare il file. Copiare e incollare può tradurre una chiave, cambiare un segno di citazione o perdere una parentesi graffa. Ognuna di queste cose rompe il file.

Mantenere le chiavi è la parte facile. La maggior parte dei problemi arriva dopo: un segnaposto {name} che torna come {nom}, un plurale ICU che perde il caso other, un URL inviato per la traduzione come qualsiasi altro testo e alcune modifiche che il traduttore apporta al file stesso. Questo è ciò che copre questa guida.

Abbiamo creato un file di test con ognuno di questi casi e scritto un verificatore gratuito che confronta un file sorgente con la sua traduzione. Abbiamo anche eseguito il file di test attraverso una copia locale del codice di parsing e scrittura JSON utilizzato da BookTranslator, con un marcatore al posto di un modello, così puoi vedere esattamente quali valori vengono inviati e come ritorna il file.

Risposta rapida: cosa succede a ogni parte del file

Parte del fileEsempio dal nostro testCosa fa BookTranslatorCosa controllare
Chiavi"greeting", "error"Mantenute così come sonoNiente
Valori di testo semplice"Reading list"TradottiSignificato, lunghezza sullo schermo
Valori con segnaposto"Welcome back, {name}!", "Saved %s of %d chapters"Tradotti, segnaposto inclusi nel testo inviatoNomi e conteggi dei segnaposto (lo fa il verificatore)
Messaggi plurali ICU"{count, plural, one {# book} other {# books}}"Inviati come un'unica stringaIl caso other e le categorie plurali per la lingua di destinazione
HTML inline"accept the <b>Terms</b>."Tradotto; il conteggio dei tag viene verificato dopo la traduzioneNomi e conteggi dei tag (lo fa il checker)
URL memorizzati come testo"https://example.com/help"Inviati per la traduzioneChe è tornato invariato
Valori senza lettere"2.4.1", "—", ""Lasciati come eranoNiente
Numeri, true/false, null20, trueLasciati come eranoID molto grandi (vedi sotto)
Array di stringhe["Open", "Save", "Export as EPUB"]Tradotti nel file tradotto; lasciati non tradotti nel file bilingueIl file bilingue, se lo usi
Commenti (JSONC)// Shown on the home screenRimossi. Se un valore contiene anche //, il file può non caricarsiRimuovi i commenti prima del caricamento

Il resto di questa guida mostra da dove viene ogni riga e cosa fare al riguardo.

Passo 1: Controlla il file sorgente prima di caricarlo

Esegui il checker sul file che intendi tradurre. Richiede Python 3 e nient'altro:

python3 check_i18n_json.py en.json

Sul nostro file di test ha stampato:

WARN  limits.projectId: 9007199254740993 is above 2^53 and can change in a JavaScript round trip; store IDs as strings
WARN  error.network: a flat key with dots and a nested key resolve to the same dot path; tools that address strings by dot path can mix them up
INFO  (root): 3 keys look like integers; JavaScript sorts those first and in numeric order when it rewrites the object
INFO  source: 17 strings, 2 numbers

I due avvisi e la nota sulle chiavi simili a interi corrispondono ciascuno a una modifica che abbiamo visto quando il nostro file di test è passato attraverso il traduttore. Se il tuo file non ne riceve nessuno, puoi passare al Passo 3.

Il checker rifiuta anche un file che non è JSON rigoroso, come uno con commenti o virgole finali, perché quello è il problema successivo.

Cosa è tornato dal nostro file di test

Il test è stato eseguito il 2 novembre 2026, sulla gestione JSON attuale nel backend di BookTranslator. Invece di chiamare un modello, il test ha sostituito ogni valore che sarebbe stato inviato per la traduzione con [ZH] più il testo originale. Questo mantiene il risultato prevedibile: qualsiasi cosa con [ZH] davanti è stata inviata, qualsiasi cosa senza non lo è stata. Entrambi gli output sono pubblicati: il file tradotto e il file bilingue.

Il file tradotto

Ogni chiave è tornata invariata e il file è stato comunque analizzato correttamente. Sono state inviate le stringhe contenenti lettere, inclusi {name}, %s, il messaggio ICU, il tag <b> e l'URL della guida. La stringa di versione "2.4.1", il trattino e la stringa vuota non sono stati inviati, perché non contengono lettere. Numeri e valori booleani sono rimasti invariati.

Sono cambiate altre quattro cose:

  1. Una stringa è finita nella chiave sbagliata. Nel nostro test, il file aveva una chiave piatta "error.network" con il testo "Check your connection." e anche una chiave annidata "error": { "network": "Network error" }. Il traduttore identifica ogni stringa tramite il suo percorso con i punti tra le parti, quindi entrambe le stringhe avevano lo stesso indirizzo, error.network. Nell'output, entrambe le chiavi contenevano la traduzione di "Network error". "Check your connection." era scomparso. Questo richiede entrambi gli stili nello stesso file, cosa rara, ma fallisce silenziosamente. Il verificatore avvisa prima del caricamento.
  2. Le chiavi simili a numeri interi sono state riordinate. "steps": { "10": ..., "2": ..., "1": ... } è tornato come "1", "2", "10". JavaScript elenca sempre per prime le chiavi simili a numeri interi, in ordine numerico, quando ricostruisce un oggetto. Le chiavi e i valori corrispondono ancora, quindi la tua app funziona, ma un diff rispetto al file di origine sarà rumoroso.
  3. Un ID grande ha perso precisione. 9007199254740993 è tornato come 9007199254740992. JavaScript memorizza i numeri come virgola mobile a 64 bit e gli interi superiori a 2^53 non possono essere tutti rappresentati esattamente (MDN su Number.MAX_SAFE_INTEGER). Memorizza gli ID lunghi come stringhe o tienili fuori dal file di lingua.
  4. La formattazione è stata riscritta. L'output usa un'indentazione di due spazi e termina con un a capo. Se il tuo file di origine usava tabulazioni o quattro spazi, aspettati modifiche agli spazi bianchi nel diff.

Il nostro file di test non aveva chiavi duplicate, ma vale la pena conoscerle: il parser JSON di JavaScript mantiene solo l'ultimo valore per una chiave ripetuta, quindi il testo precedente non viene mai tradotto. La tua app caricherebbe lo stesso ultimo valore, quindi nulla di visibile si rompe, ma il verificatore elenca le chiavi duplicate in modo che tu possa ripulirle.

Il file bilingue

Il file bilingue mantiene ogni valore originale e aggiunge una chiave gemella con _translated alla fine:

"greeting": "Welcome back, {name}!",
"greeting_translated": "[ZH] Welcome back, {name}!",

Funziona bene per la revisione, perché l'originale e la traduzione sono affiancati. Non è un file che la tua app può caricare, perché ogni chiave ora ha un gemello. Usa il file tradotto nella tua app.

Una lacuna: le stringhe all'interno degli array non ricevono un gemello _translated, perché gli elementi dell'array non hanno una chiave a cui aggiungerlo. Nel nostro test, "menu": ["Open", "Save", "Export as EPUB"] è tornato in inglese nel file bilingue, ma tradotto nel file tradotto. Se revisioni dal file bilingue, controlla gli array nel file tradotto.

File con commenti

Molti progetti mantengono commenti nei file di lingua (JSONC), cosa che il JSON rigoroso non consente. Il traduttore prova prima il JSON rigoroso. Se fallisce, rimuove i commenti e le virgole finali e riprova. Rimuovere i commenti significa eliminare tutto ciò che segue // su una riga, incluso il // in https://.

Il nostro file con un commento e un URL non è stato caricato affatto; l'analisi è fallita al primo commento. Un file con commenti ma senza // all'interno di alcun valore è stato caricato correttamente e i commenti sono stati rimossi dall'output.

Quindi: se il tuo file contiene commenti, rimuovili prima di caricarlo, oppure conserva una copia con i commenti e accetta che la traduzione non li avrà.

Passo 2: prepara il file

Puoi risolvere la maggior parte di questi problemi prima di tradurre:

  • Rendilo JSON rigoroso. Rimuovi commenti e virgole finali. Se il tuo strumento di build legge JSONC, conserva il file commentato come origine ed esporta una copia pulita per la traduzione.
  • Usa un solo stile di chiavi. Annida le chiavi oppure appiattiscile con i punti, non entrambi nello stesso file. Se usi i18next, la sua opzione keySeparator controlla come vengono letti i punti nelle chiavi, quindi verifica questa impostazione prima di appiattire qualsiasi cosa.
  • Sposta fuori i dati non testuali. ID, URL, flag di funzionalità e limiti appartengono alla configurazione, non al file di lingua. Se un URL deve rimanere, tienilo, ma aspettati di verificarlo dopo la traduzione. La nostra guida su cosa non tradurre spiega come decidere cos'altro deve rimanere nella lingua originale.
  • Scrivi i segnaposto allo stesso modo ovunque. Uno stile, come {name}, è più facile da verificare rispetto a un mix di {name}, {{name}} e %s.

Passo 3: traduci l'intero file

Carica il file ripulito nel traduttore di documenti di BookTranslator, che elenca .json tra gli altri formati di localizzazione e testo strutturato che accetta. Il prezzo è mostrato prima del pagamento. Al termine dell'attività, la pagina della cronologia offre il file tradotto e il file bilingue come download separati.

Due aspetti del modo in cui il testo viene tradotto influenzano il risultato:

  • Il modello non vede le tue chiavi. Ogni valore viene inviato come segmento numerato, senza il nome della chiave. Se "button.open" e "status.open" dicono entrambi "Open", il modello non ha modo di sapere che uno è un verbo e l'altro un aggettivo. Le stringhe brevi e ambigue sono quelle da controllare a mano.
  • Ogni valore viene tradotto singolarmente. Nulla collega due chiavi, quindi la stessa parola in due punti può tornare in due modi diversi, e una parola che richiede due traduzioni diverse può tornare uguale. Il glossario automatico opzionale di BookTranslator raccoglie nomi, luoghi e termini specialistici e li mantiene coerenti, ma non puoi fornirgli traduzioni fisse tue. Per i termini che devono essere tradotti in un modo esatto, tieni un elenco di termini e controlla quelle stringhe dopo la traduzione; la nostra guida al glossario spiega come pianificarlo.

I tag HTML inline vengono contati dopo la traduzione, e un segmento i cui tag non corrispondono viene ritentato. I segnaposto con parentesi graffe, quelli in stile %s e la sintassi ICU vengono inviati come parte del testo ma non sono controllati allo stesso modo. Esegui il Passo 4 su ogni traduzione.

Se preferisci tradurre con un modello chat o un modello locale, invia solo i valori, mai il file grezzo, e reinseriscili per chiave con uno script. I controlli seguenti valgono in entrambi i casi.

Passo 4: controlla il file tradotto

Confronta la traduzione con il testo di partenza:

python3 check_i18n_json.py en.json fr.json

Per mostrare cosa rileva, abbiamo creato un file francese con errori inseriti ad arte. È fatto a mano, non è output di un modello. Dopo gli stessi avvisi sulla fonte del Passo 1, il checker ha stampato:

ERROR app.greeting: placeholders differ; lost ['name'] extra ['nom']
ERROR app.help_url: urls differ; lost ['https://example.com/help'] extra ['https://example.com/aide']
ERROR app.items: ICU message has no 'other' case
ERROR app.legacy: placeholders differ; lost ['%d'] extra []
ERROR limits.maxFiles: type changed from int to str
ERROR limits.projectId: non-text value changed: 9007199254740993 -> 9007199254740992
INFO  menu[1]: identical to source: 'Save'
INFO  compared 20 source values, 1 unchanged strings

Ognuno di questi si presenterebbe come un bug nell'app: un nome vuoto, un link rotto, un crash o un messaggio grezzo quando viene renderizzato il plurale, un conteggio dei capitoli mancante, un limite confrontato come testo. La riga INFO elenca le stringhe tornate invariate. Alcune vanno bene, come i nomi di marca; "Save" in un menu francese no.

Il checker confronta chiavi, tipi di valore, valori non testuali, segnaposto ({name}, {{name}}, %s, %1$s, %@), nomi degli argomenti ICU, tag HTML e URL. Non giudica la traduzione in sé.

I casi plurali devono cambiare

Un plurale ICU elenca un messaggio per categoria plurale. L'inglese ha due categorie, one e other, ma molte lingue ne hanno un insieme diverso. Una buona traduzione russa del nostro messaggio items userebbe normalmente one, few, many e other, e una giapponese solo other. Quindi una discrepanza qui non è sempre un errore.

Le categorie provengono dalle regole plurali CLDR di Unicode, e other è quella che ogni lingua ha. Queste sono le categorie cardinali riportate da Intl.PluralRules in Node.js con CLDR 48:

LinguaCategorie plurali
Inglese, tedescoone, other
Francese, spagnolo, portogheseone, many, other
Russo, polaccoone, few, many, other
Arabozero, one, two, few, many, other
Giapponese, cinese, coreanoaltro

Il francese, lo spagnolo e il portoghese usano many solo per numeri tondi molto grandi, come un milione, quindi un messaggio per conteggi piccoli di solito può farne a meno. Il verificatore segnala un other mancante come errore e qualsiasi altra modifica nelle categorie come avviso da confrontare con questa tabella. Puoi stampare l'elenco per qualsiasi lingua da solo:

node -e 'console.log(new Intl.PluralRules("ru").resolvedOptions().pluralCategories)'

Al traduttore vengono forniti i casi inglesi, quindi controlla cosa è tornato indietro. Se un messaggio in russo o arabo ha ancora solo one e other, aggiungi i casi mancanti a mano, oppure fallo fare a un traduttore.

Poi caricalo nell'app

Il verificatore dimostra che il file è sicuro da caricare, non che si legga bene. Passa l'app alla nuova lingua e guarda le schermate: parole lunghe in tedesco o finlandese che escono da un pulsante, testo da destra a sinistra in arabo o ebraico, e date o numeri che il tuo codice formatta separatamente dal file di lingua. La nostra guida alla traduzione versus localizzazione illustra cos'altro cambia tra i mercati oltre alle parole.

Problemi comuni

Il file tradotto non si carica nella mia app. Esegui il verificatore su di esso. Se il verificatore non riesce ad analizzarlo, il file è stato modificato dopo la traduzione o non era valido fin dall'inizio. Se viene analizzato, cerca le righe ERROR relative a chiavi o tipi.

Una stringa appare come messaggio ICU grezzo, tipo {count, plural, ...}. La sintassi ICU si è rotta durante la traduzione, di solito per una parentesi graffa mancante o un caso other mancante. Copia la struttura dall'originale e traduci solo le parole all'interno di ogni caso.

Il mio file è YAML, un file .po o Markdown. BookTranslator accetta anche questi, ma ogni formato ha le sue regole. Per la documentazione, consulta la nostra guida alla traduzione Markdown; per le pagine web, la guida ai file HTML.

Posso tradurre solo le nuove chiavi? Non all'interno di un singolo caricamento; viene tradotto l'intero file. Metti le nuove chiavi in un file separato, traducilo e unisci il risultato per chiave. Il verificatore confermerà che il file unito contiene tutte le chiavi.

Devo tradurre le chiavi? No. Le chiavi sono identificatori che il tuo codice cerca. Solo i valori sono testo destinato alla lettura delle persone.

Post Correlati

Come tradurre un file di lingua JSON senza rompere chiavi o segnaposto