Fix flutter_gen gen_l10n Import Errors After Upgrading
You bumped the SDK, ran flutter pub get, and now every file in the project is red:
Target of URI doesn't exist: 'package:flutter_gen/gen_l10n/app_localizations.dart'.
Undefined name 'AppLocalizations'.
Nothing in your code changed. What changed is Flutter. As of the 3.32.0 stable line, the tool no longer generates the synthetic package:flutter_gen — the fake package it used to inject into .dart_tool/package_config.json at build time. In 3.35 the remaining machinery (generateSyntheticPackages and the now-inert "synthetic" references) was deleted outright, so on any modern SDK — 3.47 as of this writing — that import can never resolve again.
This is not a one-line fix. It's a small migration: config, regeneration, a mass import rewrite, then CI, .gitignore, monorepo packages, and third-party dependencies. Here is the checklist in the order that actually works.
1. Point l10n.yaml at a real directory
Generated files now land in your source tree. The output location is output-dir if you set it, otherwise arb-dir. Be explicit:
# l10n.yaml (project root)
arb-dir: lib/l10n
output-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
And confirm pubspec.yaml still opts into generation — this flag is now required for the l10n step to run at all:
flutter:
generate: true
Delete any synthetic-package: line. On 3.32 it was honored but deprecated; on 3.35+ it is inert — the tool writes real files no matter what you set. Keeping it around only misleads the next person who reads the file. If you're unsure which keys your SDK still accepts, the full l10n.yaml configuration guide walks through each one.
Also check your pubspec.yaml dependency list for a stray flutter_gen: any. Older dart fix runs sometimes added it, chasing the missing import. The flutter_gen package on pub.dev is an unrelated asset code generator (FlutterGen) — it has nothing to do with gen_l10n and will not restore your localizations. Remove it.
2. Regenerate and confirm the files exist
flutter clean
flutter pub get
flutter gen-l10n
ls lib/l10n
You should see app_localizations.dart plus one file per locale (app_localizations_en.dart, app_localizations_fr.dart, …). If lib/l10n only contains .arb files, the tool never ran — 95% of the time that's a missing generate: true or an arb-dir that doesn't match where your ARB files actually live.
3. Rewrite every import
The docs show a relative import (import 'l10n/app_localizations.dart';), which is correct but depth-dependent — it breaks the moment you move a widget one folder deeper. For a mass rewrite, use a package-scoped absolute import instead. It's identical for every file in lib/, regardless of nesting:
// Before
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
// After (replace my_app with the `name:` from your pubspec.yaml)
import 'package:my_app/l10n/app_localizations.dart';
One command for the whole repo, macOS/BSD sed:
grep -rl "package:flutter_gen/gen_l10n/app_localizations.dart" lib test \
| xargs sed -i '' \
"s|package:flutter_gen/gen_l10n/app_localizations.dart|package:my_app/l10n/app_localizations.dart|g"
On GNU sed (Linux/CI), drop the '' after -i. Don't forget test/, integration_test/, and any example/ app — they import it too.
The call sites themselves don't change. nullable-getter still defaults to true, so this stays exactly as it was:
import 'package:my_app/l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Builder(
builder: (context) => Text(AppLocalizations.of(context)!.helloWorld),
),
);
Then restart the analysis server — VS Code's Dart: Restart Analysis Server, or invalidate caches in Android Studio. Stale analyzer state is the reason the red squiggles often survive a successful flutter gen-l10n.
4. Decide: commit the generated files, or generate in CI
This is the step teams skip, and it's why "it works on my machine" shows up two days later. The generated Dart now lives in lib/, so you must pick one policy:
Option A — commit them. Simplest. A fresh clone analyzes cleanly, IDEs resolve imports immediately, and code review shows translation diffs. Make sure nothing in .gitignore swallows them — a broad lib/**/*.g.dart is fine, but rules like lib/l10n/*.dart or a blanket **/generated/** will silently exclude the output.
Option B — gitignore them and generate in CI. Then add to .gitignore:
lib/l10n/app_localizations*.dart
…and make every CI job generate before it analyzes:
- run: flutter pub get
- run: flutter gen-l10n # must precede analyze/test/build_runner
- run: dart run build_runner build --delete-conflicting-outputs
- run: flutter analyze
- run: flutter test
Order matters. flutter gen-l10n is not a build_runner builder; nothing triggers it for you in an analyze-only job. If a build_runner generator (freezed, json_serializable, riverpod_generator) reads a file that imports AppLocalizations, it will fail unless gen-l10n ran first.
If generated files trip your lints, exclude them rather than weakening the rules:
# analysis_options.yaml
analyzer:
exclude:
- lib/l10n/app_localizations*.dart
5. The melos / multi-package case
In a monorepo, flutter gen-l10n is per-package. Any package that owns .arb files needs its own l10n.yaml and its own generate: true. Run generation across all of them before anything else:
melos exec -c 1 -- flutter gen-l10n
If you share one set of translations across apps, put them in a shared Flutter package (it must depend on flutter_localizations, so a plain Dart package won't do) and export the generated class from its public API:
// packages/my_l10n/lib/my_l10n.dart
export 'src/l10n/app_localizations.dart';
# packages/my_l10n/l10n.yaml
arb-dir: lib/src/l10n
output-dir: lib/src/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
Consumers then write import 'package:my_l10n/my_l10n.dart'; — one stable import path across every app in the workspace. This is strictly better than the old synthetic package, which was invisible to pub and couldn't be shared across packages at all.
6. When a third-party package still imports flutter_gen
If the failing import is inside .pub-cache, not your code, you cannot fix it from your side — the synthetic package is gone and there's no flag to bring it back. Your options, in order:
- Upgrade the package. Most maintained packages shipped a fix during 2025. Check the changelog for "synthetic" or "gen_l10n".
dependency_overridesto a patched fork — a git ref with the imports rewritten, while the upstream PR lands.- Vendor it into the repo as a path dependency and fix the two import lines yourself.
A package that generates its own localizations must also ship its own l10n.yaml and export the result — the same pattern as the melos case above.
Then take the opportunity to check the ARBs themselves
A migration that touches every locale file is the right moment to verify the translations are structurally sound — plural categories in particular. Dropping few or many from Arabic, Polish or Russian compiles fine and renders wrong for real users. FlutterLocalisation is an ARB editor and translation-management platform for exactly these files: edit app_<locale>.arb in a real UI instead of raw JSON, manage many locales side by side, and get ICU plural-syntax validation that flags a locale missing a category its language actually requires.
If your import errors turn out to be a different flavor of the same problem, the companion post on fixing the flutter_gen gen_l10n import error covers the narrower single-app case.
Try FlutterLocalisation free — import your ARB files and see what the plural validator finds.