Gettext PO to JSON Converter
Convert Gettext .po translation files to JSON format online. Supports Jed, mf, and raw formats. No upload needed - runs entirely in your browser.
About
Gettext PO files remain the dominant format for managing translations in GNU-based projects, WordPress plugins, and many PHP frameworks. JSON, however, is the required format for JavaScript i18n libraries such as Jed, i18next, and FormatJS. Manual conversion introduces encoding errors, drops plural forms, and silently corrupts msgctxt scoping. This tool implements a strict line-by-line state machine parser that handles multi-line concatenated strings, plural indices msgstr[n], obsolete entries, and header metadata extraction. It outputs valid JSON in four formats: raw key-value, Jed 1.x, messageformat, and po2json default. All processing runs locally in your browser. No files are uploaded to any server.
Limitation: fuzzy-flagged entries (marked #, fuzzy) are excluded from output by default, matching the behavior of GNU msgfmt --check. PO files referencing external .mo binaries are not supported. The parser assumes UTF-8 encoding. Pro tip: always verify your PO file compiles cleanly with msgfmt -c before converting, as syntax errors in the source propagate silently into malformed JSON keys.
Formulas
The PO parser operates as a finite state machine with states: Sidle, Smsgctxt, Smsgid, Smsgid_plural, Smsgstr. Transitions occur on keyword detection at line start.
For the Jed output format, the compound key is constructed as:
Where msgctxt is the disambiguation context, msgid is the source string, and "\u0004" is the EOT character used as separator per Jed specification. The value for plural entries becomes an array: [msgid_plural, msgstr[0], msgstr[1], …, msgstr[n]].
String unescaping applies the mapping: \n → newline, \t → tab, \\ → backslash, \" → quote.
Reference Data
| PO Directive | Description | JSON Mapping | Example |
|---|---|---|---|
| msgid | Source string (key) | Object key | msgid "Hello" |
| msgstr | Translated string (value) | Object value (string) | msgstr "Hola" |
| msgctxt | Disambiguation context | Compound key: ctx\u0004msgid | msgctxt "menu" |
| msgid_plural | Plural source form | Array value in Jed format | msgid_plural "%d items" |
| msgstr[0] | Singular translation | Array index 0 | msgstr[0] "%d elemento" |
| msgstr[N] | Nth plural form | Array index N | msgstr[2] "%d elementos" |
| #: | Source code reference | Ignored in output | #: src/app.js:42 |
| #. | Extracted comment | Ignored in output | #. Translator note |
| #, | Flags (fuzzy, c-format) | fuzzy → entry skipped | #, fuzzy |
| #~ | Obsolete entry | Excluded from output | #~ msgid "old" |
| "" (empty msgid) | PO header metadata | Parsed for Plural-Forms | "Plural-Forms: nplurals=2;..." |
| Plural-Forms | Header: plural rule | Jed plural_forms field | nplurals=3; plural=(n%10==1 ...) |
| Content-Type | Header: charset | Informational only | text/plain; charset=UTF-8 |
| Language | Header: target language | Jed lang field | Language: es_ES |
| Multi-line strings | Adjacent "..." lines concatenated | Single string value | "line1" + "line2" |
| Format: raw | Simple key → value map | {"Hello": "Hola"} | Flat object |
| Format: jed | Jed 1.x compatible | Nested with domain, locale_data | Array values for plurals |
| Format: jed1.x | Same as jed | Includes header entry | Used by wp-i18n |
| Format: mf | MessageFormat style | Key → string (singular only) | No plural arrays |