Setting WPF Program's culture in App.config - c#

I've got a WPF application that I'm modifying to support localization. My program is part of a suite of products that my company offers. We have created a resource DLL that contains all of the strings that need to be translated for all of our products. I've added a reference to this DLL to my program, added string resources to it, and modified my code to use the string resources instead of hard-coded strings. Everything works fine when I run my program in English.
We have had the string resources translated into Spanish. I've created a resx file with the Spanish translations in it. I've rebuilt my application. Now I want to see the Spanish text appear in my program without having to change my computer's culture settings.
It's not necessary for the program to change culture settings on the fly. The program will run in one language only for a particular installation.
The program has an App.config file. Short of adding a custom setting with the culture information in it, how do I tell my program to run in Spanish?

You could just define a key in your App.config like this
<configuration>
<appSettings>
<add key="DefaultCulture" value="es-CO" />
</appSettings>
</configuration>
and in your application read that value and set the culture
CultureInfo culture = new CultureInfo(ConfigurationManager.AppSettings["DefaultCulture"]);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
In the example of the config I set it to Spanish-Colombia
This is a list of culture codes

I decided to add this answer because while #MauricioGarcia's answer works if you want to always display a particular language on a machine with multiple language packs installed on it, no matter what the current region settings on the machine are, we didn't implement it that way.
Instead, we just use whatever CultureInfo objects are set in the current Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture properties. When you set the region settings on your computer to a particular location and language, these properties are automatically changed. So they're always right & we don't have to add any code to change anything.
Interestingly, the object in the CurrentUICulture property is used to determine which language strings to display and the object in the CurrentCulture property is used to format numbers & DateTime.

Related

Can I use any other parameters besides CurrentCulture to select a C# resource file?

As you probably know .NET selects resource files in a solution based on the .resx filename and the CurrentCulture setting. Meaning that if I have 3 resource files (say Resource.resx, Resource.fr-FR.resx and Resource.nl-NL.resx), I can select the French resources by simply changing the CurrentCulture to "fr-FR" in my app.config. The code that gets the string from the resource file does not have to be changed.
For my current project I'm exploring ways to switch strings in a similar way to how this works, but based on a parameter of my choosing. Say I have Resource.resx, Resource.Bar.resx and Resource.Fu.resx: can I automatically select a resource by changing a custom setting that is not the CurrentCulture, or would I have to build my own ResourceManager extension?
Or could I just set the CurrentCulture to "Fu"? I imagine this would clash with other built-in .NET functions.

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
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'.

Change the "(default)" ResX language in a C# app

I'm making an app in C#, with a lot of forms and other stuff.
I wanted to localize it, so I used the integrated localization functions in VS.
The app was originally in French (cause I am) with English translation RESXes, but now that it is on Codeplex with some other developers who doesn't speak french, I want to change the "default" language in the app and the RESX files so they can translate to other languages without reading French.
Cause when you choose another language in VS Form Designer, it shows the default language (here, French). I tried to rename all the files, but the problem is all the form properties are stored in the default RESX, the French one, so if I rename, it will break all the stuff. Is it possible to change the default language to English?
EDIT: I think I need to be more precise.
The app is originally in French. Then I localized it in English. There is now a MainWindow.resx that contains form properties + original french localization and a MainWindow.en-US.resx that contains ONLY english localization. So if in the Designer, in "Language" I choose "(default)" it shows me the MainWindow.resx FRENCH, and if I want to translate, It shows me the French texts. To make the translation more easy for the other developers, I want to make the MainWindow.resx ENGLISH localization and create a seperate MainWindow.fr-FR.resx. I also tried to change "Neutral Language" in AssemblyInfo.cs, no effect.
While you could do renames in file system to achieve neutral culture/resource change, you need to update project file as well, which is cumbersome. I found the simplest way was to do this via Visual studio extension named ResXManager.
Steps in detail:
1. Run & configure ResXManager
In VS: Tools -> ResXManager.
Choose configuration tab (below)
Disable option "Confirm adding new resource files". Otherwise you would have to click later per each file to accept its creation.
Set Neutral Resource language so it would show up with a correct flag for your viewing pleasure.
Switch back to main tab where you see all solution resources with translations side-by-side.
2. Extract neutral culture resources as explicitly French
Adda a new column for French using the "Add new language" button in the toolbar.
Copy all French resources from existing neutral language column (CTRL-SHIFT-DOWN helps top select full column)
Paste all resources to new French column.
Note that ResXManager will create new resx files for you and add them to project file.
3. Set neutral culture reousrces to English ones
Copy all English resources from specific culture column
Paste all resources to Neutral culture column
4. Inform .Net that neutral culture is now english
[assembly: NeutralResourcesLanguage("en-GB", UltimateResourceFallbackLocation.MainAssembly)]
5. Remove explicit English resx files.
Since the neutral resx files now already contain english resources then you don't need to keep them the culture-specific ones. Unfortunately ResXManager didn't seem to have a button for this but you can I chose to use VS solution manager filter "en-GB.resx" and deleted all files it found. Again, doing it within VS automatically updates your project file.
All done.
You can change the CurrentCulture and CurrentUICulture in your application through code.
It's the same approach that is used to change the apps language at runtime.
Have a look at this code:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
Hope it helps.

