Parsers
September 19, 2026 · View on GitHub
Official implementations of the Curly Message Format — a small message syntax for software translations, in which values are interpolated through double-curly placeholders that may carry a modifier, a set of options and a fallback.
{
"greeting": "Hello, {{name; default:Guest;}}!",
"inbox": "You have {{count:number;}} {{count; 1:message; default:messages;}}."
}
Status
Stable. The JavaScript implementation is on npm as
@curly-message/parser, and implements curly-message-3 — version 3 of the
format, which the specification states is stable.
It resolves over the format's own inputs and depends on no host library.
Implementations
| Path | Package | State |
|---|---|---|
js/ | @curly-message/parser | Stable, latest |
One directory per language, each a standalone package with its own build,
tests and version line. Release tags are namespaced by directory
(js-v1.0.0), so an implementation can leave for its own repository without
that being a breaking change for the others.
Releasing
A release is cut from main by the JavaScript parser publish workflow
(.github/workflows/publish-js.yml, started by hand). The changelog's pending
section names the version it will be released as — ### 1.1.0 (Unreleased) —
so a version is settled in the commit that writes the section rather than in
the dispatch. patch, minor and major cut that section under the latest
dist-tag, and the run is refused unless the bump arrives at the version the
section names — over an open prerelease line that is the bump which drops the
prerelease rather than the one that opened it, so 1.1.0-next.3 reaches
1.1.0 under patch. next publishes a prerelease of that same version —
1.1.0-next.0, then .1 — under the next dist-tag and leaves the section
open, because a prerelease has not released what the section names. The
workflow runs the test matrix, bumps the version, cuts the section where the
release closes it, commits, tags (js-v1.0.0), pushes, publishes to npm, and
publishes a GitHub release carrying that changelog section.
The commit, the tag and the release are made as a GitHub App, whose id and
private key the repository holds as the APP_ID variable and the
APP_PRIVATE_KEY secret. npm holds no token: the workflow is the package's
trusted publisher, registered
in the package's settings on npmjs.com or with
npm trust github --file publish-js.yml --repository curly-message/parsers --allow-publish
— the calling workflow's filename, which is the one the registry checks — and
the registry attaches provenance itself. A trusted publisher can be
registered only for a package that exists, so the first version,
1.0.0-next.0, was published by hand from main by a maintainer of the scope
(cd js && npm ci && npm publish --access public --tag next); the workflow
refuses to run for a package the registry does not know.
Specification
The format is defined in curly-message/spec.
Its machine-readable identifier is curly-message; versioned references use
curly-message-3, and so on.