Simple Variable Substitution in ICU Messages
Understand how simple argument replacement works in ICU MessageFormat with named placeholders. Covers best practices for naming variables and handling missing values.
Detailed Explanation
Simple Variable Substitution
The most basic ICU MessageFormat feature is simple variable substitution. You place a variable name inside curly braces, and the runtime replaces it with the provided value.
Syntax
Hello, {firstName} {lastName}!
Welcome to {appName}.
Your order #{orderId} has been confirmed.
Variable Naming Best Practices
ICU variable names are identifiers that appear inside curly braces. Following consistent naming conventions makes translation files easier to maintain:
- Use camelCase:
{firstName},{itemCount},{userName} - Be descriptive: Prefer
{recipientName}over{name}when context matters - Keep names language-neutral: Use
{count}not{numberOfThings}since translators should not need to understand English variable names - Document variables: In translation management systems, provide context for each variable (e.g., "userName: the logged-in user's display name")
How It Works Internally
When the ICU formatter processes Hello, {name}! with values { name: "Alice" }:
- The parser splits the message into segments: text("Hello, "), argument("name"), text("!")
- The formatter iterates through segments
- For each argument segment, it looks up the value in the provided values object
- Text segments pass through unchanged
- The final string is assembled: "Hello, Alice!"
Handling Missing Variables
If a variable is referenced in the pattern but not provided in the values object, most ICU implementations either:
- Leave the placeholder as-is:
Hello, {name}! - Throw a runtime error
- Substitute an empty string
The safest approach is to always provide all required variables and validate your translation files against the source messages during your build process.
Multiple Variables
A single ICU message can contain any number of variables:
{senderName} sent you a message about "{subject}" at {timestamp}.
The order of variables in the message does not need to match the order in the values object. This is crucial for translation -- different languages will reorder these variables to match their natural sentence structure.
Use Case
Frontend developers implementing their first translated UI strings who need to understand how to pass dynamic values like user names, product names, and IDs into localized messages.