Localizely logo
  • Home
  • Getting started
  • How it works
  • Pricing
  • FAQ
Sign up

I18n questions · React

How do I use a translated string in an input placeholder with react-intl? 

<FormattedMessage> is a component; it renders the formatted text into a React.Fragment or the element named in tagName, so it cannot be assigned to an attribute. placeholder, title, alt and aria-label take plain strings, and the react-intl docs list exactly this case, "setting text attributes such as title, aria-label", as the reason the imperative API exists.

Get the intl object with the useIntl hook and call formatMessage:

import { defineMessages, useIntl } from 'react-intl';

const messages = defineMessages({
  searchPlaceholder: {
    id: 'search.placeholder',
    defaultMessage: 'Search',
    description: 'Placeholder text of the search box',
  },
});

function SearchBox() {
  const intl = useIntl();
  const label = intl.formatMessage(messages.searchPlaceholder);

  return <input type="search" placeholder={label} aria-label={label} />;
}

An inline descriptor works the same: intl.formatMessage({ id: 'search.placeholder', defaultMessage: 'Search' }). defineMessages returns the descriptors unchanged; its job is to keep them in a shape the formatjs CLI and Babel plugin can extract, so prefer it over building ids at runtime.

formatMessage returns a string as long as every value is a primitive, as in { count } or { name: 'Ana' }. Pass a React element or a rich-text function and you get an array of nodes instead, which is again unusable in an attribute. Variables in attribute text otherwise work like anywhere else; see How to use dynamic strings in a localization message in React?.

useIntl only works in function components. The injectIntl higher-order component that used to supply this.props.intl to class components was removed in react-intl 10 (upgrade guide). A class you cannot convert can read the exported IntlContext through static contextType and call this.context.formatMessage(...), or be wrapped by a small function component that calls useIntl and passes intl down as a prop.

Outside React, for example in a validation helper, build the same object with createIntl, as shown in How to use localization messages in non-component code in React?.

With react-i18next there is nothing to work around: t returns a string, so placeholder={t('search.placeholder')} is all it takes.

Published Oct 9, 2026 · Markdown version

Related React internationalization questions:

React internationalization tutorial:

Learn about internationalization in React
Localizely logo
About
Free tools
Boring stuff
  • Privacy Policy
  • Terms of Service
  • Cookie Policy
Newsletter
Copyrights 2026 © Localizely