Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
messageformat-parser
Advanced tools
The messageformat-parser npm package is a tool for parsing ICU MessageFormat strings. It is used to handle internationalization (i18n) by parsing messages that can include variables, plurals, and select statements. This package is particularly useful for applications that need to support multiple languages and complex message formatting.
Parsing Simple Messages
This feature allows you to parse simple messages with placeholders. The `parse` function takes a message string and returns an abstract syntax tree (AST) representing the structure of the message.
const { parse } = require('messageformat-parser');
const message = 'Hello, {name}!';
const parsed = parse(message);
console.log(JSON.stringify(parsed, null, 2));
Handling Plurals
This feature allows you to parse messages that include pluralization. The `parse` function can handle ICU MessageFormat plural syntax, making it easier to manage messages that need to change based on quantity.
const { parse } = require('messageformat-parser');
const message = '{count, plural, one {# item} other {# items}}';
const parsed = parse(message);
console.log(JSON.stringify(parsed, null, 2));
Handling Select Statements
This feature allows you to parse messages that include select statements. The `parse` function can handle ICU MessageFormat select syntax, which is useful for gender-specific or other conditional messages.
const { parse } = require('messageformat-parser');
const message = '{gender, select, male {He} female {She} other {They}} will respond soon.';
const parsed = parse(message);
console.log(JSON.stringify(parsed, null, 2));
The intl-messageformat package provides similar functionality for parsing and formatting ICU MessageFormat strings. It also includes additional features for formatting dates, times, and numbers, making it a more comprehensive solution for internationalization.
The format-message package offers a similar capability to parse and format ICU MessageFormat strings. It also includes utilities for message extraction and translation, making it a good choice for projects that require a full i18n workflow.
The messageformat package is another alternative that not only parses ICU MessageFormat strings but also compiles them into JavaScript functions for runtime evaluation. This can be useful for performance optimization in large applications.
A PEG.js parser for ICU MessageFormat strings – part of messageformat. Outputs an AST defined by parser.pegjs.
The generated parse(src, [options])
function takes two parameters, first the
string to be parsed, and a second optional parameter options
, an object with
the following possible keys:
cardinal
and ordinal
– Arrays of valid plural categories for the current
locale, used to validate plural
and selectordinal
keys. If these are
missing or set to false, the full set of valid Unicode CLDR keys is used:
'zero', 'one', 'two', 'few', 'many', 'other'
. To disable this check, pass in
an empty array.
strict
– By default, the parsing applies a few relaxations to the ICU
MessageFormat spec. Setting strict: true
will disable these relaxations:
argType
of simpleArg
formatting functions will be restricted to the
set of number
, date
, time
, spellout
, ordinal
, and duration
,
rather than accepting any lower-case identifier that does not start with a
number.argStyle
of simpleArg
formatting functions will not be
parsed as any other text, but instead as the spec requires: "In
argStyleText, every single ASCII apostrophe begins and ends quoted literal
text, and unquoted {curly braces} must occur in matched pairs."plural
or selectordinal
statement, a pound symbol (#
) is
replaced with the input number. By default, #
is also parsed as a special
character in nested statements too, and can be escaped using apostrophes
('#'
). In strict mode #
will be parsed as a special character only
directly inside a plural
or selectordinal
statement. Outside those, #
and '#'
will be parsed as literal text.The parser only supports the default DOUBLE_OPTIONAL
apostrophe mode, in
which a single apostrophe only starts quoted literal text if it immediately
precedes a curly brace {}
, or a pound symbol #
if inside a plural format. A
literal apostrophe '
is represented by either a single '
or a doubled ''
apostrophe character.
npm install messageformat-parser
> var parse = require('messageformat-parser').parse;
> parse('So {wow}.')
[ 'So ', { type: 'argument', arg: 'wow' }, '.' ]
> parse('Such { thing }. { count, selectordinal, one {First} two {Second}' +
' few {Third} other {#th} } word.')
[ 'Such ',
{ type: 'argument', arg: 'thing' },
'. ',
{ type: 'selectordinal',
arg: 'count',
offset: 0,
cases:
[ { key: 'one', tokens: [ 'First' ] },
{ key: 'two', tokens: [ 'Second' ] },
{ key: 'few', tokens: [ 'Third' ] },
{ key: 'other', tokens: [ { type: 'octothorpe' }, 'th' ] } ] },
' word.' ]
> parse('Many{type,select,plural{ numbers}selectordinal{ counting}' +
'select{ choices}other{ some {type}}}.')
[ 'Many',
{ type: 'select',
arg: 'type',
cases:
[ { key: 'plural', tokens: [ ' numbers' ] },
{ key: 'selectordinal', tokens: [ ' counting' ] },
{ key: 'select', tokens: [ ' choices' ] },
{ key: 'other', tokens: [ ' some',
{ type: 'argument', arg: 'type' } ] } ] },
'.' ]
> parse('{Such compliance')
// SyntaxError: Expected ",", "}" or [ \t\n\r] but "c" found.
> var msg = '{words, plural, zero{No words} one{One word} other{# words}}';
> var englishKeys = { cardinal: [ 'one', 'other' ],
ordinal: [ 'one', 'two', 'few', 'other' ] };
> parse(msg)
[ { type: 'plural',
arg: 'words',
offset: 0,
cases:
[ { key: 'zero', tokens: [ 'No words' ] },
{ key: 'one', tokens: [ 'One word' ] },
{ key: 'other', tokens: [ { type: 'octothorpe' }, ' words' ] } ] } ]
> parse(msg, englishKeys)
// Error: Invalid key `zero` for argument `words`. Valid plural keys for this
// locale are `one`, `other`, and explicit keys like `=0`.
For more example usage, please take a look at our test suite.
The output of parse()
is a Token
array:
type Token = string | Argument | Plural | Select | Function
type Argument = {
type: 'argument',
arg: Identifier
}
type Plural = {
type: 'plural' | 'selectordinal',
arg: Identifier,
offset: number,
cases: PluralCase[]
}
type Select = {
type: 'select',
arg: Identifier,
cases: SelectCase[]
}
type Function = {
type: 'function',
arg: Identifier,
key: Identifier,
param: {
tokens: options.strict ? [string] : (Token | Octothorpe)[]
} | null
}
type PluralCase = {
key: 'zero' | 'one' | 'two' | 'few' | 'many' | 'other' | '=0' | '=1' | '=2' | ...,
tokens: (Token | Octothorpe)[]
}
type SelectCase = {
key: Identifier,
tokens: options.strict ? Token[] : (Token | Octothorpe)[]
}
type Octothorpe = {
type: 'octothorpe'
}
type Identifier = string // not containing whitespace or control characters
Messageformat is an OpenJS Foundation project, and we follow its Code of Conduct.
FAQs
A PEG.js parser for ICU MessageFormat strings
The npm package messageformat-parser receives a total of 522,044 weekly downloads. As such, messageformat-parser popularity was classified as popular.
We found that messageformat-parser demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.