Flutter ARB Placeholders: Complete Guide to Dynamic Values in Translations
Master Flutter ARB placeholders with this comprehensive guide. Learn how to use variables, format dates, numbers, and create dynamic translations that adapt to user data.
What Are ARB Placeholders?
ARB (Application Resource Bundle) placeholders allow you to insert dynamic values into your translations. Instead of hardcoding values, you use placeholders that get replaced at runtime with actual data.
{
"greeting": "Hello, {userName}!",
"@greeting": {
"placeholders": {
"userName": {
"type": "String",
"example": "John"
}
}
}
}
This generates a method you can call with the actual value:
Text(AppLocalizations.of(context)!.greeting('John'))
// Output: "Hello, John!"
Basic Placeholder Syntax
Simple String Placeholders
The most common placeholder type passes a string value:
{
"welcomeMessage": "Welcome to {appName}",
"@welcomeMessage": {
"placeholders": {
"appName": {
"type": "String",
"example": "FlutterLocalisation"
}
}
}
}
Multiple Placeholders
You can use multiple placeholders in a single message:
{
"orderConfirmation": "Order #{orderId} for {customerName} has been confirmed",
"@orderConfirmation": {
"placeholders": {
"orderId": {
"type": "String",
"example": "12345"
},
"customerName": {
"type": "String",
"example": "John Smith"
}
}
}
}
Usage:
Text(AppLocalizations.of(context)!.orderConfirmation('12345', 'John Smith'))
Number Placeholders
Integer Values
For whole numbers:
{
"itemCount": "You have {count} items",
"@itemCount": {
"placeholders": {
"count": {
"type": "int",
"example": "5"
}
}
}
}
Double/Decimal Values
For decimal numbers:
{
"averageRating": "Average rating: {rating}",
"@averageRating": {
"placeholders": {
"rating": {
"type": "double",
"example": "4.5"
}
}
}
}
Formatted Numbers with decimalDigits
Control decimal precision:
{
"price": "Price: {amount}",
"@price": {
"placeholders": {
"amount": {
"type": "double",
"format": "decimalPattern",
"example": "1234.56"
}
}
}
}
Currency Formatting
Format numbers as currency:
{
"totalPrice": "Total: {price}",
"@totalPrice": {
"placeholders": {
"price": {
"type": "double",
"format": "currency",
"optionalParameters": {
"symbol": "$",
"decimalDigits": 2
},
"example": "99.99"
}
}
}
}
Compact Numbers
For large numbers that should be abbreviated:
{
"followers": "{count} followers",
"@followers": {
"placeholders": {
"count": {
"type": "int",
"format": "compact",
"example": "1200000"
}
}
}
}
Output examples:
- English: "1.2M followers"
- German: "1,2 Mio. followers"
Percentage Formatting
{
"completionRate": "{rate} complete",
"@completionRate": {
"placeholders": {
"rate": {
"type": "double",
"format": "percentPattern",
"example": "0.75"
}
}
}
}
Date and Time Placeholders
Basic Date Formatting
{
"eventDate": "Event on {date}",
"@eventDate": {
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMMMd",
"example": "2025-12-07"
}
}
}
}
Available Date Formats
Flutter supports ICU date format skeletons:
| Format | Example Output |
|---|---|
yMd |
12/7/2025 |
yMMMd |
Dec 7, 2025 |
yMMMMd |
December 7, 2025 |
yMMMMEEEEd |
Saturday, December 7, 2025 |
Hm |
14:30 |
Hms |
14:30:45 |
jm |
2:30 PM |
jms |
2:30:45 PM |
yMd_Hm |
12/7/2025, 14:30 |
Full DateTime Example
{
"appointmentTime": "Your appointment is on {dateTime}",
"@appointmentTime": {
"placeholders": {
"dateTime": {
"type": "DateTime",
"format": "yMMMMEEEEd",
"example": "2025-12-07T14:30:00"
}
}
}
}
Custom Date Formats
For more control, use custom patterns:
{
"customDate": "Posted on {date}",
"@customDate": {
"placeholders": {
"date": {
"type": "DateTime",
"format": "dd/MM/yyyy",
"isCustomDateFormat": "true",
"example": "2025-12-07"
}
}
}
}
Combining Placeholders with Plurals
Placeholders work seamlessly with plural rules:
{
"cartItems": "{count, plural, =0{Your cart is empty} =1{You have {count} item in your cart} other{You have {count} items in your cart}}",
"@cartItems": {
"placeholders": {
"count": {
"type": "int",
"example": "3"
}
}
}
}
Named Placeholders in Plurals
{
"unreadMessages": "{count, plural, =0{No new messages from {sender}} =1{1 new message from {sender}} other{{count} new messages from {sender}}}",
"@unreadMessages": {
"placeholders": {
"count": {
"type": "int",
"example": "5"
},
"sender": {
"type": "String",
"example": "John"
}
}
}
}
Best Practices for ARB Placeholders
1. Always Provide Examples
Examples help translators understand context:
{
"@welcomeBack": {
"placeholders": {
"userName": {
"type": "String",
"example": "Sarah"
},
"lastLoginDate": {
"type": "DateTime",
"format": "yMMMd",
"example": "2025-12-01"
}
}
}
}
2. Add Descriptions
Help translators understand how placeholders are used:
{
"fileSize": "File size: {size}",
"@fileSize": {
"description": "Displays the size of a file. The size is pre-formatted (e.g., '2.5 MB')",
"placeholders": {
"size": {
"type": "String",
"example": "2.5 MB"
}
}
}
}
3. Use Meaningful Placeholder Names
// Good
{
"greeting": "Hello, {firstName}!",
"@greeting": {
"placeholders": {
"firstName": {"type": "String"}
}
}
}
// Avoid
{
"greeting": "Hello, {x}!",
"@greeting": {
"placeholders": {
"x": {"type": "String"}
}
}
}
4. Consider Word Order Variations
Different languages have different word orders. Always use named placeholders:
{
"transferMessage": "{sender} sent {amount} to {recipient}",
"@transferMessage": {
"description": "Note: Word order may differ in translations",
"placeholders": {
"sender": {"type": "String", "example": "Alice"},
"amount": {"type": "String", "example": "$50"},
"recipient": {"type": "String", "example": "Bob"}
}
}
}
In German, this might become: "{sender} hat {amount} an {recipient} gesendet"
5. Handle Optional Values
If a placeholder might be empty, handle it in your code:
String displayName = user.nickname?.isNotEmpty == true
? user.nickname!
: user.email;
Text(AppLocalizations.of(context)!.greeting(displayName))
Common Placeholder Errors and Solutions
Error: "The argument type 'int' can't be assigned to 'String'"
Cause: Type mismatch between ARB definition and usage.
Solution: Check your placeholder type:
{
"itemCount": "{count} items",
"@itemCount": {
"placeholders": {
"count": {
"type": "int" // Make sure this matches your Dart code
}
}
}
}
Error: "Missing placeholder definition"
Cause: Using a placeholder without defining it in the metadata.
Solution: Add the @key metadata with placeholders:
{
"greeting": "Hello, {name}!",
"@greeting": {
"placeholders": {
"name": {
"type": "String"
}
}
}
}
Error: "Invalid date format"
Cause: Using an invalid format skeleton.
Solution: Use valid ICU format skeletons or mark custom formats:
{
"@eventDate": {
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMMMd", // Use valid skeleton
"isCustomDateFormat": "false"
}
}
}
}
Real-World Examples
E-commerce Order Status
{
"orderStatus": "Order #{orderId} - {status}. Estimated delivery: {deliveryDate}",
"@orderStatus": {
"description": "Shows order status with delivery estimate",
"placeholders": {
"orderId": {
"type": "String",
"example": "ORD-12345"
},
"status": {
"type": "String",
"example": "Shipped"
},
"deliveryDate": {
"type": "DateTime",
"format": "yMMMd",
"example": "2025-12-15"
}
}
}
}
Social Media Stats
{
"profileStats": "{posts} posts • {followers} followers • {following} following",
"@profileStats": {
"placeholders": {
"posts": {
"type": "int",
"format": "compact",
"example": "1234"
},
"followers": {
"type": "int",
"format": "compact",
"example": "50000"
},
"following": {
"type": "int",
"format": "compact",
"example": "500"
}
}
}
}
Banking Transaction
{
"transactionDetails": "{type} of {amount} on {date}",
"@transactionDetails": {
"description": "Transaction summary line item",
"placeholders": {
"type": {
"type": "String",
"example": "Withdrawal"
},
"amount": {
"type": "double",
"format": "currency",
"optionalParameters": {
"symbol": "$"
},
"example": "150.00"
},
"date": {
"type": "DateTime",
"format": "yMd",
"example": "2025-12-07"
}
}
}
}
Streamline Placeholder Management with FlutterLocalisation
Managing placeholders across multiple languages can get complex quickly. FlutterLocalisation.com helps you:
- Visual placeholder editing - See placeholders highlighted in your translations
- Validation - Catch missing or mismatched placeholders before building
- AI-powered translations - Automatically preserve placeholder syntax across 80+ languages
- Type safety - Ensure placeholder types are consistent across all translations
Stop wrestling with placeholder syntax errors. Try FlutterLocalisation free and manage your ARB files with confidence.
Summary
ARB placeholders are essential for creating dynamic, user-personalized translations in Flutter. Key takeaways:
- Use typed placeholders -
String,int,double,DateTime - Format numbers and dates - Use format options for locale-aware display
- Provide examples and descriptions - Help translators understand context
- Test all languages - Placeholder positions may vary by language
- Use tools - Visual editors prevent syntax errors
Master placeholders, and your Flutter app will deliver professional, dynamic translations that feel native to every user.