ICU MessageFormat Parser
icu-messageformat-parser is a JavaScript library that provides a PEG.js-based parser for ICU MessageFormat strings. It transforms a given MessageFormat string into an Abstract Syntax Tree (AST), enabling programmatic manipulation or interpretation of localized messages. The current stable version is 4.0.0. New major versions are released periodically to introduce breaking changes, often related to stricter conformance with the ICU MessageFormat specification, and to expand parsing capabilities. Key differentiators include its robust AST output, configurable strictness options (e.g., for number signs and function parameters), and its role as a fundamental parsing component for internationalization workflows involving MessageFormat, prioritizing accurate parsing according to Unicode CLDR and ICU standards.
Common errors
-
SyntaxError: Expected ",", "}" or [ \t\n\r] but "c" found.
cause The MessageFormat string contains a syntax error, such as an unclosed curly brace or incorrect argument format.fixReview the MessageFormat string for common syntax errors like `{Such compliance` missing a closing brace or incorrect separator characters. Ensure all arguments and elements are correctly formatted according to the ICU MessageFormat specification. -
Error: Invalid key
cause A plural or selectordinal key (e.g., 'zero', 'one', 'few') used in the MessageFormat string is not present in the allowed keys specified in the parser options (or default CLDR keys).fixCheck the `cardinal` and `ordinal` arrays in the parser `options` object. Ensure they contain all the plural rule keys used in your MessageFormat string for the target locale. If 'zero' is used but not listed in `options.cardinal`, it will cause this error. -
ReferenceError: require is not defined
cause Attempting to use CommonJS `require()` syntax in an ES Module context.fixFor versions 3.0.0 and above, use ES Module `import` syntax: `import { parse } from 'icu-messageformat-parser';`. If you are in a CommonJS environment, ensure your `package.json` does not have `"type": "module"` or configure your build system to correctly transpile. -
TypeError: (0 , icu_messageformat_parser__WEBPACK_IMPORTED_MODULE_0__.parse) is not a function
cause Attempting to import `parse` as a default export when it is a named export, or module resolution issues in bundlers.fixEnsure you are using named import syntax: `import { parse } from 'icu-messageformat-parser';`. If using a bundler like Webpack or Rollup, verify its configuration for ES Module resolution and tree-shaking.
Warnings
- breaking Backslash (`\`) escaping is no longer supported and will be parsed as literal text. This change was introduced to conform with the ICU MessageFormat standard.
- breaking The `strictNumberSign` option has been replaced by a broader `strict` option.
- breaking Function parameters can now contain MessageFormat content, which changes how they are parsed and represented in the AST.
- gotcha The `options` object for `cardinal` and `ordinal` rule keys validates plural and selectordinal keys. If a key used in the MessageFormat string is not present in the provided options (or the default CLDR keys if options are omitted), parsing will fail.
- gotcha The `strictFunctionParams` option significantly changes how function parameters are parsed. By default, parameters are split by commas and trimmed. With `strictFunctionParams: true`, parameters are treated as a single, untrimmed string.
- gotcha Apostrophe escaping follows `DOUBLE_OPTIONAL` mode. Single apostrophes only quote literal text if preceded by `{}` or `#` (inside `plural`/`selectordinal` and depending on `strict` option). Otherwise, they are literal apostrophes.
Install
-
npm install icu-messageformat-parser -
yarn add icu-messageformat-parser -
pnpm add icu-messageformat-parser
Imports
- parse
const parse = require('icu-messageformat-parser').parse; // or const parse = require('messageformat-parser').parse;import { parse } from 'icu-messageformat-parser'; - AST Types
import type { Ast } from 'icu-messageformat-parser'; - Default Export (hypothetical)
import { parse } from 'icu-messageformat-parser';import parse from 'icu-messageformat-parser';
Quickstart
import { parse } from 'icu-messageformat-parser';
// Basic argument parsing
console.log('Basic argument:', parse('So {wow}.'));
// Expected output: [ 'So ', { type: 'argument', arg: 'wow' }, '.' ]
// Complex selectordinal with octothorpe
const selectOrdinalAst = parse(
'Such { thing }. { count, selectordinal, one {First} two {Second}' +
' few {Third} other {#th} } word.'
);
console.log('Selectordinal AST:', selectOrdinalAst);
// Nested select statements
const nestedSelectAst = parse(
'Many{type,select,plural{ numbers}selectordinal{ counting}' +
'select{ choices}other{ some {type}}}.'
);
console.log('Nested Select AST:', nestedSelectAst);
// Example with options for plural key validation
const msg = '{words, plural, zero{No words} one{One word} other{# words}}';
const englishKeys = { cardinal: [ 'one', 'other' ], ordinal: [ 'one', 'two', 'few', 'other' ] };
console.log('Parsed with default keys (zero is valid):', parse(msg));
try {
// This will throw an error because 'zero' is not in englishKeys.cardinal
parse(msg, englishKeys);
} catch (error: any) {
console.error('Error during parsing with strict keys for plurals:', error.message);
}
// Example demonstrating the `strict` option (replaces `strictNumberSign` in v4+)
// In strict mode, '#' is only special inside plural/selectordinal contexts.
const strictParse = parse('In plural, # is special. Outside, # is text.', { strict: true });
console.log('Strict parsing of #:', strictParse);