flutterdarttranslationflutter-easy-localization

change language on runtime with flutter easy localization package remote


I'm using translation files from server response and i want to change the translation after i select my preferred language and the page closes in language selection page, currently the translation works but until i reload the whole app on my device which is not ideal: here's language selection page:


class LanguageSelectionScreen extends StatelessWidget {
  final bool navigateToAgreementPage;

  LanguageSelectionScreen({this.navigateToAgreementPage = true});

  Future<List<String>> _loadSelectedLanguages() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.getStringList('selectedLanguages') ?? [];
  }

  Future<void> _saveSelectedLanguages(List<String> selectedLanguages) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setStringList('selectedLanguages', selectedLanguages);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<String>>(
      future: _loadSelectedLanguages(),
      builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        } else {
          List<String> _selectedLanguages = snapshot.data ?? [];
          return Scaffold(
            appBar: AppBar(
              title: Text('Select your Language').tr(),
            ),
            body: Center(
              child: Padding(
                padding: EdgeInsets.only(top: 100),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: <Widget>[
                    Text("Choose your preferred languages"),
                    IconButton(
                      icon: Icon(Icons.add),
                      onPressed: () async {
                        String? selectedLanguage = await showDialog<String>(
                          context: context,
                          builder: (BuildContext context) {
                            return SimpleDialog(
                              title: Text('Select a language'),
                              children: <String>[
                                'English',
                                'Hindi',
                                'Arabic',
                                'French',
                                'Spanish',
                                'German',
                                'Italian',
                                'Russian',
                                'Japanese',
                                'Punjabi',
                                'Tamil',
                                'Gujarati',
                              ].map((String value) {
                                return SimpleDialogOption(
                                  child: Text(value),
                                  onPressed: () {
                                    Navigator.pop(context, value);
                                  },
                                );
                              }).toList(),
                            );
                          },
                        );

                        if (selectedLanguage != null) {
                          _selectedLanguages.add(selectedLanguage);
                          _saveSelectedLanguages(_selectedLanguages);
                          changeLanguage(context, selectedLanguage);
                        }
                      },
                    ),
                    ..._selectedLanguages
                        .map((language) => Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                ElevatedButton(
                                  style: ButtonStyle(
                                    backgroundColor:
                                        MaterialStateProperty.all<Color>(
                                            Color(0xffF0E4D6)),
                                  ),
                                  onPressed: () {
                                    changeLanguage(context, language);
                                  },
                                  child: Text(
                                    language,
                                    style: TextStyle(color: Colors.black),
                                  ),
                                ),
                                IconButton(
                                  icon: Icon(Icons.delete, color: Colors.red),
                                  onPressed: () {
                                    if (_selectedLanguages.length > 1) {
                                      _selectedLanguages.remove(language);
                                      _saveSelectedLanguages(
                                          _selectedLanguages);
                                    } else {
                                      showDialog(
                                        context: context,
                                        builder: (BuildContext context) {
                                          return AlertDialog(
                                            title: Text('Warning'),
                                            content: Text(
                                                'At least one language must be selected.'),
                                            actions: <Widget>[
                                              TextButton(
                                                child: Text('OK'),
                                                onPressed: () {
                                                  Navigator.of(context).pop();
                                                },
                                              ),
                                            ],
                                          );
                                        },
                                      );
                                    }
                                  },
                                )
                              ],
                            ))
                        .toList(),
                  ],
                ),
              ),
            ),
          );
        }
      },
    );
  }

  void changeLanguage(BuildContext context, String newValue) async {
    Locale newLocale;
    switch (newValue) {
      case 'English':
        newLocale = Locale('en');
        break;
      case 'Hindi':
        newLocale = Locale('hi');
        break;
      case 'Arabic':
        newLocale = Locale('ar');
        break;
      case 'French':
        newLocale = Locale('fr');
        break;
      case 'Spanish':
        newLocale = Locale('es');
        break;
      case 'German':
        newLocale = Locale('de');
        break;
      case 'Italian':
        newLocale = Locale('it');
        break;
      case 'Russian':
        newLocale = Locale('ru');
        break;
      case 'Japanese':
        newLocale = Locale('ja');
        break;
      case 'Punjabi':
        newLocale = Locale('pa');
        break;
      case 'Tamil':
        newLocale = Locale('ta');
        break;
      case 'Gujarati':
        newLocale = Locale('gu');
        break;
      default:
        newLocale = Locale('en');
    }
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString('languageCode', newLocale.languageCode);

    context.setLocale(newLocale);

    if (navigateToAgreementPage) {
      Navigator.of(context).pushReplacement(
        MaterialPageRoute(builder: (context) => AgreementPage()),
      );
    } else {
      Navigator.of(context).pop();
    }
  }
}

here's my main.dart:


class CustomHttpAssetLoader extends AssetLoader {
  @override
  Future<Map<String, dynamic>?> load(String path, Locale locale) async {
 
    String url =
        '$path?filename=${locale.languageCode}.json&language=${locale.languageCode}';
    final response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
     
      return jsonDecode(response.body);
    } else {
  
      // load the English translations as default
      final response =
          await http.get(Uri.parse('$path?file=en&language=en'));
      if (response.statusCode == 200) {
        return jsonDecode(response.body);
      } else {
        throw Exception('Failed to load translation file');
      }
    }
  }
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  FirebaseFirestore.instance.settings = Settings(persistenceEnabled: true);
  await dotenv.load();
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String languageCode = prefs.getString('languageCode') ?? 'en';
  Locale locale = Locale(languageCode);
  tz.initializeTimeZones();

  runApp(
    EasyLocalization(
        supportedLocales: [
          Locale('en'),
          Locale('fr'),
          Locale('hi'),
          Locale('ar'),
          Locale('es'),
          Locale('de'),
          Locale('it'),
          Locale('ru'),
          Locale('ja'),
          Locale('pa'),
          Locale('ta'),
          Locale('gu'),
        ],
        path:
            'http://example/exp/get-language-translation-file',
        assetLoader: CustomHttpAssetLoader(),
        fallbackLocale: Locale('en', 'US'),
        child: MyApp()),
  );
}

class MyApp extends StatefulWidget {
  const MyApp({
    Key? key,
  }) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final Brightness brightness = MediaQuery.of(context).platformBrightness;
    final bool isDarkMode = brightness == Brightness.dark;

    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      theme: isDarkMode ? ThemeData.dark() : ThemeData.light(),
      home: Material(
        child: InkWell(
          onTap: () {
            HapticFeedback.heavyImpact();
          },
          child: SplashScreen(),
        ),
      ),
    );
  }
}

Please help me and thank you in advance


Solution

  • I've fixed the issue since I'm using GetMaterialApp in my main.dart I have to use Get.updateLocale() to inform GetMaterialApp about the language change in my language selection page as well like this:

      await context.setLocale(newLocale);
      Get.updateLocale(newLocale);