Skip to content

showTimePicker does not allow for use of 12-hour format for locales that default to a 24-hour format #54839

Closed

Description

@DhavalRKansara

Hello guys, I am using showTimePicker in my application. Also, I am using Internationalizing for my flutter app with two languages(English 'en' & Spanish 'es').

  • Code for present showTimePicker:
Padding(
              padding: EdgeInsets.all(2),
              child: MaterialButton(
                minWidth: double.infinity,
                onPressed: () async {
                  TimeOfDay picked = await showTimePicker(
                    context: context,
                    initialTime: TimeOfDay.now(),
                    builder: (BuildContext context, Widget child) {
                      return MediaQuery(
                        data: MediaQuery.of(context)
                            .copyWith(alwaysUse24HourFormat: false),
                        child: child,
                      );
                    },
                  );
                },
                child: Text(
                  S.of(context).set_time,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                      color: Theme.of(context).primaryColor, fontSize: 14),
                ),
              ),
            ),

Issue what I am facing is Initially when I run my App with the English language it's working fine and showing timePicker with 12 hours formate. But when I am changing App language to Spanish from the App then it will start showing timePicker with 24 hours formate. Please find the below screenshots for the same.

1. When App language is English:

App_in_english_lang

2. When App Language is Changed to Spanish:

App_in_spanish_lang

Activity

  1. VladyslavBondarenko commented on Apr 15, 2020

    @VladyslavBondarenko

    Hi @DhavalRKansara
    Checked, yes, format depends on the chosen locale. I'll label it as proposal, possibility to set always use 12 hour format, not only alwaysUse24HourFormat property

    flutter doctor -v ``` [✓] Flutter (Channel dev, v1.18.0-dev.5.0, on Mac OS X 10.15.4 19E287, locale en-GB) • Flutter version 1.18.0-dev.5.0 at /Users/nevercode/dev/flutter_dev • Framework revision 7f56b53 (3 days ago), 2020-04-12 12:00:01 -0400 • Engine revision beb8a7e • Dart version 2.8.0 (build 2.8.0-dev.20.0 89b0f67261)

    [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at /Users/nevercode/Library/Android/sdk
    • Platform android-29, build-tools 29.0.3
    • Java binary at: /Applications/Android
    Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
    1.8.0_212-release-1586-b4-5784211)
    • All Android licenses accepted.

    [✓] Xcode - develop for iOS and macOS (Xcode 11.4)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.4, Build version 11E146
    • CocoaPods version 1.9.0

    [✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

    [✓] Android Studio (version 3.6)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 45.1.1
    • Dart plugin version 192.7761
    • Java version OpenJDK Runtime Environment (build
    1.8.0_212-release-1586-b4-5784211)

    [✓] VS Code (version 1.43.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.9.1

    [✓] Connected device (6 available)
    • Redmi Note 7 • 6345c469 •
    android-arm64 • Android 9 (API 28)
    • Android SDK built for x86 • emulator-5554 •
    android-x86 • Android 10 (API 29) (emulator)
    • iPhone 11 Pro Max • 5D5365D0-C0F6-4440-B758-FFA83896129E • ios
    • com.apple.CoreSimulator.SimRuntime.iOS-13-4 (simulator)
    • macOS • macOS •
    darwin-x64 • Mac OS X 10.15.4 19E287
    • Chrome • chrome •
    web-javascript • Google Chrome 81.0.4044.92
    • Web Server • web-server •
    web-javascript • Flutter Tools

    • No issues found!

    
    </details>
    
  2. added
    p: material_uimaterial_ui package in flutter/packages
    frameworkflutter/packages/flutter repository. See also f: labels.
    c: proposalA detailed proposal for a change to Flutter
    on Apr 15, 2020
  3. DhavalRKansara commented on Apr 15, 2020

    @DhavalRKansara
    Author

    @VladyslavBondarenko But I have marked alwaysUse24HourFormat false while opening the dialog.

  4. HansMuller commented on Apr 15, 2020

    @HansMuller
    Contributor
  5. DhavalRKansara commented on May 4, 2020

    @DhavalRKansara
    Author

    I found that I am facing this issue while I change supportedLocales value to Locale('es', '') from Locale('en', ''). But I have no idea how I can fix this

    @zoechi @darrenaustin @VladyslavBondarenko any idea?

  6. HansMuller commented on May 4, 2020

    @HansMuller
    Contributor
  7. rami-a commented on May 4, 2020

    @rami-a
    Contributor

    hey @DhavalRKansara, the time picker decides whether to use 12 or 24hr clock depending on the locale. Is your application primarily targeting the US only? I found that if you specify the country in the locale (like Locale('es', 'US')), you can get Spanish translations and the 12 hour clock.

  8. DhavalRKansara commented on May 4, 2020

    @DhavalRKansara
    Author

    hey @DhavalRKansara, the time picker decides whether to use 12 or 24hr clock depending on the locale. Is your application primarily targeting the US only? I found that if you specify the country in the locale (like Locale('es', 'US')), you can get Spanish translations and the 12 hour clock.

    @rami-a Thanks for the reply. I tried to set Locals with their country code but when I am setting Locale('es', 'US') and Locale('es', 'ES') for my MaterialApp but after this changes my app starts running in the English language on behalf of Spanish.

  9. rami-a commented on May 5, 2020

    @rami-a
    Contributor

    Hmm this seems like a separate issue. How are you specifying the locale?

  10. DhavalRKansara commented on May 7, 2020

    @DhavalRKansara
    Author

    Previous code before this reply:

    MaterialApp(
                  navigatorKey: _scaffoldKey,
                  debugShowCheckedModeBanner: false,
                  locale: this.locale,
                  localizationsDelegates: const [
                    S.delegate,
                    GlobalMaterialLocalizations.delegate,
                    GlobalWidgetsLocalizations.delegate,
                  ],
                  supportedLocales: S.delegate.supportedLocales,
                  // ignore: missing_return
                  localeResolutionCallback: (deviceLocale, supportedLocales) {
                    S.delegate.resolution(fallback: deviceLocale);
                  },
                  localeListResolutionCallback:
                      S.delegate.listResolution(fallback: const Locale('en', '')),
                  theme: ThemeData(
                    primaryColor: const Color(0xFF2090A6),
                    accentColor: const Color(0xFFFF7043),
                    fontFamily: 'Quicksand',
                  ),
                  home: Home()),
    

    For the value of this.local in above code I am getting one language parameter from the backend and according to that I am setting Local as below:

     _fetchLocale() async {
        int language = await SharedPrefPharmacy()
            .getSharedProperty(key: SharedPrefKeysEnum.language);
        if (language == 0) {
          // English
          return Locale('en', '');
        } else if (language == 1) {
          // Spanish
          return Locale('es', '');
        } else {
          return Locale('en', '');
        }
      }
    

    Calliing _fetchLocale from the initState:

    _fetchLocale().then((locale) {
          setState(() {
            this.localeLoaded = true;
            this.locale = locale;
          });
        });
    
  11. DhavalRKansara commented on May 11, 2020

    @DhavalRKansara
    Author

    @rami-a any idea/suggestions?

  12. rami-a commented on May 11, 2020

    @rami-a
    Contributor

    hey @DhavalRKansara, unfortunately I'm not sure how to fix the problem you're seeing. If I'm understanding correctly, you are specifying the spanish locale but seeing english strings correct? @shihaohong any ideas?

  13. DhavalRKansara commented on May 11, 2020

    @DhavalRKansara
    Author

    No @rami-a for the Spanish local ShowTimePicker comes up with 24 hours formate on behalf of 12 hours.

  14. rami-a commented on May 11, 2020

    @rami-a
    Contributor

    Oh I see. Well like I mentioned earlier, the time picker displays 24 or 12 hour depending on which locale is being used. Since users in those locales expect either a 12 or 24 hour clock.

    If you want to override this behavior entirely, I suggest wrapping your widget tree with a MediaQuery copy that sets the alwaysUse24HourFormat to false. Something like:

    return MediaQuery(
      data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: false)
      child: RestOfYourApp
    )
    
  15. DhavalRKansara commented on May 12, 2020

    @DhavalRKansara
    Author

    Oh I see. Well like I mentioned earlier, the time picker displays 24 or 12 hour depending on which locale is being used. Since users in those locales expect either a 12 or 24 hour clock.

    If you want to override this behavior entirely, I suggest wrapping your widget tree with a MediaQuery copy that sets the alwaysUse24HourFormat to false. Something like:

    return MediaQuery(
      data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: false)
      child: RestOfYourApp
    )
    

    I have already tried to set alwaysUse24HourFormat: false in the for showTimePicker as shown in showTimePicker Documentation. You can see my that in my question. Still, I for Spanish local TimePicker comes in 24 hr formate.

  16. rami-a commented on May 12, 2020

    @rami-a
    Contributor

    I see, something is certainly wrong here. If I follow that documentation with english set, it does make the picker 24hr format, but if I do it with spanish set and then use false for alwaysUse24HourFormat it still stays 24hr. Off the top of my head, I'm not sure why this is the case, so I'll have to look into it. Thanks for pointing this out!

  17. shihaohong commented on May 14, 2020

    @shihaohong
    Contributor

    Sorry about the delay, I've been working on other issues and have finally gotten to this one!

    @DhavalRKansara, I did some digging and found that it's because if you use Locale('es'), the designated time format is the 24 hour format as described in material_es.arb. Unfortunately, there is no way to shake this default value due to the way timeOfDayFormat is defined.

    Since 'es_US' defaults to a 12-hour time format, as a hack, you can do something like the following:

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_localizations/flutter_localizations.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          supportedLocales: <Locale>[
            const Locale('en', 'US'),
            const Locale('es', 'ES'),
          ],
          localizationsDelegates: <LocalizationsDelegate>[
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Time Picker localization demo'),
          ),
          body: Center(
            child: RaisedButton(
              onPressed: () async {
                await showTimePicker(
                  initialTime: TimeOfDay.now(),
                  context: context,
                  builder: (context, child) {
                    final Widget mediaQueryWrapper = MediaQuery(
                      data: MediaQuery.of(context).copyWith(
                        alwaysUse24HourFormat: false,
                      ),
                      child: child,
                    );
                    // A hack to use the es_US dateTimeFormat value.
                    if (Localizations.localeOf(context).languageCode == 'es') {
                      return Localizations.override(
                        context: context,
                        locale: Locale('es', 'US'),
                        child: mediaQueryWrapper,
                      );
                    }
                    return mediaQueryWrapper;
                  },
                );
              },
              child: Text('Show time picker'),
            ),
          ),
        );
      }
    }
    
  18. shihaohong commented on May 14, 2020

    @shihaohong
    Contributor

    That being said, maybe we should rethink the way that timeOfDayFormat is defined, since this doesn't allow a developer to override the default localization setting if the default format is a 24-hour format. The fix would unfortunately be a breaking change.

  19. changed the title [-]After changing Application language showTimePicker dialog comes with 24 hour[/-] [+]showTimePicker does not allow for use of 12-hour format for locales that default to a 24-hour format[/+] on May 14, 2020
  20. DhavalRKansara commented on May 19, 2020

    @DhavalRKansara
    Author

    @shihaohong @rami-a Thanks for your replies...

    For the above issues as I found one library(flutter_rounded_date_picker) and using it, I am able to fix my problem. It is not a solution but we can use it as a workaround.

    Code for ShowTimer:

    
     TimeOfDay picked = await showRoundedTimePicker(
                            context: context,
                            theme: ThemeData(primaryColor:Theme.of(context).primaryColor),
                            initialTime: TimeOfDay.now(),
                            locale: Locale("en", "")
    );
    

    As shown in the above code using flutter_rounded_date_picker we can pass the locale and I am passing Locale("en", "") for Spanish and English. So It is showing 12 hours timePicker for any locale.

    Flutter Team can provide such one optional parameter for the passing locale in the showTimerPicker as they are providing for the [showDatePicker](https://api.flutter.dev/flutter/material/showDatePicker.html).

  21. rami-a commented on May 19, 2020

    @rami-a
    Contributor

    @DhavalRKansara adding locale so that the time picker API matches date picker's seems like a reasonable idea.

    Doing what @shihaohong mentioned and overriding the locale inside the builder parameter will work as well.

  22. anoopkumar1223 commented on Oct 23, 2020

    @anoopkumar1223

    TimeOfDay time = await showTimePicker(
    context: context,
    initialTime: TimeOfDay.now());
    MaterialLocalizations localization = MaterialLocalizations.of(context);
    String formattedTimeOfDay = localization.formatTimeOfDay(time);
    Use formatTimeOfDay() to get time in 12hr format

  23. spixy commented on Jul 9, 2021

    @spixy

    hi @DhavalRKansara I think you accidentally closed this issue while posting your message 🙂

  24. github-actions commented on Jul 30, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  25. locked as resolved and limited conversation to collaborators on Jul 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    c: proposalA detailed proposal for a change to Flutterframeworkflutter/packages/flutter repository. See also f: labels.p: material_uimaterial_ui package in flutter/packages

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions