format-message
Advanced tools
Comparing version 4.0.1 to 5.0.0-beta.0
# Changelog | ||
## 5.0.0 | ||
* **New Feature** | ||
* `setup()` returns the current settings | ||
* Added localization helpers to public api | ||
* `number (value [, style [, locale ]])` | ||
* `date (value [, style [, locale ]])` | ||
* `time (value [, style [, locale ]])` | ||
* `select (value, options)` | ||
* `plural (value [, offset ], options [, locale ])` | ||
* `selectordinal (value [, offset ], options [, locale ])` | ||
* Allow `missingReplacement` to be a function | ||
* Added format-message/react module | ||
## 4.0.0 | ||
@@ -4,0 +18,0 @@ |
58
index.js
@@ -7,2 +7,3 @@ /* globals Intl */ | ||
var interpret = require('format-message-interpret') | ||
var plurals = require('format-message-interpret/plurals') | ||
var lookupClosestLocale = require('lookup-closest-locale') | ||
@@ -22,3 +23,3 @@ var formats = require('format-message-formats') | ||
module.exports = formatMessage | ||
module.exports = exports = formatMessage | ||
function formatMessage (msg, args, locale) { | ||
@@ -30,3 +31,3 @@ locale = locale || currentLocale | ||
var format = cache[key] || | ||
(cache[key] = generateFormat(locale, pattern, id)) | ||
(cache[key] = generateFormat(pattern, id, locale)) | ||
if (typeof format === 'string') return format | ||
@@ -36,8 +37,8 @@ return format(args) | ||
function generateFormat (locale, pattern, id) { | ||
pattern = translate(locale, pattern, id) | ||
function generateFormat (pattern, id, locale) { | ||
pattern = translate(pattern, id, locale) | ||
return interpret(locale, parse(pattern)) | ||
} | ||
function translate (locale, pattern, id) { | ||
function translate (pattern, id, locale) { | ||
if (!translations) return pattern | ||
@@ -51,2 +52,5 @@ | ||
var replacement = missingReplacement || pattern | ||
if (typeof replacement === 'function') { | ||
replacement = replacement(pattern, id, locale) || pattern | ||
} | ||
var message = 'Translation for "' + id + '" in "' + locale + '" is missing' | ||
@@ -65,3 +69,3 @@ | ||
formatMessage.setup = function setup (opt) { | ||
exports.setup = function setup (opt) { | ||
opt = opt || {} | ||
@@ -78,5 +82,14 @@ if (opt.locale) currentLocale = opt.locale | ||
} | ||
return { | ||
locale: currentLocale, | ||
translations: translations, | ||
generateId: generateId, | ||
missingReplacement: missingReplacement, | ||
missingTranslation: missingTranslation, | ||
formats: { number: number, date: date, time: time } | ||
} | ||
} | ||
formatMessage.number = function (locale, value, style) { | ||
exports.number = function (value, style, locale) { | ||
locale = locale || currentLocale | ||
var options = number[style] || number.decimal | ||
@@ -92,3 +105,4 @@ if (typeof Intl === 'undefined') { | ||
formatMessage.date = function (locale, value, style) { | ||
exports.date = function (value, style, locale) { | ||
locale = locale || currentLocale | ||
var options = date[style] || date.medium | ||
@@ -104,3 +118,4 @@ if (typeof Intl === 'undefined') { | ||
formatMessage.time = function (locale, value, style) { | ||
exports.time = function (value, style, locale) { | ||
locale = locale || currentLocale | ||
var options = time[style] || time.medium | ||
@@ -115,1 +130,26 @@ if (typeof Intl === 'undefined') { | ||
} | ||
exports.select = function (value, options) { | ||
return options[value] || options.other | ||
} | ||
function selectPlural (pluralType, value, offset, options, locale) { | ||
if (typeof offset === 'object') { // offset is optional | ||
locale = options | ||
options = offset | ||
offset = 0 | ||
} | ||
var closest = lookupClosestLocale(locale || currentLocale, plurals) | ||
var plural = plurals[closest][pluralType] | ||
if (!plural) return options.other | ||
return ( | ||
options['=' + +value] || | ||
options[plural(value - offset)] || | ||
options.other | ||
) | ||
} | ||
exports.plural = selectPlural.bind(null, 'cardinal') | ||
exports.selectordinal = selectPlural.bind(null, 'ordinal') |
{ | ||
"name": "format-message", | ||
"version": "4.0.1", | ||
"version": "5.0.0-beta.0", | ||
"description": "Internationalize text, numbers, and dates using ICU Message Format", | ||
@@ -5,0 +5,0 @@ "author": "Andy VanWagoner <thetalecrafter@gmail.com> (https://thetalecrafter.com/)", |
137
README.md
@@ -19,4 +19,4 @@ # ![format-message][logo] | ||
```js | ||
var formatMessage = require('format-message'); | ||
var message = formatMessage('Hello { place }!', { place: 'World' }); | ||
var formatMessage = require('format-message') | ||
var message = formatMessage('Hello { place }!', { place: 'World' }) | ||
``` | ||
@@ -106,3 +106,3 @@ | ||
Configure `formatMessage` behavior for subsequent calls. This should be called before any code that uses `formatMessage`. | ||
Configure `formatMessage` behavior for subsequent calls. This should be called before any code that uses `formatMessage`. Returns an object containing the current options. | ||
@@ -118,3 +118,3 @@ Parameters | ||
- The [`format-message-generate-id`][format-message-generate-id] module has a few functions you can use if you don't want to use your own. | ||
- `missingReplacement` is a string that will be used when a message translation isn't found. If null or not specified, then the default message is used. | ||
- `missingReplacement` is a string or function that returns a string that will be used when a message translation isn't found. If a function, it will be called with `(pattern, id, locale)` parameters to get the replacement. If null or not specified, then the default message is used. | ||
- `missingTranslation` is one of `"ignore"`, `"warning"`, `"error"`. By default it is `"warning"`, and missing translations cause a console warning. If `"error"`, an error is thrown. | ||
@@ -126,7 +126,120 @@ - `formats` is an object containing objects that define placeholder styles `{ name, type, style }`: | ||
### internal apis | ||
### Localization apis | ||
`formatMessage.number`, `formatMessage.date`, and `formatMessage.time` are used internally and are not intended for external use. If you want to just format numbers and dates, you can use the `Intl` APIs directly. | ||
format-message also provides a few extra functions to simplify localizing (but not translating) data. These mostly just pass through to `Intl` APIs. | ||
```js | ||
import { number, date, time, select, plural, selectordinal } from 'format-message' | ||
// or | ||
var { number, date, time, select, plural, selectordinal } = require('format-message') | ||
``` | ||
### `number(value [, style [, locale ]])` | ||
Convert a number to a localized string. | ||
Parameters | ||
- `value` is the number to format. | ||
- `style` is the optional string name of a style (decimal, integer, percent, etc). Defaults to `'decimal'`. | ||
- `locale` is the optional BCP 47 language tag. If not passed, the locale passed to `setup()` will be used. | ||
### `date(value [, style [, locale ]])` | ||
Convert a date to a localized date string. | ||
Parameters | ||
- `value` is the date to format. | ||
- `style` is the optional string name of a style (short, medium, long, full, etc). Defaults to `'medium'`. | ||
- `locale` is the optional BCP 47 language tag. If not passed, the locale passed to `setup()` will be used. | ||
### `time(value [, style [, locale ]])` | ||
Convert a date to a localized time string. | ||
Parameters | ||
- `value` is the date to format. | ||
- `style` is the optional string name of a style (short, medium, long, full, etc). Defaults to `'medium'`. | ||
- `locale` is the optional BCP 47 language tag. If not passed, the locale passed to `setup()` will be used. | ||
### `select(value, options)` | ||
Select an option by exact text match. (This is not locale-specific.) | ||
Parameters | ||
- `value` is the string to match. | ||
- `options` is an object whose keys are candidates for matching `value`. The value of the property with the matching key is returned, or the `other` property's value. The object should always have an `other` property. | ||
### `plural(value [, offset ], options [, locale ])` and `selectordinal(value [, offset ], options [, locale ])` | ||
Select an option by matching plural rules. `plural` matches rules for cardinal numbers, and `selectordinal` matches rules for ordinal numbers. These function very similar to the parameters `plural` and `selectordinal` embedded in a message. | ||
Parameters | ||
- `value` is the number to match against plural rules. | ||
- `offset` is an optional number subtracted from value before matching keyword plural rules. The offset is not applied when matching exact number options. | ||
- `options` is an object whose keys are candidates for matching `value`. The value of the property with the matching key is returned, or the `other` property's value. The object should always have an `other` property. Keys should be either plural keywords (zero, one, two, few, many, other), or exact number matches (=13, =4, etc). Note that not all languages use all rules. For example English doesn't have a `zero` rule (0 falls under the `other` rule), but can still match `=0`. | ||
### format-message/react | ||
This module includes utilities for working specifically with react when composing messages with embedded components. | ||
### `formatChildren(message, elements)` | ||
Applies a message to a map of React elements to produce a list of child nodes. | ||
Parameters | ||
- `message` is a pre-formatted string containing tokens marking the beginning and ending of nodes. | ||
- `elements` is an object with keys matching tokens in the message, and values of React elements to put message parts in. | ||
Example | ||
```jsx | ||
import formatMessage from 'format-message' | ||
import {formatChildren} from 'format-message/react' | ||
export default ({ extensions }) => | ||
<div title={formatMessage('Choose a file')}> | ||
{formatChildren( | ||
formatMessage('Drag & Drop {extensions} files here _or_ __Browse__', { | ||
extensions | ||
}), | ||
{ | ||
_: <span className="or" />, | ||
__: <span className="browse" /> | ||
} | ||
)} | ||
</div> | ||
``` | ||
produces the same tree as | ||
```jsx | ||
<div title="something"> | ||
Drag & Drop {extensions} files here | ||
<span className="or">or</span> | ||
<span className="browse"> | ||
Browse | ||
</span> | ||
</div> | ||
``` | ||
### format-message/inferno | ||
This module includes utilities for working specifically with Inferno when composing messages with embedded components. The API is identical to format-message/react, only it works with Inferno vdom nodes instead of React elements. | ||
### `formatChildren(message, elements)` | ||
Applies a message to a map of vdom nodes to produce a list of child nodes. | ||
Parameters | ||
- `message` is a pre-formatted string containing tokens marking the beginning and ending of nodes. | ||
- `elements` is an object with keys matching tokens in the message, and values of vdom elements to put message parts in. | ||
Example Messages | ||
@@ -147,3 +260,3 @@ ---------------- | ||
```js | ||
formatMessage('Welcome, {name}!', { name: 'Bob' }); | ||
formatMessage('Welcome, {name}!', { name: 'Bob' }) | ||
// "Bem Vindo, Bob!" | ||
@@ -155,9 +268,13 @@ ``` | ||
```js | ||
formatMessage('{ n, number, percent }', { n: 0.1 }); | ||
formatMessage('{ n, number, percent }', { n: 0.1 }) | ||
// or preferred since there is no text to translate: | ||
number(0.1, 'percent') | ||
// "10%" | ||
formatMessage('{ shorty, date, short }', { shorty: new Date() }); | ||
formatMessage('{ shorty, date, short }', { shorty: new Date() }) | ||
// or preferred since there is no text to translate: | ||
date(new Date(), 'short') | ||
// "1/1/15" | ||
formatMessage('You took {n,number} pictures since {d,date} {d,time}', { n: 4000, d: new Date() }); | ||
formatMessage('You took {n,number} pictures since {d,date} {d,time}', { n: 4000, d: new Date() }) | ||
// "You took 4,000 pictures since Jan 1, 2015 9:33:04 AM" | ||
@@ -164,0 +281,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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
28253
7
203
330
1
3