【问题标题】:How to get timezone, Language and County Id in flutter by the location of device in flutter?如何通过颤动中的设备位置获取颤动中的时区、语言和县 ID?
【发布时间】:2018-11-28 03:38:48
【问题描述】:

我是 Flutter 的新手,我想在我的设备 android 或 iOS 上运行我的项目时获取时区、语言和县 ID。它应该从设备的位置检测时区、语言和国家 ID。我是新手,不知道如何获得这些。

我可以通过内部库获得这些吗?

【问题讨论】:

    标签: datetime dart timezone flutter


    【解决方案1】:

    https://flutter.io/tutorials/internationalization/#tracking-locale

    Locale myLocale = Localizations.localeOf(context);

    提供countryCodelanguageCode

    https://docs.flutter.io/flutter/dart-ui/Locale-class.html

    时区应该可用(未尝试)

    DateTime.now().timeZoneName
    

    https://docs.flutter.io/flutter/dart-core/DateTime-class.html

    【讨论】:

    • 谢谢@Gunter,但我得到了国家代码“US”和语言ID“en”,我怎样才能相应地得到它我当前的位置,因为我在印度它应该显示“IND”
    • 语言环境 myLocale = Localizations.localeOf(context);对我不起作用。 myLocale.languageCode 始终为“en”
    • 执行此操作时,我收到错误“断言失败”、“Scope != null,未找到本地化祖先”。
    • Localizations.localeOf(context) 并非对所有人都有效的原因:它提供了当前上下文的语言环境,该语言环境源自系统语言环境,但已解析为supportedLocales 中的语言环境。这是传递给MaterialAppWidgetsApp 小部件的参数,默认只有[en_US]。使用WidgetsBinding.instance.window.locale 可以为您提供原始的东西。
    • 如果你们使用的是 iOS,请不要忘记在 info.plist 中添加支持的语言,否则您将无法使用它。
    【解决方案2】:

    试试这个:

    import 'dart:ui' as ui;
    ......
     @override
      Widget build(BuildContext context) {
    // get system language code
        _sysLng = ui.window.locale.languageCode;    
    ...
    

    【讨论】:

    • 在应用开始时总是返回 null。
    • 无论如何总是返回'en'。
    • 使用 iOS 13 似乎有一个错误,因为它返回 null ...所以我觉得这种方法不可靠。从现在开始我只使用 Locale myLocale = Localizations.localeOf(context);
    【解决方案3】:

    你可以使用

    import 'dart:io' show Platform;
    
    String languageCode = Platform.localeName.split('_')[0];
    String countryCode = Platform.localeName.split('_')[1];
    

    【讨论】:

    • 如果我将 iOS 模拟器更改为美国西班牙语,这对我不起作用。我仍然得到“en”、“US”。
    • 我刚刚修好了
    【解决方案4】:

    使其工作的步骤是:

    1. 将包作为依赖项添加到您的 pubspec.yaml 文件中

      dependencies:
         flutter:
         sdk: flutter
      flutter_localizations:
         sdk: flutter
      
    2. 导入flutter_localizations库并为MaterialApp指定localizationsDelegates和supportedLocales

      import 'package:flutter_localizations/flutter_localizations.dart';
      
      MaterialApp(
      localizationsDelegates: [
          // ... app-specific localization delegate[s] here
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate,
      ],
      
      supportedLocales: [
          const Locale('en', ''), // English, no country code
          const Locale('es', ''), // Spanish, no country code
          // ... other locales the app supports
       ],
      // ...
      )
      
    3. 仅适用于 iOS:打开 ios 模块并在本地化

      下添加支持的语言

    1. 获取当前语言环境

      Locale myLocale = Localizations.localeOf(context);

    如果需要,您可以访问 Locale 的 countryCodelanguageCode 字符串属性

    【讨论】:

      【解决方案5】:

      Flutter 语言环境解释

      首先,你应该了解系统设置和你的应用设置的区别:

      • 系统设置 - 系统向您的应用提供的内容,作为您的信息的用户首选项。
      • 应用程序设置 - 决定(显式或隐式)作为应用程序区域设置的内容。您可以允许您的用户选择您应用的任何语言环境,或者让 Flutter 为您完成。

      获取当前系统首选项

      获取当前默认系统语言环境

      import 'dart:io';
      
      final String defaultLocale = Platform.localeName; // Returns locale string in the form 'en_US'
      
      

      获取系统区域列表

      import 'package:flutter/material.dart';
      
      final List<Locale> systemLocales = WidgetsBinding.instance.window.locales; // Returns the list of locales that user defined in the system settings.
      
      

      import 'dart:ui';
      
      final List<Locale> systemLocales = window.locales;
      

      应用程序的语言环境

      MaterialApp 小部件支持本地化。它接受 决定您的应用支持的语言环境列表。这意味着 应该在 supportedLocales 属性的小部件初始化中明确定义它们,并提供所谓的“本地化委托”,将实际翻译到选定的语言环境(localizationsDelegates 属性) .如果您的应用支持除en_US 之外的任何其他语言环境,则需要提供委托。 当您请求应用程序区域设置时,您将从supportedLocales 列表中获得准确的值

      获取您的应用程序语言环境

      final Locale appLocale = Localizations.localeOf(context);
      

      仅在 MaterialApp 小部件已初始化时有效。在MaterialApp 初始化之前不能使用它。显然,如果您的应用小部件未初始化,您将无法获取其语言环境。要使用它,您必须在子组件的build 方法中调用此表达式。例如:

      void main() async {
        runApp(
          MaterialApp(
            title: 'MyApp',
            home: MyApp(),
          )
        );
      }
      
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          // Show the name of the current application locale
          return Text(Localizations.localeOf(context).toString());
        }
      }
      
      

      这将在屏幕上打印en_US 文本(因为这是默认语言环境,我们没有提供任何其他内容)。系统区域设置是什么并不重要,因为在此示例中我们没有为我们的应用明确定义任何区域设置,因此它返回默认设置。

      捕捉系统区域设置变化

      为了能够对系统区域设置更改做出反应,您应该使用实现 WidgetsBindingObserver mixin 的有状态小部件并定义将在系统区域设置更改时调用的 didChangeLocales 方法:

        @override
        void didChangeLocales(List<Locale> locale) {
          // This is run when system locales are changed
          super.didChangeLocales(locale);
          setState(() {
            // Do actual stuff on the changes
          });
        }
      

      完整示例

      总结以上所有内容,以下是启动时获取语言环境并对系统设置更改做出反应的直观示例:

      import 'dart:io';
      import 'package:flutter/material.dart';
      import 'package:flutter_localizations/flutter_localizations.dart';
      
      void main() async {
        WidgetsFlutterBinding.ensureInitialized();
      
        // Get the initial locale values
        final String defaultSystemLocale = Platform.localeName;
        final List<Locale> systemLocales = WidgetsBinding.instance.window.locales;
      
        // Define locales that our app supports (no country codes, see comments below)
        final appSupportedLocales = <Locale>[
          Locale('ru'),
          Locale('en'),
        ];
      
        final MyApp myApp = MyApp(defaultSystemLocale, systemLocales);
      
        runApp(
          MaterialApp(
            title: 'MyApp',
            home: myApp,
            supportedLocales: appSupportedLocales,
            localizationsDelegates: [
              // These are default localization delegates that implement the very basic translations for standard controls and date/time formats.
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
            ],
          )
        );
      }
      
      class MyApp extends StatefulWidget {
        // Store initial locale settings here, they are unchanged
        final String initialDefaultSystemLocale;
        final List<Locale> initialSystemLocales;
      
        MyApp(this.initialDefaultSystemLocale, this.initialSystemLocales);
      
        @override
        _MyAppState createState() => _MyAppState();
      }
      
      
      class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
        // Store dynamic changeable locale settings here, they change with the system changes
        String currentDefaultSystemLocale;
        List<Locale> currentSystemLocales;
      
        // Here we read the current locale values
        void setCurrentValues() {
          currentSystemLocales = WidgetsBinding.instance.window.locales;
          currentDefaultSystemLocale = Platform.localeName;
        }
      
        @override
        void initState() {
          // This is run when the widget is first time initialized
          WidgetsBinding.instance.addObserver(this); // Subscribe to changes
          setCurrentValues();
          super.initState();
        }
      
        @override
        void didChangeLocales(List<Locale> locale) {
          // This is run when system locales are changed
          super.didChangeLocales(locale);
          // Update state with the new values and redraw controls
          setState(() {
            setCurrentValues();
          });
        }
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(),
            body: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                Text('Initial system default locale: ${widget.initialDefaultSystemLocale}.'),
                Text('Initial language code: ${widget.initialDefaultSystemLocale.split('_')[0]}, country code: ${widget.initialDefaultSystemLocale.split('_')[1]}.'),
                Text('Initial system locales:'),
                for (var locale in widget.initialSystemLocales) Text(locale.toString()),
                Text(''),
                Text('Current system default locale: ${currentDefaultSystemLocale}.'),
                Text('Current system locales:'),
                for (var locale in currentSystemLocales) Text(locale.toString()),
                Text(''),
                Text('Selected application locale: ${Localizations.localeOf(context).toString()}.'),
                Text(''),
                Text('Current date: ${Localizations.of<MaterialLocalizations>(context, MaterialLocalizations).formatFullDate(DateTime.now())}.'),
                Text('Current time zone: ${DateTime.now().timeZoneName} (offset ${DateTime.now().timeZoneOffset}).'),
              ],
            ),
          );
        }
      }
      
      

      支持的语言环境是在没有国家代码的情况下定义的,以向您展示当前应用语言环境的选择是如何工作的。在内部,MaterialApp 小部件正在将应用支持的语言环境列表与系统传递的用户偏好列表进行比较,并选择最合适的一个。

      假设我们有以下系统语言环境列表(en_US、en_GB、ru_RU):

      ** 点击缩略图查看完整截图。

      我们的应用在启动时将如下所示:

      我们看到初始值和当前值显然相同。该应用选择了en 语言环境作为其当前语言环境。

      现在让我们将语言环境列表更改为以下内容,将 en_GB 语言环境移到顶部,使其成为默认系统语言环境:

      应用将反映这一变化:

      应用程序显然仍然选择 en 语言环境作为其当前语言环境,因为它与 en_USen_GB 语言环境最接近。

      现在让我们将设置更改为俄语作为默认系统值:

      我们的应用将反映这一变化:

      现在您可以看到 ru 语言环境被选为应用语言环境。

      希望这有助于理解 Flutter 中本地化的工作原理、如何获取当前值以及如何反映系统变化。关于区域设置委托的详细信息不作解释,因为这里离题了。

      PS:此代码仅在 Android 下测试。我认为只要稍作改动,它就可以适应所有其他平台。

      【讨论】:

      • 这就是如何回答问题。做得很好,尽管仅(如上所述)适用于 Android。
      • 天哪,这是神级答案!我是来找别的东西的,但不后悔读了这个:) @AmmyKang 你介意把这个改成“正确”的答案吗?
      【解决方案6】:

      如果您编写 Platform.localeName,它会为您提供语言和国家/地区,例如“en_US”、“tr_TR”。

      要只取“en”或“tr”,您可以使用 substring() 并取前 2 个字母。

      String deviceLanguage= Platform.localeName.substring(0,2);
      

      它只给你“en”或“tr”等......

      如果你想要国家代码,使用这个;

      String deviceCountry= Platform.localeName.substring(3,5);
      

      它只给你“US”或“TR”等......

      【讨论】:

        【解决方案7】:

        对于时区,所有其他答案都会给出“CET”、“MSK”等缩写以及 GMT 偏移量。

        要以Europe/Paris 格式获取设备的时区,请使用flutter_native_timezone package

        final String currentTimeZone = await FlutterNativeTimezone.getLocalTimezone();
        

        【讨论】:

          猜你喜欢
          • 2019-09-21
          • 2017-12-15
          • 2021-09-15
          • 2021-12-08
          • 2019-06-08
          • 1970-01-01
          • 2021-01-26
          • 1970-01-01
          • 2022-12-21
          相关资源
          最近更新 更多