7

我有一种情况,我想为我的应用程序提供一个“可用语言”的列表(顺便说一下,如果有可能的话,它是一个 ASP .NET MVC 3 应用程序)。我认为我可以以某种方式自动获取此列表,因为它应该只是构建中包含的 resx 文件(我不需要支持英语英国、德国奥地利或任何东西,只需要英语或德语),我想出了我将在下面介绍的方案(作为单例实现,因为它有点密集的方法)。

问题是,即使我没有这样的资源,在某些机器上它也会返回“阿拉伯语”,而在我的机器上(因为我安装了 VS 2012)它会返回所有这些资源(这对我来说比只返回两种真实文化加上阿拉伯语更有意义但似乎 ResourceManager 并不是为了让我获得这些信息而设计的,所以我可能不应该抱怨)。这是方案...

(我有一个 Strings.resx 和一个 Strings.de.resx 文件)

IEnumerable<CultureInfo> cultures =
    CultureInfo.GetCultures(CultureTypes.NeutralCultures)
        .Where(c =>
                   {
                       // Exclude the invariant culture and then load up
                       // an arbitrary string so the resource manager
                       // loads a resource set, then get the set for the
                       // current culture specifically and it is, sometimes
                       // (I thought always but I was wrong) null if no
                       // set exists
                       if (c.LCID == CultureInfo.InvariantCulture.LCID)
                           return false;

                       var rm = Strings.ResourceManager;
                       rm.GetString("HELLO", c);
                       return rm.GetResourceSet(c, false, false) != null;
                   });

所以我想,好吧,我可以根据特定语言的目录是否存在来做到这一点,如下所示:

var neutralCulture = new[]
{
    CultureInfo
        .CreateSpecificCulture(((NeutralResourcesLanguageAttribute)
                                Assembly
                                    .GetExecutingAssembly()
                                    .GetCustomAttributes(
                                        typeof (NeutralResourcesLanguageAttribute),
                                        false)[0])
                                .CultureName)
};

IEnumerable<CultureInfo> cultures =
    CultureInfo.GetCultures(CultureTypes.NeutralCultures)
        .Where(c => Directory.Exists(c.TwoLetterISOLanguageName))
        .Union(neutralCulture);

这个“有效”(它返回英语和德语)但我认为这不是一个非常稳定的方法,因为它容易出现随机问题,比如有人创建文件夹并将其全部扔掉。我可能可以通过一些更明智的检查来缓解这些问题(where 子句迫切需要更复杂),但这是问题(最后)......

现在我正在考虑只使用一个配置文件并保持它完全简单,因为我真的不喜欢我必须去的地方,但是有没有更好的方法来做到这一点(或者:它可以以安全的方式自动完成) ?

4

2 回答 2

2

我喜欢你的第二种自动检测方法。我要补充一点,您应该只执行一次(在应用程序启动时或作为静态构造函数的一部分)并将其设为静态,而不是在每次请求支持的文化信息时计算它。

我认为配置方法也可以,尽管它不是真正自动的。对于这种情况,我唯一的想法是,如果您正在为一种语言进行本地化,那么它就不会在雷达下潜入您的应用程序。话虽如此,此时添加配置值似乎是一件容易的事(或忘记做)。

我不知道 .NET Framework 中内置了任何东西来通过方法调用为您提供此信息。

于 2012-08-20T11:37:14.813 回答
1

我发现没有有效和可靠的方法来做到这一点。

在我的每个程序集中,我都编写了这样的代码来引用支持的文化。这就是我们所能做的。添加本地化时,您必须记住更新此数组。

internal static class ThisAssembly
{
    static readonly string[] SupportedCultures = new string[] { "en-US", "de-DE", };
}

我也尝试过:

  • 枚举加载的卫星程序集:没有办法;
  • 获取值ResourceManager._resourceSets:加载集的字典给出正确和无效的值。

但无济于事。

于 2016-01-10T12:11:07.253 回答