如何在UWP应用中遵循“区域格式”设置

4
我希望能够根据用户在Windows 10中配置的“区域格式”设置来格式化日期和数字。使用WPF并不是问题,但是在UWP中,如果不采用一些技巧,似乎很难实现。 样例代码供您参考
我提出了一个新的问题,因为最好的类似问题已有3年没有被答复。
“区域格式”是一个Windows设置,用户可以独立于语言和地区进行配置。例如,用户可以配置以下内容:
- 语言:英语(作为Windows显示语言)、法语、德语 - 地区:泰国(获取地区信息) - 区域格式:德语(以德语格式显示日期和数字)

enter image description here

微软似乎希望我们使用UserProfile.GlobalizationPreferences,但它没有公开活动的“区域格式”。在上面提到的问题中,有一份微软声明:“这是有意的。微软正在摆脱强制应用程序使用操作系统语言的做法......” 我们从未遇到过在与操作系统不同的语言中创建应用程序的问题。这也无法解释如何在UWP应用程序中尊重用户的选择。

  • UserProfile.GlobalizationPreferences.HomeGeographicRegion返回的是地区而不是“区域格式”。
  • Windows.Globalization.Language.CurrentInputMethodLanguageTag取决于键盘选择。
  • Windows.System.UserProfile.GlobalizationPreferences.Languages(1)只有在用户意外配置了与第二种语言匹配的“区域格式”时才起作用。

我阅读了所有能找到的关于此问题的帖子,唯一的解决方案似乎是描述在此处

 var systemLanguage = GlobalizationPreferences.Languages.First();
 var regionInfo = new RegionInfo(systemLanguage);
 var dtf = new DateTimeFormatter("longdate", new[] { regionInfo.TwoLetterISORegionName });
 var regionInfoName = dtf.ResolvedLanguage;
 var regionFormatCultureInfo = new CultureInfo(regionInfoName);

“微软似乎建议的方法对我不起作用,我的客户抱怨我的应用程序没有遵守他们的设置。能否有人解释一下这是为什么?如果这是一个SDK的bug,那么早就应该被修复了。内置的日历UWP应用程序确实遵守区域格式。”

2
这里的WinRT/UWP概念似乎基于“语言”(甚至XAML ValueConverters的签名也从使用文化转变为使用语言),并没有考虑到用户希望“区域格式”设置独立于语言选择。我希望有人能够解释其背后的原理,并提出一个干净的解决方案来回答我的问题场景。 - Peter Meinl
1
你不需要使用RegionInfo。只需使用new DateTimeFormatter("longdate", new[] { "US" }); - Marcel Wolterbeek
这确实非常令人恼火。微软自己的许多UWP应用程序(如天气和计算器)不考虑您的区域设置,而是依赖于显示语言。许多用户喜欢将界面设置为美式英语,但使用其他键盘和区域来正确地获取根据其地区格式化的日期/时间、小数分隔符等。如果您查看Windows 10反馈中心,有数百个与此相关的项目,所有这些都被微软忽视,这似乎清楚地表明微软可能是出于(错误的)设计而这么做的。 - vzczc
1个回答

0

看看 Pedro Lamas 的帖子:UWP 中的 CultureInfo 更改 - 第 2 部分。我也遇到了同样的问题,它有效。

using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;

public class CultureInfoHelper
{
    [DllImport("api-ms-win-core-localization-l1-2-0.dll", CharSet = CharSet.Unicode)]
    private static extern int GetLocaleInfoEx(string lpLocaleName, uint LCType, StringBuilder lpLCData, int cchData);

    private const uint LOCALE_SNAME = 0x0000005c;
    private const string LOCALE_NAME_USER_DEFAULT = null;
    private const string LOCALE_NAME_SYSTEM_DEFAULT = "!x-sys-default-locale";
    private const int BUFFER_SIZE = 530;

    public static CultureInfo GetCurrentCulture()
    {
        var name = InvokeGetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME);
        if (name == null)
        {
            name = InvokeGetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_SNAME);
            if (name == null)
            {
                // If system default doesn't work, use invariant
                return CultureInfo.InvariantCulture;
            }
        }
        return new CultureInfo(name);
    }

    private static string InvokeGetLocaleInfoEx(string lpLocaleName, uint LCType)
    {
        var buffer = new StringBuilder(BUFFER_SIZE);
        var resultCode = GetLocaleInfoEx(lpLocaleName, LCType, buffer, BUFFER_SIZE);
        if (resultCode > 0)
        {
            return buffer.ToString();
        }
        return null;
    }
}

正如他所说:

你只需要将上述内容复制到你的UWP项目中的一个文件中,然后调用CultureInfoHelper.GetCurrentCulture()。

话虽如此,看看这两个例子。

对于日期

例如,要使用短格式来格式化日期,请执行以下操作:
var cultureInfo = CultureInfoHelper.GetCurrentCulture();
string dateStr = DateTime.Now.ToString(cultureInfo.DateTimeFormat.ShortDatePattern, cultureInfo);

针对数字

以下是使用标准数字格式字符串格式化数字的示例:
double number = 12345.678;
string numberStr = number.ToString("N", cultureInfo);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接