easy_localization icon indicating copy to clipboard operation
easy_localization copied to clipboard

child call setLocale cannot change all widgets language

Open KevinTsangSKH opened this issue 1 year ago • 11 comments

child call setLocale cannot change all widgets language

KevinTsangSKH avatar Jul 26 '23 04:07 KevinTsangSKH

Hi @KevinTsangSKH, could you explain the issue with more details? What do you observe, what did you expect?

bw-flagship avatar Aug 30 '23 15:08 bw-flagship

Hello, @bw-flagship

As you mentioned in the documentation, when we change the language, the languages of some widgets do not change. For example, the language of the widget I wrap with StreamBuilder does not change, but the language of the fields such as the page title changes. If we save the app with CMD + S or do a HOT reload, it gets fixed. At the user level, I need to open and close the app once for the language change to be detected.

If I print a log like the one below in the build function on the pages that do not change, that error is corrected. (I don't know if this will cause performance loss)

print('setting_view: ${context.locale}');

ismailcaakir avatar Aug 30 '23 17:08 ismailcaakir

@ismailcaakir The desired behavior is that all the widgets update when changing the language. If you experience it differently, could you provide a minimal sample to reproduce? Thanks!

bw-flagship avatar Aug 31 '23 09:08 bw-flagship

@KevinTsangSKH did you manage to resolve the issue? I'm facing the same

filippkowalski avatar Oct 25 '23 11:10 filippkowalski

ok, I've managed to fix it by removing const from home: const HomePage(), in main.dart

filippkowalski avatar Oct 25 '23 12:10 filippkowalski

@filippkowalski This should not be necessary. I suppose your homePage was located in a place where it does not react on the BuildContext, e.g. because it is the home-attribute of the materialApp. If that's the case, the proper fix would be to wrap it with a Builder()

bw-flagship avatar Oct 25 '23 12:10 bw-flagship

@bw-flagship this is my main.dart, it's rather a standard one:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();

  runApp(
    EasyLocalization(
        supportedLocales: const [ Locale('pl'), Locale('en')],
        path: 'assets/translations',
        fallbackLocale: const Locale('en'),
        child: const myappApp()
    ),
  );
}

class myappApp extends StatefulWidget {
  const myappApp({super.key});

  @override
  State<myappApp> createState() => _myappAppState();
}

class _myappAppState extends State<myappApp> {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: AppColors.colorBrand),
        useMaterial3: true,
      ),
      home: HomePage(), // do not put const as it's going to stop refreshing the language
    );
  }
}

filippkowalski avatar Oct 26 '23 07:10 filippkowalski

@filippkowalski I sadly cannot run the example because I don't have the HomePage() widget and the required assets.

However, it's exactly as I expected, the HomePage is a direct value for the "home"-Attribute. This means that it does not react on the Build Context. E.g. if you would change the theme, the update would not work as well.

The fix to not make it const might work, but this is not the correct solution. IMHO you should wrap the HomePage in a builder, I expect it to work then, and you can leave it const.

bw-flagship avatar Oct 26 '23 13:10 bw-flagship

@bw-flagship I did try it, but to no avail image

filippkowalski avatar Oct 29 '23 09:10 filippkowalski

@filippkowalski Strange, this should work from my point of view. However, I can't provide any further info because I don't have the code

bw-flagship avatar Oct 30 '23 08:10 bw-flagship

Use this Code,ChatGPT gives me this solution,it works!!!

  1. wrap your root widget with RestartWidget
  2. call RestartWidget.restartApp
import 'package:flutter/material.dart';

class RestartWidget extends StatefulWidget {
  final Widget child;

  const RestartWidget({Key? key, required this.child}) : super(key: key);

  static restartApp(BuildContext context) {
    context.findAncestorStateOfType<_RestartWidgetState>()?.restartApp();
  }

  @override
  State createState() => _RestartWidgetState();
}

class _RestartWidgetState extends State<RestartWidget> {
  Key key = UniqueKey();

  void restartApp() {
    setState(() {
      key = UniqueKey();
    });
  }

  @override
  Widget build(BuildContext context) {
    return KeyedSubtree(
      key: key,
      child: widget.child,
    );
  }
}

ihou avatar Jan 25 '24 07:01 ihou