image

01 Feb 2026

9K

35K

Building a Language Selector Dropdown Widget in Flutter

Developing applications for a global audience often requires supporting multiple languages. Flutter provides robust tools for internationalization and localization, making it relatively straightforward to implement multi-language support. A common UI element for switching languages is a dropdown selector. This article will guide you through building a professional language selector dropdown widget in Flutter, leveraging Flutter's localization features and state management.

Prerequisites

  • Basic understanding of Flutter development.
  • Familiarity with state management concepts (we'll use Provider for simplicity).

1. Setting Up Localization Infrastructure

First, we need to set up Flutter's localization system. This involves configuring pubspec.yaml, defining a l10n.yaml file, and creating ARB (Application Resource Bundle) files for our localized strings.

1.1. Configure pubspec.yaml

Add the following dependencies to your pubspec.yaml file:


dependencies:
  flutter:
    sdk: flutter
  flutter_localizations: # Add this
    sdk: flutter
  provider: ^6.0.5 # For state management

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0
  intl: ^0.18.1 # For code generation

flutter:
  uses-material-design: true
  generate: true # Enable localization code generation

The flutter_localizations package provides the core localization delegates, and intl is used by Flutter's code generation for localization. generate: true under the flutter section is crucial to enable automatic generation of localization files.

1.2. Create l10n.yaml

Create a file named l10n.yaml in the root of your project (same level as pubspec.yaml) with the following content:


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 (lib/l10n), which file to use as the template (app_en.arb), and what to name the generated localization class file.

1.3. Create ARB Files

Create a folder lib/l10n. Inside this folder, create your ARB files. For example, for English and Spanish:

lib/l10n/app_en.arb:


{
    "@@locale": "en",
    "language": "English",
    "helloWorld": "Hello World!",
    "selectLanguage": "Select Language"
}

lib/l10n/app_es.arb:


{
    "@@locale": "es",
    "language": "Español",
    "helloWorld": "¡Hola Mundo!",
    "selectLanguage": "Seleccionar Idioma"
}

After saving these files, run flutter pub get and then flutter gen-l10n (or simply run your app). Flutter will automatically generate app_localizations.dart and related files in your .dart_tool directory. You can access generated strings via AppLocalizations.of(context)!.myString.

2. Managing Application Locale State

To dynamically change the application's language, we need a way to manage and expose the current Locale. We'll use ChangeNotifier and Provider for this.

lib/providers/locale_provider.dart:


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

class LocaleProvider extends ChangeNotifier {
  Locale? _locale;

  Locale? get locale => _locale;

  // List of all supported locales
  static final all = AppLocalizations.supportedLocales;

  void setLocale(Locale newLocale) {
    if (!AppLocalizations.supportedLocales.contains(newLocale)) return;
    _locale = newLocale;
    notifyListeners();
  }

  void clearLocale() {
    _locale = null;
    notifyListeners();
  }
}

This LocaleProvider holds the currently selected Locale and notifies listeners whenever it changes. It also exposes a list of all supportedLocales from the generated AppLocalizations.

3. Implementing the Language Selector Dropdown Widget

Now, let's create the dropdown widget itself. This widget will listen to the LocaleProvider and allow users to select a new language.

lib/widgets/language_selector_dropdown.dart:


import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:your_app_name/providers/locale_provider.dart'; // Adjust path

class LanguageSelectorDropdown extends StatelessWidget {
  const LanguageSelectorDropdown({super.key});

  @override
  Widget build(BuildContext context) {
    final localeProvider = Provider.of<LocaleProvider>(context);
    final currentLocale = localeProvider.locale ?? Localizations.localeOf(context);

    // Get the localized name for each language
    String getLanguageName(Locale locale) {
      switch (locale.languageCode) {
        case 'en':
          return AppLocalizations.of(context)!.language; // Use localized string for "English"
        case 'es':
          return AppLocalizations.of(context)!.language; // Use localized string for "Español"
        default:
          return locale.languageCode;
      }
    }

    return DropdownButton<Locale>(
      value: currentLocale,
      icon: const Icon(Icons.language),
      onChanged: (Locale? newLocale) {
        if (newLocale != null) {
          localeProvider.setLocale(newLocale);
        }
      },
      items: LocaleProvider.all.map<DropdownMenuItem<Locale>>((Locale locale) {
        return DropdownMenuItem<Locale>(
          value: locale,
          child: Text(getLanguageName(locale)),
        );
      }).toList(),
    );
  }
}

This widget:

  • Retrieves the current Locale from the LocaleProvider.
  • Builds a DropdownButton where each item represents a supported language.
  • Uses AppLocalizations.of(context)!.language to display the localized name of the language (e.g., "English" or "Español") within the dropdown itself.
  • When a new language is selected, it calls localeProvider.setLocale() to update the application's locale.

4. Integrating with MaterialApp

Finally, we need to integrate our LocaleProvider and the generated localization delegates into our MaterialApp.

lib/main.dart:


import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:your_app_name/providers/locale_provider.dart'; // Adjust path
import 'package:your_app_name/widgets/language_selector_dropdown.dart'; // Adjust path

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

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

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => LocaleProvider(),
      builder: (context, child) {
        final localeProvider = Provider.of<LocaleProvider>(context);

        return MaterialApp(
          title: 'Flutter Localization Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          // Set the locale based on the provider
          locale: localeProvider.locale, 
          
          // Define all supported localization delegates
          localizationsDelegates: const [
            AppLocalizations.delegate, // Generated app localizations
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          // Define all supported locales
          supportedLocales: LocaleProvider.all,
          
          home: const MyHomePage(),
        );
      },
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(AppLocalizations.of(context)!.selectLanguage), // Localized app bar title
        actions: const [
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 8.0),
            child: LanguageSelectorDropdown(), // Our language selector widget
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              AppLocalizations.of(context)!.helloWorld, // Display localized greeting
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(height: 20),
            Text(
              'Current Locale: ${Localizations.localeOf(context).languageCode}',
            ),
          ],
        ),
      ),
    );
  }
}

In main.dart:

  • We wrap our MaterialApp with a ChangeNotifierProvider<LocaleProvider> to make the provider accessible throughout the widget tree.
  • The locale property of MaterialApp is set to localeProvider.locale, ensuring the app reacts to language changes.
  • localizationsDelegates must include AppLocalizations.delegate (generated from our ARB files) along with the global material, widgets, and cupertino delegates.
  • supportedLocales specifies all the languages your app supports, sourced from LocaleProvider.all.

5. Using Localized Strings

Once everything is set up, accessing your localized strings is straightforward using AppLocalizations.of(context)!:


Text(AppLocalizations.of(context)!.helloWorld)

The ! operator assumes the context always has AppLocalizations available. If you need null safety, you can check for null or provide a fallback.

Conclusion

You have now successfully built a functional language selector dropdown widget in Flutter. This setup provides a clean, maintainable way to handle multi-language support in your application, allowing users to switch languages dynamically with immediate effect. Remember to add more ARB files for any additional languages you wish to support.

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