Giter Site home page Giter Site logo

Use as static methods about formatjs HOT 37 CLOSED

formatjs avatar formatjs commented on May 2, 2024
Use as static methods

from formatjs.

Comments (37)

ericf avatar ericf commented on May 2, 2024 20

@zabojad

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.

steida avatar steida commented on May 2, 2024 3

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.

MarcoNicolodi avatar MarcoNicolodi commented on May 2, 2024 3

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.

adyz avatar adyz commented on May 2, 2024 3

@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.

caridy avatar caridy commented on May 2, 2024 2

guys, let's not be opinionated here. we do offer:

  1. The React way by providing react components (e.g.: <ReactIntl.Number style="percent">{0.95}</ReactIntl.Number>)
  2. 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 message SHORT, but also low level methods to format numbers, dates and messages with the corresponding cache layer on top of react.
  3. 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.

zabojad avatar zabojad commented on May 2, 2024 2

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 avatar ericf commented on May 2, 2024 1

@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:

  1. A declarative way to format data in templates.
  2. Caching of Intl* instances.
  3. Automatic lookup of locales, messages, and formats within the React component hierarchy.
  4. 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.

veddermatic avatar veddermatic commented on May 2, 2024 1

@adyz : Have you been using your solution, and if so, how does it perform?

from formatjs.

mtcanada avatar mtcanada commented on May 2, 2024 1

The discussion is related to #1609

from formatjs.

caridy avatar caridy commented on May 2, 2024

can you elaborate more?

from formatjs.

pselden avatar pselden commented on May 2, 2024

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.

klimashkin avatar klimashkin commented on May 2, 2024

Yes, @pselden understood me correctly. Sometimes I need to format message outside of component instance

from formatjs.

ericf avatar ericf commented on May 2, 2024

You guys can use the IntlMessageFormat API directly by depending on intl-messageformat as well as react-intl.

from formatjs.

ericf avatar ericf commented on May 2, 2024

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.

deviousdodo avatar deviousdodo commented on May 2, 2024

@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.

klimashkin avatar klimashkin commented on May 2, 2024

Yep, intl-messageformat good, but in this way react-intl became redundant in project

from formatjs.

deviousdodo avatar deviousdodo commented on May 2, 2024

@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.

ericf avatar ericf commented on May 2, 2024

@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.

deviousdodo avatar deviousdodo commented on May 2, 2024

@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.

steffenmllr avatar steffenmllr commented on May 2, 2024

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.

steida avatar steida commented on May 2, 2024

@steffenmllr Have you succeeded? I suppose for formating outside component, we can bypass whole react-intl.

from formatjs.

DmitryOlkhovoi avatar DmitryOlkhovoi commented on May 2, 2024

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.

ericf avatar ericf commented on May 2, 2024

@zabojad React Intl builds on a set of core libraries: http://formatjs.io/github/#core

from formatjs.

zabojad avatar zabojad commented on May 2, 2024

@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.

lizhenhua86 avatar lizhenhua86 commented on May 2, 2024

@ericf your solution is work for me. thank you very much.

from formatjs.

cwtuan avatar cwtuan commented on May 2, 2024

@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.

mschipperheyn avatar mschipperheyn commented on May 2, 2024

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.

mtcanada avatar mtcanada commented on May 2, 2024

@adyz Any update on the performance of this code?

from formatjs.

longlho avatar longlho commented on May 2, 2024

this issue is very old, what r you looking for specifically?

from formatjs.

mtcanada avatar mtcanada commented on May 2, 2024

@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.

mtcanada avatar mtcanada commented on May 2, 2024

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 avatar longlho commented on May 2, 2024

@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.

mtcanada avatar mtcanada commented on May 2, 2024

@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.

mtcanada avatar mtcanada commented on May 2, 2024

@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.

longlho avatar longlho commented on May 2, 2024

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.

mtcanada avatar mtcanada commented on May 2, 2024

@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.

longlho avatar longlho commented on May 2, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.