QuickAnswer
by

Multilingualize with Flutter, dynamically switch languages, save languages, hamburger menu

Multilingualize with Flutter, dynamically switch languages, save languages, hamburger menu

Android Studio Chipmunk | 2021.2.1 Patch 1
Flutter 3.0.3
Windows 11 Pro 21H2

Multilingualize with Flutter, dynamically switch languages, save languages, hamburger menu

Minimal configuration with Flutter for multilingualization, dynamic language switching, language storage, and hamburger menus

packages

Save data to device
https://pub.dev/packages/shared_preferences

flutter_localizations (official)
https://docs.flutter.dev/development/accessibility-and-localization/internationalization

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.0.15
  flutter_localizations:
    sdk: flutter
  intl: ^0.17.0
flutter:
  generate: true

main.dart

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

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});
  @override
  State<MainApp> createState() => _MainAppState();
}

class Pref {
  static const String keyLanguage = "keyLanguage";
}

class LanguageChoice {
  final Map<String,String> langMap = {
    'en': 'English',
    'bg': 'български език',
    'cs': 'Čeština',
    'da': 'dansk',
    'de': 'Deutsch',
    'el': 'Ελληνικά',
    'es': 'Español',
    'et': 'eesti keel',
    'fi': 'Suomen kieli',
    'fr': 'Français',
    'hu': 'magyar nyelv',
    'it': 'Italiano',
    'ja': '日本語',
    'lt': 'lietuvių kalba',
    'lv': 'Latviešu',
    'nl': 'Nederlands',
    'pl': 'Polski',
    'pt': 'Português',
    'ro': 'limba română',
    'ru': 'русский',
    'sk': 'Slovenčina',
    'sv': 'svenska',
    'th': 'ภาษาไทย',
    'zh': '中文',
  };
  List<String> languageList() {
    List<String> languages = [];
    langMap.forEach((key, value) {
      languages.add(key);
    });
    return languages;
  }
  String getLanguageName(String str) {
    if (langMap.containsKey(str)) {
      return langMap[str]!;
    }
    return '';
  }
  List<Locale> localeList() {
    List<Locale> locales = [];
    langMap.forEach((key, value) {
      locales.add(Locale(key));
    });
    return locales;
  }
}

class _MainAppState extends State<MainApp> {
  Locale locale = AppLocalizations.supportedLocales.first;
  @override
  Widget build(BuildContext context) {
    final LanguageChoice languageChoice = LanguageChoice();
    final List<Locale> localeList = languageChoice.localeList();
    return MaterialApp(
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: localeList,
      locale: locale,
      home: const MainPage(),
    );
  }
}

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);
  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
  @override
  void initState() {
    super.initState();
    _loadLanguage();
  }
  void _loadLanguage() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String lang = prefs.getString(Pref.keyLanguage) ?? 'en';
    if (!mounted) {
      return;
    }
    context.findAncestorStateOfType<_MainAppState>()!
      ..locale = Locale(lang)
      ..setState(() {});
  }
  void _saveLanguage(String lang) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(Pref.keyLanguage, lang);
  }
  Widget _dialogLanguage() {
    final LanguageChoice languageChoice = LanguageChoice();
    final List<String> langList = languageChoice.languageList();
    return SimpleDialog(
      title: Text(AppLocalizations.of(context)!.language),
      children: List.generate(langList.length,(index) {
        return SimpleDialogOption(
          child: Row(
            children:[
              SizedBox(
                width: 25,
                child: Text(langList[index])
              ),
              Text('- ${languageChoice.getLanguageName(langList[index])}')
            ]
          ),
          onPressed: () {
            _saveLanguage(langList[index]);
            context.findAncestorStateOfType<_MainAppState>()!
              ..locale = Locale(langList[index])
              ..setState((){});
            Navigator.pop(context);
          }
        );
      }),
    );
  }
  Widget _hamburgerMenu() {
    return Drawer(
      child: ListView(
        padding: EdgeInsets.zero,
        children: [
          const SizedBox(
            child: DrawerHeader(
              decoration: BoxDecoration(color: Colors.blue), child: null,
            )
          ),
          ListTile(
            leading: const CircleAvatar(
              child: Icon(
                Icons.language,
              ),
            ),
            title: Text(AppLocalizations.of(context)!.language),
            trailing: const Icon(
              Icons.arrow_circle_right_outlined,
            ),
            onTap: () {
              showDialog(
                context: context,
                barrierDismissible: true,
                builder: (_) {
                  return _dialogLanguage();
                }
              );
            },
          ),
        ],
      ),
    );
  }
  Widget _settingButton() {
    return IconButton(
      icon: const Icon(Icons.menu,color: Colors.white),
      tooltip: AppLocalizations.of(context)!.setting,
      onPressed: () {
        _key.currentState?.openDrawer();
      },
    );
  }
  Widget _menuBar() {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8.0),
      decoration: const BoxDecoration(color: Colors.blue),
      child: Row(children: <Widget> [
        const Expanded(
          child: SizedBox(width: 8),
        ),
        _settingButton(),
      ]),
    );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _key,
      appBar: null,
      drawer: _hamburgerMenu(),
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              _menuBar(),
            ]
          ),
        ),
      ),
    );
  }
}

l10n.yaml

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

Each language file

Create the following folders

lib/l10n

Set up each language file lib/l10n/app_en.arb

{
  "@@locale":"en",
  "language": "Language",
  "usage": "Usage"
}

lib/l10n/app_ja.arb

{
  "@@locale":"ja",
  "language": "言語",
  "usage": "使い方"
}

e.t.c.

generated_plugin_registrant.dart

lib/generated_plugin_registrant.dart

This file is automatically generated.

CONTENTS
Web Browser