image

24 Jan 2026

9K

35K

Building a Multi-Language Toggle Widget in Flutter

In today's globalized world, providing a multi-language experience in your applications is no longer a luxury but a necessity. Flutter, with its robust internationalization and localization features, makes it straightforward to adapt your app to different languages and regions. This article will guide you through building a dynamic multi-language toggle widget, allowing users to switch the application's language on the fly.

1. Understanding Flutter Localization Basics

Before diving into the toggle widget, let's briefly recap Flutter's localization mechanism. Flutter uses the intl package and ARB (Application Resource Bundle) files to manage localized strings.

Key Components:

  • AppLocalizations: A class generated by Flutter's localization tool that provides access to your localized strings.
  • Localizations.of(context)!: The method used to retrieve an instance of AppLocalizations for the current BuildContext.
  • MaterialApp properties: localizationsDelegates, supportedLocales, and locale are crucial for configuring localization.

2. Initial Setup for Localization

First, ensure your project is set up for localization.

Add Dependencies

Update your pubspec.yaml file:


dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: ^0.18.0 # Ensure intl is available for l10n.yaml configuration

flutter:
  generate: true # This line is crucial for generating localization files

Create l10n.yaml

Create a file named l10n.yaml at the root of your project:


arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

This configuration tells Flutter where to find your ARB files, which one is the template, and what to name the generated localization class.

Create ARB Files

Create a folder lib/l10n and add your ARB files. For English and Spanish, you'd have:

lib/l10n/app_en.arb:


{
  "@@locale": "en",
  "helloWorld": "Hello World",
  "currentLanguage": "Current Language",
  "english": "English",
  "spanish": "Spanish"
}

lib/l10n/app_es.arb:


{
  "@@locale": "es",
  "helloWorld": "Hola Mundo",
  "currentLanguage": "Idioma Actual",
  "english": "Inglés",
  "spanish": "Español"
}

After saving these files, run flutter pub get (or save your pubspec.yaml in VS Code/Android Studio) to generate app_localizations.dart.

3. Integrating Localization with MaterialApp

Your MaterialApp needs to be configured to use the generated localization delegates and supported locales. To allow dynamic language switching, we'll wrap MaterialApp in a StatefulWidget and manage the locale property.

lib/main.dart:


import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // Generated localization file
import 'package:flutter_localizations/flutter_localizations.dart'; // For GlobalMaterialLocalizations

import 'package:your_app_name/language_toggle_widget.dart'; // Our custom widget

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State createState() => _MyAppState();
}

class _MyAppState extends State {
  Locale? _locale; // Null means system locale or first supportedLocale

  void _setLocale(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Multi-Language App',
      // List of all localization delegates
      localizationsDelegates: const [
        AppLocalizations.delegate, // Our generated AppLocalizations delegate
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      // List of all supported locales for our app
      supportedLocales: AppLocalizations.supportedLocales, // Provides locales like 'en', 'es'
      // The currently selected locale. Changing this will rebuild the app with the new language.
      locale: _locale,
      home: MyHomePage(setLocale: _setLocale),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final Function(Locale) setLocale;

  const MyHomePage({super.key, required this.setLocale});

  @override
  Widget build(BuildContext context) {
    // Access localized strings using AppLocalizations.of(context)
    final appLocalizations = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(
        title: Text(appLocalizations.helloWorld),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              appLocalizations.helloWorld,
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(height: 30),
            // Our language toggle widget
            LanguageToggleWidget(setLocale: setLocale),
          ],
        ),
      ),
    );
  }
}

4. Building the Multi-Language Toggle Widget

Now, let's create the widget that allows users to switch languages. This widget will receive a callback function (setLocale) from its parent (_MyAppState) to update the app's locale.

lib/language_toggle_widget.dart:


import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class LanguageToggleWidget extends StatelessWidget {
  final Function(Locale) setLocale;

  const LanguageToggleWidget({super.key, required this.setLocale});

  @override
  Widget build(BuildContext context) {
    // Get the current locale being used by the app
    final currentLocale = Localizations.localeOf(context);
    final appLocalizations = AppLocalizations.of(context);

    if (appLocalizations == null) {
      return const SizedBox.shrink(); // Or a loading indicator
    }

    return Column(
      children: [
        Text(
          '${appLocalizations.currentLanguage}: ${currentLocale.languageCode.toUpperCase()}',
          style: Theme.of(context).textTheme.titleLarge,
        ),
        const SizedBox(height: 20),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: AppLocalizations.supportedLocales.map((locale) {
            final isSelected = currentLocale.languageCode == locale.languageCode;
            final buttonText = _getLanguageName(appLocalizations, locale.languageCode);

            return Padding(
              padding: const EdgeInsets.symmetric(horizontal: 5.0),
              child: ElevatedButton(
                onPressed: () {
                  // Call the callback to update the app's locale
                  setLocale(locale);
                },
                style: ElevatedButton.styleFrom(
                  backgroundColor: isSelected ? Colors.blue : Colors.grey,
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
                  textStyle: const TextStyle(fontSize: 16),
                ),
                child: Text(buttonText),
              ),
            );
          }).toList(),
        ),
      ],
    );
  }

  // Helper function to get the localized name of the language
  String _getLanguageName(AppLocalizations appLocalizations, String languageCode) {
    switch (languageCode) {
      case 'en':
        return appLocalizations.english;
      case 'es':
        return appLocalizations.spanish;
      default:
        return languageCode.toUpperCase();
    }
  }
}

5. How It Works

  1. The MyApp widget, being a StatefulWidget, holds the _locale state.
  2. The _setLocale method in _MyAppState updates the _locale and calls setState, triggering a rebuild of MaterialApp.
  3. When MaterialApp rebuilds with a new locale, Flutter's localization system automatically loads the corresponding ARB file, and AppLocalizations.of(context) will provide strings for the newly selected language.
  4. The LanguageToggleWidget displays buttons for each supportedLocale. It determines the current language using Localizations.localeOf(context).
  5. When a language button is pressed, it calls the setLocale callback, passing the new Locale up to _MyAppState, completing the cycle.

Conclusion

Building a multi-language toggle widget in Flutter is a straightforward process when you understand the underlying localization mechanism. By managing the locale property of your MaterialApp via a StatefulWidget (or a state management solution like Provider, BLoC, Riverpod), you can offer users a seamless experience to switch languages instantly. This approach ensures that your application is accessible and user-friendly to a broader global audience. Remember to keep your ARB files updated with all necessary strings as your application evolves.

Related Articles

May 14, 2026

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter Countdown timers are essential in many applic

May 11, 2026

Unleashing Dynamic UIs: Flutter's Animation Prowess

Unleashing Dynamic UIs: Flutter's Animation Prowess for Slide & Scale Effects Flutter's declarative UI framework, combined with its powerful animation capabilit

May 11, 2026

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy A well-designed Product Detail Page (PDP) is