UNPKG

17.9 kBMarkdownView Raw
1# ![format-message][logo]
2
3> Internationalize text, numbers, and dates using ICU Message Format
4
5[![npm Version][npm-image]][npm]
6[![Build Status][build-image]][build]
7[![JS Standard Style][style-image]][style]
8[![MIT License][license-image]][LICENSE]
9
10
11Quick Examples
12--------------
13
14`npm install format-message --save`
15
16By default, the passed in string is parsed and formatted.
17
18```js
19var formatMessage = require('format-message')
20var message = formatMessage('Hello { place }!', { place: 'World' })
21```
22
23You can pass an object to provide more information about a message.
24
25```js
26import formatMessage from 'format-message'
27
28let message = formatMessage({
29 id: 'welcome_name', // optional, can be generated from `default`
30 default: 'Welcome, {name}!',
31 // optional description gives translators more context
32 description: 'Greeting at the top of the home page, showing the current user’s preferred name'
33}, {
34 name: user.preferredName
35})
36```
37
38Configure format-message to use translations, infer missing ids from the default message, report and replace missing translations, and add custom placeholder style formats.
39
40```js
41formatMessage.setup({
42 locale: 'es-ES', // what locale strings should be displayed
43 translations: require('./locales'), // object containing translations
44 generateId: require('format-message-generate-id/underscored_crc32'), // function to generate a missing id from the default message
45 missingReplacement: '!!NOT TRANSLATED!!', // use this when a translation is missing instead of the default message
46 missingTranslation: 'ignore', // don't console.warn or throw an error when a translation is missing
47 formats: {
48 number: { // add '{ amount, number, EUR }' format
49 EUR: { style: 'currency', currency: 'EUR' }
50 },
51 date: { // add '{ day, date, weekday }' format
52 weekday: { weekday: 'long' }
53 }
54 }
55})
56```
57
58Formatting `number`, `date`, and `time` arguments relies on the ECMAScript Internationalization API (`Intl`). If you are in an environment missing this API ([like node <= 0.12, IE < 11, or Safari < 10][caniuse-intl]) you'll want to use a [polyfill][intl]. Otherwise an error will be thrown when trying to format these arguments.
59
60
61Format Overview
62---------------
63
64The [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]. There is a [guide for translators][icu-for-translators] you can send to your translators, and it's a nice primer for developers as well.
65
66`format-message` provides a way to write your default (often English) message patterns as literals in your source, and then lookup translations at runtime. There are also tools to lint, extract, and inline translations.
67
68This relies on [message-format][message-format] for parsing and formatting ICU messages.
69
70### Supported ICU Formats
71
72See [message-format][message-format] for supported ICU formats.
73
74### Quoting escaping rules
75
76See the [ICU site][icu-message] and [message-format][message-format] for details on how to escape special characters in your messages.
77
78### Loading locale data
79
80`format-message` supports plurals for all CLDR languages. Locale-aware formatting of number, date, and time are delegated to the `Intl` apis, and select is the same across all locales. You don't need to load any extra files for particular locales for `format-message` itself.
81
82
83API
84---
85
86### `formatMessage(pattern[, args[, locales]])`
87
88Translate and format the message with the given pattern and arguments. Literal arguments for `pattern` and `locales` are recommended so you can take advantage of linting, extraction, and inlining tools.
89
90Parameters
91
92- `pattern` is a string or object describing the message. A string value is equivalent to `{ default: value }`.
93 - `default` is a properly formatted ICU Message Format pattern. A poorly formatted pattern will cause an `Error` to be thrown.
94 - This will be used directly if no translations are conifgured or if the translation is missing and no `missingReplacement` is configured.
95 - This is also used to generate an inferred `id`, if none is explicitly included.
96 - `id` is a string identifier for the message. This is used as a key to look up the translation from the configured `translations`. If none is specified, one is generated from the `default` pattern.
97 - `description` is a string providing additional context for this message. This has no runtime effect, but can be extracted along with the default message to be sent to translators.
98- `args` is an object containing the values to replace placeholders with. Required if the pattern contains placeholders.
99- `locales` is an optional string with a BCP 47 language tag, or an array of such strings.
100 - When specified, format-message will attempt to look up the translation for each language until one is found.
101 - When omitted the locale configured in `setup()` is used instead.
102
103### `formatMessage.rich(pattern[, args[, locales]])`
104
105Translate and format the message with the given pattern and arguments and return an array of message parts. If the pattern contains any html-like tags (`<a>go</a>`, `<icon/>`, etc.) they are interpreted as placeholders expecting a function that will receive the children message parts as an array. Attributes are not supported for the placeholder tags and will throw a parse error.
106
107Note that for React, and perhaps other libraries as well, elements in an array should have a `key` specified, or you will trigger warnings.
108
109```jsx
110formatMessage.rich("Click <a>here<a/>", {
111 a: ({ children }) => <Link key="a">{children}</Link>
112})
113// returns [ "Click ", <Link key="a">here</Link> ]
114```
115
116Parameters
117
118 The same as `formatMessage(pattern[, args[, locales]])`.
119
120### `formatMessage.setup(options)`
121
122Configure `formatMessage` behavior for subsequent calls. This should be called before any code that uses `formatMessage`. Returns an object containing the current options.
123
124Parameters
125
126- `options` is an object containing the following config values:
127 - `locale` is the default locale to use when no locale is passed to `formatMessage`. Defaults to `"en"`.
128 - `translations` is an object with locales as properties, each value is an object with message ids as properties. The value for each message id property is either the translated message pattern string, or an object with the `message` property containing the translated message pattern string.
129 - `generateId(defaultPattern)` is a function to generate an id from the default message pattern.
130 - `defaultPattern` is the default message pattern.
131 - This function must return a string id.
132 - 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.
133 - `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.
134 - `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.
135 - `formats` is an object containing objects that define placeholder styles `{ name, type, style }`:
136 - `number` is an object containing number format styles to add. Each property name can be used afterwards as a style name for a number placeholder. The value of each property is an object that will be passed to an [`Intl.NumberFormat`][mdn-intl-numberformat] constructor as the second argument.
137 - `date` is an object containing date format styles to add. Each property name can be used afterwards as a style name for a date placeholder. The value of each property is an object that will be passed to an [`Intl.DateTimeFormat`][mdn-intl-datetimeformat] constructor as the second argument.
138 - `time` is an object containing time format styles to add. Each property name can be used afterwards as a style name for a time placeholder. The value of each property is an object that will be passed to an [`Intl.DateTimeFormat`][mdn-intl-datetimeformat] constructor as the second argument.
139
140### `formatMessage.namespace()`
141
142Return a new instance of `formatMessage` with isolated configuration. Calls to `setup()`
143on the new namespace will not be affect any another namespace (including the global
144namespace).
145
146```js
147var namespace = formatMessage.namespace()
148
149formatMessage.setup({
150 locale: "en",
151 translations: {
152 en: {
153 foo: "foo"
154 }
155 }
156})
157
158namespace.setup({
159 locale: "fr",
160 transations: {
161 fr: {
162 foo: "bar"
163 }
164 }
165})
166
167formatMessage("foo") // => "foo"
168namespace("foo") // => "bar"
169```
170
171If you are using a custom namespace and still want to be able to extract strings using the format message CLI, create a module named `format-message.js` that exports the new namespace. Import formatMessage from this module in all other modules that use the namespace.
172
173### Localization apis
174
175format-message also provides a few extra functions to simplify localizing (but not translating) data. These mostly just pass through to `Intl` APIs.
176
177```js
178import { number, date, time, select, plural, selectordinal } from 'format-message'
179// or
180var { number, date, time, select, plural, selectordinal } = require('format-message')
181```
182
183### `number(value [, style [, locale ]])`
184
185Convert a number to a localized string.
186
187Parameters
188
189- `value` is the number to format.
190- `style` is the optional string name of a style (decimal, integer, percent, etc). Defaults to `'decimal'`.
191- `locale` is the optional BCP 47 language tag. If not passed, the locale passed to `setup()` will be used.
192
193### `date(value [, style [, locale ]])`
194
195Convert a date to a localized date string.
196
197Parameters
198
199- `value` is the date to format.
200- `style` is the optional string name of a style (short, medium, long, full, etc). Defaults to `'medium'`.
201- `locale` is the optional BCP 47 language tag. If not passed, the locale passed to `setup()` will be used.
202
203### `time(value [, style [, locale ]])`
204
205Convert a date to a localized time string.
206
207Parameters
208
209- `value` is the date to format.
210- `style` is the optional string name of a style (short, medium, long, full, etc). Defaults to `'medium'`.
211- `locale` is the optional BCP 47 language tag. If not passed, the locale passed to `setup()` will be used.
212
213### `select(value, options)`
214
215Select an option by exact text match. (This is not locale-specific.)
216
217Parameters
218
219- `value` is the string to match.
220- `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.
221
222### `plural(value [, offset ], options [, locale ])` and `selectordinal(value [, offset ], options [, locale ])`
223
224Select 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.
225
226Parameters
227
228- `value` is the number to match against plural rules.
229- `offset` is an optional number subtracted from value before matching keyword plural rules. The offset is not applied when matching exact number options.
230- `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`.
231
232### format-message/react
233
234**Deprecated: Use `formatMessage.rich()` instead.**
235This module includes utilities for working specifically with react when composing messages with embedded components.
236
237### `formatChildren(message, elements)`
238
239Applies a message to a map of React elements to produce a list of child nodes.
240
241Parameters
242
243- `message` is a pre-formatted string containing tokens marking the beginning and ending of nodes.
244- `elements` is an object with keys matching tokens in the message, and values of React elements to put message parts in.
245
246Example
247
248```jsx
249import formatMessage from 'format-message'
250import {formatChildren} from 'format-message/react'
251
252export default ({ extensions }) =>
253 <div title={formatMessage('Choose a file')}>
254 {formatChildren(
255 formatMessage('Drag & Drop {extensions} files here <0>or</0> <1>Browse</1>', {
256 extensions
257 }),
258 [
259 <span className="or" />,
260 <span className="browse" />
261 ]
262 )}
263 </div>
264```
265
266produces the same tree as
267
268```jsx
269<div title="something">
270 Drag & Drop {extensions} files here
271 <span className="or">or</span>
272 <span className="browse">
273 Browse
274 </span>
275</div>
276```
277
278You can also provide an Object and use tag names that match the object's property names
279
280```jsx
281import formatMessage from 'format-message'
282import {formatChildren} from 'format-message/react'
283
284export default ({ extensions }) =>
285 <div title={formatMessage('Choose a file')}>
286 {formatChildren(
287 formatMessage('Drag & Drop {extensions} files here <span1>or</span1> <span2>Browse</span2>', {
288 extensions
289 }),
290 {
291 span1: <span className="or" />,
292 span2: <span className="browse" />
293 }
294 )}
295 </div>
296```
297To be valid, a tag name can include any character except `<`, `/`, `>`, and whitespace characters.
298
299
300### format-message/inferno
301
302**Deprecated: Use `formatMessage.rich()` instead.**
303This 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.
304
305### `formatChildren(message, elements)`
306
307Applies a message to a map of vdom nodes to produce a list of child nodes.
308
309Parameters
310
311- `message` is a pre-formatted string containing tokens marking the beginning and ending of nodes.
312- `elements` is an object with keys matching tokens in the message, and values of vdom elements to put message parts in.
313
314
315Example Messages
316----------------
317
318The examples provide sample output. Some assume you have configured with translations.
319
320### Simple messages with no placeholders
321
322```js
323formatMessage('My Collections')
324// "Minhas Coleções"
325```
326
327### Simple string placeholders
328
329```js
330formatMessage('Welcome, {name}!', { name: 'Bob' })
331// "Bem Vindo, Bob!"
332```
333
334### String placeholders with nested data
335
336```js
337formatMessage('Welcome, {people.wes.name}, {people.julie.name}, and {people.sharon.name}!', {
338 people: {
339 wes: {
340 name: 'Wes Phillips'
341 },
342 julie: {
343 name: 'Julie Roberts'
344 },
345 sharon: {
346 name: 'Sharon Sanders'
347 }
348 }
349})
350// "Welcome, Wes Phillips, Julie Roberts, and Sharon Sanders!"
351```
352
353### Complex number, date, and time placeholders
354
355```js
356formatMessage('{ n, number, percent }', { n: 0.1 })
357// or preferred since there is no text to translate:
358number(0.1, 'percent')
359// "10%"
360
361formatMessage('{ shorty, date, short }', { shorty: new Date() })
362// or preferred since there is no text to translate:
363date(new Date(), 'short')
364// "1/1/15"
365
366formatMessage('You took {n,number} pictures since {d,date} {d,time}', { n: 4000, d: new Date() })
367// "You took 4,000 pictures since Jan 1, 2015 9:33:04 AM"
368```
369
370### Complex string with select and plural in ES6
371
372```js
373import formatMessage from 'format-message'
374
375// using a template string for multiline, NOT for interpolation
376formatMessage(`On { date, date, short } {name} ate {
377 numBananas, plural,
378 =0 {no bananas}
379 =1 {a banana}
380 =2 {a pair of bananas}
381 other {# bananas}
382 } {
383 gender, select,
384 male {at his house.}
385 female {at her house.}
386 other {at their house.}
387 }`, {
388 date: new Date(),
389 name: 'Curious George',
390 gender: 'male',
391 numBananas: 27
392})
393// "On 1/1/15 Curious George ate 27 bananas at his house."
394```
395
396
397License
398-------
399
400This software is free to use under the MIT license. See the [LICENSE-MIT file][LICENSE] for license text and copyright information.
401
402
403[logo]: https://cdn.rawgit.com/format-message/format-message/2febdd8/logo.svg
404[npm]: https://www.npmjs.org/package/format-message
405[npm-image]: https://img.shields.io/npm/v/format-message.svg
406[build]: https://travis-ci.org/format-message/format-message
407[build-image]: https://img.shields.io/travis/format-message/format-message.svg
408[style]: https://github.com/feross/standard
409[style-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg
410[license-image]: https://img.shields.io/npm/l/format-message.svg
411[caniuse-intl]: http://caniuse.com/#feat=internationalization
412[icu-message]: http://userguide.icu-project.org/formatparse/messages
413[icu-cpp]: http://icu-project.org/apiref/icu4c/classicu_1_1MessageFormat.html
414[icu-php]: http://php.net/manual/en/class.messageformatter.php
415[icu-java]: http://icu-project.org/apiref/icu4j/
416[intl]: https://github.com/andyearnshaw/Intl.js
417[icu-for-translators]: http://format-message.github.io/icu-message-format-for-translators/
418[format-message-generate-id]: https://github.com/format-message/format-message/tree/master/packages/format-message-generate-id
419[message-format]: https://github.com/format-message/message-format
420[mdn-intl-datetimeformat]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
421[mdn-intl-numberformat]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
422[LICENSE]: https://github.com/format-message/format-message/blob/master/LICENSE-MIT