Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nesting not supported with custom fortmatters #201

Closed
johanblumenberg opened this issue Jul 30, 2018 · 2 comments · Fixed by #204
Closed

Nesting not supported with custom fortmatters #201

johanblumenberg opened this issue Jul 30, 2018 · 2 comments · Fixed by #204

Comments

@johanblumenberg
Copy link

johanblumenberg commented Jul 30, 2018

The Format Guide states this:

All types of messageformat statements may be nested within each other, to unlimited depth

However, it doesn't work to nest anything within a custom formatter:

const chalk = require('chalk');
const MessageFormat = require('messageformat');
const mf = new MessageFormat('en-GB');
mf.addFormatters({
  error: function(v, lc, p) { return chalk.red(p); }
});
const messages = mf.compile({
  describe: 'There were {numErrors, error, {# errors}}'
});

messages.describe({ numErrors: 5 })        // 'There were 5 errors', where '5 errors' prints as red

You could also imagine nesting a plural format in there, to get 'no error', 'one error', '# errors', and so on, printed in red.

@eemeli
Copy link
Member

eemeli commented Jul 30, 2018

You're right, custom formatters arguments don't work like you'd expect them to. They're not as such a part of the MessageFormat spec, but a relaxation/extension of the simpleArg pattern as its argType is not restricted to "number" | "date" | "time" | "spellout" | "ordinal" | "duration", but may refer to any user-determined custom formatter. However, the spec does specify the following regarding the optional argument to such a formatter:

In argStyleText, every single ASCII apostrophe begins and ends quoted literal text, and unquoted {curly braces} must occur in matched pairs. [...] Any argStyleText must be a valid pattern string for the Format subclass used.

So I'm not really sure what the "right" thing to do here would be. At a minimum, the "All types" statement should be reworded. But to address your specific use case, a slight reformulation should get you the result you're looking for:

const mf = new MessageFormat('en-GB');
mf.addFormatters({
  error: (v, lc, p) => chalk.red(p.replace(/#/g, v))
});
const messages = mf.compile({
  describe: 'There were {numErrors, error, # errors}'
});

Note that this slightly abuses the meaning of # as no check is made to make sure that it's a number. And to get proper pluralisation, you should wrap the whole thing in a plural:

There were {numErrors, plural,
  one {{numErrors, error, # error}}
  other {{numErrors, error, # errors}}
}

@johanblumenberg
Copy link
Author

johanblumenberg commented Aug 9, 2018

Currently, this message does not even compile:

const messages = mf.compile({
  describe: 'There were {numErrors, error, {# errors}}'
});

This message, however, does:

const messages = mf.compile({
  describe: 'There were {numErrors, error, {# errors}'
});

The second string is invalid, since an ending curly bracket is missing.

... unquoted {curly braces} must occur in matched pairs ...

It seems the parsing breaks whenever there is a new ending curly bracket, and the parsing doesn't accept any string containing an ending curly bracket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants