← Back to Blog

A VS Code Extension for Flutter Localization: Find Hardcoded Strings, Extract to ARB

fluttervscodegen-l10narbtools

The Flutter Intl extension made one thing easy: put the cursor on a string, extract it to an ARB file, done. It was last updated in 2023, and the generator behind it, intl_utils, is now marked discontinued on pub.dev. Projects moving to gen-l10n lose that workflow.

We built a replacement for gen-l10n: Flutter Localization (ARB, gen-l10n). It's free and open source, and it works in VS Code, Cursor, Windsurf and other VS Code-based editors.

Install

Search for "Flutter Localization" in the Extensions view, or:

code --install-extension flutterlocalisation.flutter-l10n

It's on the Visual Studio Marketplace and on Open VSX, which Cursor and Windsurf use. The source is on GitHub.

What it does

Reports the text you forgot to translate. Strings the user reads show up in the Problems panel: the text of Text, SelectableText and TextSpan, and arguments like labelText, hintText, errorText, tooltip and title. Map keys, routes, asset paths, logs and identifiers are not reported. // l10n-ignore skips a line on purpose, for a brand name for example.

Extracts a string in one step. Use the quick fix, the context menu, or Cmd+Alt+E (Ctrl+Alt+E on Windows and Linux). Accept the suggested key and

const Text('Hello $name')

becomes

Text(AppLocalizations.of(context)!.helloName(name))

The extension also adds "helloName": "Hello {name}" to your template ARB, with the placeholder declared. Three details make the result compile without a second pass:

  • Interpolations become placeholders, and the expressions are passed back in the call. ${user.name} becomes {userName}.
  • A const that would no longer compile is removed, including one on an enclosing list such as children: const [...].
  • The import of your localizations file is added once.

If the same text already has a key, the extension reuses it instead of creating a duplicate.

Regenerates on save. Saving an ARB file runs flutter gen-l10n, so the new getter exists before you switch back to the Dart file.

Shows translations on hover. Hover over .helloName to see its text in every locale, with missing ones marked.

Flags missing translations. Each locale's ARB file lists the keys the template has and it doesn't.

Previews a widget in every language. On a widget class, Preview in all locales adds a @LocalePreview() function, and the Flutter Widget Previewer shows the widget in each locale, right to left, and in a pseudo-locale that makes every string 40% longer. See Flutter widget previews in every language.

Your setup, not ours

The extension reads your configuration instead of assuming one:

Project Code it writes
gen-l10n AppLocalizations.of(context)!.key, with the class name, output folder and nullable-getter read from l10n.yaml
The flutter_localisation package context.tr.key
intl_utils / Flutter Intl S.of(context).key

If you wrap the call in your own extension, such as context.l10n, set flutterL10n.accessor to context.l10n.{key}.

An intl_utils project keeps working while you migrate. The extension points you to the migration guide to gen-l10n, which keeps your S class and your ARB files.

Tested before release

Each release runs in a real VS Code against a sample app: it checks the diagnostics, the quick fix, extracting with placeholders, reusing a key, the hover and the missing-translation warning. We also extracted every string of a fresh Flutter app, including ones inside a const list and a nested const widget, then ran flutter gen-l10n and flutter analyze. Both came back clean.

Translating the keys

The extension never sends your text anywhere. When you want the new keys translated, the Translate and Sync command runs our free fl command line tool. It AI-translates new keys into every locale of your FlutterLocalisation project and pulls the ARB files back. Use any workflow you like; the extension doesn't depend on it.