Default Resource.resx file not used - c#

I have a WPF application which is localized.
When I set Format to Hindi(India) from ControlPanel -> Region -> Formats, Following lines of code in my WPF application at the beginning of launching of my WPF Application is not reading CultureInfo.CurrentCulture(hi-IN) instead it uses en-US.
Application.Current.MainWindow = new MainWindow();
Application.Current.MainWindow.Show();
Because of this, My WPF Application is not using greeting message from Resources.resx file. Instead, it is use greeting message from in Resources.en.resx
I am getting proper value in CultureInfo.CurrentCulture.
Any idea why above lines of code are not picking proper value?

The ControlPanel->Region->Formats setting doesn't apply to .resx files. It is in ControlPanel->Region->Language that you specify the default language.
What is the difference between CurrentCulture and CurrentUICulture properties of CultureInfo in .NET?
Alternatively you could specify the default language of your resources in your App class (App.xaml.cs):
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Resources.Culture = System.Threading.Thread.CurrentThread.CurrentCulture;
}
}
Please refer to the following link for more information: https://social.msdn.microsoft.com/Forums/vstudio/en-US/6bfb8d13-3a86-4c10-a632-bb20c99d0535/localization-in-wpf-using-resx-files-for-different-languages?forum=wpf.

Related

Using NLog with WPF richtextbox

I have an application which has several tabs. I am trying to add logging with NLog where the output is directed to a richtextbox.
My main form is an instance of a class MyNamespace.MainWindow and its name is MainWindow1. It has a tab and in that tab I have a RichTextBox called rtbLogBox
I have imported WpfRichTextBox extension from NuGetand place this piece of code in the MainWindow class's loaded event
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if(logger == null) logger = LogManager.GetCurrentClassLogger();
WpfRichTextBoxTarget rtbTarget = new WpfRichTextBoxTarget
{
Name = "rtbLog",
ControlName = "rtbLogBox",
FormName = "MainWindow"
};
LogManager.Configuration.AddTarget(rtbTarget);
LogManager.Configuration.AddRule(LogLevel.Info, LogLevel.Fatal, rtbTarget.Name);
logger.Info("This");
}
The problem is that this does not produce any outputs in the RichTextBox control.
I have an output to a file in addition to this and that target gets the log when I run the app.
Since the logger is created before you are changing the LogManager's configuration, you need to notify the logger of the change.
Calling LogManager.ReconfigExistingLoggers() should do the trick.
Documentation is here.
You can also use my wpf control. (https://github.com/dojo90/NLogViewer). There is also a nuget package available.

Localize dataannotation error messages as per culture

In my WPF appliation, I have property defined as following
[Required(AllowEmptyStrings =false, ErrorMessageResourceName ="Msg1", ErrorMessageResourceType =typeof(*<AssemblyName>*.Resources.*<ResourceFileName>*))]
public string Name
{
get
{
return _name;
}
set
{
if (_name == value)
{
return;
}
_name = value;
}
}
I have my error messages defined in separate assembly which has resource file for different cultures e.g. Resources.resx, Resources.en-GB.Resx, Resources.fr-FR.Resx, Resources.en-US.Resx, etc.
With above code in place, I'm able to retrieve the error message from default resource file in my satellite assembly but I don't see any provision to find the string resource from culture specific resource file. What I mean is if my CurrentUICluture is set as english(United Kingdom) then I want to retrieve the resource value from the file "Resources.en-GB.Resx" instead of the default file (i.e. Resources.Resx).
I don't see any way to pass the culture info in the Required attribute definition. Also, I have tested that it is not inherently look into the culture specific resource file based on the current culture set.
What I want is some way to make the resource retrieval mechanism culture aware.
Thanks,
I came up with an easy idea that saves me from decorating all properties individually.
Indeed a nasty solution because it involves reflection but works.
Caution: this can break if the .NET Core team decide to rename fields or classes or if internal stuff change, so use at your own discretion.
First create a resx file in your app be either creating one from scratch or by copying this or this one, the replace the strings with the desired translations, in the same format as they appear (pay attention to {0} placeholders and to their order).
Obviously, you can then add DataAnnotations.en-UK.resx-like files and translate them all, as long as your app is properly set to operate with the desired culture, it'll work.
In your project, call the following at early startup:
void InitializeDataAnnotationsCulture()
{
var sr =
typeof(ValidationAttribute)
.Assembly
.DefinedTypes
.Single(t => t.FullName == "System.SR");
var resourceManager =
sr
.DeclaredFields
.Single(f => f.IsStatic && f.Name == "s_resourceManager");
resourceManager
.SetValue(null,
DataAnnotationsResources.ResourceManager, /* The generated RESX class in my proj */
BindingFlags.NonPublic | BindingFlags.Static, null, null);
var injected = resourceManager.GetValue(null) == DataAnnotationsResources.ResourceManager;
Debug.Assert(injected);
}
What it does is it takes advantage of this field to replace the default DataAnnotations resource manager with your own.
It's been tested and works in .NET Core 3.1 WPF, but you can browse the .NET Source of any .NET to find the resource location and inject your own resources.
If you'd like to make your website culture aware, you'll need to modify the globalization attribute in the web.config under the system.web element:
<globalization fileEncoding="utf-8" requestEncoding="utf-8" culture="auto" uiCulture="auto" enableClientBasedCulture="true" />
Then it will look for resources based on the browser's preferred language settings.
Alternatively, you can specify it explicitly:
<globalization fileEncoding="utf-8" requestEncoding="utf-8" responseEncoding="" culture="en-US" uiCulture="en-US" />
Finally I got the fix for my problem from this link
In my app, I was setting the culture at the time of starting the application by putting following code in app.xaml.cs file.
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
InitializeCultures();
}
private static void InitializeCultures()
{
var culture = ConfigurationManager.AppSettings.Get("Culture");
if (!String.IsNullOrEmpty(culture))
{
Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
}
var UICulture = ConfigurationManager.AppSettings.Get("UICulture");
if (!String.IsNullOrEmpty(UICulture))
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo(UICulture);
}
}
However problem is even if I set the Culture initially, not all threads will use the same culture set by me initially. So the thread which was reading the resource value for me was still using the default culture and this resulted in reading of resource string always from default culture resource file rather then the culture specific resource file.
So the trick was to set all the threads in my app to use the same culture which I set initially. There are two properties for this
CultureInfo.DefaultThreadCurrentCulture
CultureInfo.DefaultThreadCurrentUICulture
Setting required culture value to these two properties initially will ensure that all the subsequent threads used in the application will have the same culture as set by user. These two properties sets the culture on all the threads in current app domain.
Once culture is set properly, reading of resource values inherently becomes culture aware and reads resource values from culture specific resource files.
So following is the updated version of InitializeCulture method :
private static void InitializeCultures()
{
var culture = ConfigurationManager.AppSettings.Get("Culture");
if (!String.IsNullOrEmpty(culture))
{
Thread.CurrentThread.CurrentCulture = CultureInfo.DefaultThreadCurrentCulture = new CultureInfo(culture);
}
var UICulture = ConfigurationManager.AppSettings.Get("UICulture");
if (!String.IsNullOrEmpty(UICulture))
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(UICulture);
}
}
P.S. There is a word of caution of using this fix in web application. Pls read about it on original link.
Hope this helps...

