C#单组装多语言应用程序 - 资源未正确加载

时间:2013-04-30 15:55:28

标签: visual-studio-2010 .net-4.0 localization ilmerge resourcemanager

我正在开发一个简单的C#.NET 4.0应用程序,并希望将其本地化为多种语言。但是,为本地化创建的附属程序集(即de / MyApp.resources.dll)会因为必须拖动那些dll及其文件夹而使其简单化。

这就是为什么我寻找一种方法将这些dll包含在main(且唯一的)程序集中,因此只需要将可执行文件发送给最终用户。我偶然发现了this very promising question并给了它一个机会。

在建议的解决方案中采用该类之后,我在预构建命令中使用FART替换了我在.Designer.cs文件中使用SingleAssemblyResourceManager找到的ResourceManager的所有出现:

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文件,对于MessageBoxes和诸如此类的东西,这两种方式似乎都不起作用。但这可能是另一个问题。

我知道原始解决方案是为.NET 2.0环境设计的,并且ResourceSets已经过时,但我理解 应该工作,即使不推荐它也是如此。

关于我应该调查的地方的任何指示都会很棒。

1 个答案:

答案 0 :(得分:1)

事实证明,我最终能够使其工作,稍微修改一下CurrentUIculture线。似乎代码不会尝试父母文化(正确),因为如果我将它设置为通用文化(即“de”而不是“de-DE”),它就能完美地运作。

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

我发现了这一点,因为它是来自InitializeComponent()和ChangeLanguage()的ApplyResources调用之间唯一明显的区别。

现在,我不知道为什么会这样,当然可能有更好的解决方案,但这是我到目前为止唯一找到的解决方案。

字符串部分仍然无效:/