Skip to main content

Convert CSV to JSON (i18next) — dotted keys become nested objects, deterministic ordering

Free CLI to convert translator-friendly CSV spreadsheets into i18next-style nested JSON. Expands dotted keys into objects and sorts output for clean diffs.

Free CLI — convert csv files to i18next:

npm install -g @i18n-agent/i18n-convert
Need to translate, not just convert? Try i18nagent.ai MCP →

CSV is what your translators actually hand back: it opens in Google Sheets, in Excel, in LibreOffice, and it gives non-engineers a sane editing surface for thousands of keys. JSON (in the i18next-style nested shape) is what your web app consumes. Going from the translator's spreadsheet to the runtime bundle is therefore a daily operation in any team that doesn't run a TMS — and it's where most ad-hoc Python scripts get the structural detail wrong. CSV is flat; i18next JSON is nested. A key like app.title in the spreadsheet has to expand into {"app": {"title": "..."}} in JSON, or the namespacing logic in your client breaks. Quoting rules also differ: CSV escapes embedded commas and quotes with doubled-up "", while JSON uses backslash escapes.

i18n-convert reads the CSV with the first column as the key, the second column as the English value (the source-language convention used by all the major translator handoff templates), splits dotted keys on . to produce nested JSON objects, and sorts every level of the resulting tree alphabetically for deterministic output. Deterministic ordering matters more than it sounds: it makes diffs reviewable when a translator hands back a new column or an updated value, and it eliminates the noisy "the JSON output reshuffled itself" PRs that hand-rolled scripts produce. The fixture below is no_comments.csv from the test suite — three entries including a dotted key app.title that expands into a nested app object in the output.

Command

i18n-convert no_comments.csv --to i18next -o messages.json

Input

key,en
greeting,Hello
farewell,Goodbye
app.title,My App

Output

{
  "app": {
    "title": "My App"
  },
  "farewell": "Goodbye",
  "greeting": "Hello"
}

Related conversions