Search by

codinglombok / lomboklocale

codinglombok

BCP 47 negotiation, CLDR 47 plural rules, number/currency/date formatting and an ICU MessageFormat subset with identical results in PHP, Rust, TypeScript, Python and Go. No dependencies.

Package info

github.com/codinglombok/LombokLocale

Language:Rust

pkg:composer/codinglombok/lomboklocale

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.2.0 2026-10-28 06:02 UTC

This package is auto-updated.

Last update: 2026-10-30 07:06:04 UTC


README

BCP 47 tags and negotiation, CLDR 47 plural rules, number/percent/currency and date formatting, an ICU MessageFormat subset, and JSON message catalogs. The same input gives the same text in Rust, TypeScript, Python, Go and PHP. No runtime dependencies.

License CI Vectors CLDR Lombok Ecosystem

Part of the Lombok Ecosystem.

Mengapa library ini? (Why this library?)

  • The same text everywhere. Intl in browsers, ICU in PHP, Babel in Python and hand-written code in Go each ship a different CLDR version and different defaults, so an invoice total or a "3 files" message can differ between your frontend and backend. LombokLocale pins CLDR 47 and runs 342 shared cases (SPEC) in CI for every port.
  • Checked against ICU. Number, currency, percent, date and plural results are cross-checked against ICU 77.1; the four known differences are listed in the SPEC.
  • Exact decimals. Numbers are taken as decimal text, so 0.1 + 0.2, 1e21 or a 30-digit amount are rounded exactly (half away from zero), never through binary floating point.
  • Small and embeddable. No dependencies; the Rust crate is no_std + alloc; data for 28 locales and plural rules for all CLDR locales are embedded.

Installation

Language Package Status
Rust lomboklocale (crates.io) not yet published
TypeScript / JavaScript lomboklocale (npm) not yet published
Python lomboklocale (PyPI) not yet published
Go github.com/codinglombok/lomboklocale/go tag go/v0.2.0 on release
PHP codinglombok/lomboklocale (Packagist) root composer.json, no version field: versioned by the v* tags

The npm package ships dual ESM and CJS builds: import ... from 'lomboklocale' and require('lomboklocale') both work.

Quick start

import { formatNumber, formatDate, formatMessage, negotiate, pluralCategory } from 'lomboklocale';

negotiate(['id-ID', 'en'], ['en', 'id'], 'en');                         // "id"
formatNumber('id', 1234567.891);                                        // "1.234.567,891"
formatNumber('de', '15000', { style: 'currency', currency: 'EUR' });    // "15.000,00 €"
formatNumber('hi', '1234567.5');                                        // "12,34,567.5"
formatDate('id', '2026-10-02', 'full');                                 // "Jumat, 02 Oktober 2026"
pluralCategory('pl', 21);                                               // "many"
formatMessage('en', '{n, plural, one{# file} other{# files}}', { n: 1234 });   // "1,234 files"
formatMessage('en', '{n, selectordinal, one{#st} two{#nd} few{#rd} other{#th}}', { n: 23 }); // "23rd"
use lomboklocale::{format_message, format_number, Arg, NumberOptions};

format_number("id", "15000", &NumberOptions::currency("IDR"))?;     // "Rp 15.000,00"
format_message("id", "Total {n}", &[("n", Arg::from(1234567.5))])?; // "Total 1.234.567,5"
from lomboklocale import format_date, format_number, Num

format_number("fr", 1234.5, style="currency", currency="EUR")   # "1 234,50 €"
format_date("ja", "2026-10-02", "full")                          # "2026年10月2日金曜日"
s, err := lomboklocale.FormatNumber("en", "0.256", lomboklocale.NumberOptions{Style: "percent"}) // "26%"
use LombokLocale\Locale;

Locale::formatNumber('ko', 15000, 'currency', 'KRW');   // "₩15,000"

Spaces shown above inside amounts are U+00A0 or U+202F, as CLDR specifies.

Message catalogs

locales/<tag>/lomboklocale.json holds the messages of this library itself; en and id are reviewed, the others are machine-translated drafts awaiting native review (see locales/STATUS.md). Any application can use the same format: parse_catalog reads a strict JSON object of strings, and resolve formats one message or returns !!id!! so a missing translation is visible.

Known limitations

Latin digits and the Gregorian calendar only; number/date data for 28 locales (other locales fall back to en for formatting but use their own plural rules); no time-of-day, time zones, relative time, lists, units, compact or scientific notation; MessageFormat is a subset (no choice, spellout, ordinal styles, no MessageFormat 2 syntax). See docs/full_summary_project_LombokLocale_v0.2.0.md.

Development

python3 scripts/gen_ports.py --check && python3 vectors/build_vectors.py && node vectors/check_icu.mjs
cd rust && cargo test && cargo clippy --all-targets -- -D warnings
cd typescript && npm ci && npm run coverage
cd python && python -m pytest && python -m ruff check --select E4,E7,E9,F . && python -m mypy lomboklocale
cd go && go test ./...
cd php && php tests/run.php
bash scripts/lombok-doctor.sh LombokLocale
docker build -t lomboklocale:local . && docker run --rm lomboklocale:local

License

Code: Apache-2.0 OR MIT, at your option (LICENSE-APACHE, LICENSE-MIT). Embedded CLDR data: Unicode License v3 (LICENSE-UNICODE); the data subset, its source and its license are recorded in NOTICE.