Structured PO catalog converter
Convert UTF-8 gettext PO and structured JSON while preserving context, plural indices, headers, comments, previous values and obsolete entries.
- 1Add input
- 2Adjust settings
- 3Get your result
Tool input and files are processed in this browser without being uploaded.
Before you start
Move a translation catalog through an explicit record model without flattening its meaning. Review active and obsolete entries, edit indexed translations, and regenerate a readable PO file.
How to use this tool
- Choose PO → JSON or structured JSON → PO and open one local UTF-8 catalog.
- Review context, plural forms, comments and obsolete state in JSON; retain all six fields when editing an entry.
- Download catalog.json and catalog.po, then validate them in the receiving gettext workflow.
Supported inputs and limits
One UTF-8 PO/JSON file or pasted source up to 1 MiB. At most 10,000 entries, 100,000 physical PO lines and 100 contiguous translation indices per entry. Generated PO is bounded to 4 MiB. Selected file takes precedence; BOM is omitted and generated PO uses LF with canonical quoted/multiline strings. JSON parsing also has a 200,000-node and depth-128 budget.
JSON must use schema neatbo-po-v1, encoding UTF-8, entries and trailingComments. Each entry has context, msgid, plural, translations, comments and obsolete. Context null differs from an empty context. Singular translations use key 0; plural indices begin at 0 and are contiguous. Duplicate active/obsolete identities and unknown schema fields reject.
Preserves the header entry and its translation text, translator/extracted/reference/flag/previous comment lines, obsolete records and trailing comments. Does not flatten to a msgid dictionary, preserve original wrapping/spacing, compile MO, translate or evaluate plural formulas. A declared nplurals is checked for active plural form counts only.
Strict UTF-8 input and declared UTF-8 charset only; other charsets reject. PO uses unindented declarations and C string escapes for quotes/backslashes, common controls and UTF-8 byte octal/hex escapes. Unknown escapes, NUL, malformed quotes, missing msgstr and comments inside an unfinished entry reject. JSON/PO downloads retain complete records; the table/CSV summarize entries, not every translation.
Worked example
Example input
# catalog comment msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. extracted comment #: app.ts:1 other.ts:2 #, fuzzy, c-format #| msgctxt "old-menu" #| msgid "old file" msgctxt "menu" msgid "%d file" msgid_plural "%d files" msgstr[0] "%d 个文件" msgstr[1] "%d 个文件" # obsolete comment #~| msgid "older" #~ msgctxt "old" #~ msgid "gone" #~ msgstr "旧" # trailing catalog comment
Example options
{"params": {"direction": "po-to-json"}}Example output
{
"schema": "neatbo-po-v1",
"encoding": "UTF-8",
"entries": [
{
"context": null,
"plural": null,
"translations": {
"0": "Content-Type: text/plain; charset=UTF-8\nPlural-Forms: nplurals=2; plural=(n != 1);\n"
},
"comments": [
"# catalog comment"
],
"obsolete": false,
"msgid": ""
},
{
"context": "menu",
"plural": "%d files",
"translations": {
"0": "%d 个文件",
"1": "%d 个文件"
},
"comments": [
"#. extracted comment",
"#: app.ts:1 other.ts:2",
"#, fuzzy, c-format",
"#| msgctxt \"old-menu\"",
"#| msgid \"old file\""
],
"obsolete": false,
"msgid": "%d file"
},
{
"context": "old",
"plural": null,
"translations": {
"0": "旧"
},
"comments": [
"# obsolete comment",
"#~| msgid \"older\""
],
"obsolete": true,
"msgid": "gone"
}
],
"trailingComments": [
"# trailing catalog comment"
]
}When something does not work
Use the complete exported schema and repair missing or duplicate fields/indices. Convert non-UTF-8 catalogs explicitly before opening them. Fix malformed quoting or unsupported escapes; separate comments from unfinished entries. Reduce catalog size if a budget is exceeded.
Frequently asked questions
Can I use a flat translation JSON object?
No. It cannot represent context, indexed plural forms and obsolete state faithfully; use the exported record schema.
Does it evaluate Plural-Forms?
No. The expression stays in the header. Only an explicitly declared nplurals count is checked against active plural translations.
Will the output look byte-for-byte like the source?
No. Field values and comment lines are preserved, but PO quoting, multiline layout, blank spacing and line endings are canonicalized.
Documentation & further reading
Related tools
JSON formatting workspace
Format or minify strict JSON, sort object keys, and encode or decode strings while preserving raw number tokens.
Regex tester
Try a pattern and see what it matches in your text.
Compare text
See what changed, side by side.
HTML formatter
Format HTML indentation so its structure is easier to read.