Common Flutter Localization Errors and How to Fix Them
Every Flutter developer encounters localization errors. From cryptic build failures to runtime crashes, these issues can be frustrating to debug. This guide covers the most common errors, their causes, and step-by-step solutions.
Build-Time Errors
Error: "The getter 'xyz' isn't defined for the class 'AppLocalizations'"
Error message:
lib/screens/home_screen.dart:45:32: Error: The getter 'welcomeMessage' isn't defined for the class 'AppLocalizations'.
- 'AppLocalizations' is from 'package:flutter_gen/gen_l10n/app_localizations.dart'.
Cause: The key exists in some .arb files but not in your template file, or gen-l10n hasn't been run.
Solution:
- Check your template .arb file has the key:
{
"welcomeMessage": "Welcome!",
"@welcomeMessage": {
"description": "Greeting shown on home screen"
}
}
- Regenerate localizations:
flutter gen-l10n
- If still failing, clean and rebuild:
flutter clean
flutter pub get
flutter gen-l10n
Error: "Missing required resource attribute"
Error message:
Error: Missing required resource attribute "@welcomeMessage" for message "welcomeMessage".
Cause: You have required-resource-attributes: true in l10n.yaml but missing metadata.
Solution:
Add the @key metadata for every translation key:
{
"welcomeMessage": "Welcome!",
"@welcomeMessage": {
"description": "Main greeting on home screen"
}
}
Or disable the requirement (not recommended):
# l10n.yaml
required-resource-attributes: false
Error: "The arb-dir does not exist"
Error message:
Error: The specified arb-dir (lib/l10n) does not exist.
Cause: The directory specified in l10n.yaml doesn't exist.
Solution:
mkdir -p lib/l10n
Then create your template .arb file:
touch lib/l10n/app_en.arb
Error: "Invalid ARB file format"
Error message:
Error: app_en.arb: Invalid JSON format at line 15, column 8
Cause: Syntax error in your .arb file (it's JSON).
Common issues:
- Trailing comma:
{
"key1": "value1",
"key2": "value2", // <-- Remove this trailing comma
}
- Missing quotes:
{
key1: "value1" // <-- Keys must be quoted
}
- Single quotes:
{
'key1': 'value1' // <-- Must use double quotes
}
Solution: Validate your JSON:
# Using Python
python -m json.tool lib/l10n/app_en.arb
# Using jq
jq . lib/l10n/app_en.arb
Error: "Placeholder not defined"
Error message:
Error: The placeholder "userName" is not defined for message "greeting".
Cause: You used a placeholder in the message but didn't define it in metadata.
Wrong:
{
"greeting": "Hello, {userName}!"
}
Correct:
{
"greeting": "Hello, {userName}!",
"@greeting": {
"description": "Personalized greeting",
"placeholders": {
"userName": {
"type": "String",
"example": "John"
}
}
}
}
Error: "Invalid plural format"
Error message:
Error: Invalid ICU message format in "itemCount": Expected '=' or keyword after '{'
Cause: ICU MessageFormat syntax error in plural/select messages.
Common syntax errors:
// Wrong: Missing space after 'plural,'
"{count,plural,=0{No items}}"
// Correct: Space after plural,
"{count, plural, =0{No items} =1{One item} other{{count} items}}"
// Wrong: Using 'one' instead of '=1' in English
"{count, plural, one{One item}}"
// Correct: Use '=1' for exact matches
"{count, plural, =1{One item} other{{count} items}}"
// Wrong: Nested braces not doubled for variable
"{count, plural, other{{count items}}"
// Correct: Variable inside plural needs double braces
"{count, plural, other{{count} items}}"
Correct plural format:
{
"itemCount": "{count, plural, =0{No items} =1{One item} other{{count} items}}",
"@itemCount": {
"placeholders": {
"count": {"type": "int"}
}
}
}
Runtime Errors
Error: "Null check operator used on a null value"
Error message:
Null check operator used on a null value
Location: Usually at AppLocalizations.of(context)!
Cause: Localizations not properly configured in MaterialApp.
Solution:
Ensure your MaterialApp has all required delegates:
MaterialApp(
localizationsDelegates: [
AppLocalizations.delegate, // Your generated delegate
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
// Or manually:
// supportedLocales: [
// Locale('en'),
// Locale('es'),
// ],
home: MyHomePage(),
);
Also check you're not accessing localizations before MaterialApp builds:
// Wrong: Accessing in initState before MaterialApp
@override
void initState() {
super.initState();
final text = AppLocalizations.of(context)!.hello; // Crashes!
}
// Correct: Access in build method or after first frame
@override
Widget build(BuildContext context) {
final text = AppLocalizations.of(context)!.hello;
return Text(text);
}
Error: "Looking up a deactivated widget's ancestor is unsafe"
Error message:
Looking up a deactivated widget's ancestor is unsafe.
Cause: Accessing AppLocalizations.of(context) after the widget is disposed.
Solution:
Store the localization reference before async operations:
// Wrong
Future<void> onButtonPressed() async {
await someAsyncOperation();
// Context may be invalid here
final message = AppLocalizations.of(context)!.success;
showSnackbar(message);
}
// Correct
Future<void> onButtonPressed() async {
// Store reference before async gap
final localizations = AppLocalizations.of(context)!;
await someAsyncOperation();
if (!mounted) return; // Check if widget still exists
showSnackbar(localizations.success);
}
Error: "No MaterialLocalizations found"
Error message:
No MaterialLocalizations found.
LocalizationsDelegate<MaterialLocalizations> is required.
Cause: Missing GlobalMaterialLocalizations delegate.
Solution:
import 'package:flutter_localizations/flutter_localizations.dart';
MaterialApp(
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate, // Required for Material widgets
GlobalWidgetsLocalizations.delegate, // Required for directionality
GlobalCupertinoLocalizations.delegate, // Required for Cupertino widgets
],
);
Don't forget the package import:
# pubspec.yaml
dependencies:
flutter_localizations:
sdk: flutter
Error: "The following assertion was thrown during performLayout: RenderFlex overflowed"
Error message:
A RenderFlex overflowed by 42 pixels on the right.
Cause: Translated text is longer than the original and breaks the layout.
Solution:
- Use flexible widgets:
// Wrong
Row(
children: [
Icon(Icons.info),
Text(AppLocalizations.of(context)!.longMessage),
],
)
// Correct
Row(
children: [
Icon(Icons.info),
Expanded(
child: Text(
AppLocalizations.of(context)!.longMessage,
overflow: TextOverflow.ellipsis,
),
),
],
)
- Test with pseudo-localization:
{
"@@locale": "xx",
"buttonLabel": "[Ţĥĩš ĩš å ɱũċĥ łöŋğëŕ ţëẋţ]"
}
- Set maximum text scale:
MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.linear(
MediaQuery.of(context).textScaler.scale(1.0).clamp(1.0, 1.3),
),
),
child: MyWidget(),
)
Placeholder Errors
Error: "The argument type 'int' can't be assigned to 'String'"
Error message:
Error: The argument type 'int' can't be assigned to the parameter type 'String'.
Cause: Placeholder type mismatch between .arb definition and usage.
Solution:
Match your .arb placeholder type to your Dart code:
{
"itemCount": "You have {count} items",
"@itemCount": {
"placeholders": {
"count": {
"type": "int" // Define as int
}
}
}
}
// Usage matches the type
Text(AppLocalizations.of(context)!.itemCount(5)) // int parameter
Available types:
String(default)intdoublenumDateTime
Error: "Expected 2 positional arguments but got 1"
Error message:
Error: Too few positional arguments: 2 required, 1 given.
Cause: Your message has multiple placeholders but you're not passing all of them.
Your .arb:
{
"greeting": "Hello {name}, you have {count} messages",
"@greeting": {
"placeholders": {
"name": {"type": "String"},
"count": {"type": "int"}
}
}
}
Wrong usage:
Text(AppLocalizations.of(context)!.greeting("John")) // Missing count!
Correct usage:
Text(AppLocalizations.of(context)!.greeting("John", 5))
Missing Translation Errors
Warning: "Translation missing for locale 'de'"
Log message:
Warning: Translation for key "newFeature" missing in app_de.arb
Cause: Key exists in template but not in translation file.
Solution:
- Add missing translation:
// app_de.arb
{
"newFeature": "Neue Funktion"
}
- Use nullable-getter for graceful fallback:
# l10n.yaml
nullable-getter: true
// Handle missing translations
final text = AppLocalizations.of(context)?.newFeature ?? 'New Feature';
- Track missing translations:
# l10n.yaml
untranslated-messages-file: lib/l10n/untranslated.txt
Configuration Errors
Error: "output-dir must be specified when synthetic-package is false"
Error message:
Error: The output-dir option is required when synthetic-package is false.
Cause: Incomplete l10n.yaml configuration.
Solution:
# l10n.yaml
synthetic-package: false
output-dir: lib/generated/l10n # Must specify this
Error: "Could not find a file named 'l10n.yaml'"
Error message:
Because flutter_localizations from sdk depends on ... version solving failed.
Cause: Missing l10n.yaml file.
Solution:
Create l10n.yaml in your project root:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
Enable generation in pubspec.yaml:
flutter:
generate: true
Debug Checklist
When localization isn't working, check these in order:
1. [ ] l10n.yaml exists in project root
2. [ ] pubspec.yaml has `flutter: generate: true`
3. [ ] flutter_localizations is in dependencies
4. [ ] Template .arb file exists and is valid JSON
5. [ ] All locale .arb files are valid JSON
6. [ ] MaterialApp has all localization delegates
7. [ ] supportedLocales matches your .arb files
8. [ ] `flutter gen-l10n` runs without errors
9. [ ] Generated files exist in output directory
10. [ ] Imports use correct generated file path
Quick Debug Commands
# Validate JSON syntax
for file in lib/l10n/*.arb; do
echo "Checking $file"
python -m json.tool "$file" > /dev/null && echo "OK" || echo "INVALID"
done
# Clean and regenerate
flutter clean && flutter pub get && flutter gen-l10n
# Check generated files
ls -la .dart_tool/flutter_gen/gen_l10n/
# or if using synthetic-package: false
ls -la lib/generated/l10n/
Related Resources:
- Complete Guide to Flutter .arb Files
- Flutter l10n.yaml Configuration Deep Dive
- 5 Flutter Localization Tips
Still running into localization issues? FlutterLocalisation validates your translations automatically and catches these errors before they reach your codebase.