@messageformat/core, format-message, and intl-messageformat are JavaScript libraries designed to handle dynamic text interpolation, pluralization, and select logic using the ICU MessageFormat syntax. They enable developers to write translation strings that adapt to different languages and contexts without hard-coding logic. While they share a common goal, they differ in compilation strategy, runtime dependencies, and ecosystem support. intl-messageformat is the most widely adopted in modern React ecosystems, @messageformat/core serves as a low-level compiler for custom tools, and format-message offers a standalone alternative with a simpler API.
All three libraries solve the same core problem — turning static translation strings into dynamic, language-aware text. They support the ICU MessageFormat standard, which handles plurals, gender selection, and variable interpolation. However, they approach the task differently in terms of compilation, dependencies, and ecosystem fit. Let's break down how they work in real engineering scenarios.
How and when the message string turns into executable code matters for performance and bundle size.
intl-messageformat compiles messages at runtime by default.
// intl-messageformat: Runtime compilation
import IntlMessageFormat from 'intl-messageformat';
const msg = new IntlMessageFormat('Hello {name}', 'en-US');
const output = msg.format({ name: 'Alice' });
@messageformat/core is a compiler only.
// @messageformat/core: Build-time compilation
import MessageFormat from '@messageformat/core';
const mf = new MessageFormat('en-US');
const comp = mf.compile('Hello {name}');
// `comp` is a standalone function you can ship
const output = comp({ name: 'Alice' });
format-message supports both runtime and build-time.
// format-message: Runtime usage
import formatMessage from 'format-message';
const output = formatMessage('Hello {name}', { name: 'Alice' }, 'en-US');
Dependency management affects bundle size and browser support.
intl-messageformat relies on the native Intl API.
// intl-messageformat: Requires Intl polyfill for old browsers
// import '@formatjs/intl-pluralrules/polyfill';
// import '@formatjs/intl-numberformat/polyfill';
const msg = new IntlMessageFormat('You have {count} items', 'en-US');
@messageformat/core generates dependency-free code.
Intl.// @messageformat/core: No Intl dependency in output
const mf = new MessageFormat('en-US');
const comp = mf.compile('You have {count} items');
// Compiled code handles plural logic internally
format-message also depends on Intl for some features.
intl-messageformat but less integrated tooling.// format-message: Intl dependent for plurals
formatMessage.setup({ locale: 'en-US' });
const output = formatMessage('You have {count, plural, one {item} other {items}}', { count: 5 });
The way you call these libraries impacts code readability and maintenance.
intl-messageformat uses a class-based API.
// intl-messageformat: Class instance
const msg = new IntlMessageFormat('Welcome {user}', 'en-US');
console.log(msg.format({ user: 'Bob' }));
@messageformat/core uses a compiler-function flow.
// @messageformat/core: Compile then call
const mf = new MessageFormat('en-US');
const renderWelcome = mf.compile('Welcome {user}');
console.log(renderWelcome({ user: 'Bob' }));
format-message uses a functional API.
// format-message: Single function call
console.log(formatMessage('Welcome {user}', { user: 'Bob' }, 'en-US'));
Long-term support matters for enterprise applications.
intl-messageformat is part of the FormatJS ecosystem.
@messageformat/core is part of the messageformat project.
format-message has lower recent activity.
| Feature | intl-messageformat | @messageformat/core | format-message |
|---|---|---|---|
| Primary Use | Runtime formatting in apps | Build-time compilation | Runtime or CLI |
| Dependencies | Needs Intl polyfills | None in output | Needs Intl polyfills |
| API Style | Class-based | Compiler + Function | Functional |
| Ecosystem | Large (FormatJS) | Medium (Tooling) | Smaller |
| Best For | React/Modern Web Apps | Custom i18n Tools | Simple Scripts |
intl-messageformat is the safe bet for most teams. It offers the best balance of features, support, and integration with modern frameworks. If you are building a React app, this is likely what you want.
@messageformat/core is for tool builders. If you are creating your own i18n platform or need to ship zero-dependency code, this gives you the engine without the overhead.
format-message is a viable alternative for simpler needs. It works well if you want ICU support without buying into the FormatJS ecosystem, but check maintenance status before committing to large projects.
Final Thought: All three handle ICU syntax correctly. The choice depends on whether you need a full ecosystem (intl-messageformat), a compiler engine (@messageformat/core), or a lightweight standalone tool (format-message).
Choose @messageformat/core if you are building your own internationalization tooling or need a compiler that generates standalone JavaScript functions without runtime dependencies. It is ideal for build-time compilation pipelines where you want to ship zero-dependency formatting code to the browser. Avoid using it directly in application code if you need a ready-made formatting API.
Choose format-message if you need a lightweight, standalone library that supports ICU syntax without the overhead of the larger FormatJS ecosystem. It is suitable for smaller projects or non-React environments where simplicity is key. However, verify current maintenance status before committing, as community activity is lower compared to alternatives.
Choose intl-messageformat if you are building a modern web application, especially with React, and need robust support for the Intl API, polyfills, and a large ecosystem. It is the standard choice for projects requiring long-term maintenance, strong TypeScript support, and integration with tools like react-intl or next-intl.
The experience and subtlety of your program's text is important. The messageformat project provides a complete set of tools for handling all the messages of your application, for both front-end and back-end environments; for both runtime and build-time use. It's built around the ICU MessageFormat standard and supports all the languages included in the Unicode CLDR, but it can be just as useful if you're dealing with only one of them.
ICU MessageFormat is a mechanism for handling both pluralization and gender in your applications. This is the core compiler of a JavaScript project supports and extends all parts of the official Java/C++ implementation, with the exception of the deprecated ChoiceFormat. In addition to compiling messages into JavaScript functions, it also provides tooling for making their use easy during both the build and runtime of your site or application.
For more details, please see the project's documentation site: http://messageformat.github.io/
This package was previously named messageformat.
Messageformat is an OpenJS Foundation project, and we follow its Code of Conduct.
Copyright OpenJS Foundation and messageformat contributors. All rights reserved. The OpenJS Foundation has registered trademarks and uses trademarks. For a list of trademarks of the OpenJS Foundation, please see our Trademark Policy and Trademark List. Trademarks and logos not indicated on the list of OpenJS Foundation trademarks are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Browser testing provided by: