Security News
Combatting Alert Fatigue by Prioritizing Malicious Intent
In 2023, data breaches surged 78% from zero-day and supply chain attacks, but developers are still buried under alerts that are unable to prevent these threats.
react-intl
Advanced tools
The react-intl package is a comprehensive internationalization library for React that provides React components and an API to format dates, numbers, and strings, including pluralization and handling translations.
Internationalized messages
Allows you to define messages for translations that can be used throughout your application. The FormattedMessage component displays the message corresponding to the current locale.
{"<FormattedMessage id='greeting' defaultMessage='Hello, World!' />"}
Date and time formatting
Enables you to format dates and times according to the rules of the user's locale. The FormattedDate component automatically formats the date value to a readable string.
{"<FormattedDate value={new Date()} year='numeric' month='long' day='numeric' weekday='long' />"}
Number and currency formatting
Provides components to format numbers and currencies. The FormattedNumber component formats the number as a currency string according to the current locale and specified currency.
{"<FormattedNumber value={1000} style='currency' currency='USD' />"}
Pluralization
Supports plural forms in messages, allowing you to handle singular and plural cases for different languages. The FormattedMessage component is used with a plural format string to correctly display singular or plural text based on the count.
{"<FormattedMessage id='itemCount' defaultMessage='{count, plural, one {# item} other {# items}}' values={{count: itemCount}} />"}
Rich text formatting
Allows for rich text formatting within translations by passing components or HTML elements as values to the FormattedMessage component.
{"<FormattedMessage id='welcome' defaultMessage='Welcome, <b>{name}</b>!' values={{name: <b>John</b>}} tagName='p' />"}
i18next is a powerful internationalization framework for JavaScript, which provides a similar set of features for translating content. It is more flexible than react-intl and can be used with other frameworks besides React.
react-i18next is built on top of i18next and is specifically designed for React applications. It offers a similar feature set to react-intl but with a different API and additional features like namespace support and server-side rendering capabilities.
React-i18nify is a simple translation and localization library for React and React Native, offering a simpler API and smaller bundle size compared to react-intl. It lacks some of the advanced formatting options provided by react-intl.
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.
The ReactIntlMixin
implements a ReactJS Component Mixin that adds these new methods to any React component:
formatDate()
to format a date valueformatTime()
to format a date value with time
formatsformatRelative()
to format a date relative to now; e.g. "3 hours ago"formatNumber()
to format a numeric valueformatMessage()
to format a complex messageformatDate()
, 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.
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.
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 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.
formatRelative()
is similar to formatMessage()
in that it's a sugar layer on top of a non-started library, intl-relativeformat, which takes a JavaScript date or timestamp, compares it with "now", and returns the formatted string; e.g., "3 hours ago".
Intl
DependencyThis package assumes that the Intl
global object exists in the runtime. Intl
is present in all modern browsers except Safari, and there's work happening to integrate Intl
into Node.js.
Luckly, there's the Intl.js polyfill! You will need to conditionally load the polyfill if you want to support runtimes which Intl
is not already built-in.
If the browser does not already have the Intl
APIs built-in, the Intl.js Polyfill will need to be loaded on the page along with the locale data for any locales that need to be supported:
<script src="intl/Intl.min.js"></script>
<script src="intl/locale-data/jsonp/en-US.js"></script>
Note: Modern browsers already have the Intl
APIs built-in, so you can load the Intl.js Polyfill conditionally, by for checking for window.Intl
.
Conditionally require the Intl.js Polyfill if it doesn't already exist in the runtime. As of Node <= 0.10, this polyfill will be required.
if (!global.Intl) {
require('intl');
}
Note: When using the Intl.js Polyfill in Node.js, it will automatically load the locale data for all supported locales.
bower install react-intl
.<script src="react/react.min.js"></script>
<script src="react-intl/react-intl.min.js"></script>
Note: for older browsers and Safari you may need to also load the Intl.js polyfill before including react-intl.js
.
Be default, React Intl ships with the locale data for English built-in. When you need to format data in another locale, include its data; e.g., for French:
<script src="react-intl/locale-data/fr.js"></script>
Note: All 150+ locales supported use their root BCP 47 language tag; i.e., the part before the first hyphen (if any).
var MyComponent = React.createClass({
mixins: [ReactIntlMixin],
render: function () {
return <div>
<p>{this.formatDate(new Date())}</p>
<p>{this.formatNumber(600)}</p>
<p>{this.formatMessage(this.getIntlMessage('product.info'), {
product: 'Mac Mini',
price: 2000.0015,
deadline: 1390518044403
})}</p>
</div>;
}
});
locales
:var i18n = {
locales: ['en-US'],
messages: {
product: {
info: '{product} will cost {price, number} if ordered by {deadline, date}'
}
}
};
React.renderComponent(
<MyComponent locales={i18n.locales} messages={i18n.messages}/>,
document.getElementById('example')
);
npm install react-intl
.var ReactIntlMixin = require('react-intl');
Note: in Node.js, the data for all locales is pre-loaded.
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:
var MyComponent = React.createClass({
mixins: [ReactIntlMixin],
render: function () {
return <div>
<p>A: {this.formatDate(1390518044403, {
hour: 'numeric',
minute: 'numeric'
})}</p>
<p>B: {this.formatNumber(400, { style: 'percent' })}</p>
</div>;
}
});
In the example above, if locales
is set to ["fr-FR"]
, the output will be:
<div>
<p>A: 18:00</p>
<p>B: 40 000 %</p>
</div>
But if locales
is set to ["en-US"]
, the output will be:
<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 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".
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.
var MyComponent = React.createClass({
mixins: [ReactIntlMixin],
getDefaultProps: function() {
return {
// 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"
},
EUR: {
style: "currency",
currency: "EUR"
}
}
}
};
},
render: function () {
return <div>
<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',
price: 2000.0015,
deadline: 1390518044403
})}</p>
</div>;
}
});
The component above will now be rendered with locales
and mesages
set externally:
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:
<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 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.
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:
var i18n = {
locales: ['en-US'],
formats: { number: {}, date: {}, time: {} },
messages: {}
};
React.renderComponent(
<MyRootComponent
locales={i18n.locales}
formats={i18n.formats}
messages={i18n.messages} />,
document.getElementById('container')
);
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.
formatMessage()
var MyComponent = React.createClass({
mixins: [ReactIntlMixin],
render: function () {
return <p>{this.formatMessage(this.getIntlMessage("reporting"), {
employee: this.props.name,
manager: this.props.manager
})}</p>;
}
});
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"]} messages={messages["en-US"]}
name="John" manager="Mike" />,
document.getElementById("example")
);
// - English output: "John reports to Mike."
// Render in german:
React.renderComponent(
<MyComponent locales={["de-DE"]} messages={messages["de-DE"]}
name="John" manager="Mike" />,
document.getElementById("example")
);
// - German output: "John berichtet an Mike."
var MyComponent = React.createClass({
mixins: [ReactIntlMixin],
render: function () {
return <p>{this.formatMessage(this.getIntlMessage("posted"), {
relativeTime: this.formatRelative(this.props.postDate),
})}</p>;
}
});
var messages = {
"en": {
reporting: "posted {relativeTime}"
},
"es": {
reporting: "publicado {relativeTime}"
}
};
// Render in English:
React.renderComponent(
<MyComponent locales={["en"]} messages={messages["en"]}
postDate="2014-05-11" />,
document.getElementById('example')
);
// - English output: "posted 4 months ago"
// Render in Spanish:
React.renderComponent(
<MyComponent locales={["es"]} messages={messages["es"]}
postDate="2014-05-11" />,
document.getElementById('example')
);
// - German output: "publicado hace 4 meses"
var MyComponent = React.createClass({
mixins: [ReactIntlMixin],
render: function () {
return <p>{this.formatMessage(this.getIntlMessage("publishers"), {
COMPANY_COUNT: this.props.count
})}</p>;
}
});
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"]} messages={messages["en-US"]} count=1 />,
document.getElementById("example")
);
// - English output: "One company published new books."
// Render in Russian:
React.renderComponent(
<MyComponent locales={["ru-RU"]} messgaes={messages["ru-RU"]} count=1 />,
document.getElementById('example')
);
// - Russian output: "Одна компания опубликовала новые книги."
// If the `count` property that is passed into `MyComponent` is 2, then:
// - English output: "2 companies published new books."
// - Russian output: "2 компании опубликовали новые книги."
// if the `count` property that is passed into `MyComponent` is 99, then:
// - English output: "99 companies published new books."
// - Russian output: "99 компаний опубликовали новые книги."
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
.
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.
var MyComponent = React.createClass({
mixins: [ReactIntlMixin],
render: function () {
return <p>
{this.formatMessage(this.getIntlMessage('product'), this.props)}
</p>;
}
});
var i18n = {
locales: ["en-US"],
messages: {
product: "{product} will cost {price, number, eur} if ordered by {deadline, date, timeStyle}"
},
formats: {
date: {
timeStyle: {
hour: "numeric",
minute: "numeric"
},
number: {
EUR: {
style: "currency",
currency: "EUR"
}
}
}
};
// Render in English:
React.renderComponent(
<MyComponent
locales={i18n.locales} formats={i18n.formats} messages={i18n.messages}
product="Mac Mini" price=200 deadline=1390518044403 />,
document.getElementById('example')
);
// - English output: "Mac Mini will cost €200 if ordered by 6:00 PM"
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.
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.
This software is free to use under the Yahoo Inc. BSD license. See the LICENSE file for license text and copyright information.
FAQs
Internationalize React apps. This library provides React components and an API to format dates, numbers, and strings, including pluralization and handling translations.
The npm package react-intl receives a total of 1,451,119 weekly downloads. As such, react-intl popularity was classified as popular.
We found that react-intl demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
In 2023, data breaches surged 78% from zero-day and supply chain attacks, but developers are still buried under alerts that are unable to prevent these threats.
Security News
Solo open source maintainers face burnout and security challenges, with 60% unpaid and 60% considering quitting.
Security News
License exceptions modify the terms of open source licenses, impacting how software can be used, modified, and distributed. Developers should be aware of the legal implications of these exceptions.