Introduction
The fast, modern PO file toolkit for JavaScript
pofile-ts is a complete solution for working with GNU gettext PO files in modern JavaScript and TypeScript projects. Whether you're building translation pipelines, integrating with i18n frameworks like Lingui or FormatJS, or creating custom localization tooling — pofile-ts gives you everything you need.
Why pofile-ts?
- Battle-tested parsing — Handles edge cases, malformed files, and complex escape sequences
- Complete i18n toolkit — Not just a parser: includes CLDR plural rules, ICU conversion, and workflow helpers
- Production-ready — Fully tested against CLDR 48 specification
- Runs everywhere — Node.js, browsers, edge runtimes, and build tools
- Lightweight — Zero dependencies, ~14KB gzipped, tree-shakeable to ~5KB
Features
Core
- Parse PO Files — Read PO files from strings, 8× faster than alternatives
- Serialize PO Files — Convert PO data back to strings, 5× faster than alternatives
- Full PO Support — Headers, comments, flags, plurals, and message context
i18n Toolkit
- CLDR 48 Plural Rules — 100% compliant for all major languages (140+ locales)
- ICU MessageFormat — Convert between Gettext plurals and ICU syntax
- ICU Parser — Parse ICU v1 messages, 2.5× faster and 4× smaller than FormatJS
- ICU Compiler — Compile ICU to JavaScript functions, 6× faster than Lingui at runtime
- Plural Helpers — Get categories, sample numbers, and Plural-Forms headers
Developer Experience
- Zero Dependencies — No bloat, works in browsers and edge runtimes
- Tree-Shakeable — Only bundle what you use (~5KB for parsing only)
- TypeScript-First — Full type definitions, excellent IDE support
- CSP-Safe — No
eval()ornew Function()
Installation
npm install pofile-tsQuick Example
import { parsePo, stringifyPo } from "pofile-ts"
// Parse a PO file
const po = parsePo(`
msgid "Hello"
msgstr "Hallo"
`)
console.log(po.items[0].msgid) // "Hello"
console.log(po.items[0].msgstr) // ["Hallo"]
// Serialize back to string
console.log(stringifyPo(po))Performance
Benchmarked on Apple M1 Ultra, Node.js 22. Relative performance is consistent across different hardware.
PO File Parsing
10,000 entries (~10% plurals):
| Library | Parsing | Serialization |
|---|---|---|
| pofile-ts | 185 ops/s | 217 ops/s |
| gettext-parser | 27 ops/s | 53 ops/s |
| pofile | 8 ops/s | 100 ops/s |
→ 8× faster parsing, 5× faster serialization
ICU MessageFormat Parsing
Realistic messages with plurals, selects, nested structures, and tags:
| Library | Speed | Bundle (gzip) |
|---|---|---|
| pofile-ts | 2.5× faster | ~2KB |
| @formatjs/icu-messageformat-parser | baseline | ~9KB |
→ 2.5× faster, 4× smaller bundle
ICU Compilation & Runtime
| Metric | pofile-ts | vs intl-messageformat | vs @lingui |
|---|---|---|---|
| Compilation | 470k ops/s | 8× faster | — |
| Runtime | 1.2M ops/s | 5× faster | 6× faster |
→ 6× faster than Lingui at runtime (even with pre-compiled AST)
Bundle Size
The library is fully tree-shakeable. Import only what you need:
| Import | Gzipped |
|---|---|
| Full library | ~14KB |
parsePo + stringifyPo only | ~5KB |
| + CLDR plural helpers | +3KB |
| + ICU conversion | +2KB |
| + ICU parser | +3KB |
All exports are named exports — modern bundlers automatically eliminate unused code.