How to change the Application's language programmatically in Flutter?
Asked Answered
L

1

10

Currently, I am using flutter_localizations in order to translate strings in an application. It works perfectly fine, but it is required to be able to switch localization from the app's settings by pressing a button or choosing the language from a dropdown list. For this app, the BLoC design pattern is used.

Can you please suggest any potential solution to this problem? Thanks in advance :)

Lymn answered 6/6, 2020 at 9:59 Comment(5)
youtube.com/watch?v=lDfbbTvq4qMSalsbury
@DeanVillamia that doesn't help. I already have the localization implemented. When I switch the system language it changes the language of the app. However, I need to be able to do this in the app by pressing a button or interacting with the UI.Lymn
ok, so it's a state management problem just rebuild the widget when you change the dropdown. Sorry I'm not too familiar with bloc because I use provider -> changenotifier.Salsbury
@DeanVillamia the problem is not fully connected to the state management. Rebuilding the widget won't help because I don't do anything with the language yet. I do have a dropdown, but what should be done in order to change the app language ignoring the system language?Lymn
Get the systems language then save it to a variable that you can manipulate #50924406Salsbury
R
8

For future readers, here's how you can achieve this:

The Locale is defined by the result returned from localeResolutionCallback function, within the MaterialApp widget.

In my case, I pass a final Locale defaultValue; to my app root, the first widget in the tree (declared in runApp()).

At that point, I simply do this validation:

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

import 'package:intl/intl.dart';

import '../../localization.dart';
import '../views/home_view.dart';

class App extends StatelessWidget {
  App({Key key, this.defaultLanguage}) : super(key: key);
  final Locale defaultLanguage;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeView(),
      localizationsDelegates: [
        AppLocalization.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('en', null),
        const Locale('pl', null),
      ],
      localeResolutionCallback: (locale, supportedLocales) {
        if (defaultLanguage != null) {
          Intl.defaultLocale = defaultLanguage.toLanguageTag();
          return defaultLanguage;
        }
        if (locale == null) {
          Intl.defaultLocale = supportedLocales.first.toLanguageTag();
          return supportedLocales.first;
        }
        for (var supportedLocale in supportedLocales) {
          if (supportedLocale.languageCode == locale.languageCode) {
            Intl.defaultLocale = supportedLocale.toLanguageTag();
            return supportedLocale;
          }
        }
        Intl.defaultLocale = supportedLocales.first.toLanguageTag();
        return supportedLocales.first;
      },
    );
  }
}

If defaultLanguage was passed on by the bloc above, then it's used in the application, otherwise it does the standard validation to fetch the locale from the device.

Bear in mind that you might need to protect the check by verifying if the defaultLanguage variable is of a supported locale. In my case this is handled, so that's why I don't bother.

Rudbeckia answered 17/12, 2020 at 18:5 Comment(4)
So we have to wrap the whole MaterialApp widget in some sort of LocalizationBloc, right?Lymn
Does localeResolutionCallback gets re-executed when the defaultLanguage changes?Tempe
@Lymn that's one option, yes. On my application I handles the default value within a provider.Rudbeckia
@Tempe Yup. Changing the device language settings also does execute the callback.Rudbeckia

© 2022 - 2024 — McMap. All rights reserved.