1

The application needs to implement language switching at runtime. Wrote a bloc with event and state and called BlocBuilder in main.dart. But I don't know how to implement the switch. How can I do that? In total, the application has two languages. My bloc:

class LanguageBloc extends Bloc<LanguageEvent, LanguageState> {
  LanguageBloc() : super(InitialLang()) {
    on<ChangeLang>(
      (event, emit) {
        emit(NewLang());
      },
    );
  }
  
  @immutable
abstract class LanguageEvent {}

class ChangeLang extends LanguageEvent {}

@immutable
abstract class LanguageState {}

class InitialLang extends LanguageState {}
class NewLang extends LanguageState {}

My main.dart

Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (context) => BottomNavyBloc(),
        ),
        BlocProvider(
          create: (context) => LanguageBloc(),
        ),
      ],
      child: BlocBuilder<LanguageBloc, LanguageState>(
        builder: (context, state) {
          return MaterialApp(
            title: 'Flutter Demo',
            localizationsDelegates: const [
              S.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
            ],
            supportedLocales: S.delegate.supportedLocales,
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            debugShowCheckedModeBanner: false,
            home: const HomeScreen(),
          );
        },
      ),
    );
  }

My lang btn:

ElevatedButton(onPressed: (){}, child: Text('Switch lang'))
userName
  • 903
  • 2
  • 20

1 Answers1

1

What you can do is to send a variable Locale with the language of your choice, and in your MaterialApp in the locale attribute, you attach it.

Without complications you can use Cubit instead of Bloc, because it is not necessary to have events, then you could do the following:

class LanguageCubit extends Cubit<Locale?> { // change state here, you dont use LanguageState
  LanguageCubit() : super(null);

  void initialLang () { // your initial lang
    emit(
      Locale("en", ""),
    );
  }

  void newLang(
    bool isEnglish, // in your checkbox you are gonna send the boolean value here
  ) {
    emit(
      isEnglish ? Locale("en") : Locale("fr"),
    );
  }
}

Now in your main, as you have it, it would only look like this:

Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (context) => BottomNavyBloc(),
        ),
        BlocProvider(
          create: (context) => LanguageBloc(),
        ),
      ],
      child: BlocBuilder<LanguageBloc, Locale?>( // change the state for Locale? cause could be null
        builder: (context, lang) { // different name to lang
          return MaterialApp(
            title: 'Flutter Demo',
            localizationsDelegates: const [
              S.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
            ],
            supportedLocales: S.delegate.supportedLocales,
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            locale: lang, // here you set the lang
            debugShowCheckedModeBanner: false,
            home: const HomeScreen(),
          );
        },
      ),
    );
  }

----- EDIT WITH BUTTON -----

I thought you would need a Switch Button that handles the booleans but no, you only need one button that will be the one to change it so I did it this way:

class _HomePageState extends State<HomePage> {
  bool _currentLanguageBool = false; // variable to know if is english or french

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
     create: (context) => LanguageCubit(), // with this we can use the Cubit in all the page, normally you have to have it in main and in the MaterialApp
     child: Scaffold(
      body: Center(
        child: ElevatedButton(
           onPressed: () {
              BlocProvider.of<LanguageCubit>(context)
                  .newLang(_currentLanguageBool);

              setState(() {
                _currentLanguageBool = !_currentLanguageBool;
              }); // with this you change the variable
            },
           child: Text('Switch lang'),
        ),
      ),
     ),
    );
  }
}

We will make our widget a StatefulWidget so we can just change the boolean variable and know if it is in English or French. If you don't want to use Stateful let me know, because we can use it with the same Cubit, but it would change the code and a little bit the logic of the LanguageCubit.

Daniel Roldán
  • 1,328
  • 3
  • 20
  • 1
    Thanks for the help. How can I bind languages ​​to the switch button? One button switches to English, and the second to French – userName May 13 '22 at 08:46
  • It's simple, because you only have two values, french and english, only one will be true and the other false because remember that the Switch handles boolean, so you have to change the logic of the newLang function, let me edit it. – Daniel Roldán May 13 '22 at 08:51
  • Do I need to add newLang to the button? Could you please show the example of the button I added? – userName May 13 '22 at 10:05
  • It depends, you want to confirm the selected language in your Switch with a button, or change the language at the moment you change your Switch? – Daniel Roldán May 13 '22 at 10:32
  • Didn't quite understand the question. I need to change the language of the application to French when I click on the button. And when I press it again, it changes back to English – userName May 13 '22 at 10:43
  • I edit it, you want it like that ? – Daniel Roldán May 13 '22 at 11:16