1

간단한 C# .NET 4.0 응용 프로그램을 개발 중이며 여러 언어로 현지화하고 싶습니다. 그러나 현지화를 위해 만든 위성 어셈블리 (즉, de/MyApp.resources.dll)는 해당 dll과 해당 폴더를 드래그하여 단순성을 파괴합니다.C# 단일 어셈블리 다국 언어 응용 프로그램 - 리소스가 제대로로드되지 않는다.

그래서 내가 dll을 주 어셈블리에 포함시키는 방법을 찾았으므로 최종 사용자에게 실행 파일 만 보내야했습니다. 나는 this very promising question을 우연히 만나고 그에게 총을 줬다. 내가 만든 다음

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

:

은 제안 된 솔루션에 클래스를 도입 한 후, 나는 사전 빌드 명령 FART을 사용하여 .Designer.cs 파일에 SingleAssemblyResourceManager와는 ResourceManager의 찾을 수있는 모든 발행 수를 교체 배치과 같이 파일 :

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

"%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 

그리고는 빌드 후 명령에서 호출

참고 :이 경우 TargetName과 ProjectName은 동일합니다.

성공적으로 빌드되었지만 예상대로 작동하지 않습니다 ... 양식이 InstalledUICulture 언어 (사용 가능한 경우)로 표시되어야합니다.

Thread.CurrentThread.CurrentUICulture = CultureInfo.InstalledUICulture; 

프로그램의 "표준"버전에서 속임수를 썼는지 :이를 위해, 나는이 줄을 InitializeComponent를() 이전에 추가했다. 더 이상. 하나! 또한 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로 대체되었습니다.

또한 단추 모양의 텍스트 이외에 MessageBoxes 및 기타 등등의 언어마다 strings.resx 파일이 있는데 그 중 하나는 작동하지 않는 것 같습니다. 하지만 그것은 또 다른 질문 일 수 있습니다.

원래 솔루션은 NET 2.0 환경 용으로 설계되었으며 ResourceSet이 더 이상 사용되지 않는다는 것을 알고 있지만 이어야한다고 생각합니다.

내가 들여다보아야 할 부분에 대한 유용한 정보는 정말 멋지다.

답변

1

결국 나는 CurrentUIculture 행을 약간 수정하여 결국 동작시킬 수있었습니다. 그것은 코드가 부모 문화를 (올바르게) 시도하지 않는 것처럼 보일 것입니다. 왜냐하면 내가 일반 문화 ("de-DE"대신 "de")로 설정하면 완벽하게 작동하기 때문입니다. 그것은 ApplyResources 사이의 유일한 명백한 차이를 InitializeComponent()와 ChangeLanguage()에서 호출 된 이후

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

나는이를 발견했다.

이제 왜 이것이 더 나은 해결책이 될지 모르지만, 지금까지 발견 한 유일한 수정 사항입니다.

문자열의 여전히 일부하지만 나던 작업 :/

+0

내가 .NET 2.0 .NET 4.0에서 변경 같은 문제에 직면했다 (이것은 SingleAssemblyComponentResourceManager 및 .NET 2.0와 매력으로 일) 코드의 귀하의 라인 InitializeComponent()를 호출하기 전에; 마술처럼 고정시켰다. 그래도 여전히 현악기 부분은 나에게도 효과가 없다! :/이것에 대한 새로운 해결책이 있습니까? – Gerrit