npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pofile-ts

v4.0.3

Published

Parse and serialize Gettext PO files.

Readme

CI Coverage npm version npm downloads Bundle Size Tree Shakeable Node 20+ Bun

pofile-ts is a modern i18n toolkit for GNU gettext PO files. Not just a parser — includes an ICU compiler with 3-4× faster runtime than Lingui/FormatJS, native CLDR plural rules, and format conversion helpers. Zero dependencies. TypeScript-first. Built for Node 20+, Bun, and modern browsers.

Why pofile-ts?

  • 20× faster parsing — Hand-optimized with first-char dispatch and fast-paths. No regex soup.
  • ICU Compiler — Compile ICU messages to JavaScript functions. 3-4× faster runtime than Lingui and FormatJS.
  • Native CLDR plurals — Uses Intl.PluralRules for all 100+ locales. Zero CLDR data in bundle.
  • CSP-safe — No eval(), no new Function(). Works in strict security environments.
  • Modern-first — Built for Node 20+, ESM-native, tree-shakeable. No legacy polyfills.
  • Zero dependencies — ~11KB full, ~5KB tree-shaken. No transitive deps, no supply chain bloat.

Features

Core

  • 📖 Parse PO files from strings — 20× faster than pofile, 7× faster than gettext-parser
  • ✏️ Serialize PO files back to strings — 2.5× faster than pofile, ~4.5× faster than gettext-parser
  • 🎯 Full PO support — headers, comments, flags, plurals, 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 and analyze ICU messages (<3KB gzipped, 5× faster than FormatJS)
  • ICU Compiler — Compile ICU messages to fast JavaScript functions (3-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 stylescompact, percent, bytes, iso, relative, and more
  • 🔧 Custom styles — Register your own Intl.NumberFormat, DateTimeFormat, ListFormat options
  • 💱 Dynamic currency — Currency code read from message values at runtime
  • 🏭 Factory patterncreateIcuCompiler() for pre-configured, reusable compilers

Developer Experience

  • 📦 Zero dependencies — No bloat, no supply chain risk
  • 🌳 Tree-shakeable — ~5KB for PO parsing only, ~11KB full
  • 💎 TypeScript-first — Written in TypeScript, full type definitions
  • 🛡️ CSP-safe — No eval(), no new Function()
  • Modern-first — Node 20+, ESM-native, no legacy polyfills

Use Cases

  • Vite/Webpack plugins — Parse and compile PO files at build time for zero runtime cost
  • TMS pipelines — Crowdin, Lokalise, Phrase — sync and transform translations
  • CI/CD validation — Validate plural forms, variables, and syntax in PRs
  • Custom tooling — Low-level APIs for message extraction and code generation

Installation

npm install pofile-ts

Quick Start

import { parsePo, stringifyPo } from "pofile-ts"

const po = parsePo(`
msgid "Hello"
msgstr "Hallo"
`)

console.log(po.items[0].msgid) // "Hello"
console.log(po.items[0].msgstr) // ["Hallo"]

console.log(stringifyPo(po))

ICU MessageFormat

A fast, lightweight ICU MessageFormat parser — 5× faster and 4× smaller than FormatJS:

import { parseIcu, extractVariables, validateIcu, hasPlural } from "pofile-ts"

// Parse ICU messages into an AST
const result = parseIcu("{count, plural, one {# item} other {# items}}")
if (result.success) {
  console.log(result.ast) // AST with plural node
}

// Extract variables from messages
extractVariables("{name} has {count} messages")
// → ["name", "count"]

// Validate syntax before use
const validation = validateIcu("{gender, select, male {He} other {They}}")
console.log(validation.valid) // true

// Check message structure
hasPlural("{n, plural, one {#} other {#}}") // true
hasPlural("Hello {name}") // false

Supports ICU MessageFormat v1: arguments, plurals, selects, selectordinals, number/date/time formatting, tags, and escaping. Trade-offs for size: no AST location tracking, styles stored as opaque strings.

ICU Compiler

Compile ICU messages to fast JavaScript functions — about 3× faster than intl-messageformat and 4× faster than Lingui at runtime:

import { compileIcu, compileCatalog, generateCompiledCode } from "pofile-ts"

// Compile a single message
const greet = compileIcu("Hello {name}!", { locale: "en" })
greet({ name: "World" }) // → "Hello World!"

// Full ICU support: plurals, select, number/date/time, tags
const msg = compileIcu("{count, plural, one {# item} other {# items}} in <link>cart</link>", {
  locale: "en"
})
msg({ count: 5, link: (text) => `<a>${text}</a>` })
// → "5 items in <a>cart</a>"

// Dynamic currency from values
const price = compileIcu("{amount, number, currency}", { locale: "de" })
price({ amount: 99.99, currency: "EUR" }) // → "99,99 €"
price({ amount: 99.99, currency: "USD" }) // → "99,99 $"

// Custom format styles with full Intl options
const size = compileIcu("{bytes, number, filesize}", {
  locale: "en",
  numberStyles: {
    filesize: { style: "unit", unit: "kilobyte", unitDisplay: "short" }
  }
})
size({ bytes: 512 }) // → "512 kB"

// Compile an entire catalog at runtime
const compiled = compileCatalog(catalog, { locale: "de" })
compiled.format("messageId", { name: "Sebastian" })

// Or generate static code for build-time compilation
const code = generateCompiledCode(catalog, { locale: "de" })
// → TypeScript file with pre-compiled functions

Supports named tags (<link>), numeric tags (<0>, <1> — Lingui-style), and React components (returns array when tag functions return objects).

Extended Intl Formatters

Go beyond standard ICU with built-in support for modern Intl APIs:

import { compileIcu } from "pofile-ts"

// Lists — "Alice, Bob, and Charlie" or "Alice, Bob, or Charlie"
const list = compileIcu("{authors, list}", { locale: "en" })
list({ authors: ["Alice", "Bob", "Charlie"] }) // → "Alice, Bob, and Charlie"

// Relative time — "in 3 days" or "2 hours ago"
const ago = compileIcu("{days, ago, day}", { locale: "de" })
ago({ days: -2 }) // → "vor 2 Tagen"

// Display names — Localized country, language, currency names
const name = compileIcu("{lang, name, language}", { locale: "de" })
name({ lang: "en" }) // → "Englisch"

// Durations — "2 hours, 30 minutes" (Baseline 2025)
const dur = compileIcu("{time, duration, short}", { locale: "en" })
dur({ time: { hours: 2, minutes: 30 } }) // → "2 hr, 30 min"

All formatters use native browser APIs — zero additional bundle size. See browser support.

Documentation

For full documentation including API reference, i18n helpers, and migration guide:

📖 Documentation

Performance

Speed matters for build tools and CI pipelines. pofile-ts is hand-optimized for performance — no regex soup, no unnecessary allocations, just fast parsing.

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

Compiling ICU messages to functions and executing them:

| 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 | — |

3× faster at runtime vs intl-messageformat, 4× faster vs Lingui

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.

All exports are named exports — modern bundlers (Vite, esbuild, Rollup, webpack) automatically tree-shake unused code.

Monorepo Structure

packages/pofile-ts/  # The library (published to npm)
apps/docs/           # Documentation site (Fumadocs)
benchmark/           # Performance benchmarks

Development

pnpm install
pnpm test           # Run tests
pnpm build          # Build library
pnpm docs:dev       # Start docs dev server

Credits

Originally forked from pofile by Ruben Vermeersch. Completely rewritten with modern TypeScript, expanded with CLDR plural support, ICU conversion, and comprehensive i18n helpers.

Maintained by Sebastian Software.

License

MIT — Use it freely in personal and commercial projects.