Comments (37)
Everything goes through IntlProvider
have you tried creating an instance of that?
import {IntlProvider} from 'react-intl';
const {intl} = new IntlProvider({
locale: 'en',
messages: {},
}, {}).getChildContext();
intl.formatNumber(1000); // "1,000"
from formatjs.
It's easy. First, you have to realize everything happen in component, at least in app component
https://github.com/este/este/blob/master/src/common/app/start.js
You will render message on UI sooner or later, directly or with side effects helper. Check Este https://github.com/este/este/blob/master/src/browser/auth/LoginError.react.js
from formatjs.
Hey guys.
Its been three years since this issue has been opened.
Considering the fact that the current user language is stored in the redux store, have you guys come up with common pratices to vanilla js intl with react-intl ?
For example i have this validation library which my file-uploader component uses to validate a given file:
const maxSize = (file, size) => {
if (file.size > size) {
return 'File size is bigger than the max allowed';
}
}
This is not the whole code, but should i just return a messageId, which makes my client code dependent on react-intl, or should i turn this .js file into a .jsx file and return a FormattedMessage
? Both of them dont look any good, but which approach have you guys done lately?
We also have the case which a alert message component listens to notification actions emmited by the store. If my component only accepts a message id, i would lose features provided by FormattedMessage
such as plularization and arguments. This is an exemple of an action that dispatches a alert message:
.catch(() => {
showDangerNotification(<FormattedMessage id="AnErrorOcurred" />);
});
from formatjs.
@ericf - do you think that creating a function out of your code like this
import { FormattedMessage, IntlProvider } from 'react-intl';
import { language, messages } from '../../i18nSetup';
const {intl} = new IntlProvider({locale: language, messages}, {}).getChildContext();
const translate = (id: string, values?: {}) => {
return intl.formatMessage({id}, values);
};
export default translate;
and using it all over a react app
// a react component
import translate from '../translate';
// a react class
<h1>{translate('key.id')}</h1>
would create any performance issues compared with the recommended way <FormatMessage id="">
?
from formatjs.
guys, let's not be opinionated here. we do offer:
- The React way by providing react components (e.g.:
<ReactIntl.Number style="percent">{0.95}</ReactIntl.Number>
) - A React Mixin:
ReactIntl.Mixin
that allow you to add new methods to your existing components (e.g.:this.getIntlMessage('SHORT')
to look up for messageSHORT
, but also low level methods to format numbers, dates and messages with the corresponding cache layer on top of react. - A low level API to access the helper methods to programmatically call them when needed, without relying on React components lifecycle (e.g.:
require('intl-messageformat')
).
If none of those 3 options fulfill your needs, just provide more information and we can evaluate what else can we do to help you.
from formatjs.
Not being able to translate messages outside of components is just a pain, I have to move controller code to views just because of that... And for things that do not concern views at all like generating emails, etc...
We should definitively be able to translate things outside of components but with the same intl instance as the one used by our components (so that we do not have to provide twice the messages, etc...)...
from formatjs.
@ericf Is there any particular advantage of using this.formatMessage instead of something like t()?
What I'm thinking:var Intl = require('intl');
Intl.t('my.string'); // this can be used anywhere
@deviousdodo We don't plan on extending the built-in Intl
object since that could be future hostile, that's why we provide message formatting via the intl-messageformat
package at IntlMessageFormat
.
Here are the advantages that the React Intl Mixin and upcoming React Intl Components provide over our core intl-*
libraries:
- A declarative way to format data in templates.
- Caching of
Intl*
instances. - Automatic lookup of
locales
,messages
, andformats
within the React component hierarchy. - Convenience for custom named formats.
Yes, it can be built using IntlMessageFormat (ie. a new adapter), but I don't see why you guys have built a mixin instead of providing some generic functionality.
This is not either or, we provide both a set of core libraries and a set of high level integration libraries built on the core.
from formatjs.
@adyz : Have you been using your solution, and if so, how does it perform?
from formatjs.
The discussion is related to #1609
from formatjs.
can you elaborate more?
from formatjs.
I'm not sure if this is what @klimashkin is asking for, but I've found myself wanting to use the this.formatMessage, this.getIntlMessage, etc... methods from outside of a React component. It seems like we'll need to also include intl-messageformat directly and rebuild much of logic for caching/getting messages that react-intl already does.
For instance, when writing a validator for a form which returns error messages, I would want to have my validation logic outside of my component and pass back an internationalized/localized error message that my component could then display.
from formatjs.
Yes, @pselden understood me correctly. Sometimes I need to format message outside of component instance
from formatjs.
You guys can use the IntlMessageFormat
API directly by depending on intl-messageformat
as well as react-intl
.
from formatjs.
Does using intl-messageformat
directly work for you guys?
Our original vision is that we'd build up APIs like IntlMessageFormat
and IntlRelativeFormat
that look at work similar to the built-in Intl.NumberFormat
and Intl.DateTimeFormat
APIs. So when you wanted to format data in pure JavaScript code, you'd use these APIs directly. And the high-level integrations like React Intl provide a declarative sugar layer over top of the low level APIs.
from formatjs.
@ericf Is there any particular advantage of using this.formatMessage
instead of something like t()
?
What I'm thinking:
var Intl = require('intl');
Intl.t('my.string'); // this can be used anywhere
This approach would get rid of the mixin and having to pass messages as props. You can also reuse it from anywhere.
Yes, it can be built using IntlMessageFormat (ie. a new adapter), but I don't see why you guys have built a mixin instead of providing some generic functionality.
from formatjs.
Yep, intl-messageformat good, but in this way react-intl became redundant in project
from formatjs.
@ericf Thank you for the answer!
However, it seems my comment wasn't clear enough. When I said require('intl')
I wasn't referring to the built-in object, but to a "generic" adapter. I do agree that having an adapter has advantages over using the intl-*
libraries and I was in fact advocating an adapter that's not tied to a specific library. So my code would probably be more clear if I write it like this:
var i18n = require('generic-intl-adapter'); // sugar package, just like react-intl, without the react integration
i18n.formatMessage('my.example.message'); // same API as the react component, just without the "this." prefix
i18n.formatNumber(1000, { style : 'currency', currency: 'USD' }); // etc
I believe this approach would have the same benefits you outlined above, plus you wouldn't have to propagate the message, formats, etc throughout the react component hierarchy (they would just be added to an i18n object used everywhere) and you wouldn't need to add a mixin to every react component.
@caridy Right now we're using react-intl
as is and it serves our needs. My comment was more of a question rather than a statement, sorry if it came out differently. Given the low-level API we'll be able to build anything we want, if need be.
from formatjs.
@deviousdodo Okay I see, that's more clear now.
@caridy and I have been debating this. We're trying to determine if we want people to just use the low-level APIs like Intl.NumberFormat
, IntlMessageFormat
, etc. or provide a higher-level library for use in JavaScript — probably called Format.js 😄
I've also been investigating how we can support ES6 template strings, as the way to provide a declarative way to format messages in pure JavaScript code. And this is something we'll likely be supporting since the implementation is trivial to do so:
var num = 1000;
var msg = formatMessage`{${num}, number, integer} photos`
console.log(msg); // => "1,000 photos"
So for now, our answer is use the Intl*
apis, if you want caching support you can also use the intl-format-cache
package on npm which memoizes the Intl*
constructors. And know that we're actively working on creating a possible Format.js lib that's higher level, and we could use that as the base for all our higher level template libs integrations as well.
from formatjs.
@ericf A Format.js lib would be awesome, both standalone and as the base for the lib adapters (since it would make writing other adapters easier).
Thanks again for the detailed reply!
from formatjs.
I'm also struggling with this - is there a way to access the translations outside of the component? Without the mixin? I'm trying get some model validation messages translated that don't live inside a component and couldn't find something in the docs
from formatjs.
@steffenmllr Have you succeeded? I suppose for formating outside component, we can bypass whole react-intl.
from formatjs.
Oh i'm stuck... how i can use it outside component? I need translate message on action creator
export const fetchNotificationsFailure = () => ({
type: appConstants.SHOW_ERROR,
message: 'Please try to the refresh page. Error code: #n1.',
});
from formatjs.
@zabojad React Intl builds on a set of core libraries: http://formatjs.io/github/#core
from formatjs.
@ericf I know that. I've tried to used Intl MessageFormat
outside of my react components but when I do so, I have to give it all the app messages and locale data as it's another instance of intl than the one used by my IntlProvider at the root of my App component... IMO, there should be a way to use the same intl instance for both...
from formatjs.
@ericf your solution is work for me. thank you very much.
from formatjs.
@klimashkin, Try https://www.npmjs.com/package/react-intl-universal, it Internationalize React apps not only for React.Component but also for Vanilla JS. It's just the right tool for your question.
import intl from 'react-intl-universal';
class App extends React.Component {
render() {
return <div> intl.get('key') </div>
}
}
from formatjs.
If you use React 16, this is now possible simply with a little sugar. The reason it is possible is that React 16 allows you to return text directly from a component now. The difference with FormatMessage is that FormatMessage returns a <span>Result text</span>
around your result text.
import React from 'react';
import { injectIntl } from 'react-intl';
const GetMessage = ({ id, params, intl }) => intl.formatMessage({ id, params });
export default injectIntl(GetMessage);
<GetMessage id="ui.key"/>
Unfortunately, the result is still a React Element. Just without the extra span.
from formatjs.
@adyz Any update on the performance of this code?
from formatjs.
this issue is very old, what r you looking for specifically?
from formatjs.
@longlho I have 2 questions.
First thing is for using React-Intl API outside of React components. I know we can now use 'createIntl' to achieve this, and I'm wondering whether it is okay to make a util file with the custom functions like the following and use it everywhere. I did not want to call createIntl() and getLocale, message again and again everywhere.
import { createIntl, createIntlCache } from 'react-intl';
const locale = getLocale(); // this is my func
const messages = getMessage(); // this is my func
const cache = createIntlCache();
const intl = createIntl({locale, messages}, cache);
export function formatMessage(message) {
intl.formatMessage(message);
}
from formatjs.
Also, secondly, I know for the class component, we need to call injectIntl() to wrap the class component and preferably I do not want to wrap so many components just to have the access to the props of Intl. So is there any way to being able to use Intl without calling injectIntl()?
OR if the solution above is feasible, why don't we just call the custom function created above to use Intl in the class component?
I'm guessing this is not possible, otherwise, there wouldn't be so much discussion around InjectIntl() when there is a simple solution like this. Thank you in advance.
from formatjs.
@longlho I have 2 questions.
First thing is for using React-Intl API outside of React components. I know we can now use 'createIntl' to achieve this, and I'm wondering whether it is okay to make a util file with the custom functions like the following and use it everywhere. I did not want to call createIntl() and getLocale, message again and again everywhere.import { createIntl, createIntlCache } from 'react-intl'; const locale = getLocale(); // this is my func const messages = getMessage(); // this is my func const cache = createIntlCache(); const intl = createIntl({locale, messages}, cache); export function formatMessage(message) { intl.formatMessage(message); }
Yes you can do that, we're doing at at Dropbox.
from formatjs.
@longlho Sorry the discussion is kind of everywhere. Yes, I would like to use this custom formatMessage in react class component as well, and it seemed like its working fine.
Do you see any potential issue with this approach of creating the util file like above rather than calling InjectIntl() for every class component?
from formatjs.
@longlho just before closing this old thread and moving to the new one, could you answer the question about the potential issue with using this custom function in class components when you get chance? Thank you so much
from formatjs.
Since locale
& messages
are global you'd have to make sure your code operate in a runtime where those variables never change, which is generally the correct assumption for code in browser (but not SSR). Other than that it's ok.
from formatjs.
@longlho sorry i'm a bit confused by 'operate in a runtime where those variables never change'. Why they should not change when you use this approach?
We allow users to choose a language on a setting page and we set locale
to the chosen language so locale
does change sometimes.
from formatjs.
Every time you change locale or messages or config you need to re-create intl
object. Based on your code snippet above it looks like you don't?
from formatjs.
Related Issues (20)
- @formatjs/intl-numberformat/polyfill: roundingIncrement seems to be a no-op HOT 3
- [docs] Rich Text Formatting example doesn't work HOT 2
- Polyfill.io has been sold to a weird Chinese company and should no longer be recommended HOT 1
- chore: update tzdata to 2024a
- INVALID_TAG when parsing regular HTML tag with attribute HOT 1
- Can't catch error HOT 1
- Feature request: allow units greater than `day` in `FormattedRelativeTime` with `updateIntervalInSeconds` to be picked HOT 2
- It's incredibly slow on lower end Android devices HOT 2
- Intl.Segmenter: isWordLike does not match Node.js and browsers HOT 2
- @formatjs/intl-locale/polyfill-force TypeError: Error uninitialized locale at Locale2.getWeekInfo HOT 3
- .formatMessage is not working when provided messages has object with `type: 1` HOT 8
- Extract does not work on vue template since vue 3.4.0 HOT 1
- eslint-plugin-formatjs doesn't check `this.intl.formatMessage(...)` usages HOT 1
- `LocaleMatcher` doesn't work on propietary tags
- Node 20.12.1 x Jest; shouldPolyfill results in RangeError. Incorrect locale information provided
- eslint-plugin-formatjs and eslint v9 support
- Website - search is broken
- @formatjs/intl-localematcher documentation is wrong... incorrect order HOT 1
- @formatjs/swc-plugin-experimental incompatible with latest SWC core version
- cli-lib's `extract` function ignores `throws` setting for errors in `processFile`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from formatjs.