DEV Community

Luis Scripcaru
Luis Scripcaru

Posted on

Why I Switched to Slang for Flutter Localization (and You Might Want To Too)

When I started my first Flutter app, I did what every tutorial told me to do: set up flutter_localizations with .arb files and let the official intl-based codegen handle translations. It worked. It also made me miserable.

Here's why I moved to slang (with slang_flutter) instead, and why beginners especially might want to skip the "official" route.

The problem with ARB + intl

The built-in Flutter localization setup isn't bad, exactly. It's just clunky for small and mid-size projects:

  • .arb files are verbose JSON with metadata blocks for every single string.
  • You need flutter: generate: true, an l10n.yaml file, and a rebuild step that sometimes silently fails.
  • Accessing strings means AppLocalizations.of(context)!.someKey, and that ! is doing a lot of quiet lying to you.
  • Typos in keys aren't caught until runtime, which for a beginner means a confusing "LateInitializationError" instead of a helpful compile error.

What changed with Slang

Slang flips the experience. You write plain JSON (or YAML/CSV if you prefer) files per locale:

// en.i18n.json
{
  "hello": "Hello $name",
  "login": {
    "success": "Logged in successfully"
  }
}
Enter fullscreen mode Exit fullscreen mode

Run the generator, and you get fully typed Dart code. Usage looks like this:

import 'package:my_app/i18n/strings.g.dart';

String greeting = t.hello(name: 'Tom');
Text(t.login.success);
Enter fullscreen mode Exit fullscreen mode

No context lookups, no nullable bang operator, and (this is the part that sold me) if you typo a key, your code doesn't compile. As a beginner, that single change removed an entire category of "why is my text blank" bugs.

Where Slang beat easy_localization for me

I'd also tried easy_localization before landing on Slang. It's a solid package, but it resolves keys as strings at runtime ('login.success'.tr()), which means the same typo problem as ARB, just with a friendlier API. Slang's compile-time generation is the real differentiator: your IDE autocompletes every translation key, and refactors (renaming a key) are safe, because you're renaming a real Dart property, not a magic string.

Setup, quickly

dependencies:
  slang: ^4.18.0
  slang_flutter: ^4.18.0
dev_dependencies:
  build_runner: ^2.15.1
Enter fullscreen mode Exit fullscreen mode

Drop your JSON files in lib/i18n/, run:

dart run slang
Enter fullscreen mode Exit fullscreen mode

Wire it into MaterialApp:

MaterialApp(
  locale: TranslationProvider.of(context).flutterLocale,
  supportedLocales: AppLocaleUtils.supportedLocales,
  localizationsDelegates: GlobalMaterialLocalizations.delegates,
  child: MyApp(),
)
Enter fullscreen mode Exit fullscreen mode

That's genuinely most of it. Pluralization, rich text, and namespaces are all supported when you're ready to grow into them, but you don't need to touch a single YAML config file to get started, which is rare for an i18n package.

Bottom line

If you're new to Flutter and dreading localization setup, skip the ARB detour. Slang gets you type-safe, typo-proof translations with less boilerplate and a much gentler learning curve. My only regret is not switching sooner.

Have you tried Slang or another i18n package in Flutter? I'd love to hear what's worked for you in the comments.

Top comments (1)

Collapse
 
pakvothe profile image
Franco Ortiz

"It worked. It also made me miserable" is the entire .arb + intl experience in two sentences. The silent rebuild failures were what got me too.

slang fixes the ergonomics, but curious how you handle the other half: actually filling the JSONs for each locale when copy changes. That was the part that stayed manual for me even after fixing the tooling, so I built i1n (i1n.ai), one command AI-translates missing keys against the source locale and a check catches drift in CI. Works on plain JSON so it composes with slang. For apps with six-figure downloads the languages compound fast. Free tier if you want to poke at it.