从国家名称或RegionInfo对象获取CultureInfo对象

18

如何通过特定的国家代码(例如“CH”)获取CultureInfo对象?该特定国家代码是动态的(在运行时更改)。 我只有国家代码,并且想知道是否可以仅通过这个国家代码创建一个CultureInfo对象。无论我得到哪种确切的文化(fr-CH/de-CH),都没有关系。

我正在尝试做类似于以下的事情:

CultureInfo c = CultureInfo.CreateSpecificCulture("CH");

能否从RegionInfo对象创建一个Culture呢?如果可以,它将看起来像这样:

RegionInfo r= new RegionInfo("CH");
CultureInfo c = CultureInfo.CreateSpecificCulture(r);

显然,前面的例子并不能编译通过,它们只是给出了我试图实现的想法。


1
你期望从加拿大或比利时获得哪种文化? - Ilya Kogan
1
你正在寻找 CultureInfo.GetCultureInfo 方法 吗? - Shadow The Spring Wizard
对于美国,您将获得 chr-US en-US es-US和haw-US:_切罗基语,英语,西班牙语,夏威夷语_。 - Kiquenet
3个回答

26

如果您只有国家代码,您可以使用类似以下的方法获取与该国家关联的所有文化信息:

var cultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures)
                              .Where(c => c.Name.EndsWith("-CH"));

编辑:根据@JeppeStigNielsen的指出(见下面的评论),在CH之前添加-以避免一个边缘情况。


有用的 iso2 = "US"; 代码: var cultureInfo = CultureInfo.GetCultures(CultureTypes.AllCultures).Where(c => c.Name.EndsWith(iso2)).ToList(); foreach (System.Globalization.CultureInfo culture in cultureList) { Response.Write("<br /> Culture for " + iso2 + ": " + culture.DisplayName + " *** " + culture.NativeName + " " + culture.TwoLetterISOLanguageName + " - " + culture.ThreeLetterISOLanguageName + " - " + culture.DateTimeFormat.FullDateTimePattern); } - Kiquenet
1
这个问题有点需要一个不太好的答案(我刚刚发布了另一个),但是:当我尝试使用__海地__,国家代码为“HT”的代码时,我得到的其中一种文化是“zh-CHT”,__中文(繁体)遗留版__,本地称为__中文(繁體) 舊版__。 - Jeppe Stig Nielsen
@JeppeStigNielsen 将上面的代码更改为 EndsWith("-CH") 就可以解决问题,或者您可以考虑另一个边缘情况? - Anderson Pimentel
1
如果这样做,我认为不会有任何示例。即使一些中性文化包含连字符,例如“sr-Cyrl”(塞尔维亚语(西里尔字母))(未指定国家),或“mn-Mong”(蒙古语(传统蒙古字母))(未指定国家),第二部分指定了书写系统,因为该语言可以用不同的书写体系书写,在这种情况下,第二部分将有超过两个字母。 - Jeppe Stig Nielsen
这非常脆弱。不要依赖于字符串存在检查,否则你会在某个地方出错。 - Tanveer Badar

6
你是否正在尝试创建一个CultureInfo对象?就像这样:
CultureInfo c = new CultureInfo("de-CH"); //culture for  German (Switzerland)
CultureInfo c = new CultureInfo("fr-CH"); //culure for French (Switzerland)
CultureInfo c = new CultureInfo("it-CH"); //culture for Italian (Switzerland)

也许这个链接有用:http://www.csharp-examples.net/culture-names/ 它展示了所有文化。

我只有国家代码,想知道是否可能仅通过国家代码创建CultureInfo对象。但它必须是动态的。 - Ben
我能否使用 HKCU\Control Panel\International\Geo 中的 Nation 值来获取 CultureInfo? - Kiquenet

6
当然,这样做很不好看,因为一个国家(包括你的例子“CH”瑞士)可能有多种语言。不过,我会提供两种不太美观的方法。第一种:
static IEnumerable<CultureInfo> FindCandidateCultures(RegionInfo region)
{
  return CultureInfo.GetCultures(CultureTypes.SpecificCultures)
    .Where(x => (new RegionInfo(x.Name)).GeoId == region.GeoId);
}

当使用new RegionInfo("CH")时,在我的.NET Framework和Windows版本上会得到以下结果:
de-CH: 德语(瑞士)
fr-CH: 法语(瑞士)
gsw-CH: 阿尔萨斯语(瑞士)
it-CH: 意大利语(瑞士)
rm-CH: 罗曼什语(瑞士)
wae-CH: 瓦尔瑟语(瑞士)

编辑:更高版本还包括以下两种语言:

en-CH: 英语(瑞士)
pt-CH: 葡萄牙语(瑞士)

我将提供给您的第二种方法:

// ugly reflection, this can break any day!
static CultureInfo ConvertToCulture(RegionInfo region)
{
  var data = typeof(RegionInfo).GetField("m_cultureData", BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(region);

  var name = (string)(data.GetType().GetProperty("SNAME", BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(data));

  return CultureInfo.GetCultureInfo(name);
}

显然,它使用mscorlib.dll的内部表示方式,我们永远不知道它是否会在未来版本中失效。但它确实为您提供了一种选择特定区域设置的方法。在我的计算机上,从new RegionInfo("CH"),您可以得到it-CH: Italian (Switzerland)
编辑:毫不奇怪,.NET的某些版本中第二种方法已经改变。类似这样的东西:
var data = typeof(RegionInfo).GetField("_cultureData", BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(region);

var name = (string)(data.GetType().GetProperty("CultureName", BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(data));

或者(如果您使用可空引用类型)使用许多

var data = typeof(RegionInfo).GetField("_cultureData", BindingFlags.NonPublic | BindingFlags.Instance)
    !.GetValue(region);

var name = (string)(data!.GetType().GetProperty("CultureName", BindingFlags.NonPublic | BindingFlags.Instance)
    !.GetValue(data)!);

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