aissat / easy_localization

Easy and Fast internationalizing your Flutter Apps
https://pub.dev/packages/easy_localization
MIT License
920 stars 329 forks source link

startLocale may not be used #430

Open emri99 opened 3 years ago

emri99 commented 3 years ago

Depending on arguments passed to the EasyLocalization widget, the startLocale is not used.

Problem encountered The device locale is used as initial locale even if we supply another value in startLocale argument.

Why is this happenning ? In our case, this happens because we explicitly ask the widget not to handle save & restoration to handle it in our app, and we store the locale in SharedPreferences with the same key than this package.

Context to reproduce To get into this usecase :

Source code issue explanation Source code of controller where the problem occurs annotated :

class EasyLocalizationController extends ChangeNotifier {
  static Locale? _savedLocale;   ## value initialized in static method
                                 ## initEasyLocation
  // ....

  EasyLocalizationController({
    // ....
    required this.saveLocale,  # false
    // ....
    Locale? startLocale,   # value initialized to anything else than device locale to see the problem
    // ....
  }) {
    _fallbackLocale = fallbackLocale;
    if (forceLocale != null) {
      _locale = forceLocale;

   // #### ISSUE IS HERE #####
   // #### startLocale is NOT USED because the `_savedLocale` is read ####
   // #### from the `locale` SharedPreferences key, which is the one ####
   // #### we use internally in our app ####
    } else if (_savedLocale == null && startLocale != null) {
      _locale = _getFallbackLocale(supportedLocales, startLocale);
      EasyLocalization.logger('Start locale loaded ${_locale.toString()}');
    }

    // ####
    // #### It don't match this condition neither as `saveLocale` is false ####
    // If saved locale then get
    else if (saveLocale && _savedLocale != null) {
      EasyLocalization.logger('Saved locale loaded ${_savedLocale.toString()}');
      _locale = _savedLocale!;

    // ####
    // #### so although we supply a startLocale, it's ignored ####
    // #### and the device locale is used ####
    } else {
      // From Device Locale
      _locale = supportedLocales.firstWhere(
          (locale) => _checkInitLocale(locale, _deviceLocale),
          orElse: () => _getFallbackLocale(supportedLocales, fallbackLocale));
    }
  // ...

  static Future<void> initEasyLocation() async {
    final _preferences = await SharedPreferences.getInstance();

    // #### read from SharedPreferences that can be written easily ####
    // #### outside of this class due to a too common SP key ####
    final _strLocale = _preferences.getString('locale');
    _savedLocale = _strLocale != null ? _strLocale.toLocale() : null;

  // ...

Potential resolution IMHO, the locale SharedPreferences key is too common and can conflict with the application one, I think it should be more package specific like easy_localization_locale.

jgoyvaerts commented 2 years ago

+1 same issue.

emri99 commented 2 years ago

A workaround is to rename your own sharedpreferences key containing the expected locale to use ;)

jgoyvaerts commented 2 years ago

A workaround is to rename your own sharedpreferences key containing the expected locale to use ;)

Yea, we did that, still annoying though :)