I added new Rosource file UserNotification.resx. Then I added two files for localization and named it UserNotification.hr-HR.resx and UserNotification.sl-SI.resx. (followed thread: How to use localization in C#)
Then I changed Windows language's to "si". If i print current culture using System.Globalization.CultureInfo.CurrentCulture.ToString() the output si sl-SI
But, I allways get a string from UserNotification.resx. Seams it doesn't recognizes the localization resource files.
The problem in .NET localization if you use multithreading is that you need to set culture manualy for every thread that you spawn (in case it is different than windows culture, in case when user can choose desired language). It is not inherited from the main thread.
After you create new thread and before you start it you should set it's Culture to the Culture of main thread (which normaly uses the default culture of the windows).
So, system shows good CurrentCulture. But what does current thread says? Maybe application is started with different culture for some reason so that's why it loads default resources file? Anyway, there is no reason why you shouldn't manualy set current culture. Mostly you need to do that when you want to give user the option to change application's language.
Related
Using Kentico CMS with a multi culture site, we have custom code to get a resource string, when we use ResHelper.GetString("someKey") it does not use LocalizationContext.CurrentCulture version of the string, it is always defaulting to the US culture.
When I pass in the culture code to use as the second parameter using Localization.CurrentCulture.CultureCode it returns the correct string?
Using a quick watch and breakpoint at the code, I can see that Thread.CurrentThread.CurrentCulture and CurrentUICulture are both set to US whilst LocalizationContext.CurrentCulture is set to which ever version of the website we are viewing.
Why wouldn't Kentico set the Thread culture if resource strings rely on it?
We have used many resource strings throughout the site, some are using built in cms controls <cms:LocalizedLabel ResourceString="someKey" /> - how do these controls work?
Thanks
I have a class library project (c#, .net 4.0). It has some WPF user controls which show content in english or spanish according to the culture configured in database.
For doing so, in the main window constructor, I receive a CultureInfo parameter, which I use to set the culture to be used in my Localization namespace, like this:
public MainWindow(Entities.TransactionContext transactionContext, CultureInfo culture)
{
Localization.Resources.Culture = culture;
InitializeComponent();
//Some other unrelated code here
}
That is used from the main program wich calls my dll. In there, a query is made to get the default culture. It can be either "en-US" or "es-MX", then it is send as the second parameter. The first one is not important for now.
As I said, I have a namespace named MyProject.Localization (I'm changing my project name since internal policies, you understand). In that folder, I have three resources files:
Resources.resx
Resources.en-US.resx
Resources.es-MX.resx
Default entries in Resources.resx have values in spanish since, you know, I'm mexican.
Also, in my code, when I need to show a message or set a label text, I use something like this:
this.lblStatusMessage.Content = Localization.Resources.OperationCancelled;
In this example: "OperationCancelled" is an entry that exists in all the resources files. In spanish its value is "OperaciĆ³n Cancelada" and in english it says "Operation Cancelled".
After all this story, this works great in my development environment. I run my test project, I see it in english, then I change the language in database, run it again and boom! spanish.
But.
When I commit changes to this project via SVN, it is then deployed to QA environment by some automated process (it's awesome). And then I test there and I always see the contents in spanish (as the default ones). Even when I change the language on the QA database, it always shows labels and messages in spanish.
I tried some options:
Changed the resources dll's Build Action to Resource instead of Embedded Resource. It didn't work.
Right click->Properties, Resources tab shows no Resources, so I created three resx files there and set custom namespace as MyProject.Localization. Next I excluded my original files since now there was some ambiguity errors. Again it worked in my dev machine but in QA didn't.
Any ideas about this? My hipothesis is that it has something to do with the resx files, maybe they're not included in the final built or something like that, and that's why the app cannot get the localized texts.
Thank you in advance.
Heres my answer based on personal experience: Build action "Embedded Resource" should work. All resources will be included.
Localization.Resources.Culture = culture;
// "Overrides's the current thread's CurrentUICulture property for all
// resources lookups using this this strongly typed resource class."
I havent used this method personally, but this also means it could be changed back to Localization.Resources.Culture = null; without you knowing. Instead look into using System.Threading.Thread.CurrentThread.CurrentUICulture = culture;. And heres a suggestion of a call if you intend to have an application with multiple languages:
public void SetUICulture(CultureInfo culture)
{
CultureInfo savedUICultureInfo = System.Threading.Thread.CurrentThread.CurrentUICulture;
try
{
System.Threading.Thread.CurrentThread.CurrentUICulture = uiCultureInfo;
// Do culture-specific stuff...
this.lblStatusMessage.Content = Localization.Resources.OperationCancelled;
}
finally
{
System.Threading.Thread.CurrentThread.CurrentUICulture = savedUICultureInfo
}
}
This is also useful if you later on have several different resource files. In general I would suggest to take a look at what CultureInfo you're actually passing.
Well, at the end it was simple.
This is my explanation, maybe it's incomplete, but I understood it like that and worked for me.
When you use resources files for localization and you build the solution, VS creates a DLL for each of them. They are created in a folder corresponding to its languaje. In my case, two folder were created:
en
es-MX
Inside each folder, ther was a single file: MySolution.resources.dll. Same name in both files. That way, at runtime, the application know which dll to use to load localized texts.
So you need those folders for using localized logic. If they're not present, the app could only use the texts from the default resource file.
In my case, again, when I tested my app, it worked great because the Debug folder had my MySolution.exe file and also the language folders. But it failed at prod environment because the main deployment was not considering those folders.
And also, the deployment configuration was set something like that:
-MainFolder
--MainApp.exe
--MainApp.configfile
--other files
--Folder
----MySolution.dll
----en
------MySolution.resources.dll
----es-MX
------MySolution.resources.dll
So I had to talk with the person in charge of deployments, so that could change to:
-MainFolder
--MainApp.exe
--MainApp.configfile
--other files
--MySolution.dll
--en
----MySolution.resources.dll
--es-MX
----MySolution.resources.dll
That way, my dll could load the language dlls, and the main executable could load everything ok. Happy ending.
I hope I was clear and it can help someone. Cheers.
This question already has answers here:
What is the difference between CurrentCulture and CurrentUICulture properties of CultureInfo in .NET?
(5 answers)
Closed 8 years ago.
I have noticed people use this code to localize
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Could anyone tell me what CurrentUICulture and CurrentCulture are? Why do we need to assign same value to both
What will happen if I assign the value CultureInfo("fr-FR"); to only CurrentUICulture or CurrentCulture?
I would really like to know in detail what CurrentUICulture and CurrentCulture does?
Suppose client pc language setting could be German or French etc., but I want to develop my application in such a way that whatever language setting is there, my apps will work in that pc with their language setting. I mean that all the controls will show the text in German or French. I do not want to hard code the culture this way CultureInfo("fr-FR")
I would rather the user's language setting dictate the language of my controls. How would I go about doing this?
It's pretty simple.
CurrentCulture is the culture assigned for thread to be used in various culture-specific methods. To example, ToString() one.
CurrentUICulture is
used by the Resource Manager to look up culture-specific resources at run time.
By setting both you ensure what all ToString() works correctly and your form resources are loaded from appropriate satellite.
Regarding usage, you may think to provide user with option to change language. To example, I have native German windows, but I set English culture in it (date format and default culture for console applications), while I speak Russian. Which language do you think I will chose when using your software? =P
By default, either take language chosen in installer (if you have installer in multiple languages and options to change it there) or current Windows user language preferences.
One possible scenario:
Preconditions: application is already localized, satellites are there (if not, read this). I don't like satellites myself, but they are easy to start with.
When application starts, you create a list of available languages (either statically or by enumerating satellites).
string[] Languages = new[] {"en", "fr", "de", "ru"};
Then, if application start for the first time (to example, you have string language setting and it's by default null or "", this would be a flag what no language is selected yet), you detect default os language
var language = CultureInfo.InstalledUICulture.TwoLetterISOLanguageName; // to ex, "fr"
and if it's in your list, then you set
Thread.CurrentThread.CurrentUICulture =
Thread.CurrentThread.CurrentCulture = new new CultureInfo(language);
Otherwise, if you don't have this language, then use "default" language (to example, "en"). If its done at at the start of your application, then any further constructed and used window will use proper resources.
User should be able to change language. Give him possibility to chose one of available Languages. In winforms you will have to reload forms after change culture. Easiest solution would be to simply tell user what "software restart is required".
Is there a property in some class that can tell me if the current culture is actually the default culture.
Similar to how localization works with winforms. It states in a form if the language is default.
lets say if i am in en-US - how can i tell via code if en.US is the actual default?
I need to implement some localization for some XML files which .net doesn't support hence i want to implement my own ...
And do it how winforms works i.e
nameofxml.default.xml (this is the default local)
nameofXml.de-de.xml (this is german)
etc
does a property exist?
System.Globalization.CultureInfo.CurrentCulture indicates you system's Control Panel Region settings, while System.Globalization.CultureInfo.CurrentUICulture corresponds to the system's Input UI Language setting (which you can't change unless you have Multilingual User Interface installed).
Therefore you can use the following code snippet to determine the 'default' culture:
using System.Globalization;
// N.B. execute the following line *before* you programmatically change the CurrentCulture
// (if you ever do this, of course)
// Gets the CultureInfo that represents the culture used by the current thread
CultureInfo culture = CultureInfo.CurrentCulture;
string code = culture.IetfLanguageTag; // e.g. "en-US", "de-DE", etc.
Then you can use the code to locate your .xml files.
You can state at the assembly level that the embedded resources are of a specific culture by using the NeutralResourcesLanguageAttribute.
IIRC, this way the resource manager can optimize the process of resource loading if the required culture is the one embedded in the assembly.
Since you are rolling your own implementation for localization I don't know how this can be helpful, but you can use that attribute to indicate that the culture of the XML localization information embedded directly in the assembly is of a specific culture and default to searching satellite assemblies or other custom back store if you find a mismatch between the declared culture in the assembly and the required culture you are looking for.
CultureInfo.CurrentCulture is a static member that "Gets the CultureInfo that represents the culture used by the current thread." It is accessible from any class if you just include the System.Globalization namespace.
Documentation: http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx
I have an ASP.NET3.5 (C#) ASPX page that is internationalized in 10 different languages.
The page is very complex in its structured with dozens of nested views driven by a state machine pattern.
EDIT: I am using the meta:resourcekey syntax in every asp control, which allows to use declarative syntax for Implicit Resource expressions.
I have been asked to "brand" the page based on some query string parameter. Branding will mean not just loading different CSS files, but also having different text blurbs (in all languages).
Is there an easy way to "swap" resx files without having to get resources manually for each of the hundreds of literals and images that I have on this page?
In other words, let's say I have the following RESX files:
brand1_myPage.aspx.en-US.resx
brand1_myPage.aspx.de-DE.resx
brand1_myPage.aspx.fr-FR.resx
brand2_myPage.aspx.en-US.resx
brand2_myPage.aspx.de-DE.resx
brand2_myPage.aspx.fr-FR.resx
myPage.aspx will be looking for resx files named myPage.xx-XX.resx.
Is there a way to load instead either the brand1xxx.resx files or the brand2xxx.resx based on some value?
Thanks in advance.
You can use custom cultures to achieve this effect.
First, create and register custom cultures in the system, for example:
CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder("en-US-brand1", CultureAndRegionModifiers.None);
CultureInfo parentCI = new CultureInfo("en-US");
RegionInfo parentRI = new RegionInfo("en-US");
builder.LoadDataFromCultureInfo(parentCI);
builder.LoadDataFromRegionInfo(parentRI);
builder.Parent = parentCI;
// set other properties of the custom culture (CultureEnglishName, CultureNativeName, possibly other ones)
// ...
builder.Register();
Note that you might want to build a simple tool to automate this, since those cultures need to be installed on every system where your aplication will be compiled or executed. Administrative rights are needed to be able to register the cultures.
Once you have the cultures installed, create resx files like you would normally do, but use the custom culture names (myPage.aspx.en-US-brand1.resx etc).
Now all that's left to do is to set System.Threading.Thread.CurrentThread.CurrentUICulture based on some parameter (the sooner the better, BeginRequest is a good place; or Page_PreInit if you want this only for some pages):
CultureInfo ci = new CultureInfo(Request.QueryString["paramname"]);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
(setting CurrentCulture is not really necessary, as resources work in terms of CurrentUICulture, but setting both allows you to further customize the page for each brand, e.g. use different date/time format settings for each custom culture/brand)
Some notes:
this solution gives you great flexibility, since normal culture fallback is in effect - if an entry is not found for en-US-brandX, the runtime will fall back to en-US and so on; this can greatly reduce duplicate resx entries if the brands are mostly similar, as you can put some entries only in the parent (en-US) resx file,
you can create more levels of inherited cultures, eg en-US-brandX-variantY,
all methods for accessing resources work as expected,
changing the culture of the worker thread means you will get localized exception messages if you set the culture to, say, de-DE-brandX and you have de-DE localization installed in the OS,
for the above reason, you might want to reset the current (UI) culture to CultureInfo.InvariantCulture in Application_Error, or even better also as soon as you catch an exception which you know will lead to Application_Error; this will prevent localization of the standard yellow page of death and at least part of the exception stack,
you might consider building a service tool which will register/unregister/update the cultures, especially if you anticipate frequent changes,
this solution might be problematic if you use client-based culture detection.
If you reference resources in your code like this: Resources.brand1_myPage.WelcomeMessage then it may be difficult.
But you can also retrieve resources programmatically: GetGlobalResourceObject ("brand1_myPage", "WelcomeMessage"). Here you have some room for manipulation with the resource file name.