---
title: "Which libraries and platforms support ICU message format?"
description: "ICU4C, ICU4J and Android (API 24+) implement the full syntax; FormatJS and react-intl, @messageformat/core, PHP's intl MessageFormatter, Dart intl with Flutter ARB files and Angular i18n support plural and select; java.text.MessageFormat has no plural rules, and iOS has none built in."
category: icu-message-format
date: 2026-10-09
canonical: https://localizely.com/i18n-questions/icu-message-format/which-libraries-and-platforms-support-icu-message-format/
---

# Which libraries and platforms support ICU message format?

ICU4C and ICU4J are the reference implementations, and most ecosystems have a library that covers at least the `plural` and `select` arguments. What each one supports:

- ICU4C (`icu::MessageFormat`) and ICU4J ([`com.ibm.icu.text.MessageFormat`](https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/text/MessageFormat.html)): the complete syntax, including `selectordinal`, named arguments, and number and date skeletons.
- Android: [`android.icu.text.MessageFormat`](https://developer.android.com/reference/android/icu/text/MessageFormat), ICU4J's class shipped in the platform since API level 24.
- JavaScript, [FormatJS](https://formatjs.github.io/docs/intl-messageformat/) (`intl-messageformat`, the engine behind react-intl): plural, select and selectordinal, number skeletons, a subset of the date and time skeletons, and rich-text tags.
- JavaScript, [`@messageformat/core`](https://messageformat.github.io/messageformat/) (formerly published as `messageformat`): compiles plural, select and selectordinal messages into JavaScript functions, with CLDR plural data for all languages.
- PHP: [`MessageFormatter`](https://www.php.net/manual/en/class.messageformatter.php) in the intl extension wraps the ICU library PHP is built against; its manual shows plural, selectordinal and `::currency/CAD` skeleton examples, so what works depends on that ICU version.
- Dart and Flutter: the [`intl`](https://pub.dev/packages/intl) package (`Intl.plural`, `Intl.select`) and [ARB files](/flutter-arb/) processed by Flutter's `gen_l10n` use the plural and select syntax, with `other` required and case-sensitive select matching.
- Angular: the built-in [i18n](https://angular.dev/guide/i18n/prepare) supports ICU expressions in templates, `{minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago}}` and `select`, and they can be nested.
- Java, [`java.text.MessageFormat`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/text/MessageFormat.html): only partially. Its argument types are `number`, `date`, `time` and `choice`; `ChoiceFormat` selects by numeric range without locale plural rules, and every apostrophe starts a quote. Use ICU4J for real plurals.
- iOS and macOS: no built-in ICU MessageFormat. Plurals go through [String Catalogs](https://developer.apple.com/documentation/xcode/localizing-and-varying-text-with-a-string-catalog) (Xcode 15 and later) or [`.stringsdict`](/apple-stringsdict-file/) files, which store one string per CLDR category behind a `%#@variable@` placeholder instead of a plural argument inside the message.

Implementations differ most in two places: whether an apostrophe starts a quote, explained in [How do I escape braces and apostrophes in ICU message format?](/i18n-questions/icu-message-format/how-do-i-escape-braces-and-apostrophes-in-icu-message-format/), and which skeletons they accept. Test messages in the target library, or in the [ICU message editor](/icu-message-editor/) for the reference ICU behaviour.

Source: https://localizely.com/i18n-questions/icu-message-format/which-libraries-and-platforms-support-icu-message-format/
