33

我正在使用 .resx 文件设计多语言应用程序。

我有一些文件,如 GlobalStrings.resx、GlobalStrings.es.resx、GlobalStrings.en.resx 等。当我想使用它时,我只需要设置 Thread.CurrentThread.CurrentCulture。

问题:我有一个包含所有可用语言的组合框,但我手动加载它:

comboLanguage.Items.Add(CultureInfo.GetCultureInfo("en"));
comboLanguage.Items.Add(CultureInfo.GetCultureInfo("es"));

我试过了

cmbLanguage.Items.AddRange(CultureInfo.GetCultures(CultureTypes.UserCustomCulture));

没有任何成功。还尝试了 CultureTypes 中的所有元素,但我只得到一个包含更多我没有使用的语言的大列表,或者一个空列表。

有没有办法只获得支持的语言?

4

8 回答 8

52

您可以以编程方式列出应用程序中可用的文化

// Pass the class name of your resources as a parameter e.g. MyResources for MyResources.resx
ResourceManager rm = new ResourceManager(typeof(MyResources));

CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
foreach (CultureInfo culture in cultures)
{
    try
    {
        ResourceSet rs = rm.GetResourceSet(culture, true, false);
        // or ResourceSet rs = rm.GetResourceSet(new CultureInfo(culture.TwoLetterISOLanguageName), true, false);
        string isSupported = (rs == null) ? " is not supported" : " is supported";
        Console.WriteLine(culture + isSupported);
    }
    catch (CultureNotFoundException exc)
    {
        Console.WriteLine(culture + " is not available on the machine or is an invalid culture identifier.");
    }
}
于 2012-06-15T09:21:16.810 回答
5

基于@hans-holzbart 的回答,但固定为不返回 InvariantCulture 并包装成可重用的方法:

public static IEnumerable<CultureInfo> GetAvailableCultures()
{
  List<CultureInfo> result = new List<CultureInfo>();

  ResourceManager rm = new ResourceManager(typeof(Resources));

  CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
  foreach (CultureInfo culture in cultures)
  {
    try
    {
      if (culture.Equals(CultureInfo.InvariantCulture)) continue; //do not use "==", won't work

      ResourceSet rs = rm.GetResourceSet(culture, true, false);
      if (rs != null)
        result.Add(culture);
    }
    catch (CultureNotFoundException)
    {
      //NOP
    }
  }
  return result;
}

使用该方法,您可以获得要添加到某些 ComboBox 的字符串列表,其中包含以下内容:

public static ObservableCollection<string> GetAvailableLanguages()
{
  var languages = new ObservableCollection<string>();
  var cultures = GetAvailableCultures();
  foreach (CultureInfo culture in cultures)
    languages.Add(culture.NativeName + " (" + culture.EnglishName + " [" + culture.TwoLetterISOLanguageName + "])");
  return languages;
}
于 2015-08-22T22:41:41.387 回答
4

这将是基于以下陈述的解决方案之一:
特定语言的每个附属程序集都具有相同的名称,但位于以特定文化命名的子文件夹中,例如 fr 或 fr-CA。

public IEnumerable<CultureInfo> GetSupportedCulture()
{
    //Get all culture 
    CultureInfo[] culture = CultureInfo.GetCultures(CultureTypes.AllCultures);

    //Find the location where application installed.
    string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path));

    //Return all culture for which satellite folder found with culture code.
    return culture.Where(cultureInfo => Directory.Exists(Path.Combine(exeLocation, cultureInfo.Name)));
}
于 2015-10-06T06:54:36.653 回答
2

我不确定获取语言,也许您可​​以扫描安装文件夹中的 dll 文件,但将语言设置为不受支持的语言应该不是问题。

如果找不到特定于文化的文件,.NET 将回退到文化中性资源,因此您可以安全地选择不受支持的语言。

只要您自己控制应用程序,您就可以将可用语言存储在某个应用程序设置中。只需一个带有文化名称的逗号分隔字符串就足够了:“en, es”

于 2009-02-16T13:12:35.863 回答
2

使用符文格里姆斯塔所说的,我最终得到了这个:

string executablePath = Path.GetDirectoryName(Application.ExecutablePath);
string[] directories = Directory.GetDirectories(executablePath);
foreach (string s in directories)
{
    try
    {
        DirectoryInfo langDirectory = new DirectoryInfo(s);
        cmbLanguage.Items.Add(CultureInfo.GetCultureInfo(langDirectory.Name));
    }
    catch (Exception)
    {

    }
}

或其他方式

int pathLenght = executablePath.Length + 1;
foreach (string s in directories)
{
    try
    {
        cmbLanguage.Items.Add(CultureInfo.GetCultureInfo(s.Remove(0, pathLenght)));
    }
    catch (Exception)
    {

    }
}

我仍然不认为这是一个好主意......

于 2009-02-16T21:28:06.623 回答
1

指定要搜索的资源类型的通用答案。使用反射但被缓存。

用法:

List<string> comboBoxEntries = CommonUtil.CulturesOfResource<GlobalStrings>()
    .Select(cultureInfo => cultureInfo.NativeName)
    .ToList();

实现(实用程序类):

static ConcurrentDictionary<Type, List<CultureInfo>> __resourceCultures = new ConcurrentDictionary<Type, List<CultureInfo>>();

/// <summary>
/// Return the list of cultures that is supported by a Resource Assembly (usually collection of resx files).
/// </summary>
static public List<CultureInfo> CulturesOfResource<T>()
{
    return __resourceCultures.GetOrAdd(typeof(T), (t) =>
    {
        ResourceManager manager = new ResourceManager(t);
        return CultureInfo.GetCultures(CultureTypes.AllCultures)
            .Where(c => !c.Equals(CultureInfo.InvariantCulture) && 
                        manager.GetResourceSet(c, true, false) != null)
            .ToList();
    });
}

它可能会遇到与接受的答案相同的问题,因为可能会加载所有语言资源。

于 2019-08-28T01:20:13.157 回答
0

@"Ankush Madankar" 提出了一个有趣的起点,但它有两个问题:1) 还找到了引用程序集资源的资源文件夹 2) 没有找到基本汇编语言的资源

我不会尝试解决问题 2),但对于问题 1),代码应该是

public List<CultureInfo> GetSupportedCultures()
{
    CultureInfo[] culture = CultureInfo.GetCultures(CultureTypes.AllCultures);

    // get the assembly
    Assembly assembly = Assembly.GetExecutingAssembly();

    //Find the location of the assembly
    string assemblyLocation =
        Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(assembly.CodeBase).Path));

    //Find the file anme of the assembly
    string resourceFilename = Path.GetFileNameWithoutExtension(assembly.Location) + ".resources.dll";

    //Return all culture for which satellite folder found with culture code.
    return culture.Where(cultureInfo =>
        assemblyLocation != null &&
        Directory.Exists(Path.Combine(assemblyLocation, cultureInfo.Name)) &&
        File.Exists(Path.Combine(assemblyLocation, cultureInfo.Name, resourceFilename))
    ).ToList();
}
于 2018-05-05T12:12:45.223 回答
0

1.获取用户偏好的语言集,按偏好顺序排列:

Windows.System.UserProfile.GlobalizationPreferences.Languages;

2.获取或设置此上下文(应用程序)的语言限定符:

Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Languages;

两者都是List<string>

于 2021-03-18T00:47:33.127 回答