Search code examples
c#wpflocalizationtranslationglobalization

Localization not properly working


I wrote a small application that shall automatically start in either English or German. English is default and German would be used on a German Windows.

The problem:

The German strings aren't loaded on a German Windows, although the program recognizes the client as German. Explicitly setting the current culture (in code) to German however will result in a German UI.

What I did:

I followed this guide: http://www.codeproject.com/Articles/299436/WPF-Localization-for-Dummies

  • I created copies of the Resources.resx in the Properties section
  • Now there are: Resources.resx, Resources.en-US.resx, Resources.de-DE.resx
  • I put all Strings in the three Resources files. Resources.resx and *.en-US.resx contain the exact same strings
  • The name of the strings are consistent, Access Modifier on all files set to Public
  • File Properties of the Resources: Build Action: Embedded Resource; Do not copy; Custom Tool: PublicResXFileCodeGenerator

Code:

private void InitLocalization() // Executed on startup
    {

    if (CultureInfo.CurrentCulture.Name != "de-DE") //  only use german on german systems. Otherwise use english
    {
        CultureInfo.DefaultThreadCurrentCulture = CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("en-US");
    }
    else
    {
        CultureInfo.DefaultThreadCurrentCulture = CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("de-DE");
    }

    rm = new ResourceManager("SaveEye.Properties.Resources", Assembly.GetExecutingAssembly());

     // Manually assign the correct text to XAML-elements
    _SettingsTextBlock.Text = rm.GetString("Settings");
    _StartWithWindowsCheckBox.Content = rm.GetString("Startup");
    _SaveButton.Content = rm.GetString("SaveAndClose");
    }

Basically, I just want to make sure that either the Resources.en-US.resx or Resources.de-DE.resx is loaded from the ResourceManager.

In the rest of the code I grab the Strings I need with rm.GetString("").

This works just fine with English. I can even manually set the CurrentCulture to de-DE at the beginning of the InitLocalization-Method and then all German strings are loaded. But as I said, on other systems that are de-DE by default, the German strings are not loaded.

What am I doing wrong?

Regards


Solution

  • It is the CurrentUICulture that will affect which resources are loaded, and the CurrentCulture that will affect date and number formatting. A lot of people get these two confused.

    You should probably be testing CurrentUICulture if you're trying to either set, or determine what string resources to retrieve. There is a big difference between a machine running with German date and number formats (CurrentCulture) and a machine running with a full German Language Pack installed and activated (CurrentUICulture).

    Your sample code is using CultureInfo.DefaultThread(UI)CurrentCulture which will control the behaviour of all new threads created but this will default to whatever the main thread is using anyway so if it was already in German, you shouldn't need to explictly set it as such.

    You can test the resource loading behaviour by updating your InitLocalization() method and setting Thread.CurrentThread.CurrentUICulture explicitly to "de-DE" to see if the German resources start loading. Then verify that the CurrentUICulture is really set to "de-DE" and not just the CurrentCulture. It's possible the German machine has German date/number formatting (CurrentCulture) but isn't using a German language pack (CurrentUICulture).

    EDIT: In response to your comment, if you're already using CurrentUICulture correctly and the machine really has a full German UI but the German resources still aren't appearing, you should check that the German satellite resource file is actually being deployed.

    The German resources are contained within a separate assembly named de-DE\MyApp.resources.dll and must reside in the same folder as the executable and stay within the de-DE folder (so you have \Folder\MyApp.exe and \Folder\de-DE\MyApp.resources.dll). The default resources (the ones in Resources.resx stay in the main executable and are the ones the ResourceManager falls back to if no more appropriate resource is found).

    You didn't specify how you were deploying the application, but if you run you can use the 'Open in Explorer' (or Dateipfad Öffnen on the German machine) feature of Task Manager to take you to deployed folder of the running application so you can check that the de-DE folder is there (I only mention doing it this way because if you ClickOnce deploy the application it can be hard to find the installation folder).

    If you are using ClickOnce and you publish with Visual Studio, you can control the files included during publishing by right-clicking the project and selecting properties then navigating to the 'Publishing' tab. The 'Application Files' button will show you a list of all the files included when publishing. Your de-DE satellite resource file should be set to 'Include'.