Windows Universal 中的 CultureInfo 之间存在不一致
Inconsistencies between CultureInfo in Windows Universal
我需要从 UWP 应用程序生成一个 .CSV 文件,所以我正在使用 TextInfo.ListSeparator。
我发现系统设置与代码返回的值不一致。
使用区域设置:
使用 TextInfo Class:
TextInfo textInfo = System.Globalization.CultureInfo.CurrentCulture.TextInfo;
System.Diagnostics.Debug.WriteLine(textInfo.CultureName);
System.Diagnostics.Debug.WriteLine(textInfo.IsReadOnly);
System.Diagnostics.Debug.WriteLine(textInfo.ListSeparator);
System.Diagnostics.Debug.WriteLine(textInfo.IsRightToLeft);
我的系统配置:
- Windows 显示语言:英语(美国)
- 区域格式:葡萄牙语(巴西)
- 地区首页位置:美国
已编辑
正如一些答案所建议的那样,我重新启动了我的电脑。然后编写了一个 UWP 和一个使用相同代码的 Windows Forms 应用程序。为了比较我 运行 一个 Windows PowerShell。值仍然不同,如下图所示。
PowerShell 和 Windows 表单返回了预期结果,但 UWP 失败。
这对我有效。
我认为是因为您更改设置后没有重新打开visual studio。
更改设置后,它不会通知并强制visual studio(或其他应用程序)已打开更改其环境值。您必须关闭并重新打开 visual studio 才能让 visual studio 以新设置开始。
[更新]
我成功了,因为我认为您只想更改 ListSeparator 设置,但没有更改区域格式。 @user5596450 方向正确。所以你的问题的答案是否。您无法获取您在区域设置中指定的自定义区域格式。
实际上,自定义设置并非适用于所有设备系列。我相信目前的结果是有道理的。您所期望的应该由 UWP 的桌面扩展之类的东西提供,而不是 .net 核心 APIs。您可以随时向 wpdev.uservoice.com 提出请求,Microsoft 正在那里听取开发人员的反馈。
作为替代方案,.Net core API 将检查 UWP 应用程序的 PreferredLanguage 并为您获取相应的设置。例如,如果您在 UWP 应用程序中调用 Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "pt-br";
(通常在 App.xaml.cs 中的 OnLaunched 事件中),您将得到您期望的 但那不是来自 设置您在区域设置中自定义。这就是针对不同设备系列的通用应用程序的工作方式。请查看 ApplicationLanguages.PrimaryLanguageOverride MSDN 文档以了解其实际作用。
仅供参考,UWP 使用的 .net 核心 API 中的 CurrentCulture 可以在 github 上找到。这是它的实现方式:
public static CultureInfo CurrentCulture
{
get
{
Contract.Ensures(Contract.Result<CultureInfo>() != null);
#if !FEATURE_CORECLR
return Thread.CurrentThread.CurrentCulture;
#else
// In the case of CoreCLR, Thread.m_CurrentCulture and
// Thread.m_CurrentUICulture are thread static so as not to let
// CultureInfo objects leak across AppDomain boundaries. The
// fact that these fields are thread static introduces overhead
// in accessing them (through Thread.CurrentCulture). There is
// also overhead in accessing Thread.CurrentThread. In this
// case, we can avoid the overhead of Thread.CurrentThread
// because these fields are thread static, and so do not
// require a Thread instance to be accessed.
#if FEATURE_APPX
if(AppDomain.IsAppXModel()) {
CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX();
if (culture != null)
return culture;
}
#endif
return Thread.m_CurrentCulture ??
s_DefaultThreadCurrentCulture ??
s_userDefaultCulture ??
UserDefaultCulture;
#endif
}
set
{
#if FEATURE_APPX
if (value == null) {
throw new ArgumentNullException("value");
}
if (AppDomain.IsAppXModel()) {
if (SetCultureInfoForUserPreferredLanguageInAppX(value)) {
// successfully set the culture, otherwise fallback to legacy path
return;
}
}
#endif
Thread.CurrentThread.CurrentCulture = value;
}
}
上面的答案可能是正确的。然而,更可能的原因是 Win32 或系统 API 使用基于特定区域格式设置(在本例中为 pt-BR)的区域设置数据,即“;”。 UWP 使用 WinRT API,它使用基于 Windows 显示语言(在本例中为 en-US)的区域设置数据,即“,”。
我需要从 UWP 应用程序生成一个 .CSV 文件,所以我正在使用 TextInfo.ListSeparator。
我发现系统设置与代码返回的值不一致。
使用区域设置:
使用 TextInfo Class:
TextInfo textInfo = System.Globalization.CultureInfo.CurrentCulture.TextInfo;
System.Diagnostics.Debug.WriteLine(textInfo.CultureName);
System.Diagnostics.Debug.WriteLine(textInfo.IsReadOnly);
System.Diagnostics.Debug.WriteLine(textInfo.ListSeparator);
System.Diagnostics.Debug.WriteLine(textInfo.IsRightToLeft);
我的系统配置:
- Windows 显示语言:英语(美国)
- 区域格式:葡萄牙语(巴西)
- 地区首页位置:美国
已编辑 正如一些答案所建议的那样,我重新启动了我的电脑。然后编写了一个 UWP 和一个使用相同代码的 Windows Forms 应用程序。为了比较我 运行 一个 Windows PowerShell。值仍然不同,如下图所示。
PowerShell 和 Windows 表单返回了预期结果,但 UWP 失败。
这对我有效。
我认为是因为您更改设置后没有重新打开visual studio。
更改设置后,它不会通知并强制visual studio(或其他应用程序)已打开更改其环境值。您必须关闭并重新打开 visual studio 才能让 visual studio 以新设置开始。
[更新]
我成功了,因为我认为您只想更改 ListSeparator 设置,但没有更改区域格式。 @user5596450 方向正确。所以你的问题的答案是否。您无法获取您在区域设置中指定的自定义区域格式。
实际上,自定义设置并非适用于所有设备系列。我相信目前的结果是有道理的。您所期望的应该由 UWP 的桌面扩展之类的东西提供,而不是 .net 核心 APIs。您可以随时向 wpdev.uservoice.com 提出请求,Microsoft 正在那里听取开发人员的反馈。
作为替代方案,.Net core API 将检查 UWP 应用程序的 PreferredLanguage 并为您获取相应的设置。例如,如果您在 UWP 应用程序中调用 Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "pt-br";
(通常在 App.xaml.cs 中的 OnLaunched 事件中),您将得到您期望的 但那不是来自 设置您在区域设置中自定义。这就是针对不同设备系列的通用应用程序的工作方式。请查看 ApplicationLanguages.PrimaryLanguageOverride MSDN 文档以了解其实际作用。
仅供参考,UWP 使用的 .net 核心 API 中的 CurrentCulture 可以在 github 上找到。这是它的实现方式:
public static CultureInfo CurrentCulture
{
get
{
Contract.Ensures(Contract.Result<CultureInfo>() != null);
#if !FEATURE_CORECLR
return Thread.CurrentThread.CurrentCulture;
#else
// In the case of CoreCLR, Thread.m_CurrentCulture and
// Thread.m_CurrentUICulture are thread static so as not to let
// CultureInfo objects leak across AppDomain boundaries. The
// fact that these fields are thread static introduces overhead
// in accessing them (through Thread.CurrentCulture). There is
// also overhead in accessing Thread.CurrentThread. In this
// case, we can avoid the overhead of Thread.CurrentThread
// because these fields are thread static, and so do not
// require a Thread instance to be accessed.
#if FEATURE_APPX
if(AppDomain.IsAppXModel()) {
CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX();
if (culture != null)
return culture;
}
#endif
return Thread.m_CurrentCulture ??
s_DefaultThreadCurrentCulture ??
s_userDefaultCulture ??
UserDefaultCulture;
#endif
}
set
{
#if FEATURE_APPX
if (value == null) {
throw new ArgumentNullException("value");
}
if (AppDomain.IsAppXModel()) {
if (SetCultureInfoForUserPreferredLanguageInAppX(value)) {
// successfully set the culture, otherwise fallback to legacy path
return;
}
}
#endif
Thread.CurrentThread.CurrentCulture = value;
}
}
上面的答案可能是正确的。然而,更可能的原因是 Win32 或系统 API 使用基于特定区域格式设置(在本例中为 pt-BR)的区域设置数据,即“;”。 UWP 使用 WinRT API,它使用基于 Windows 显示语言(在本例中为 en-US)的区域设置数据,即“,”。