Categories
React

React-Intl — Message Formatting

Spread the love

Many apps have to be made usable by different users from various parts of the world.

To make this easier, we can use the react-intl to do the internationalization for us.

In this article, we’ll look at how to get started with formatting messages with the react-intl library.

Message Syntax

We can format messages with placeholders and quantities.

For instance, we can write:

import React from "react";
import { IntlProvider, FormattedMessage } from "react-intl";
const messages = {
  en: {
    greeting: `Hello, {name}, you have {itemCount, plural,
      =0 {no items}
      one {# item}
      other {# items}
    }.`
  }
};
export default function App() {
  const [name] = React.useState("james");
  const [itemCount] = React.useState(20);
  return (
    <IntlProvider locale="en" messages={messages.en}>
      <p>
        <FormattedMessage id="greeting" values={{ name, itemCount }} />
      </p>
    </IntlProvider>
  );
}

to create a translation with the placeholders.

We have placeholder for name and itemCount .

The plural rules are defined by:

{itemCount, plural,
  =0 {no items}
  one {# item}
  other {# items}
}

Then we pass in the name and itemCount and they’ll be interpolated.

The id also has to be set.

Default Message

We can set the default message in the FormattedMessage component.

For instance, we can write:

import React from "react";
import { IntlProvider, FormattedMessage } from "react-intl";
const messages = {
  en: {
    greeting: `Hello, {name}.`
  }
};
export default function App() {
  const [name] = React.useState("james");
  return (
    <IntlProvider locale="en" messages={messages.en}>
      <p>
        <FormattedMessage
          id="greeting"
          description="a greeting"
          defaultMessage="Hello, {name}!"
          values={{
            name
          }}
        />
      </p>
    </IntlProvider>
  );
}

We have the defaultMessage prop which is overridden by the message that we defined.

If we remove the greeting message, then it’ll be used:

import React from "react";
import { IntlProvider, FormattedMessage } from "react-intl";
const messages = {
  en: {}
};
export default function App() {
  const [name] = React.useState("james");
  return (
    <IntlProvider locale="en" messages={messages.en}>
      <p>
        <FormattedMessage
          id="greeting"
          description="a greeting"
          defaultMessage="Hello, {name}!"
          values={{
            name
          }}
        />
      </p>
    </IntlProvider>
  );
}

We can also format the translated text with a function:

import React from "react";
import { IntlProvider, FormattedMessage } from "react-intl";
const messages = {
  en: {}
};
export default function App() {
  const [name] = React.useState("james");
  return (
    <IntlProvider locale="en" messages={messages.en}>
      <p>
        <FormattedMessage
          id="greeting"
          description="a greeting"
          defaultMessage="Hello, {name}!"
          values={{
            name
          }}
        >
          {txt => <h1>{txt}</h1>}
        </FormattedMessage>
      </p>
    </IntlProvider>
  );
}

We have a function instead of nothing as the child of FormattedMessage so we’ll see an h1 heading instead of the default style.

Rich Text Formatting

We can divide the text into chunks and format it.

For instance, we can write:

import React from "react";
import { IntlProvider, FormattedMessage } from "react-intl";
const messages = {
  en: {}
};
export default function App() {
  const [name] = React.useState("james");
  return (
    <IntlProvider locale="en" messages={messages.en}>
      <p>
        <FormattedMessage
          id="greeting"
          description="greeting"
          defaultMessage="Hello, <b>{name}</b>"
          values={{
            b: (...chunks) => <b>{chunks}</b>,
            name
          }}
        />
      </p>
    </IntlProvider>
  );
}

to format the bold text by returning our own component.

b is the tag name and it should match the message.

name has the value of the name placeholder.

It can be any XML tag.

We can have more complex formatting:

import React from "react";
import { IntlProvider, FormattedMessage } from "react-intl";
const messages = {
  en: {}
};
export default function App() {
  return (
    <IntlProvider locale="en" messages={messages.en}>
      <p>
        <FormattedMessage
          id="greeting"
          defaultMessage="Go <a>visit our website</a> and <cta>read it</cta>"
          values={{
            a: (...chunks) => (
              <a
                class="external_link"
                target="_blank"
                rel="noopener noreferrer"
                href="https://www.example.com/"
              >
                {chunks}
              </a>
            ),
            cta: (...chunks) => <b>{chunks}</b>
          }}
        />
      </p>
    </IntlProvider>
  );
}

We replace the a and cta tags with our own components.

FormattedDisplayName

We can format the display name with the FormattedDisplayName component.

For example, we can write:

import React from "react";
import { IntlProvider, FormattedDisplayName } from "react-intl";
const messages = {
  en: {}
};
export default function App() {
  return (
    <IntlProvider locale="en" messages={messages.en}>
      <p>
        <FormattedDisplayName type="currency" value="USD" />
      </p>
    </IntlProvider>
  );
}

We can pass in the type and value props to return the full name of the value .

Conclusion

We can display translated and formatted text with the FormattedMessage component.

FormattedDisplayName lets us display the full name of languages and currencies.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *