Multilingualize with Flutter, dynamically switch languages, save languages, hamburger menu
Multilingualize with Flutter, dynamically switch languages, save languages, hamburger menu
Category:Flutter
Pub.date:2022-07-02
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
JavaScript
Unreal Engine
CakePHP4
CakePHP4
Flutter
Flutter
Other
JavaScript
JavaScript
CakePHP4
Web Server
Photoshop
Unreal Engine
CakePHP4
Web Browser
Web Server
iOS
Android
Web Browser
CakePHP4
Plesk
Illustrator
Plesk
Web Server
Web Server
CakePHP3
Web Browser
CakePHP3
JavaScript
JavaScript
CakePHP3
CakePHP3