Current Culture and OS date configuration

I have a very tricky question here. I've been benging my head on this issue for several hours with no success.
I am building an application to be deployed on numerous machines, with different cultures.
As a precautionary I decided to use the Culture class to help convert between string to dates.
I noticed that when I change my windows operation system date from :
10/07/2011 to 10-07-2011
The CurrentCulture doesn't get updated, I keep seeing the dates as 10/07/2011.
Why is that? Is there any workaround?
You need to change the Culture in the IIS environment (or better in Web.config) and not in the OS.
that way you'll Guarantee that all the machines will work on the same Culture.
try to add the following line to your web.config:
<globalization culture="he-IL" enableClientBasedCulture="false" uiCulture="he-IL" />
just change the he-IL to your proffered culture
It works correctly for me, but only after I restart my application. I assume the current culture is loaded at the start of the application and cached, so, for the change to take effect, you have to restart the application.
A long as the value can still be interpreted as a date, it will always be formatted to your CurrentCulture. This is by design.
You need to explicitly change CurrentCulture, so data shows (or is converted) to a new format. Look at CurrentCulture as how data is going to be displayed on your end.

Where is the system locale/culture set for .Net

I have a problem with a c# assembly (.net 2.0 written using Visual studio 2005) that is installed on a UK server and should use UK regional settings.
What my code does is to convert a date in the form dd/MM/yyyy into utc. i.e. yyyy-mm-dd. The problem arose with dates like 16/02/2010 where the component failed to convert the date and returned Error. After debugging I realised that, for a strange reason, the CultureInfo returned by System.CultureInfo is en-US.
I can programatically change those settings using:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB", false);
and my code works fine.
However I don't want to do that all the time as my system should be UK. Not US.
So, how do I change the default culture for .Net framework to be by default en-GB instead of en-US ?
For information:
I have tried to update the machine.config file and specify culture=en-GB for the globalization section (it was set to neutral) but it doesn't work either [have done that for 1.1 and 2.0] but it's possible I have not changed it correctly.
I have verified my windows regional settings and they are definitely set-up to UK with dates as dd/MM/yyyy
I am running in a Virtual server and have verified my host system. It too is set to UK
Edit:
A bit of extra detail about the context. The assembly in question is being called via COM interop from a native C++ third party component that is running as a COM+ application.
The server is not configured correctly. Control Panel + Region and Language, Location tab. Changing this could be a bit tricky. The server may well have been mis-configured on purpose. Talk to the server administrator first before doing anything.
Your fallback plan is to use the DateTime.TryParse() method overload that takes the IFormatProvider argument. Pass CultureInfo.GetCultureInfo("en-gb").DateTimeFormat.
To set the UI culture and culture for all pages, add a globalization section to the Web.config file, and then set the uiculture and culture attributes, as shown in the following example:
<globalization uiCulture="en" culture="en-GB" />
Hmmm, according to the API Docs:
When a thread is started, its culture is initially determined by using GetUserDefaultLCID from the Windows API.
This method derives it's locale from the (as the name implies) User's Default Locale, which I assume is in the Control Panel. NOTE: This is NOT the same as the UI Locale.
thanks for your answers (andy posted the question on my behalf). It was indeed an issue with regional settings but neither with the user I was connected under, nor with the user the process was running under. That would have been too easy. It looks like that the default user was still en-US. I did reset by clicking the checkbox "Apply settings to the current user and default user..." in the advanced tab and rebooting the server. System.Globalization.CultureInfo now return {en-GB}. And a MyDate.ToString(yyyy-mm-dd) works fine whether the date is passed as dd/MM/yyyy or dd-MM-yyyy or yyyy-MM-dd without the need to parse.
However thanks you all very much for your suggestions (ParseExact, etc) that did indeed work. They ill be very helpful for other date formats that I was not able to handle in a nice way (yyyyMMdd).
Marc
I believe this is represented by System.Globalization.CultureInfo.InstalledUICulture, so if nothing else maybe you can copy that to the thread's current culture. I'm surprised that you found a case where the threads culture is different than the installed culture. Perhaps your code is running in a process that changed the culture?
It is possible the account running the code has different regional settings than the system default. Have you checked that?
You do not have to change the CurrentCulture to do the transformation. If you are certain that the date is in the form of "dd/MM/yyyy" you could use
DateTime dtTemp = DateTime.ParseExact(dateString, "dd/MM/yyyy", null) // in order not to have to specify a FormatProvider
and then use
dtTemp.ToString("yyyy-MM-dd")
This way you will not have a problem no matter what the CurrentCulture is. However, if you are not certain that the Date is of the form "dd/MM/yyyy" rather it is based on the CurrentCulture short date format, then you should use
DateTime dtTemp = DateTime(dateString, CurrentCulture.DateTimeFormat.ShortDatePattern, CurrentCulture.DateTimeFormat);
Assemblies in .net framework are culture neutral.
What code are you trying to convert the date?
If you are using Parse or TryParse, try providing the culture argument for it to understand the date.

Categories