To translate a JSON language file, upload the source, name the target language and translate the text values. Start with a small file in the free JSON translator, then check the returned file in your app. You can download the example used here.
This guide is for app strings, such as locales/en.json. If your file contains a product catalogue or API records, decide which fields are human-readable text before applying the same workflow. An identifier stored as a string is still an identifier.
Try these six strings first
The sample contains a checkout screen and two settings labels:
{
"checkout": {
"title": "Your order",
"greeting": "Hello, {{name}}",
"pay": "Pay now",
"support": "Contact Pinecart support"
},
"settings": {
"language": "Language",
"notifications": "Email notifications"
}
}
Upload it to the JSON tool and enter:
Translate every text value into French.
Keep Pinecart in English and preserve {{name}} exactly.
The free tool accepts files up to 2 MB, five per day, and translates up to 5,000 words per file. Larger files return complete, with the remaining text unchanged. That makes the download usable as a sample, but it is not a fully translated locale. Use the app for a complete large file, a workspace glossary and repeat releases.
Know which parts belong to your app
The application calls checkout.title; your reader sees its value. The name variable is filled at runtime. Both have to survive a language change.
"title": "Your order","title": "Votre commande","greeting": "Hello, {{name}}","greeting": "Bonjour, {{name}}","pay": "Pay now""pay": "Payer maintenant"AI Glot reads JSON as a structure and writes it back with two-space indentation. A diff may therefore include whitespace changes. Review the values separately from formatting.
Name your placeholder convention. The example uses i18next-style {{name}}. Other projects use {name}, %s or ICU messages. Copy a real string from your app when writing the instruction. Don’t convert one convention into another during translation.
Check the plan before a large job
- 1UploadThe English source file
- 2Set the scopeTarget language and excluded keys
- 3Read the planCheck words, scope and cost
- 4TranslateUse the glossary and wording rules
- 5ValidateReview the file and the app
For recurring releases, use a workspace glossary for product terms and feature names. Scope instructions decide which values are translated; wording rules decide how each value is written.
A source-only en.json does not say which French labels were translated last month. Asking it to “translate only the missing French strings” provides no French file to compare against. Exclude known key prefixes, or prepare source and target fields together and check the plan’s interpretation. The app language file guide covers the broader workflow and other formats.
Run a structural check before committing
Save the download as fr.json alongside en.json. Copy this into check-locale.mjs and run node check-locale.mjs with Node.js. It checks nested object keys, array lengths, value types, unchanged non-text values and the sample’s double-brace placeholders.
import { readFileSync } from 'node:fs';
import assert from 'node:assert/strict';
const source = JSON.parse(readFileSync('en.json', 'utf8'));
const target = JSON.parse(readFileSync('fr.json', 'utf8'));
const tokens = text => [...text.matchAll(/\{\{[^{}]+\}\}/g)]
.map(match => match[0]).sort();
function check(a, b, path = '$') {
assert.equal(typeof b, typeof a, `${path}: value type changed`);
if (a === null || typeof a !== 'object') {
if (typeof a === 'string') {
assert.ok(b.trim().length || !a.trim().length,
`${path}: translation is empty`);
assert.deepEqual(tokens(b), tokens(a),
`${path}: placeholders changed`);
} else {
assert.deepEqual(b, a, `${path}: non-text value changed`);
}
return;
}
assert.equal(Array.isArray(b), Array.isArray(a),
`${path}: container type changed`);
assert.ok(b !== null, `${path}: container is null`);
if (Array.isArray(a)) {
assert.equal(b.length, a.length, `${path}: array length changed`);
}
assert.deepEqual(Object.keys(b).sort(), Object.keys(a).sort(),
`${path}: keys changed`);
for (const key of Object.keys(a)) check(a[key], b[key], `${path}.${key}`);
}
check(source, target);
console.log('Keys, types and {{placeholders}} match. Review the wording next.');
This validates a contract, not translation quality. A value left in English still passes. So can a translation that is grammatically wrong or too long for its button. The token rule covers {{name}}, not every placeholder format; adapt it to your application’s syntax.
For i18next JSON v4, plural variants use language-specific suffixes and your calls supply a count. Prepare and test the keys your target locale needs. This key-equality check deliberately rejects a changed key set; it does not generate or validate a new plural inventory.
Finish inside the application
Point your app’s existing French locale loader at fr.json. Open the checkout, interpolate a real name and check the longest button at the smallest supported screen width. If you use plurals, test counts that exercise each target-language form.
For a small file, a careful manual pass may be enough. For thousands of strings every release, keep the source file, the glossary, this structural check and the UI review in the same workflow. The app localization solution explains where AI Glot fits when several people maintain that process.
