Button to change the language Flutter
You can set the locale
property of MaterialApp
with your favourite state management method. For example:
class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); static _MyAppState of(BuildContext context) => context.findAncestorStateOfType<_MyAppState>();}class _MyAppState extends State<MyApp> { Locale _locale; void setLocale(Locale value) { setState(() { _locale = value; }); } @override Widget build(BuildContext context) { return MaterialApp( locale: _locale, home: Dashboard(), ); }}class Dashboard extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: [ TextButton( child: Text("Set locale to German"), onPressed: () => MyApp.of(context).setLocale(Locale.fromSubtags(languageCode: 'de')), ), TextButton( child: Text("Set locale to English"), onPressed: () => MyApp.of(context).setLocale(Locale.fromSubtags(languageCode: 'en')), ), ], ); }}
You have to use Localizations given from Flutter. You have to use custom delegate and JSON files for your supported languages.I implemented using bloc
Steps to follow,
- Create a folder
assets/languages/
in the root folder - Create
JSON
files for your supported languages.Like: en.json, es.json - Create a key, value pairs for your strings in each file accordingly with their specific language strings
- In
main.dart
create defaultlocale, supportedLocales and localizationsDelegates
.
import 'package:flutter/material.dart';import 'package:flutter_bloc/flutter_bloc.dart';import 'package:flutter_localizations/flutter_localizations.dart';import 'package:movie_app/common/constants/languages.dart';import 'package:movie_app/presentation/app_localizations.dart';import 'package:movie_app/presentation/blocs/language/language_bloc.dart';import 'package:movie_app/presentation/journeys/home/home_screen.dart';class MovieApp extends StatefulWidget { @override _MovieAppState createState() => _MovieAppState();}class _MovieAppState extends State<MovieApp> { LanguageBloc _languageBloc; @override void initState() { _languageBloc = LanguageBloc(); super.initState(); } @override void dispose() { _languageBloc.close(); super.dispose(); } @override Widget build(BuildContext context) { return BlocProvider<LanguageBloc>.value( value: _languageBloc, child: BlocBuilder<LanguageBloc, LanguageState>( builder: (context, state) { if (state is LanguageLoaded) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Movie App', home: HomeScreen(), supportedLocales: Languages.languages.map((e) => Locale(e.code)).toList(), locale: state.locale, localizationsDelegates: [ AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], ); } return SizedBox.shrink(); }, ), ); }}
- Now create Languages Language models and constants
class LanguageEntity { final String code; final String value; const LanguageEntity({ this.code, this.value, });}class Languages { const Languages._(); static const languages = [ LanguageEntity(code: 'en', value: 'English'), LanguageEntity(code: 'es', value: 'Spanish'), ];}
- Now Create app localization delegate
import 'dart:convert';import 'package:flutter/material.dart';import 'package:flutter/services.dart';import 'package:movie_app/common/constants/languages.dart';class AppLocalizations { final Locale locale; AppLocalizations(this.locale); static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationDelagate(); static AppLocalizations of(context) => Localizations.of<AppLocalizations>(context, AppLocalizations); Map<String, String> _localisedString; Future<bool> load() async { final jsonString = await rootBundle .loadString('assets/languages/${locale.languageCode}.json'); final Map<String, dynamic> jsonMap = json.decode(jsonString); _localisedString = jsonMap.map((key, value) => MapEntry(key, value.toString())); return true; } String translate(String key) { return _localisedString[key]; }}class _AppLocalizationDelagate extends LocalizationsDelegate<AppLocalizations> { const _AppLocalizationDelagate(); @override bool isSupported(Locale locale) { return Languages.languages .map((e) => e.code) .toList() .contains(locale.languageCode); } @override bool shouldReload(covariant LocalizationsDelegate old) { return false; } @override Future<AppLocalizations> load(Locale locale) async { AppLocalizations appLocalizations = AppLocalizations(locale); await appLocalizations.load(); return appLocalizations; }}
- Now create blocs
import 'dart:async';import 'package:bloc/bloc.dart';// import 'package:equatable/equatable.dart';import 'package:flutter/material.dart';import 'package:movie_app/common/constants/languages.dart';import 'package:movie_app/domain/entities/language_entity.dart';part 'language_event.dart';part 'language_state.dart';class LanguageBloc extends Bloc<LanguageEvent, LanguageState> { LanguageBloc() : super(LanguageLoaded(Locale(Languages.languages[0].code))); @override Stream<LanguageState> mapEventToState( LanguageEvent event, ) async* { if (event is ToggleLanguageEvent) { yield LanguageLoaded(Locale(event.language.code)); } }}
8.Now create event
part of 'language_bloc.dart';abstract class LanguageEvent { const LanguageEvent();}class ToggleLanguageEvent extends LanguageEvent { final LanguageEntity language; ToggleLanguageEvent(this.language);}
- Now create state
part of 'language_bloc.dart';abstract class LanguageState { const LanguageState();}class LanguageLoaded extends LanguageState { final Locale locale; LanguageLoaded(this.locale);}
10.Now Create button to change languages.
RaisedButton(child: ,RaisedButton(child: Text('Switch', onPressed: (int index) { BlocProvider.of<LanguageBloc>(context).add( ToggleLanguageEvent( Languages.languages[index], // index value can be 0 or 1 in our case ), // 0 - en, 1 - es ); Navigator.of(context).pop(); },);
Also, please refer the link for clear implementationhttps://www.youtube.com/watch?v=W-2p3zB1z8k
If you are using provider as state management then you can follow this article .