← Back to Blog

intl_utils Is Discontinued: Migrate from Flutter Intl to gen-l10n

flutterintl_utilsgen-l10nmigrationarb

intl_utils, the generator behind the Flutter Intl plugin for VS Code and Android Studio, is marked discontinued on pub.dev, with no replacement named. The last release is 2.8.17, from October 2026. It still installs and still runs, but it will not follow new Flutter and Dart releases.

The natural replacement is gen-l10n, the generator built into Flutter. Your ARB files carry over as they are, and if you keep the class name S, most of your code does too. We migrated a test app (strings with and without placeholder metadata, a plural, a select, S.current, a French widget test) on Flutter 3.47. Only two lines failed to compile, and one behaviour change did not show up at compile time. All three are covered below.

1. Replace the configuration

Remove the flutter_intl: section from pubspec.yaml, drop the intl_utils dependency, and turn on code generation:

flutter pub remove intl_utils
dependencies:
  flutter_localizations:
    sdk: flutter
  intl: any

flutter:
  generate: true

Create l10n.yaml at the project root. These values reproduce what intl_utils generated, so imports keep working:

arb-dir: lib/l10n
template-arb-file: intl_en.arb
output-dir: lib/generated
output-localization-file: l10n.dart
output-class: S
nullable-getter: false

If you had arb_dir, output_dir, class_name or main_locale set in flutter_intl, use the same values here (main_locale: fr means template-arb-file: intl_fr.arb). use_deferred_loading: true becomes use-deferred-loading: true.

Do not add synthetic-package. Current Flutter rejects it.

2. Regenerate

Delete the old output, which includes the intl/messages_*.dart files gen-l10n does not use, and generate:

rm -rf lib/generated
flutter gen-l10n

lib/generated/l10n.dart now holds a gen-l10n class called S. S.of(context), S.delegate and every message getter keep the same names. Placeholders that had no @key metadata in intl_utils still work; gen-l10n types them as Object, as intl_utils did.

The Flutter Intl IDE plugin has nothing left to do and can be uninstalled.

3. Fix the two compile errors

S.delegate.supportedLocales becomes S.supportedLocales:

supportedLocales: S.supportedLocales,

S.current does not exist in gen-l10n. Where you have a BuildContext, use S.of(context). For code without one (services, view models, error mappers), set a global from MaterialApp.builder, which runs under the localizations and again when the locale changes:

late S currentS;

MaterialApp(
  localizationsDelegates: const [
    S.delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: S.supportedLocales,
  builder: (context, child) {
    currentS = S.of(context);
    Intl.defaultLocale = Localizations.localeOf(context).toString();
    return child!;
  },
);

Then replace S.current with currentS. In tests, await S.load(locale) becomes lookupS(locale), which is synchronous. S.maybeOf(context) becomes Localizations.of<S>(context, S).

4. The change the compiler does not catch

intl_utils' S.load also set Intl.defaultLocale. gen-l10n does not. Every DateFormat and NumberFormat created without an explicit locale then falls back to the system default. In our French test, DateFormat.MMMM() printed "janvier" under intl_utils and "January" after the migration, with no warning.

The Intl.defaultLocale line in the builder above restores the old behaviour. With it, the French test passed again. Keep it if your code formats dates or numbers without passing a locale.

5. Check

flutter analyze
flutter test

Our fl doctor command (from flutter_localisation_cli) also checks the setup offline, with no account needed. It flags a project that still depends on intl_utils, and the gen-l10n mistakes that break builds on current Flutter: synthetic-package, a missing generate: true, package:flutter_gen imports.

dart pub global activate flutter_localisation_cli
fl doctor

Where your translations live next

intl_utils came with a hosted service for managing the ARB files. Once you are on gen-l10n, any tool that reads ARB files works with your project. FlutterLocalisation is one of them. After creating a project in the dashboard, import your existing files, the template first:

fl import lib/l10n/intl_en.arb
fl languages add fr
fl import lib/l10n/intl_fr.arb --language fr

From then on the backend AI-translates new strings, pushes the ARBs to your git repository, and can update strings in the running app without a store release.