react-intl
Advanced tools
Comparing version 0.1.0-rc-1 to 1.0.0-rc-1
16
index.js
@@ -0,9 +1,15 @@ | ||
'use strict'; | ||
// setting up the global requirements of the component | ||
global.Intl = global.Intl || global.IntlPolyfill || require('intl'); | ||
global.IntlMessageFormat = require('intl-messageformat'); | ||
// Expose `React` as a global, because the ReactIntlMixin assumes it's global. | ||
var oldReact = global.React; | ||
global.React = require('react'); | ||
require('./src/component.js'); | ||
exports = module.exports = require('./lib/mixin').default; | ||
Object.defineProperty(exports, 'default', {value: exports}); | ||
module.exports = global.ReactIntlMixin; | ||
// Put back `global.React` to how it was. | ||
if (oldReact) { | ||
global.React = oldReact; | ||
} else { | ||
delete global.React; | ||
} |
{ | ||
"name": "react-intl", | ||
"version": "0.1.0-rc-1", | ||
"description": "reactjs helpers for internationalization", | ||
"version": "1.0.0-rc-1", | ||
"description": "React mixin for internationalization.", | ||
"keywords": [ | ||
@@ -12,38 +12,33 @@ "intl", | ||
"author": "Caridy Patino <caridy@gmail.com>", | ||
"contributors": [ | ||
"Eric Ferraiuolo <eferraiuolo@gmail.com>" | ||
], | ||
"license": "BSD-3-Clause", | ||
"bugs": { | ||
"url": "https://github.com/caridy/react-intl/issues" | ||
"url": "https://github.com/yahoo/react-intl/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git@github.com:caridy/react-intl.git" | ||
"url": "git@github.com:yahoo/react-intl.git" | ||
}, | ||
"files": ["src/", "index.js"], | ||
"main": "index.js", | ||
"directories": { | ||
"test": "tests" | ||
}, | ||
"jsnext:main": "src/mixin.js", | ||
"dependencies": { | ||
"intl-messageformat": "^0.1.0", | ||
"react": "*" | ||
"intl-format-cache": "^1.0.0", | ||
"react": "^0.11.1" | ||
}, | ||
"devDependencies": { | ||
"chai": "1.8.*", | ||
"grunt": "0.4.*", | ||
"grunt-cli": "0.1.*", | ||
"grunt-contrib-jshint": "0.7.*", | ||
"grunt-wrap": "~0.3.0", | ||
"grunt-contrib-uglify": "0.2.*", | ||
"react": "*", | ||
"istanbul": "0.1.*", | ||
"mocha": "1.15.*", | ||
"intl": "*", | ||
"benchmark": "~1.0.0", | ||
"xunit-file": "*", | ||
"grunt-contrib-watch": "^0.6.1", | ||
"grunt-contrib-concat": "^0.4.0" | ||
"grunt": "^0.4.5", | ||
"grunt-bundle-jsnext-lib": "^0.2.1", | ||
"grunt-cli": "^0.1.13", | ||
"grunt-contrib-clean": "^0.6.0", | ||
"grunt-contrib-copy": "^0.5.0", | ||
"grunt-contrib-jshint": "^0.10.0", | ||
"grunt-contrib-uglify": "^0.5.1", | ||
"intl": "^0.1.4" | ||
}, | ||
"scripts": { | ||
"pretest": "grunt jshint build", | ||
"test": "istanbul cover -- _mocha tests/ --reporter spec" | ||
} | ||
"prepublish": "grunt" | ||
}, | ||
"homepage": "https://github.com/yahoo/react-intl" | ||
} |
374
README.md
React Intl Mixin | ||
================ | ||
This repository contains a [ReactJS][] Component Mixin to implement Internationalization | ||
features in a React component. The Intl Mixin provides a series of methods that | ||
can be used in the `render()` method of the component to provide date formatting, | ||
number formatting, as well as plural and gender based translations. | ||
This repository contains a [ReactJS][] Component Mixin to implement Internationalization features for a React component. The Intl Mixin provides a set of methods that can be used in the `render()` method of the component to provide date, number, and message formatting, as well as plural and gender based translations. | ||
## Overview | ||
[![npm Version][npm-badge]][npm] | ||
[![Dependency Status][david-badge]][david] | ||
Overview | ||
-------- | ||
The `ReactIntlMixin` implements a [ReactJS][] Component [Mixin][] that adds these new methods to any React component: | ||
* `intlDate()` to format a date value | ||
* `intlNumber()` to format a numeric value | ||
* `intlMessage()` to format a complex message | ||
* `formatDate()` to format a date value | ||
* `formatTime()` to format a date value with `time` formats | ||
* `formatNumber()` to format a numeric value | ||
* `formatMessage()` to format a complex message | ||
`intlDate()` and `intlNumber()` are just sugar on top of [Intl.NumberFormat][] and [Intl.DateTimeFormat][], APIs implemented by most modern browsers. On top of them, React Intl Mixin uses an internal caching mechanism to reuse instances of `Intl.NumberFormat` and `Intl.DateTimeFormat` when possible to avoid the performance penalty of creating these objects over and over again. | ||
`formatDate()`, `formatTime()`, and `formatNumber()` are sugar on top of [Intl.NumberFormat][] and [Intl.DateTimeFormat][] APIs implemented by most modern browsers. To improve runtime performance, React Intl Mixin uses an internal cache to reuse instances of `Intl.NumberFormat` and `Intl.DateTimeFormat` when possible. | ||
Similarly, `intlMessage()` is a sugar layer on top of [intl-messageformat][], a library to support more advanced translation patterns that include complex pluralization and gender support. This library is based on the [Strawman Draft][] that is set to evolve [ECMAScript 402][] to provide a standardized way to concatenate strings with localization support in JavaScript. | ||
Similarly, `formatMessage()` is a sugar layer on top of [intl-messageformat][], a library to support more advanced translation patterns that include complex pluralization and gender support. This library is based on a [Strawman Draft][] proposing to evolve [ECMAScript 402][] to provide a standard way to format message strings with localization support in JavaScript. | ||
In general, `intlMessage()` provides different ways to translate content in the `render()` method of your React components. It also provides the right hooks for your application to implement i18n in an effective way, including the ability to cache expensive objects created through `new IntlMessageFormat(pattern, locale, [optFieldFormatters])`. | ||
The `formatMessage()` method accepts a string message and values to format it with. It too uses an internal cache to improve runtime performance by reusing `IntlMessageFormat` instances. | ||
The data consumed by `intlMessage()` follows the same format supported by [intl-messageformat][], which is one of the industry standards used in other programming languages like Java and PHP. Although this format looks complex, professional translators are familiar with it. You can learn more about this format here: https://github.com/yahoo/intl-messageformat#how-it-works. | ||
The data consumed by `formatMessage()` follows the same format supported by [intl-messageformat][], which is one of the industry standards used in other programming languages like Java and PHP. Although this format looks complex, professional translators are familiar with it. You can [learn more about this format](https://github.com/yahoo/intl-messageformat#how-it-works). | ||
## Installation | ||
Installation | ||
------------ | ||
### Browser | ||
@@ -44,10 +49,8 @@ | ||
mixins: [ReactIntlMixin], | ||
getMyMessage: function () { | ||
return "{product} will cost {price, number} if ordered by {deadline, date}" | ||
}, | ||
render: function () { | ||
return <div> | ||
<p>{this.intlDate(new Date())}</p> | ||
<p>{this.intlNumber(600)}</p> | ||
<p>{this.intlMessage(this.getMyMessage(), { | ||
<p>{this.formatDate(new Date())}</p> | ||
<p>{this.formatNumber(600)}</p> | ||
<p>{this.formatMessage(this.getIntlMessage('product.info'), { | ||
product: 'Mac Mini', | ||
@@ -65,4 +68,13 @@ price: 2000.0015, | ||
```javascript | ||
var i18n = { | ||
locales: ['en-US'], | ||
messages: { | ||
product: { | ||
info: '{product} will cost {price, number} if ordered by {deadline, date}' | ||
} | ||
} | ||
}; | ||
React.renderComponent( | ||
<MyComponent locales={["fr-FR"]}/>, | ||
<MyComponent locales={i18n.locales} messages={i18n.messages}/>, | ||
document.getElementById('example') | ||
@@ -81,9 +93,10 @@ ); | ||
## Advanced Options | ||
Advanced Options | ||
---------------- | ||
### Date and Time formatters | ||
### Date and Time Formats | ||
#### Explicit formats | ||
#### Explicit Formats | ||
By default, when using `{this.intlDate(new Date())}` and `{this.intlNumber(600)}`, `react-intl` will use the default format for the data, and the default numeric format for the number. To specify a custom format you can pass in a second argument with the format you want to use. The following examples will ilustrate this option: | ||
By default, when using `{this.formatDate(new Date())}` and `{this.formatNumber(600)}`, `react-intl` will use the default format for the date, and the default numeric format for the number. To specify a custom format you can pass in a second argument with the format you want to use. The following examples will illustrate this option: | ||
@@ -93,6 +106,10 @@ ```javascript | ||
mixins: [ReactIntlMixin], | ||
render: function () { | ||
return <div> | ||
<p>A: {this.intlDate(1390518044403, { hour: 'numeric', minute: 'numeric' })}</p> | ||
<p>B: {this.intlNumber(400, { style: 'percent' })}</p> | ||
<p>A: {this.formatDate(1390518044403, { | ||
hour: 'numeric', | ||
minute: 'numeric' | ||
})}</p> | ||
<p>B: {this.formatNumber(400, { style: 'percent' })}</p> | ||
</div>; | ||
@@ -106,4 +123,6 @@ } | ||
```html | ||
A: 18:00 | ||
B: 40 000 % | ||
<div> | ||
<p>A: 18:00</p> | ||
<p>B: 40 000 %</p> | ||
</div> | ||
``` | ||
@@ -114,48 +133,48 @@ | ||
```html | ||
A: 6:00 PM | ||
B: 40,000% | ||
<div> | ||
<p>A: 6:00 PM</p> | ||
<p>B: 40,000%</p> | ||
</div> | ||
``` | ||
This explicit way to specify a format works well for simple cases, but for complex applications, it falls short because you will have to pass these values everywhere. Also, it doesn't work with complex structures processed by `intlMessage()` because there is no way to pass the formatter for each individual element. To overcome this limitation, we introduced the concept of "custom formatters". | ||
This explicit way to specify a format works well for simple cases, but for complex applications, it falls short because you will have to pass these format config objects through the component hierarchy. Also, it doesn't work with complex structures processed by `formatMessage()` because there is no way to pass the format options for each individual element. To overcome this limitation, we introduced the concept of "custom formats". | ||
#### Custom Formats | ||
#### Custom formatters | ||
With custom format, you can name a set of options that can be used within the entire application or within a component subtree (a component and its child components). These custom formats will also be used by the `formatMessage()` method for complex messages. The following examples will illustrates how custom formats work. | ||
With custom formatters, you can specify a set of rules that can be applied to your entire application or to a section of the page (a component and its child components). These custom formatters can also be used thru `intlMessage()` API for complex language sentences. The following examples will ilustrate how custom formatters work. | ||
```javascript | ||
var MyContainer = React.createClass({ | ||
mixins: [ReactIntlMixin], | ||
getDefaultProps: function() { | ||
return { | ||
// hardcoding formats as properties, but they can be passed from parent... | ||
"formats": { | ||
"date": { | ||
"timeStyle": { | ||
"hour": "numeric", | ||
"minute": "numeric" | ||
// Hard-coding formats as properties, but they can be passed from the | ||
// parent component or outside of React. | ||
formats: { | ||
date: { | ||
timeStyle: { | ||
hour: "numeric", | ||
minute: "numeric" | ||
} | ||
}, | ||
"number": { | ||
"percentStyle": { | ||
"style": "percent" | ||
number: { | ||
percentStyle: { | ||
style: "percent" | ||
}, | ||
"eur": { | ||
"style": "currency", | ||
"currency": "EUR" | ||
EUR: { | ||
style: "currency", | ||
currency: "EUR" | ||
} | ||
} | ||
}, | ||
// using properties or a mixin to bring the messages in different languages... | ||
"MyMessage": "{product} will cost {price, number, eur} if ordered by {deadline, date, timeStyle}" | ||
} | ||
}; | ||
}, | ||
render: function () { | ||
return <div> | ||
<p>A: {this.intlDate(1390518044403, "timeStyle")}</p> | ||
<p>B: {this.intlNumber(400, "percentStyle")}</p> | ||
<p>{this.intlMessage(this.props.MyMessage, { | ||
<p>A: {this.formatDate(1390518044403, "timeStyle")}</p> | ||
<p>B: {this.formatNumber(400, "percentStyle")}</p> | ||
<p>C: {this.formatMessage(this.getIntlMessage('product.info'), { | ||
product: 'Mac Mini', | ||
@@ -170,21 +189,48 @@ price: 2000.0015, | ||
In the example above, if `locales` is set to `["en-US"]`, the output will be: | ||
The component above will now be rendered with `locales` and `mesages` set externally: | ||
```javascript | ||
var i18n = { | ||
locales: ["en-US"], | ||
messages: { | ||
product { | ||
info: "{product} will cost {price, number, eur} if ordered by {deadline, date, timeStyle}" | ||
} | ||
} | ||
}; | ||
React.renderComponent( | ||
<MyComponent locales={i18n.locales} messages={i18n.messages}/>, | ||
document.body | ||
); | ||
``` | ||
The above rendering of `MyComponent` will output: | ||
```html | ||
A: 6:00 PM | ||
B: 40,000% | ||
C: Mac Mini will cost €200 if ordered by 6:00 PM | ||
<div> | ||
<p>A: 6:00 PM</p> | ||
<p>B: 40,000%</p> | ||
<p>C: Mac Mini will cost €200 if ordered by 6:00 PM</p> | ||
</div> | ||
``` | ||
By defining `this.props.formats`, which specifies a set of named formats under `date` and `number` members, you can use those named formats as a second argument for `intlNumber()` and `intlDate()`. You can also reference them as a third token when defining the messages, e.g: `{deadline, date, timeStyle}`. In this case `deadline` describes the format options for its value, specifying that it is a `date` and should be formatted using the `timeStyle` custom formatter. | ||
By defining `this.props.formats`, which specifies a set of named formats under `date` and `number` members, you can use those named formats as a second argument for `formatNumber()`, `formatDate()`, and `formatTime()`. You can also reference them as the third token when defining the messages, e.g: `{deadline, date, timeStyle}`. In this case `deadline` describes the format options for its value, specifying that it is a `date` and should be formatted using the `timeStyle` custom format. | ||
### App Configuration | ||
Another feature of the Intl Mixin is its ability to propagate `formats` and `locales` to any child component. Internally, it laverages `context` to allow those child components to reuse the values defined at the parent level, making this ideal to define custom formatters for the app, and the language or the application by defining them or passing them into the root component when rendering the application. Ideally, you will do this: | ||
Another feature of the Intl Mixin is its ability to propagate `formats` and `locales` to any child component. Internally, it leverages the `context` to allow those child components to reuse the values defined at the parent level, making this ideal to define custom formats and the locale for the app by defining them or passing them into the root component when rendering the application. **This is always the recommended way to provide i18n message strings to the React component hierarchy.** Ideally, you will do this: | ||
```javascript | ||
var appLocales = ['en-US']; | ||
var appFormats = { number: {}, date: {} }; | ||
var i18n = { | ||
locales: ['en-US'], | ||
formats: { number: {}, date: {}, time: {} }, | ||
messages: {} | ||
}; | ||
React.renderComponent( | ||
<MyRootComponent locales={appLocales} formats={appFormats} />, | ||
<MyRootComponent | ||
locales={i18n.locales} | ||
formats={i18n.formats} | ||
messages={i18n.messages} />, | ||
document.getElementById('container') | ||
@@ -194,15 +240,16 @@ ); | ||
Then make sure `MyRootComponent` uses the `ReactIntlMixin`. By doing that, you can define the list of `locales`, normally one or more in case you want to support fallback, (e.g.: `["fr-FR", "en"]`); and you can define `formats` to describe how the application will format dates and numbers. All child components will be able to inherit these two structures in such a way that you don't have to propagate or define `locales` or `formats` at each level in your application. Just apply this mixin in those components that are suppose to use `this.intlNumber()`, `this.intlDate()` and/or `this.intlMessage()` in the `render()` method and you're all set. | ||
Then make sure `MyRootComponent` uses the `ReactIntlMixin`. By doing that, you can define the list of `locales`, normally one or more in case you want to support fallback, (e.g.: `["fr-FR", "en"]`); and you can define `formats` to describe how the application will format dates and numbers. You will also want to mass the `messages` for the current locale, since the string will be locale-specific. All child components will be able to inherit these three structures in such a way that you don't have to propagate or define them at each level in your application. Just apply this mixin in those components that are suppose to use `this.formatNumber()`, `this.formatDate()` and/or `this.formatMessage()` in the `render()` method and you're all set. | ||
## How to use intlMessage() | ||
How to Use `formatMessage()` | ||
---------------------------- | ||
### Example #1: Simple String Replacement | ||
### Example #1: simple string replacement | ||
```javascript | ||
var MyComponent = React.createClass({ | ||
mixins: [ReactIntlMixin], | ||
render: function () { | ||
return <p>{this.intlMessage(GlobalMessages.MSG1, { | ||
return <p>{this.formatMessage(this.getIntlMessage("reporting"), { | ||
employee: this.props.name, | ||
@@ -214,8 +261,16 @@ manager: this.props.manager | ||
// render in English: | ||
GlobalMessages = { | ||
MSG1: "{employee} reports to {manager}." | ||
var messages = { | ||
"en-US": { | ||
reporting: "{employee} reports to {manager}." | ||
}, | ||
"de-DE": { | ||
reporting: "{employee} berichtet an {manager}." | ||
} | ||
}; | ||
// Render in English: | ||
React.renderComponent( | ||
<MyComponent locales={["en-US"]} name="John" manager="Mike" />, | ||
<MyComponent locales={["en-US"]} messages={messages["en-US"]} | ||
name="John" manager="Mike" />, | ||
document.getElementById('example') | ||
@@ -225,15 +280,12 @@ ); | ||
// render in german: | ||
GlobalMessages = { | ||
MSG1: "{EMPLOYEE} berichtet an {MANAGER}." | ||
}; | ||
// Render in german: | ||
React.renderComponent( | ||
<MyComponent locales={["de-DE"]} name="John" manager="Mike" />, | ||
<MyComponent locales={["de-DE"]} messages={messages["de-DE"]} | ||
name="John" manager="Mike" />, | ||
document.getElementById('example') | ||
); | ||
// - german output: "John berichtet an Mike." | ||
// - German output: "John berichtet an Mike." | ||
``` | ||
### Example #2: string replacement with pluralization | ||
### Example #2: String Replacement with Pluralization | ||
@@ -243,4 +295,5 @@ ```javascript | ||
mixins: [ReactIntlMixin], | ||
render: function () { | ||
return <p>{this.intlMessage(GlobalMessages.OTHER, { | ||
return <p>{this.formatMessage(this.getIntlMessage("publishers"), { | ||
COMPANY_COUNT: this.props.count | ||
@@ -251,19 +304,30 @@ })}</p>; | ||
// render in English: | ||
GlobalMessages = { | ||
OTHER: "{COMPANY_COUNT, plural, one {One company} other {# companies}} published new books." | ||
var messages = { | ||
"en-US": { | ||
publishers: "{COMPANY_COUNT, plural," + | ||
"one {One company}" + | ||
"other {# companies}}" + | ||
" published new books." | ||
}, | ||
"ru-RU": { | ||
publishers: "{COMPANY_COUNT, plural," + | ||
"one {Одна компания опубликовала}" + | ||
"few {# компании опубликовали}" + | ||
"many {# компаний опубликовали}" + | ||
"other {# компаний опубликовали}}" + | ||
" новые книги." | ||
} | ||
}; | ||
// Render in English: | ||
React.renderComponent( | ||
<MyComponent locales={["en-US"]} count=1 />, | ||
document.getElementById('example') | ||
<MyComponent locales={["en-US"]} messages={messages["en-US"]} count=1 />, | ||
document.getElementById("example") | ||
); | ||
// - English output: "One company published new books." | ||
// render in Russian: | ||
GlobalMessages = { | ||
OTHER: "{COMPANY_COUNT, plural, one {Одна компания опубликовала} few {# компании опубликовали} many {# компаний опубликовали} other {# компаний опубликовали}} новые книги." | ||
}; | ||
// Render in Russian: | ||
React.renderComponent( | ||
<MyComponent locales={["ru-RU"]} count=1 />, | ||
<MyComponent locales={["ru-RU"]} messgaes={messages["ru-RU"]} count=1 />, | ||
document.getElementById('example') | ||
@@ -274,3 +338,3 @@ ); | ||
// if the `count` property that is passed into `MyComponent` is 2, then: | ||
// If the `count` property that is passed into `MyComponent` is 2, then: | ||
// - English output: "2 companies published new books." | ||
@@ -284,6 +348,7 @@ // - Russian output: "2 компании опубликовали новые книги." | ||
As you can see in this example, Russian has different rules when it comes to pluralization, having different messages for `one`, `few` and `other`, while American English is just targeting `one` and `other`. | ||
As you can see in this example, Russian has different rules when it comes to pluralization, having different sub-messages for `one`, `few` and `other`, while American English is just targeting `one` and `other`. | ||
### Example #3: Dates and Numbers Within Messages | ||
### Example #3: string replacement with pluralization and gender | ||
In any message, you can use `{<valueName>, number [, <optionalFormat>]}` and `{<valueName>, date [, <optionalFormat>]}` to format numbers and dates, which that includes combining them with plural and gender structures as well. | ||
@@ -293,100 +358,62 @@ ```javascript | ||
mixins: [ReactIntlMixin], | ||
render: function () { | ||
return <p>{this.intlMessage(GlobalMessages.ANOTHER, this.props)}</p>; | ||
return <p> | ||
{this.formatMessage(this.getIntlMessage('product'), this.props)} | ||
</p>; | ||
} | ||
}); | ||
// render in French: | ||
GlobalMessages = { | ||
ANOTHER: "{TRAVELLER_COUNT} {TRAVELLER_COUNT, plural, one {est {GENDER, select, female {allée} other {allé}}} other {sont {GENDER, select, female {allées} other {allés}}}} à {CITY}." | ||
}; | ||
React.renderComponent( | ||
<MyComponent locales={["fr-FR"]} TRAVELLER_COUNT=1 GENDER="female" />, | ||
document.getElementById('example') | ||
); | ||
// - French output: "1 est allée à Havana" | ||
var i18n = { | ||
locales: ["en-US"], | ||
messages: { | ||
product: "{product} will cost {price, number, eur} if ordered by {deadline, date, timeStyle}" | ||
}, | ||
// render in English | ||
GlobalMessages = { | ||
ANOTHER: "{TRAVELLER_COUNT} went to {CITY}." | ||
}; | ||
React.renderComponent( | ||
<MyComponent locales={["en-US"]} TRAVELLER_COUNT=1 GENDER="female" />, | ||
document.getElementById('example') | ||
); | ||
// - English output: "1 went to Havana" | ||
formats: { | ||
date: { | ||
timeStyle: { | ||
hour: "numeric", | ||
minute: "numeric" | ||
}, | ||
// render in French: | ||
GlobalMessages = { | ||
ANOTHER: "{TRAVELLER_COUNT} {TRAVELLER_COUNT, plural, one {est {GENDER, select, female {allée} other {allé}}} other {sont {GENDER, select, female {allées} other {allés}}}} à {CITY}." | ||
number: { | ||
EUR: { | ||
style: "currency", | ||
currency: "EUR" | ||
} | ||
} | ||
} | ||
}; | ||
React.renderComponent( | ||
<MyComponent locales={["fr-FR"]} TRAVELLER_COUNT=3 />, | ||
document.getElementById('example') | ||
); | ||
// - French output: "3 sont allés à Havana" | ||
// render in English | ||
GlobalMessages = { | ||
ANOTHER: "{TRAVELLER_COUNT} went to {CITY}." | ||
}; | ||
// Render in English: | ||
React.renderComponent( | ||
<MyComponent locales={["en-US"]} TRAVELLER_COUNT=3 />, | ||
<MyComponent | ||
locales={i18n.locales} formats={i18n.formats} messages={i18n.messages} | ||
product="Mac Mini" price=200 deadline=1390518044403 />, | ||
document.getElementById('example') | ||
); | ||
// - English output: "3 went to Havana" | ||
// - English output: "Mac Mini will cost €200 if ordered by 6:00 PM" | ||
``` | ||
The example above is more generic, and we pass all props as data into the `intlMessage()` method instead of picking up individual `props` that we need per translation. This is a common practive for small components. | ||
_Note: `formatMessage()` will take care of creating the internal date and number format instances, and cache them to avoid creating unnecessary objects by reusing existing instances when similar formats are applied._ | ||
You can also see how the French version of `GlobalMessages.ANOTHER` is combining the use of pluralization (for `TRAVELLER_COUNT`) and the gender of the traveler or travelers because it is derived from Latin, in which case the gender might change the structure of the sentence, while in American English this is not affecting the output of the translation. | ||
Limitations | ||
----------- | ||
### Example #4: dates and numbers within messages | ||
Not all browsers have implemented [ECMAScript 402][], which is the Internationalization API, for older browsers, and Safari, you might need to patch the browser by loading [Intl.js][] polyfill before including `react-intl.js` library. | ||
In any message, you can use `{<valueName>, number[, <optionalFormat>]}` and `{<valueName>, date[, <optionalFormat>]}` to format numbers and dates, and that includes combining them with plural and gender structures as well. | ||
License | ||
------- | ||
```javascript | ||
var MyComponent = React.createClass({ | ||
mixins: [ReactIntlMixin], | ||
render: function () { | ||
return <p>{this.intlMessage(GlobalMessages.COMBINE, this.props)}</p>; | ||
} | ||
}); | ||
This software is free to use under the Yahoo Inc. BSD license. | ||
See the [LICENSE file][] for license text and copyright information. | ||
// render in English: | ||
GlobalMessages = { | ||
COMBINE: "{product} will cost {price, number, eur} if ordered by {deadline, date, timeStyle}" | ||
}; | ||
GlobalLocales = ["en-US"]; | ||
GlobalFormats = { | ||
"date": { | ||
"timeStyle": { | ||
"hour": "numeric", | ||
"minute": "numeric" | ||
} | ||
"number": { | ||
"eur": { | ||
"style": "currency", | ||
"currency": "EUR" | ||
} | ||
} | ||
}; | ||
React.renderComponent( | ||
<MyComponent locales={GlobalLocales} formats={GlobalFormats} product="Mac Mini" price=200 deadline=1390518044403 />, | ||
document.getElementById('example') | ||
); | ||
// - English output: "Mac Mini will cost €200 if ordered by 6:00 PM" | ||
``` | ||
_Note: `IntlMessage()` will take care of caching internal structures for date and numbers to avoid creating unnecessary objects by reusing existing instances when similar formats are applied._ | ||
Limitations | ||
----------- | ||
Not all browsers have implemented [ECMAScript 402][], which is the internationalization API, for older browsers, and Safari, you might need to patch the browser by loading [Intl.js][] polyfill before including `react-intl.js` library. | ||
[npm]: https://www.npmjs.org/package/react-intl | ||
[npm-badge]: https://img.shields.io/npm/v/react-intl.svg?style=flat | ||
[david]: https://david-dm.org/yahoo/react-intl | ||
[david-badge]: https://img.shields.io/david/yahoo/react-intl.svg?style=flat | ||
[Intl.js]: https://github.com/andyearnshaw/Intl.js | ||
@@ -401,1 +428,2 @@ [ECMAScript 402]: http://www.ecma-international.org/ecma-402/1.0/ | ||
[Strawman Draft]: http://wiki.ecmascript.org/doku.php?id=globalization:messageformatting | ||
[LICENSE file]: https://github.com/yahoo/react-intl/blob/master/LICENSE.md |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
514469
8
12
0
2358
1
0
414
2
+ Addedintl-format-cache@^1.0.0
+ Addedamdefine@1.0.1(transitive)
+ Addedbase62@0.1.1(transitive)
+ Addedenvify@2.0.1(transitive)
+ Addedesprima-fb@3001.1.0-dev-harmony-fb(transitive)
+ Addedintl-format-cache@1.0.0(transitive)
+ Addedintl-messageformat@1.3.0(transitive)
+ Addedintl-messageformat-parser@1.2.0(transitive)
+ Addedjstransform@3.0.0(transitive)
+ Addedobject-keys@0.4.0(transitive)
+ Addedreact@0.11.2(transitive)
+ Addedsource-map@0.1.31(transitive)
+ Addedthrough@2.3.8(transitive)
+ Addedxtend@2.1.2(transitive)
- Removedintl-messageformat@^0.1.0
- Removedintl-messageformat@0.1.0(transitive)
- Removedjs-tokens@4.0.0(transitive)
- Removedloose-envify@1.4.0(transitive)
- Removedreact@18.3.1(transitive)
Updatedreact@^0.11.1