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:
- Java
- C & C++
- Python
- Dart & Flutter
- PHP & Symfony
- Javascript:
- FormatJS with react-intl for React
- Globalize
- Lingui.js
- MessageFormat
- ngx-translate plugin for Angular
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!
Placeholder
A text with a placeholder that will be replaced with a variable. Placeholders are wrapped into curly braces.
Welcome {firstName}
Plural
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
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. 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.
Summary
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.