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 with native Intl.PluralRules
- Runs everywhere — Node.js, Bun, browsers, edge runtimes, and build tools
- Lightweight — Zero dependencies, ~11KB gzipped, tree-shakeable to ~5KB
Features
Core
- Parse PO Files — Read PO files from strings, 20× faster than pofile, 7× faster than gettext-parser
- Serialize PO Files — Convert PO data back to strings, 2.5× faster than pofile, 5× faster than gettext-parser
- Full PO Support — Headers, comments, flags, plurals, and message context
i18n Toolkit
- CLDR Plural Rules — Uses native
Intl.PluralRules, zero bundle size for CLDR data - ICU MessageFormat — Convert between Gettext plurals and ICU syntax
- ICU Parser — Parse ICU v1 messages, 5× faster and 4× smaller than FormatJS
- ICU Compiler — Compile ICU to JavaScript functions, 4× faster at runtime
- Plural Helpers — Get categories, counts, and selector functions for any locale
- Extended Intl Formatters — Lists, durations, relative times, and display names built-in
Format Styles
- 50+ Built-in Styles — Common patterns like
compact,percent,bytes,iso,relativeready to use - Custom Styles — Register your own
Intl.NumberFormat,DateTimeFormat,ListFormatoptions - Dynamic Currency — Currency code read from message values at runtime
- Factory Pattern —
createIcuCompiler()for pre-configured, reusable compilers
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 | 209 ops/s | 256 ops/s |
| gettext-parser | 28 ops/s | 54 ops/s |
| pofile | 8 ops/s | 100 ops/s |
→ 20× faster parsing vs pofile, 7× faster vs gettext-parser
ICU MessageFormat Parsing
Realistic messages with plurals, selects, nested structures, and tags:
| Library | Speed | Bundle (gzip) |
|---|---|---|
| pofile-ts | 5× faster | <3KB |
| @formatjs/icu-messageformat-parser | baseline | ~9KB |
→ 5× faster, 4× smaller bundle
ICU Compilation & Runtime
| Metric | pofile-ts | vs intl-messageformat | vs @lingui (compiled) |
|---|---|---|---|
| Compilation | 409k op/s | 7× faster | — |
| Runtime | 792k op/s | 3× faster | 4× faster |
| Catalog (200) | ~1.35M/s | 7× faster | — |
→ 4× faster at runtime vs Lingui and FormatJS
Bundle Size
The full library is ~11KB gzipped. Tree-shaking lets you import only what you need:
| Export | Gzipped |
|---|---|
| PO parsing | ~5KB |
| Plural helpers | ~1KB |
| ICU conversion | ~2KB |
| ICU parser | ~3KB |
Plural helpers use native Intl.PluralRules — no CLDR data in the bundle.