Can't load correct ressource when I change the CurrentUICulture

I'm working on a WPF Application. When the main Window is initialized I get the system language of the user and change the CurrentCulture :
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-CA");
I have 3 .resx files (resource.fr-BE.resx, resource.nl-BE.resx, resource.resx) in a Ressources folder.
In my XAML, I refer to the default ressource.resx :
xmlns:r="clr-namespace:Renoir.UserInterface.Resources"
And user the key in my resource file for my controls :
Title="{x:Static r:resource.MAINWINDOW_TITLE}"
But the app can't load the correct resource file (for exemple when I change the Culture for french (fr-BE), it doesn't load the resource.fr-BE.resx file, it always show the string in the default resource file (resource.resx)
But in code behind, if after I changed the CurrentCulture, I try to get a string form resx, I received the correct string :
ResourceManager rm = null;
rm = new ResourceManager("Renoir.UserInterface.Resources.resource", Assembly.GetExecutingAssembly());
MessageBox.Show(rm.GetString("DATAGRID_AUTHOR"));
Someone have an idea ?
Thanks in advance !
You are trying to change culture info after initializing of your window.
You need to change culture info in app.xaml.cs before initialization of your window
public partial class App
{
public App()
{
}
protected override void OnStartup(StartupEventArgs e)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
base.OnStartup(e);
}
}
Ok, now it works and so I think I found the solution. In code behind, after windows is initialiized (thanks to Valera) I change the culture info of the app bu using the language code of the system of user.
And to use the right resource file, I have to precise it like this :
Renoir.UserInterface.Resources.Resources.Culture = new CultureInfo("nl-BE");
Try doing the following in the window class.
this.Language = System.Windows.Markup.XmlLanguage.GetLanguage(culture.IetfLanguageTag)

Call the Resource name for TextBlock control in Windows Store App

i am new to Windows store app. now i created the folder for the resource file for French[Strings -> fr-FR ->Resources.resw] and English[Strings -> en-US ->Resources.resw].
and declared the Heading1="hdFREN" and Heading1="hdENG" respectively.
now i have to call the Heading1 to the TextBlock text="".. How to declare the text in the TextBlock control???
Actually i created the resources.resw in the root folder [Strings -> fr-FR ->Resources.resw] and English[Strings -> en-US ->Resources.resw]. then i am creating manually LocalizedStrings
enter code here
public class LocalizedStrings
{
private static Resources _localizedResources = new Resources();
public Resources LocalizedResources { get { return _localizedResources; } }
}
now i can't call that Resources file. it is showing error
This is a an overview of localization, and should address most of your questions.
Quickstart: Translating UI resources (Windows Store apps using C#/VB/C++ and XAML)

Localize Prism 4 Modules with .resx files

I'm working on a modularised Prism application. After some localized WPF clients with resx files (localized.resx, localized.de.resx etc.), i thought i could adapt this technique to my prism modules. But the module always takes the default resx.
Any suggestions?
Thanks in advance
Sorry but it's not easy to explain this with a short message. So I wrote a really simple prism project with a working solution.
Try to download this example
I found out, that my ResourceManager has the wrong values in it's ResourceSet for the specific language. See my New Topic
Actually its pretty easy, just make sure to force your localization inside CreateShell() inside app.xaml.cs like this:
protected override Window CreateShell()
{
SetLocalization();
return Container.Resolve<MainWindow>();
}
the SetLocalization() method can be like this :
private void LoadLocalizationFromSettings()
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");
//set pc default localization to be used in the XAML gui
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata("en-us")));
}

Categories