1

シンプルな C# .NET 4.0 アプリケーションを開発しており、複数の言語にローカライズしたいと考えています。ただし、ローカリゼーション用に作成されたサテライト アセンブリ (つまり、de/MyApp.resources.dll) は、これらの dll とそのフォルダーをドラッグする必要があるため、その単純さが台無しになります。

そのため、これらの dll をメイン (および唯一の) アセンブリに含める手段を探したので、実行可能ファイルのみをエンド ユーザーに送信する必要がありました。私はこの非常に有望な質問に出くわし、試してみました。

提案されたソリューションのクラスを採用した後、ビルド前のコマンドでFARTを使用して、.Designer.cs ファイルで見つかった ResourceManager をすべて SingleAssemblyResourceManager に置き換えました。

fart.exe "$(ProjectDir)*.Designer.cs "System.ComponentModel.ComponentResourceManager" "SingleAssemblyComponentResourceManager"

次に、次のようなバッチ ファイルを作成しました。

"%ProgramFiles%\ILRepack.exe" /t:exe /out:%1TempProg.exe %1%2.exe %1es\%2.resources.dll 
IF %ERRORLEVEL% NEQ 0 GOTO END

"%ProgramFiles%\ILRepack.exe" /t:exe /out:%1TempProg2.exe %1TempProg.exe %1de\%2.resources.dll
IF %ERRORLEVEL% NEQ 0 GOTO END

"%ProgramFiles%\ILRepack.exe" /t:exe /out:%1SA_%2.exe %1TempProg2.exe %1tr\%2.resources.dll 
IF %ERRORLEVEL% NEQ 0 GOTO END

del %1%2.exe 
del %1%2.pdb 
del %1TempProg.exe
del %1TempProg.pdb
del %1TempProg2.exe 
del %1TempProg2.pdb 
rmdir %1es /S /Q 
rmdir %1de /S /Q 
rmdir %1tr /S /Q 

:END 

ビルド後のコマンドから呼び出します。

$(ProjectDir)postbuild.bat $(TargetDir) $(TargetName)

注: この場合、TargetName と ProjectName は同じです。

正常にビルドされましたが、期待どおりに動作しません... フォームは InstalledUICulture 言語で表示されます (利用可能な場合)。これを実現するために、InitializeComponent() の前に次の行を追加しました。

Thread.CurrentThread.CurrentUICulture = CultureInfo.InstalledUICulture;

プログラムの「標準」バージョンでトリックを行ったのはどれですか。もう違います。でも!また、ComboBox を介して、実行時に言語を変更するための小さなコントロールを追加しました。コードは次のとおりです。

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
  if (comboBox1.SelectedItem.ToString() == "English (Default)")
    {
      Thread.CurrentThread.CurrentUICulture = new CultureInfo("en");
      ChangeLanguage("en");
    }
  else if (comboBox1.SelectedItem.ToString() == "Español")
    {
      Thread.CurrentThread.CurrentUICulture = new CultureInfo("es");
      ChangeLanguage("es");
    }
    else if (comboBox1.SelectedItem.ToString() == "Deutsch")
    {
      Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");
      ChangeLanguage("de");
    }
    else if (comboBox1.SelectedItem.ToString() == "Turkce")
    {
      Thread.CurrentThread.CurrentUICulture = new CultureInfo("tr");
      ChangeLanguage("tr");
    }
}

private void ChangeLanguage(string lang)
{
  foreach (Control c in this.Controls)
  {
    SingleAssemblyComponentResourceManager resources = new SingleAssemblyComponentResourceManager(typeof(Form1));
    resources.ApplyResources(c, c.Name, new CultureInfo(lang));
    if (c.ToString().StartsWith("System.Windows.Forms.GroupBox"))
    {
      foreach (Control child in c.Controls)
      {
          SingleAssemblyComponentResourceManager resources_child = new SingleAssemblyComponentResourceManager(typeof(Form1));
          resources_child.ApplyResources(child, child.Name, new CultureInfo(lang));
      }
    }
  }
}

そして、これフォーム言語を変更します。したがって、DLLは実際にはexeに含まれています。では、InitializeComponent が適切なリソースをロードしないのはなぜでしょうか? Designer コードを確認したところ、ResourceManager が SingleAssemblyResourceManager に置き換えられていました。

また、フォームボタンのテキスト以外に、メッセージボックスなどのために、言語ごとにstrings.resxファイルがありますが、どちらの方法でも機能しないようです。しかし、それは別の問題かもしれません。

元のソリューションが NET 2.0 環境用に設計されたこと、および ResourceSet が廃止されたことは認識していますが、推奨されていなくても機能するはずであると理解しています。

私がどこを調べるべきかについての指針は素晴らしいでしょう。

4

1 に答える 1

1

結局のところ、CurrentUIculture の行を少し変更して、最終的に機能させることができました。一般的なカルチャ (つまり、「de-DE」ではなく「de」) に設定すると、コードは完全に機能するため、コードは親カルチャを (適切に) 試行しないようです。

Thread.CurrentThread.CurrentUICulture = new CultureInfo(CultureInfo.InstalledUICulture.TwoLetterISOLanguageName);

これは、InitializeComponent() と ChangeLanguage() からの ApplyResources 呼び出しの唯一の明らかな違いであるため、これを発見しました。

これがなぜなのかはわかりませんが、確かにもっと良い解決策があるかもしれませんが、これが私がこれまでに見つけた唯一の修正です。

ただし、文字列部分はまだ機能しません:/

于 2013-05-06T10:11:44.030 に答える