message-format
Advanced tools
Comparing version 0.0.2 to 0.0.3
@@ -68,4 +68,4 @@ // Karma configuration | ||
// if true, Karma captures browsers, runs the tests and exits | ||
singleRun: true | ||
singleRun: false | ||
}); | ||
}; |
{ | ||
"name": "message-format", | ||
"version": "0.0.2", | ||
"description": "Intl.MessageFormat polyfill supporting ICU formatted messages", | ||
"version": "0.0.3", | ||
"description": "Intl.MessageFormat polyfill supporting ICU message format", | ||
"main": "dist/message-format.js", | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"6to5": "3.0.12", | ||
"6to5-core": "3.0.14", | ||
"6to5": "3.1.1", | ||
"6to5-core": "3.1.1", | ||
"6to5-loader": "3.0.0", | ||
@@ -28,3 +28,3 @@ "benchmark": "1.0.0", | ||
"prepublish": "6to5 --loose all src --out-dir dist", | ||
"test": "jshint src/*.js && karma start" | ||
"test": "jshint src/*.js && karma start --browsers Firefox --single-run" | ||
}, | ||
@@ -31,0 +31,0 @@ "repository": { |
187
README.md
# message-format | ||
Intl.MessageFormat polyfill supporting ICU formatted messages | ||
Intl.MessageFormat polyfill supporting ICU message format | ||
[![npm Version][npm-image]][npm] | ||
[![Dependency Status][deps-image]][deps] | ||
[![Build Status][build-image]][build] | ||
This is still a work in progress. Only the default English locale is available. | ||
Quick Start | ||
----------- | ||
`npm install message-format --save` adds the library to `node_modules`. You can | ||
then use it as follows: | ||
```js | ||
var MessageFormat = require('message-format'); | ||
var message = new MessageFormat('Hello { place }!', 'en-US'); | ||
var formatted = message.format({ place:'World' }); | ||
``` | ||
The library works great with tools like browserify and webpack for use in | ||
front-end code. | ||
Note: message-format relies on `Intl.NumberFormat` and `Intl.DateTimeFormat` | ||
for formatting `number`, `date`, and `time` arguments. If you are in an | ||
environment missing these (like node <= 0.10, IE < 11, or Safari) you'll | ||
need to use a [polyfill][intl]. | ||
Overview | ||
-------- | ||
The [ICU Message Format][icu-message] is a great format for user-visible | ||
strings, and includes simple placeholders, number and date placeholders, and | ||
selecting among submessages for gender and plural arguments. The format is | ||
used in apis in [C++][icu-cpp], [PHP][icu-php], and [Java][icu-java]. | ||
message-format is intended as a polyfill for the yet to be standardized | ||
`Intl.MessageFormat` api. Since there is only a [strawman proposal][proposal] | ||
at this point, this library represents only one possible way the standard api | ||
could eventually work. | ||
### Unsupported ICU Formats | ||
`ordinal`, `duration`, and `spellout` arguments are supported by the parser, | ||
but will just `toString()`. These are not supported by `Intl.NumberFormat`. | ||
They require a lot of language-specific code, and would make the library | ||
undesireably large. For now, if you need these kinds of formats, you can pass | ||
them into the message pre-formatted, and refence them in the message pattern | ||
with a simple string placeholder (`{ arg }`). | ||
### Comparison to intl-messageformat | ||
intl-messageformat is in many ways the inspiration for message-format. However, | ||
intl-messageformat deviates from the ICU standard in the way you escape special | ||
characters in the message pattern, and its pegjs generated parser is fairly | ||
large and not particularly speedy. message-format's primary goals are | ||
simplicity, compliance, and performance (both in size and speed). | ||
If you prefer backslash escaping over the standard quote, you can enable it in | ||
the options: | ||
```js | ||
new MessageFormat('message with \\{braces\\}', 'en-US', { escape:'\\' }) | ||
``` | ||
API | ||
--- | ||
### `MessageFormat` | ||
```js | ||
var MessageFormat = require('message-format') | ||
// or | ||
import MessageFormat from 'message-format' | ||
new MessageFormat(pattern, [locales[, options]]) | ||
``` | ||
Construct a message format object | ||
Parameters | ||
- `pattern` is a properly formatted ICU Message Format pattern. A poorly formatted pattern will cause an `Error` to be thrown. | ||
- `locales` is an optional string with a BCP 47 language tag, or an array of such strings. | ||
- `options` is an optional object containing options that change the behavior of `MessageFormat`. | ||
-- `cache` default `true`, if `true` cache the result of preparing the `format` function. The cache is shared across all instances of `MessageFormat`. | ||
-- `escape` default `"'"`, if any other character, escape the single character following each escape character. | ||
### `MessageFormat` instances | ||
```js | ||
message.format([args]) | ||
``` | ||
Format the message with the given arguments | ||
Parameters | ||
- `args` is an object containing the values to replace placeholders with. Required if the pattern contains placeholders. | ||
Examples | ||
-------- | ||
### Simple string placeholders | ||
```js | ||
var message = new MessageFormat('Welcome back, {name}!'); | ||
message.format({ name:'Bob' }); // 'Welcome back, Bob!' | ||
message.format({ name:'Bill' }); // 'Welcome back, Bill!' | ||
``` | ||
### Quote escaping rules | ||
Escaping is a little weird in ICU Message Format. | ||
1 `''` is always `'` | ||
2 `'` begins an escaped string only if followed immediately by a syntax char (`'{}#'`) | ||
3 `'` ends an escaped string, unless it is doubled. See #1 | ||
```js | ||
var message = new MessageFormat('This isn\'\'t a \'{simple}\' \'string\''); | ||
message.format(); // "This isn't a {simple} 'string'" | ||
// double quotes or backticks (ES6) make it a little easier to read | ||
message = new MessageFormat("This isn''t a '{simple}' 'string'"); | ||
message.format(); // "This isn't a {simple} 'string'" | ||
``` | ||
### number, date, and time placeholders | ||
```js | ||
var message = new MessageFormat('You took {n,number} pictures since {d,date} {d,time}'); | ||
message.format({ n:4000, d:new Date() }); // 'You took 4,000 pictures since Jan 1, 2015 9:33:04 AM' | ||
message = new MessageFormat('{ n, number, percent }'); | ||
message.format({ n:0.1 }); // '10%' | ||
message = new MessageFormat('{ shorty, date, short }'); | ||
message.format({ shorty:new Date() }); // '1/1/15' | ||
``` | ||
### Complex string with select and plural in ES6 | ||
```js | ||
import MessageFormat from 'message-format' | ||
// using a template string for multiline, no interpolation | ||
let message = new MessageFormat(`On { date, date, short } {name} ate { | ||
numBananas, plural, | ||
=0 {no bananas} | ||
=1 {a banana} | ||
other {# bananas} | ||
} { | ||
gender, select, | ||
male {at his house.} | ||
female {at her house.} | ||
other {at their house.} | ||
}`) | ||
message.format({ | ||
date: new Date(), | ||
name: 'Curious George', | ||
gender: 'male', | ||
numBananas: 27 | ||
}) // 'On 1/1/15 Curious George ate 27 bananas at his house.' | ||
``` | ||
License | ||
------- | ||
This software is free to use under the MIT license. | ||
See the [LICENSE-MIT file][LICENSE] for license text and copyright information. | ||
[npm]: https://www.npmjs.org/package/message-format | ||
[npm-image]: https://img.shields.io/npm/v/message-format.svg | ||
[deps]: https://david-dm.org/thetalecrafter/message-format | ||
[deps-image]: https://img.shields.io/david/thetalecrafter/message-format.svg | ||
[build]: https://travis-ci.org/thetalecrafter/message-format | ||
[build-image]: https://img.shields.io/travis/thetalecrafter/message-format.svg | ||
[icu-message]: http://userguide.icu-project.org/formatparse/messages | ||
[icu-cpp]: http://icu-project.org/apiref/icu4c/classicu_1_1MessageFormat.html | ||
[icu-php]: http://php.net/manual/en/class.messageformatter.php | ||
[icu-java]: http://icu-project.org/apiref/icu4j/ | ||
[proposal]: http://wiki.ecmascript.org/doku.php?id=globalization:messageformatting | ||
[intl]: https://github.com/andyearnshaw/Intl.js | ||
[LICENSE]: https://github.com/thetalecrafter/message-format/blob/master/LICENSE-MIT | ||
@@ -48,6 +48,11 @@ /** | ||
let [ id, type, style ] = element | ||
let | ||
id = element[0], | ||
type = element[1], | ||
style = element[2] | ||
if ('#' === id) { | ||
let [ id, , offset ] = parent | ||
let | ||
id = parent[0], | ||
offset = parent[2] | ||
return this.compileNumber(id, offset, null) | ||
@@ -63,3 +68,5 @@ } | ||
case 'plural': | ||
let [ , , offset, options ] = element | ||
let | ||
offset = element[2], | ||
options = element[3] | ||
return this.compilePlural(id, offset, options) | ||
@@ -66,0 +73,0 @@ case 'select': |
@@ -59,5 +59,6 @@ /*! Intl.MessageFormat polyfill v0.0.1 | ||
function lookupClosestLocale(locale, available) { | ||
let locales = [].concat(locale || []) | ||
for (let current of locales) { | ||
current = current.split('-') | ||
let | ||
locales = [].concat(locale || []) | ||
for (let l = 0, ll = locales.length; l < ll; ++l) { | ||
let current = locales[l].split('-') | ||
while (current.length) { | ||
@@ -64,0 +65,0 @@ if (current.join('-') in available) { |
@@ -253,3 +253,4 @@ /** | ||
] | ||
for (let type of types) { | ||
for (let t = 0, tt = types.length; t < tt; ++t) { | ||
let type = types[t] | ||
if (pattern.slice(this.index, this.index + type.length) === type) { | ||
@@ -256,0 +257,0 @@ argType = type |
@@ -18,3 +18,3 @@ import MessageFormat from '../src/message-format' | ||
let | ||
pattern = 'This isn\'t a \'{simple}\' \'string\'', | ||
pattern = 'This isn\'\'t a \'{simple}\' \'string\'', | ||
message = new MessageFormat(pattern, 'en-US').format() | ||
@@ -51,3 +51,3 @@ | ||
expect(message).toMatch(/^0 \: \d\d\/\d\d\/\d\d \d\d?\:\d\d [AP]M$/) | ||
expect(message).toMatch(/^0 \: \d\d?\/\d\d?\/\d\d \d\d?\:\d\d [AP]M$/) | ||
}) | ||
@@ -54,0 +54,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30438
13
795
191