0

I am trying using satellite assemblies for localization in WinForms application. The directory structure is as follows:

  • bin
    • Program.exe
    • de
      • Program.resources.dll

In the Program.exe, this code is executed in Main method:

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");

Application.Run(new Form());

I checked the FUSLOGVW.exe output:

*** Assembly Binder Log Entry  (5/30/2012 @ 5:19:37 PM) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable  D:\tmp\bin\Program.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: User = paulius_l
LOG: DisplayName = Program.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=...
 (Fully-specified)
LOG: Appbase = file:///D:/tmp/bin/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = Program.exe
Calling assembly : Program, Version=1.0.0.0, Culture=neutral, PublicKeyToken=....
===
LOG: Start binding of native image Program.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=....
WRN: No matching native image found.
LOG: IL assembly loaded from D:\tmp\bin\de\Program.resources.dll.

This looks fine, however strings just do not get localized -- default strings from the Program.exe are still used.

To get the strings I use Visual Studio-generated Res class from the Res.resx.

What am I missing here?

Edit: added full FUSLOGVW output, for those that understand it better than I do.

paulius_l
  • 4,983
  • 8
  • 36
  • 42
  • have you tried setting the UICulture in the Form-Constructor? – Jobo May 30 '12 at 14:34
  • Yes, I have, before the call to the InitializeComponent(). The effect is the same. That is, no effect. – paulius_l May 30 '12 at 14:39
  • Have you verified (with reflector maybe) that there are different string resources in your satellite assembly? – MerickOWA May 30 '12 at 14:40
  • Yes, I have verified it. – paulius_l May 30 '12 at 14:41
  • Have you tried to set CurrentThread.CurrentCulture, too? Afaik UICulture only applies to Resources defined in Controls. If you lookup a resource manually CurrentCulture should come into play. – Jobo May 30 '12 at 14:43
  • @Jobo: yes, I have. Removed it later, though because did not get a desired result. – paulius_l May 30 '12 at 14:45
  • @HenkHolterman: I added a Res.resx manually by myself. – paulius_l May 30 '12 at 14:46
  • Maybe the issue isn't with the Res.resx, maybe its in how you get those strings onto the form? – MerickOWA May 30 '12 at 14:51
  • I use strongly typed approach. Therefore, it is like Res.StringName. Underneath, there is a simple getter which returns the value from ResourceManager, like that: return ResourceManager.GetString("StringName", resourceCulture). Since I do not set Culture property of Res class explicitly, it passes null as the resourceCulture value, therefore ResourceManager uses the Thread.CurrentThread.CurrentUICulture value, which at this point is "de" (I checked that with debugger). – paulius_l May 30 '12 at 14:54
  • Yes, but how does that property affect any controls on a Form? Visual Studio generally generates a seperate .resx for each form. These contain the text/properties which need changed in other cultures. If you're using your own Res.resx, you have to manually set the form controls somehow. – MerickOWA May 30 '12 at 14:56
  • For example, try a MessageBox.Show( Res.StringName ) just after setting the CurrentUICulture. Does that work? – MerickOWA May 30 '12 at 14:57
  • @MerickOWA, it does not work. I thought that the problem might be with the executable. I also created a localized library and referenced it from executable. It did not work anyway, though. – paulius_l May 30 '12 at 14:59
  • 1
    Theres something missing, a simple sample app with a Res.resx and Res.de.resx containing a single string "StringName", setting the CurrentUICulture and doing a MessageBox.Show( Res.StringName ) works just fine for me. It shows the string from Res.de.resx – MerickOWA May 30 '12 at 15:05
  • Probably it will be best to start over and find the difference. Thanks. – paulius_l May 30 '12 at 15:27

2 Answers2

0

This was my huge mistake I did when I wrote automated build script which would generate satellite assemblies externally. The problem was that while generating the classes in the satellite assemblies, I missed the Res class. No wonder it did not work.

After long hours spent, I found the problem this morning.

paulius_l
  • 4,983
  • 8
  • 36
  • 42
-1

I believe your culture identifier is wrong on this line:

Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");

Culture identifiers for CultureInfo take the form of "languagecode-countrycode". E.g. "en-US" for US English and "en-GB" for British/UK English.

Try "de-DE".

There's some further reading available at http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.name%28v=vs.95%29.aspx and http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx for a list of culture identifiers.

akakjs
  • 79
  • 1
  • 5
  • "de" is a valid identifier. "de-DE" would be more specific to german of Germany. Still, I have tried both of them - none works. In fact, If I have both, "de" and "de-DE" at once, only "de" resources are getting loaded because, as far as I understand, this is a more general culture identifier. – paulius_l May 30 '12 at 14:47
  • In the website with a list of culture identifiers, "de" is listed as a valid identifier also. – paulius_l May 30 '12 at 14:59
  • 1
    Even the example on MSDN gives "en" as possibility in their sample app output. The countrycode is optional. – MerickOWA May 30 '12 at 15:13