PO File to JSON Converter
Convert GNU gettext PO translation files to JSON or AMD modules. Supports msgctxt keys, plural forms, multi-file merging, and nested output.
About
GNU gettext .po files remain the dominant interchange format for software localization, yet modern front-end stacks consume JSON. A manual conversion introduces encoding errors, drops plural forms, and silently mishandles multiline msgstr continuations. This tool parses the full PO grammar - including msgctxt disambiguation, msgstr[N] plural indices, and escaped sequences (\n, \t, \") - then emits clean JSON or an AMD-wrapped JavaScript module. All parsing runs locally in your browser. No file is uploaded to any server.
Limitations: the converter assumes UTF-8 encoding. Binary .mo files are not supported. Obsolete entries (prefixed with #~) are intentionally excluded from output. Fuzzy-flagged entries (marked #, fuzzy) are included by default but can be excluded via the option toggle. Pro tip: if your PO file uses msgctxt for key namespacing, enable the "Use msgctxt as key" option to avoid collisions between identical msgid values in different contexts.
Formulas
The converter operates as a line-by-line state machine. Each line is classified by its prefix and the parser transitions between states accordingly.
Continuation lines (lines beginning with a double quote) are appended to whichever directive was active in the previous state. The final JSON key is determined by the mode:
For plural entries, the value becomes an array:
Where key is the lookup identifier and value is the translated content. The header entry (empty msgid) is always excluded from output. When AMD wrapping is enabled, the output becomes: define(function() { return JSON ; });
Reference Data
| PO Directive | Purpose | JSON Mapping | Notes |
|---|---|---|---|
| msgid | Source string (key) | Object key (default mode) | Empty msgid = file header |
| msgstr | Translated string | Object value (string) | Empty msgstr means untranslated |
| msgctxt | Disambiguation context | Used as key when option enabled | Avoids duplicate msgid collisions |
| msgid_plural | Plural source string | Ignored (informational) | Plural source not needed in output |
| msgstr[0] | Singular translation | Array index 0 | Required when plurals present |
| msgstr[N] | Nth plural form | Array index N | Count depends on language |
| # (comment) | Translator comment | Not included in output | Informational only |
| #. | Extracted comment | Not included in output | Auto-generated by xgettext |
| #: | Source reference | Not included in output | File:line location |
| #, | Flags (e.g., fuzzy) | Entry skipped if fuzzy excluded | Comma-separated flags |
| #~ | Obsolete entry | Always excluded | Deprecated translations |
| #| | Previous msgid | Not included in output | Used by tools for diffing |
| \n | Newline escape | Literal newline in value | Common in multiline strings |
| \t | Tab escape | Literal tab in value | Rare but valid |
| \" | Escaped quote | Literal " in value | Required inside quoted strings |
| \\ | Escaped backslash | Literal \ in value | Standard C escape |
| Plural-Forms | Header: plural rule | Not included (header entry) | e.g., nplurals=3; plural=... |
| Content-Type | Header: charset | Not included (header entry) | Should be text/plain; charset=UTF-8 |
| Language | Header: language code | Not included (header entry) | ISO 639-1 code (e.g., fr) |