2

I am using react-intl package for internationalization. The package, in turn, relies on intl-messageformat. I’ve been searching through the docs in both packages, but am still confused about whether it is possible to internationalize messages for variables that are fractions. For example, as discussed here:

some languages use the equivalent of “1.2 teaspoons” but “2.1 teaspoon”

Is there a way to account for fractions when using react-intl/intl-messageformat? So far I’ve only seen examples with integers in the docs.

azangru
  • 2,644
  • 5
  • 34
  • 55

1 Answers1

2

Use FormattedNumber to handle decimals. For example:

    it('formats numbers with decimal separators', () => {
        const el = <FormattedNumber value={0.1} minimumFractionDigits={2} />;

        renderer.render(el, intlProvider.getChildContext());
        expect(renderer.getRenderOutput()).toEqualJSX(
            <span>0.10</span>
        );
    });

Use different values for plural:

    it('pluralizes labels in strings', () => {
        const el = (
            <FormattedMessage
                id="num_emails"
                defaultMessage="You have 1.{teaspoons, plural, one {# teaspoons} other {# teaspoons}}."
                values={{
                    teaspoons: 2,
                }}
            />
      );

and singular:

    it('pluralizes labels in strings', () => {
        const el = (
            <FormattedMessage
                id="num_emails"
                defaultMessage="You have 2.{teaspoons, plural, one {# teaspoons} other {# teaspoons}}."
                values={{
                    teaspoons: 1,
                }}
            />
      );

References

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
  • Oh, but that's not what I am asking about! My question was not about how to handle decimal numbers, but about whether it's possible to render the correct form of noun depending on the decimal number (see teaspoon / teaspoons in my quoted example). – azangru May 01 '17 at 21:40
  • The approach you suggest in your edited answer is definitely interesting! I haven't thought of that. However this approach assumes that the number you are passing is always a decimal (and the digits before the decimal point are hardcoded). Is there a more general way though, that will handle the cases of "1 teaspoon", "2 teaspoons", "1.1 teaspoon", and "1.2 teaspoons"? – azangru May 02 '17 at 12:28
  • There is a [selectFormat](https://youtu.be/4ZXagCR9urg?t=11m58s) which works like a `switch/case` statement. There is a [test case](https://github.com/yahoo/intl-messageformat/blob/master/tests/benchmark/new_complex_msg_preparsed.js) and a [tutorial](https://medium.com/@tomi.trescak/setting-up-i18n-with-react-intl-in-mantra-react-application-12f90ff34f17) which demonstrate how it works. – Paul Sweatte May 02 '17 at 13:38
  • Right. But that means I have a very limited set of predefined values that I can pass to the `formatMessage` :-( – azangru May 02 '17 at 13:52
  • Pass a function which returns a computed value based some generic algorithm to overcome this limitation. There is a [function-as-child pattern](https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9) which covers this in react and is supported by [react-intl](https://github.com/yahoo/react-intl/commit/880270f155dba2e60bbc4a9b3b4faafe54f3d7d9) mainly for rich text. – Paul Sweatte May 02 '17 at 14:03