Flutter Pluralization: A Complete Guide for Developers
Handling plurals correctly is one of the most overlooked aspects of Flutter localization. Different languages have wildly different pluralization rules—English has two forms (one/other), but Arabic has six, and Polish has complex rules based on the last digit.
Why Pluralization Matters
Consider this simple English string: "You have 1 item" vs "You have 5 items". Now multiply that complexity across 20+ languages, each with their own rules. Getting it wrong makes your app feel unprofessional and can even change the meaning of sentences.
Flutter's ICU Message Format
Flutter uses the ICU (International Components for Unicode) message format for plurals. Here's the basic syntax:
{
"itemCount": "{count, plural, =0{No items} =1{One item} other{{count} items}}",
"@itemCount": {
"description": "Number of items",
"placeholders": {
"count": {
"type": "int"
}
}
}
}
Plural Categories
Different languages support different plural categories:
- zero: Used in Arabic for zero items
- one: Singular form
- two: Used in Arabic for exactly two items
- few: Used in languages like Polish, Russian for numbers ending in 2-4
- many: Used in Arabic for numbers 11-99
- other: Default fallback for all other cases
Real-World Example: Shopping Cart
Here's how to handle a shopping cart message across multiple languages:
English (app_en.arb)
{
"cartItems": "{count, plural, =0{Your cart is empty} =1{You have one item} other{You have {count} items}}",
"@cartItems": {
"description": "Shopping cart item count",
"placeholders": {
"count": {"type": "int"}
}
}
}
Arabic (app_ar.arb)
{
"cartItems": "{count, plural, =0{سلتك فارغة} =1{لديك منتج واحد} =2{لديك منتجان} few{لديك {count} منتجات} many{لديك {count} منتجاً} other{لديك {count} منتج}}",
"@cartItems": {
"description": "Shopping cart item count",
"placeholders": {
"count": {"type": "int"}
}
}
}
Polish (app_pl.arb)
{
"cartItems": "{count, plural, =0{Twój koszyk jest pusty} =1{Masz jeden przedmiot} few{Masz {count} przedmioty} many{Masz {count} przedmiotów} other{Masz {count} przedmiotu}}",
"@cartItems": {
"description": "Shopping cart item count",
"placeholders": {
"count": {"type": "int"}
}
}
}
Using Plurals in Your Code
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class CartPage extends StatelessWidget {
final int itemCount;
const CartPage({required this.itemCount});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(
title: Text(l10n.cartItems(itemCount)),
),
body: // ... your cart content
);
}
}
Common Mistakes to Avoid
❌ Don't concatenate strings
// Wrong!
String message = '$count ' + (count == 1 ? 'item' : 'items');
✅ Use proper pluralization
// Correct!
String message = AppLocalizations.of(context)!.itemCount(count);
❌ Don't assume English plural rules
// Wrong! Doesn't work for Arabic, Polish, etc.
if (count == 1) {
return 'item';
} else {
return 'items';
}
Testing Plural Forms
Test your plurals with edge cases:
void main() {
testWidgets('Plural forms test', (tester) async {
await tester.pumpWidget(MyApp());
// Test zero
expect(find.text(l10n.cartItems(0)), findsOneWidget);
// Test one
expect(find.text(l10n.cartItems(1)), findsOneWidget);
// Test few (for Polish)
expect(find.text(l10n.cartItems(3)), findsOneWidget);
// Test many (for Arabic)
expect(find.text(l10n.cartItems(15)), findsOneWidget);
// Test large numbers
expect(find.text(l10n.cartItems(100)), findsOneWidget);
});
}
Complex Plurals with Gender
Some languages combine plurals with gender. Here's a French example:
{
"friendsCount": "{count, plural, =0{Aucun ami} =1{Un ami} other{{count} amis}}",
"friendsCountFemale": "{count, plural, =0{Aucune amie} =1{Une amie} other{{count} amies}}"
}
FlutterLocalisation Makes This Easy
Managing plural forms across dozens of languages manually is error-prone. FlutterLocalisation provides:
- ✅ Automatic plural form validation for each language
- ✅ Visual editor showing all plural categories
- ✅ AI translation that understands plural rules
- ✅ Warning when plural forms are incomplete
- ✅ Testing tools for all plural categories
Best Practices
- Always provide all necessary plural forms for each language
- Test with real data from native speakers
- Use descriptive placeholder names like
{itemCount}not just{n} - Document your plurals with clear
@metadata - Use FlutterLocalisation to catch missing plural forms automatically
Conclusion
Pluralization is complex, but Flutter's ICU message format makes it manageable. The key is understanding that different languages have different rules, and planning for that from the start.
Don't let poor pluralization make your app feel unprofessional. With proper implementation and tools like FlutterLocalisation, you can handle even the most complex plural rules with confidence.
Ready to simplify your Flutter pluralization? Try FlutterLocalisation and get automatic plural validation, visual editing, and AI translation that understands language-specific plural rules.