Aleksa Krstic
Aleksa Krstic
January 31, 2021
3 min read
January 31, 2021
3 min read

Quick Guide to ICU Message Format

If you have localized your code in certain frameworks you probably came across the term “ICU message” for formatting texts. In this article, we will explain why it exists and how to use it.

Why do we need ICU message format?

Software localization is more than managing plain text translations. Sometimes we need to inject some dynamic values into translations, format the values depending on locale grammar, switch parts of translations depending on the input, etc.

If we don’t have a common, standardized way to do that, we end up with different solutions among libraries. ICU message is a flexible yet powerful syntax to express all nuances of grammar for each language.

Where can I use ICU message?

These are some popular libraries that support ICU message formatting:

Support for ICU messages differs a bit among libraries, but they have the same foundation.

Note: For exact limitations for each of these libraries it is best to check their official documentation.

How to use ICU message format?

Here we will list common usages for ICU message formats. You can use an online ICU editor to explore the options on your own.

Plain string

Just a plain text.

Hello world!


A text with a placeholder that will be replaced with a variable. Placeholders are wrapped into curly braces.

Welcome {firstName}


A text that contains plural content.

You have {count, plural,
  one{1 photo}
  other{{count} photos}

In given example count represents a number variable, but you can name it as you want. Some libraries support # as an abbreviated placeholder for the count.

Available plural forms are: zero, one, two, many and other (required). Not all languages support all plural forms. For instance, English and German support one and other only, but Russian supports one, few, many and other. Check out plural forms per language for more info.

If you want to customize the format for a certain number, you can use additional =<number> forms. For instance, if you want to print You don't have any photo instead of You have 0 photos you would define it with =0 form. Some libraries allow usage of zero form for all languages for such cases.

You have {count, plural,
  =0 {no photos}
  one{1 photo}
  other{{count} photos}


Select statements take the form that matches passed variable or defaults to other form, which is required.

Today is {gender, select, 
  male {his} 
  female {her} 
  other {their}
} birthday

If we pass gender variable with the value male to the example, it will print Today is his birthday.

Number formatting

The base for formatting the numbers is to define them in {variable, number, format} form, where variable is the variable we pass, and the format is optional and can have one of a few values. Be aware that not all libraries support all these formats.

The tank is {progress, number, percent} full

which prints The tank is 80% full.

Numbers are printed in a format for the selected locale. For instance:

  • 1 234,56 in France
  • 1.234,56 in Germany
  • 1,234.56 in the United States

Date & Time

The base for formatting the dates and times is to define them in {variable, date|time, format} form. The variable is the variable we pass, and the format is optional and can be short, medium, long, full or some custom format depending on the library used.

Today is: {now, date, long}

which prints Today is: January 10, 2021.

Nested structures

Any of the elements above can be combined into the same ICU message, and in addition to that plural and select elements can be nested, containing each other.

{likesCount, plural,
  one{{sex, select,
        male{He likes}
        female{She likes}
        other{They like}
      } your photo}
  other{You have {likesCount} likes}

The structure can get complex and we suggest using ICU message editor that supports syntax highlighting and validation.


We can see that some libraries do not follow all ICU message features, although have the same foundation. But a good thing is that it goes in a good direction to standardize such formats for text localization.

Like this article? Share it!

Aleksa Krstic
Aleksa Krstic

Aleksa is a Software Engineer at Localizely. Over the past few years, Aleksa has been working in the field of software localization. In his free time, he enjoys playing guitar and writing tech posts.

Enjoying the read?

Subscribe to the Localizely blog newsletter for quality product content in your inbox.


How to translate ARB files efficiently
March 01, 2024
In “Localization
Localization Statistics 2023
December 22, 2023
In “Localization
Copyrights 2024 © Localizely