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

これは、次のステートメントに基づく解決策の 1 つです
。特定の言語の各サテライト アセンブリには同じ名前が付けられますが、特定のカルチャ (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

Rune Grimstad が言ったことを使用すると、次のようになります。

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 に答える