flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
166.1k stars 27.43k forks source link

MaterialApp not building fully on Locale('ar') test #134999

Open julianniedermaier opened 1 year ago

julianniedermaier commented 1 year ago

Is there an existing issue for this?

Steps to reproduce

Unsure if this is a bug or I have just managed to break my project.

I am building a project for internationalization to be used in other projects later on. The project is using l10n and BLoC for state management. The supported languages are 'en' (default), 'ar', 'de', 'es', etc. The project works without any issues when run on a connected android device. However, automated tests fail with certain locales ('ar', 'be', 'fa', etc.) as the MaterialApp tree isn't building fully. After encountering the error and being unable to solve it I, to ensure I haven't introduced errors during the design, have started again from a blank canvas only copy-pasting my code snippets, but setting up the l10n, pubspec, etc. from scratch. The error remains that non-latin scripts fail in tests. Additionally, after unplugging the android device (after successfully running and stopping the app) any non-latin languages that have not been triggered while the phone was connected also fail to build. The app does not default to 'en', but ignores all locale changes.

I'm unsure if I am missing some initialization - WidgetsFlutterBinding.ensureInitialized(); is initialized in main() - or some boolean I need to trigger.

If this is not a bug, please close and my apologies.

Expected results

Material App building fully (using Locale('ar') and starting HomePage. Test to be able to find the HomePage element - final context = tester.element(find.byType(HomePage)); - this works successfully on locales like 'en', 'de', 'es' ...

Actual results

Material App stopping build halfway through (not building title, directionality, debugBanner, home etc.). Test failing as it cannot find the HomePage

Code sample

Code sample ```dart import 'package:advanced_internationalization/home/home.dart'; import 'package:advanced_internationalization/l10n/l10n.dart'; import 'package:advanced_internationalization/settings/settings.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_localized_locales/flutter_localized_locales.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:settings_repository/settings_repository.dart'; /// The top-level widget representing the entire application. class App extends StatelessWidget { /// Creates an instance of the [App] widget and initializes the required /// BLoc providers. const App({ required this.settingsRepository, super.key, }); /// The [settingsRepository] is responsible for managing the application's /// settings, such as locale and theme preferences. final SettingsRepository settingsRepository; @override Widget build(BuildContext context) { return RepositoryProvider.value( value: settingsRepository, child: BlocProvider( create: (context) => LocaleSettingsBloc( settingsRepository: context.read(), )..add(const GetLocaleSettings()), child: const AppView(), ), ); } } /// The root for the [MaterialApp]. class AppView extends StatefulWidget { /// Creates an instance of the [AppView] widget. /// /// This widget acts as the root for the material application and listens to /// device locale changes. const AppView({super.key}); @override State createState() => _AppViewState(); } class _AppViewState extends State with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void didChangeLocales(List? locales) { context.read().add(ChangeDeviceLocale(locales!.first)); super.didChangeLocales(locales); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { return MaterialApp( title: 'Flutter Localizations', theme: ThemeData(primarySwatch: Colors.blue), supportedLocales: AppLocalizations.supportedLocales, locale: state.selectedLocale, localeListResolutionCallback: (locales, supportedLocales) { if (state.deviceLocale == null) { // Setting initial device locale context .read() .add(ChangeDeviceLocale(locales!.first)); } return basicLocaleListResolution(locales, supportedLocales); }, localizationsDelegates: const [ ...AppLocalizations.localizationsDelegates, LocaleNamesLocalizationsDelegate(), ], home: const HomePage(), ); }, ); } } /// Testing file class MockSettingsRepository extends Mock implements SettingsRepository {} void main() { group('Locale Integration Tests', () { late MockSettingsRepository mockSettingsRepository; final supportedLocale = AppLocalizations.supportedLocales[1]; final supportedLocaleAlternative = AppLocalizations.supportedLocales[2]; final supportedLocalesList = [supportedLocale, supportedLocaleAlternative]; setUp(() { mockSettingsRepository = MockSettingsRepository(); }); testWidgets('Start in first device locale (supported)', (WidgetTester tester) async { // App starts in the first device locale if the device locale is // supported and there is no locale saved in shared preferences tester.platformDispatcher.localesTestValue = supportedLocalesList; expect(tester.platformDispatcher.locales, supportedLocalesList); // Build the AppView widget with the mocked settings repository await tester.pumpWidget( App(settingsRepository: mockSettingsRepository), ); await tester.pumpAndSettle(); debugDumpApp(); // Verify result final context = tester.element(find.byType(HomePage)); expect(Localizations.localeOf(context), supportedLocalesList.first); }); }); } ```

Screenshots or Video

Screenshots / Video demonstration [Upload media here]

Logs

Logs ```console AutomatedTestWidgetsFlutterBinding - DEBUG MODE [root](renderObject: RenderView#44f06) └View-[GlobalObjectKey TestFlutterView#9c6fe] └_ViewScope └_MediaQueryFromView(state: _MediaQueryFromViewState#044ed) └MediaQuery(MediaQueryData(size: Size(800.0, 600.0), devicePixelRatio: 3.0, textScaleFactor: 1.0, platformBrightness: Brightness.light, padding: EdgeInsets.zero, viewPadding: EdgeInsets.zero, viewInsets: EdgeInsets.zero, systemGestureInsets: EdgeInsets.zero, alwaysUse24HourFormat: false, accessibleNavigation: false, highContrast: false, disableAnimations: false, invertColors: false, boldText: false, navigationMode: traditional, gestureSettings: DeviceGestureSettings(touchSlop: null), displayFeatures: [])) └App └RepositoryProvider(value: MockSettingsRepository) └_InheritedProviderScope └BlocProvider └InheritedProvider(value: Instance of 'LocaleSettingsBloc', listening to value) └_InheritedProviderScope(value: Instance of 'LocaleSettingsBloc', listening to value) └AppView(state: _AppViewState#a9e70) └BlocBuilder(dependencies: [_InheritedProviderScope], state: _BlocBuilderBaseState#19932) └BlocListener(state: _BlocListenerBaseState#83cb9) └MaterialApp(state: _MaterialAppState#82029) └ScrollConfiguration(behavior: MaterialScrollBehavior) └HeroControllerScope └Focus(state: _FocusState#d0984) └_FocusInheritedScope └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#f2fd8) └WidgetsApp-[GlobalObjectKey _MaterialAppState#82029](state: _WidgetsAppState#3fe41) └RootRestorationScope(state: _RootRestorationScopeState#4c17c) └UnmanagedRestorationScope └RestorationScope(dependencies: [UnmanagedRestorationScope], state: _RestorationScopeState#8d2bd) └UnmanagedRestorationScope └SharedAppData(state: _SharedAppDataState#47e80) └_SharedAppModel └Shortcuts(shortcuts: , state: _ShortcutsState#5ab9f) └Focus(debugLabel: "Shortcuts", dependencies: [_FocusInheritedScope], state: _FocusState#0db38) └_FocusInheritedScope └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#e4a44) └DefaultTextEditingShortcuts └Shortcuts(shortcuts: , state: _ShortcutsState#4d2c5) └Focus(debugLabel: "Shortcuts", dependencies: [_FocusInheritedScope], state: _FocusState#8d58a) └_FocusInheritedScope └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#b1fc5) └Actions(dispatcher: null, actions: {DoNothingIntent: DoNothingAction#6ac15, DoNothingAndStopPropagationIntent: DoNothingAction#9e2e8, RequestFocusIntent: RequestFocusAction#72b81, NextFocusIntent: NextFocusAction#c1802, PreviousFocusIntent: PreviousFocusAction#bec27, DirectionalFocusIntent: DirectionalFocusAction#2ab71, ScrollIntent: _OverridableContextAction#cb939(defaultAction: ScrollAction#87e7f), PrioritizedIntents: PrioritizedAction#84877, VoidCallbackIntent: VoidCallbackAction#dbd5b}, state: _ActionsState#c0ef4) └_ActionsScope └FocusTraversalGroup(policy: ReadingOrderTraversalPolicy#1d905, state: _FocusTraversalGroupState#8772f) └Focus(debugLabel: "FocusTraversalGroup", focusNode: _FocusTraversalGroupNode#5eba6(FocusTraversalGroup), dependencies: [_FocusInheritedScope], state: _FocusState#c0ccb) └_FocusInheritedScope └TapRegionSurface(renderObject: RenderTapRegionSurface#08b56) └ShortcutRegistrar(state: _ShortcutRegistrarState#2116a) └_ShortcutRegistrarScope └Shortcuts(manager: ShortcutManager#34d54(shortcuts: {}), shortcuts: {}, state: _ShortcutsState#7c82e) └Focus(debugLabel: "Shortcuts", dependencies: [_FocusInheritedScope], state: _FocusState#f3df2) └_FocusInheritedScope └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#c4c5b) └Localizations(locale: ar, delegates: [_AppLocalizationsDelegate[AppLocalizations], GlobalMaterialLocalizations.delegate(79 locales), GlobalCupertinoLocalizations.delegate(78 locales), GlobalWidgetsLocalizations.delegate(79 locales), LocaleNamesLocalizationsDelegate[LocaleNames], DefaultMaterialLocalizations.delegate(en_US), DefaultCupertinoLocalizations.delegate(en_US), DefaultWidgetsLocalizations.delegate(en_US)], state: _LocalizationsState#28eae) └SizedBox.shrink(renderObject: RenderConstrainedBox#68818) ```

Flutter Doctor output

Doctor output ```console Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 3.13.4, on Microsoft Windows [Version 10.0.19045.3324], locale en-GB) [√] Windows Version (Installed version of Windows is version 10 or higher) [√] Android toolchain - develop for Android devices (Android SDK version 33.0.0) [√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.3.3) [√] Android Studio (version 2022.3) [√] Connected device (1 available) [√] Network resources • No issues found! ```
huycozy commented 1 year ago

Hi @julianniedermaier In order to address the issue properly, please provide a completed and minimal reproducible code sample that doesn’t include 3rd party plugins or complex production code so that we may verify this.

This may be related to https://github.com/flutter/flutter/issues/84053.

julianniedermaier commented 1 year ago

Here is a minimal reproducible code sample with l10n and a supported locale list of ['en', 'ar', 'de']:

import 'package:advanced_internationalization/l10n/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localized_locales/flutter_localized_locales.dart';
import 'package:flutter_test/flutter_test.dart';

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      supportedLocales: AppLocalizations.supportedLocales,
      localeListResolutionCallback: basicLocaleListResolution,
      localizationsDelegates: [
        ...AppLocalizations.localizationsDelegates,
        LocaleNamesLocalizationsDelegate(),
      ],
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

void main() {
  group('Locale Integration Tests', () {
    final supportedLocale = AppLocalizations.supportedLocales[1]; // 'ar'
    final supportedLocaleAlternative = AppLocalizations.supportedLocales[2]; // 'de'
    final supportedLocalesList = [supportedLocale, supportedLocaleAlternative];

    testWidgets('Start in first device locale (supported)',
        (WidgetTester tester) async {
      tester.platformDispatcher.localesTestValue = supportedLocalesList;
      expect(tester.platformDispatcher.locales, supportedLocalesList);

      await tester.pumpWidget(const App());
      await tester.pumpAndSettle();
      debugDumpApp();

      final context = tester.element(find.byType(HomePage));
      expect(Localizations.localeOf(context), supportedLocalesList.first);
    });
  });
}

Thank you for requesting this! Trimming it down more and more I figured out the addition of the LocaleNamesLocalizationsDelegate() (not necessary in this code sample, but left in for reproduction) is causing the problem. Now this is a package I only recently started using, but it seems to be built rather simple and I don't see how it causes the MaterialApp build to fail. See the simple code file here: https://github.com/guidezpl/flutter-localized-locales/tree/master/lib Has something changed recently in how delegates are being handled?

huycozy commented 1 year ago

Thanks for the update.

I checked this with a simpler sample at Flutter-demo-l10n/134999 but can't reproduce the issue, the test can run successfully. You can try it and update the code if it's necessary to replicate this issue.

Regarding delegates issue, I'm not sure about this. You can check Flutter release notes and find related changes if any.

Regarding sample code using flutter_localized_locales, I created below sample but got another error: Bad state: No element. Please also try and modify it to reproduce the initial issue. If the issue is only reproducible with flutter_localized_locales package, please file an issue at its repository for better support there.

flutter_localized_locales sample project

julianniedermaier commented 1 year ago

Thanks for testing it. I might have communicated this badly. The Bad state: No element error is the one I am getting as well. The interesting thing is how this error is coming about. I have attached a section of my terminal log below for both the failing and the passing test.

This is how I understand it: The Bad state: No element is triggered by line 29 in the test code - final context = tester.element(find.byType(HomePage)); - which is failing to find the HomePage. The reason it is not finding the HomePage is because the MaterialApp never navigates to the HomePage. As you can see in the debugDumpApp() report (which is requested before faulty line 29 in the test code), the MaterialApp stops its process after ...->Semantics->Localizations->SizedBox. (see below) If you run your code with 'es' instead of 'ar' you will see that the debugDumpApp() report shows ...->Semantics->Localizations->Semantics->...->HomePage->... So, using your code (with the flutter_localized_locales) and only swapping the primary locale from 'ar' to 'es' results in a very different debugDumpApp() report. Using 'ar' the MaterialApp never navigates to the HomePage, which means find.byType(HomePage) never finds the HomePage, which in turn triggers the Bad state: No element error.

Please correct me if I misunderstood this. But if this is correct I am confused how the combination of the delegate and 'ar' is causing such an issue.

Terminal - Locale('ar') - Failing:

...
└_FocusInheritedScope
└Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#557f6)
└Localizations(locale: ar, delegates: [_AppLocalizationsDelegate[AppLocalizations], GlobalMaterialLocalizations.delegate(79 locales), GlobalCupertinoLocalizations.delegate(78 locales), GlobalWidgetsLocalizations.delegate(79 locales), LocaleNamesLocalizationsDelegate[LocaleNames], DefaultMaterialLocalizations.delegate(en_US), DefaultCupertinoLocalizations.delegate(en_US), DefaultWidgetsLocalizations.delegate(en_US)], state: _LocalizationsState#d3f34)
└SizedBox.shrink(renderObject: RenderConstrainedBox#87ff8)

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following StateError was thrown running a test:
Bad state: No element

#2      main.<anonymous closure>.<anonymous closure> (file:///C:/Users/Julian/Downloads/test_134999/test_134999/test/widget_test.dart:29:30)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)

The test description was:
  Start in first device locale (supported)
...

Terminal - Locale('es') - passing

...
└Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#62f3a)
└Localizations(locale: es, delegates: [_AppLocalizationsDelegate[AppLocalizations], GlobalMaterialLocalizations.delegate(79 locales), GlobalCupertinoLocalizations.delegate(78 locales), GlobalWidgetsLocalizations.delegate(79 locales), LocaleNamesLocalizationsDelegate[LocaleNames], DefaultMaterialLocalizations.delegate(en_US), DefaultCupertinoLocalizations.delegate(en_US), DefaultWidgetsLocalizations.delegate(en_US)], state: _LocalizationsState#dd80e)
└Semantics(container: false, properties: SemanticsProperties, tooltip: null, textDirection: ltr, renderObject: RenderSemanticsAnnotations#2f4b3)
...
 └Builder
└Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#bf890)
└HomePage
└Placeholder
└LimitedBox(maxWidth: 400.0, maxHeight: 400.0, renderObject: RenderLimitedBox#2ff29)
└CustomPaint(renderObject: RenderCustomPaint#e8fd1)

00:14 +1: All tests passed!
huycozy commented 1 year ago

I just figured out that if I comment out LocaleNamesLocalizationsDelegate from localizationsDelegates, the test is successful (you can try this as well). Since it comes from flutter-localized-locales package, perhaps Pierre-Louis might give us more insights if this is a Flutter framework or package issue.

cc @guidezpl for thoughts.

guidezpl commented 1 year ago

I haven't touched that package substantially in a number of years, and nothing you're doing seems obviously wrong. Sorry I can't be of more help. I'd have a look in https://github.com/guidezpl/flutter-localized-locales/blob/main/lib/flutter_localized_locales.dart#L34-L85 to see where a failure (in loading JSON, for example) might be ocurring

julianniedermaier commented 1 year ago

Thanks a lot to both of you! Pierre-Louis it is a fantastic package!

I implemented flutter_localized_locales the same way as it is done in the Flutter Gallery App and so didn't assume the problem could lie in the code there.

Debugging the file I think the Bad state: no element error might not actually be triggered by line 29 of the test code, but when trying to resolve the future final data = Map<String, String>.from(await _loadJSON('data/$localeToLoad.json') as Map<dynamic, dynamic>); in this line in flutter_localized_locals. To narrow it down, I have specifically tried final testData = await _loadJSON('data/$localeToLoad.json'); and final testData = _loadJSON('data/$localeToLoad.json');, where the former fails and the latter assigns an Instance of 'Future<dynamic>' to testData. I have then tried to check if I can access the raw data using rawDataStr = await rootBundle.loadString('data/$localeToLoad.json');, but this code fails with Unable to load asset: "data/es.json". or Unable to load asset: "data/ar.json". regardless of locale. That is one side confusing, but then maybe also means it isn't the problem, since Locale('es') doesn't cause any issues in the normal code.

I have to admit this is now going beyond my abilities in programming. For further assistance I would be immensely thankful!

julianniedermaier commented 1 year ago

I think I just figured out the FakeAsync the test framework runs in is causing (at least part of) the issue. It seems some of the non-latin scripts need a tiny bit too long to jsonDecode causing the test to complete before the data has been decoded. Running the test with tester.runAsync(() async {... allows Locale('ar') data to be loaded from the ar.json file. Unfortunately, the overall test still fails. Could this have something to do with where the @overwrite load function is called in the LocalizationsDelegate? Maybe related to this: https://stackoverflow.com/questions/54021267/test-breaks-when-using-future-delayed

julianniedermaier commented 1 year ago

Maybe related to: #22193

huycozy commented 1 year ago

Labeling the issue to have more opinions from others. Reproduced this issue with sample code: flutter_localized_locales sample project on the latest Flutter stable and master channels.

flutter doctor -v (stable and master) ```bash [✓] Flutter (Channel stable, 3.13.5, on macOS 13.5 22G74 darwin-x64, locale en-VN) • Flutter version 3.13.5 on channel stable at /Users/huynq/Documents/GitHub/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 12fccda598 (31 hours ago), 2023-09-19 13:56:11 -0700 • Engine revision bd986c5ed2 • Dart version 3.1.2 • DevTools version 2.25.0 [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0) • Android SDK at /Users/huynq/Library/Android/sdk • Platform android-34, build-tools 32.0.0 • ANDROID_HOME = /Users/huynq/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 14.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 14E222b • CocoaPods version 1.11.3 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.2) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) [✓] VS Code (version 1.82.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.72.0 [✓] Connected device (3 available) • RMX2001 (mobile) • EUYTFEUSQSRGDA6D • android-arm64 • Android 11 (API 30) • macOS (desktop) • macos • darwin-x64 • macOS 13.5 22G74 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 117.0.5938.62 [✓] Network resources • All expected network resources are available. • No issues found! ``` ```bash [!] Flutter (Channel master, 3.14.0-14.0.pre.432, on macOS 13.5 22G74 darwin-x64, locale en-VN) • Flutter version 3.14.0-14.0.pre.432 on channel master at /Users/huynq/Documents/GitHub/flutter_master ! Warning: `flutter` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path. ! Warning: `dart` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision 68d5c1760b (50 minutes ago), 2023-09-21 22:14:19 -0400 • Engine revision e726798410 • Dart version 3.2.0 (build 3.2.0-187.0.dev) • DevTools version 2.28.0-dev.12 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0) • Android SDK at /Users/huynq/Library/Android/sdk • Platform android-34, build-tools 32.0.0 • ANDROID_HOME = /Users/huynq/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 14.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 14E222b • CocoaPods version 1.11.3 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.2) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) [✓] VS Code (version 1.82.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.72.0 [✓] Connected device (3 available) • RMX2001 (mobile) • EUYTFEUSQSRGDA6D • android-arm64 • Android 11 (API 30) • macOS (desktop) • macos • darwin-x64 • macOS 13.5 22G74 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 117.0.5938.62 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. ```
HansMuller commented 1 year ago

Labeling this P3 not because it's unimportant; only because there's not a simple test case that isolates the problem to Flutter's i18n tools - https://docs.flutter.dev/ui/accessibility-and-localization/internationalization

julianniedermaier commented 1 year ago

In my original issue report I mentioned a second problem, which seems to be much more severe and is most likely caused by the same issue.

Please find a simple sample code here: https://github.com/julianniedermaier/locale_test_issue/tree/main

Steps to reproduce: 1) Open project in IDE 2) Run pub get 3) Connect physical android device to IDE 4) Run project - Important: Do not interact with the app once it has been built on your android device 5) Stop the execution 6) Unplug the android device from your computer 7) Press the button on the app (this should be the first time you are interacting with the app)

Expected outcome: The app changes language from english to arabic

Actual outcome: The app stays in english

Some explanation on what is happening: I have again added flutter_localized_locales to the project, which loads a json file when a language is changed. This file is larger on unicode files than on latin-script files (i.e. the 'ar' file is significantly larger than the 'en' file). Running the app the first time in a new locale on the device disconnected from a computer results in the material app building before the json file has been fully loaded. The material app therefore stays in the current locale and does not change.

The reasons for why this works succesfully when connected to the computer and does not on a disconnected computer I don't know. However, if this is reproducible it means the issue raised in this issue report is not limited to locale testing, but affects normal app development and USAGE.

julianniedermaier commented 1 year ago

Just adding to my previous comment: The issue is (for me) also repoducible in the flutter gallery app. Download the current gallery app code from github. Run it from the IDE onto my android phone. Disconnect the phone, change to 'ar'. The test direction changes (as the gallery handles this separately), but the language does not

JamesMcIntosh commented 9 months ago

Hi @julianniedermaier, I encountered a condition where long load times for the localized message delegate caused the messages to not display. This is due to a bug in the i18n library which happens if you request any message before the delegate has loaded the locale for that message. See: https://github.com/dart-lang/i18n/pull/783