【问题标题】:WinRT apps and Regional settings. The correct way to format dates and numbers based on the user's regional settings?WinRT 应用程序和区域设置。根据用户的区域设置格式化日期和数字的正确方法?
【发布时间】:2012-09-24 07:14:58
【问题描述】:

我在 Windows 8 Metro 应用程序(XAML 和 C#)中遇到了一些关于用户区域设置的问题。似乎应用程序不会尊重用户的区域设置,因此即使您的 Windows 8 设置为以芬兰格式显示日期和时间,应用程序仍将使用美国格式显示它们。但问题这么大,一定是我遗漏了什么?

为了测试这一点,我首先创建了一个 WPF 应用程序。应用程序只打印出 CurrentCulture 和格式化的 DateTime.Now:

    private void Culture_Loaded_1(object sender, RoutedEventArgs e)
    {
        this.Culture.Text = System.Globalization.CultureInfo.CurrentCulture.DisplayName;
    }

    private void Date_Loaded_1(object sender, RoutedEventArgs e)
    {
        this.Date.Text = DateTime.Now.ToString();
    }

这是我的默认区域设置:

运行时,应用以芬兰语格式显示日期:

然后我将区域设置更改为美国:

当应用再次运行时,文化和格式发生了变化:

如我所料一切正常,这也是我期望 WinRT 应用程序正常工作的方式。

接下来,我使用相同的代码创建了一个 WinRT(XAML 和 C#)应用程序,并将区域设置恢复为芬兰语。问题:

即使我已通过区域设置定义格式应为“芬兰语”,WinRT 应用仍会使用美国格式显示日期时间。然后我修改了应用程序的项目文件并将 fi-FI 设为默认语言

这一变化也改变了应用的文化:

奇怪。我将默认语言更改回其默认值,并且格式恢复为美国。然后,我在项目中创建了文件夹“Strings - fi-FI”,并在项目中添加了一个空的“Resources.resw”。这个空文件似乎已经足够了,因为我现在得到的是芬兰语格式:

一旦我删除了空资源文件,格式就会恢复为美国格式:

很奇怪。

这导致了几个问题,但我认为主要的问题是:WinRT 应用程序是否有意不遵循 WPF 应用程序那样的用户区域设置?

【问题讨论】:

    标签: c# xaml windows-runtime currentculture windows-store-apps


    【解决方案1】:

    已经有一段时间了,但问题还没有完全回答,所以让我分享一下我的小研究。 Depechie 基本上是对的,但他只提供了一个链接,并不确定。

    是的,这种意想不到的变化是故意的。我们不应该再使用 CultureInfo,因为它包含遗留代码,而微软希望我们改用 Windows.Globalization API。

    要获取当前区域,我们可以使用:

    GeographicRegion userRegion = new GeographicRegion();
    string regionCode = userRegion.CodeTwoLetter;
    

    但我注意到它只包含地区信息,没有语言代码。要获取语言,我们可以使用:

    string langRegionCode = Windows.Globalization.Language.CurrentInputMethodLanguageTag; // depends on keyboard settings
    List<string> langs = Windows.System.UserProfile.GlobalizationPreferences.Languages; // all user  languages, like in languages control panel
    List<string> applicationlangs = Windows.Globalization.ApplicationLanguages.Languages; // application languages (user languages resolved against languages declared as supported by application)
    

    如果语言有方言,它们会以 language-REGION 格式返回 BCP47 语言标签,例如“en-US”,如果语言没有主要方言,则返回类似“pl”的语言。

    我们还可以设置一种主要语言来覆盖所有其他语言:

    Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "en-US";
    

    (这是一个持久设置,应该在用户请求时使用)

    还有用于日期、时间和数字的新 API:

    Windows.Globalization.DateTimeFormatting.DateTimeFormatter dtf = new DateTimeFormatter("longdate", new[] { "en-US" }, "US", CalendarIdentifiers.Gregorian, ClockIdentifiers.TwentyFourHour);
    string longDate = dtf.Format(DateTime.Now);
    
    Windows.Globalization.NumberFormatting.DecimalFormatter deciamlFormatter = new DecimalFormatter(new string[] { "PL" }, "PL");
    double d1 = (double)deciamlFormatter.ParseDouble("2,5"); // ParseDouble returns double?, not double
    

    Windows.Globalization API 中确实有更多内容,但我认为这为我们提供了总体思路。进一步阅读:

    您还可以在 Windows 8 开发中心论坛上找到一些有关该问题的主题,其中包含一些 Microsoft 员工的答案,但它们主要将您发送到文档。

    【讨论】:

    • 那么,究竟如何获取/尊重用户区域格式设置?我使用以下配置启动了 windows phone 8.1 模拟器以进行测试: UI 语言:德语,地区:美国,格式设置:爱尔兰语 我找不到获取信息的方法,即用户已将其格式设置设置为爱尔兰语。我唯一的愿望是像用户希望看到的那样格式化 DateTime。并且区域格式并不自动意味着我将设备设置为的区域或我选择的 UI 语言。在我的设备上,我将 UI 设置为英语,但希望以德语格式查看所有时间戳和日期...
    • 谢谢,下面的很棒,因为我需要 ISO 3166-1 alpha2 en.wikipedia.org/wiki/ISO_3166-1_alpha-2 GeographicRegion userRegion = new GeographicRegion(); string regionCode = userRegion.CodeTwoLetter;
    • 这对我有用,但现在我需要大数字,CurrencyFormatter 不支持小数,所以我需要一个解决方法...
    【解决方案2】:

    这是故意的。微软正在不再强制应用程序使用操作系统的语言。相反,每个应用程序使用应用程序声明的信息(清单语言,可在 Windows.Globalization.ApplicationLanguages.ManifestLanguages 观察)和用户声明的信息(用户语言,可在 Windows.System.UserProfile.GlobalizationPreferences.Languages 观察)来确定如何显示资源和全球化的日期和时间。这组语言称为应用程序语言(可在 Windows.Globalization.ApplicationLanguages.Languages 中观察到)。您看到的行为是因为您在摆弄用户语言和清单语言,您将获得不同的应用程序语言。

    【讨论】:

    • 有趣的方法,虽然作为居住在英国的葡萄牙人(目前为微软工作),我不能不同意更多!这是我的看法:我的 Win10 手机的语言设置为“美国英语”,国家/地区设置为“英国”,区域格式设置为“葡萄牙语(葡萄牙)”。 Outlook 以正确的 pt-PT 格式显示日期,但所有其他应用程序都坚持使用 en-US,恕我直言,这不是我所期望的!
    【解决方案3】:

    【讨论】:

      【解决方案4】:

      尽管两年前有人问过这篇文章,但它似乎仍然具有相关性。 我只是在寻找关于同一件事的答案时偶然发现了它。 我还想在我的 WP8.1 WinRT 应用程序中以区域格式显示日期。 此处发布的信息有所帮助,但拼凑起来有点困难。

      这是我想出的,它似乎对我来说是我需要的答案:

      using Windows.Globalization;
      using Windows.Globalization.DateTimeFormatting;
      
      private string FormatDate(int year, int month, int day)
      {
          GeographicRegion userRegion = new GeographicRegion();
          string regionCode = userRegion.CodeTwoLetter;
          var formatter = new DateTimeFormatter("year month day", new[] { regionCode });
          DateTime dateToFormat = new DateTime(year, month, day);
          var formattedDate = formatter.Format(dateToFormat);
          return formattedDate;
      }
      

      【讨论】:

        猜你喜欢
        • 2012-06-27
        • 2011-01-22
        • 2021-12-12
        • 1970-01-01
        • 1970-01-01
        • 2015-09-16
        • 2014-12-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多