Issues Localizing a Windows Form - c#

This is my first time trying to localize, so bear with me. I've read up on it, but am still dealing with limited experience in the subject.
I've gone through a demo and have it working fine and I feel like I understand what happens behind the scenes. I moved the same concepts into my actual application, and it will not work. I've set the Localizable property to true and created an English and French resource file.
I've confirmed that my application is still pulling from the regular .resx file instead of en-US.resx or the French one.
I've tried setting these before the InitializeComponent call:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
I've even tried to call a few particular ones explicitly:
resources.ApplyResources(this, "$this", new CultureInfo("en-US"));
resources gets declared as:
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(myForm));
It all still pulls from the .resx file. One difference in this over my test project is that this form inherits from another, but I have made sure to set that form's Localizable property and resource files as well. Any ideas would be appreciated.
EDIT: I've still been working on this. I have a test project that works and my main application that does not. If I copy over the form that works in the the test over to the main, it does not work. If I add a reference to the main app in my test, the form from the main app also does not work even though it is straight copied from the test that works. Any ideas?
EDIT: It seems like the main difference/issue is that the basic project that is working is an executable by itself while my main application is calling an assembly with this localized form in it. Still no idea what is wrong. A lot of the tutorials I am seeing use System.Resources.ResourceManager, but when I change the form to localizable it auto-uses System.ComponentModel.ComponentResourceManager.
EDIT: I can literally say
resources.ApplyResources(this, "$this", new CultureInfo("fr-CA"));
and it will ignore the $this.Text in the .fr-CA.resx file and use the default .resx file instead. I Don't Understand. And that is just me trying to FORCE it to work. I still need to just set the culture like normal. Does anyone have any ideas?

Use the CreateSpecificCulture instead of new CultureInfo() for the threads CurrentCulture.
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(languageCode);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(languageCode);
As a side note, if your default culture is going to be English then you do not need to create a labels.en-US.rex. You can put that in the labels.resx and that will load up front and be the fallback. Gives you one less file you need to keep in sync.

If you add the relevant line below to the main method in Program.cs (other lines added for context)
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// THIS LINE - Only need to set UI culture the other one is for currency etc
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
// Or whatever your form is called.
Application.Run(new Form1());
This guarantees you are setting the culture before any InitialiseComponent method calls.
I've eyeballed this working.

When you localize a form, it creates a folder per language in the build's output path that holds a resource file projectname.resources.dll.
I have a post build command that puts our .dlls elsewhere. I needed to change the command to also push out the resource files so that they were in the same directory. Once I did this, I was able to get it to work.

Related

How to set UWP language on runtime

i'm currently developing a cross-platform App using Xamarin.Forms 3.4 and Visual Studio 2017 (latest version by now).
Since that App should support multiple languages which can be changed on runtime, i'm currently looking into ways to get this done. I already added several resources and translated all interface elements which works just fine. I read through this article to get started:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/localization/
For now, when using the UWP app, the language is automatically set to my current system settings, which is the german language, even if the default app language is english. Thats fine.
Now, I got a method which configures my current language by setting several information, like the default CultureInfo object. That method looks like follows:
public void UpdateAppLanguage()
{
CultureInfo ci;
Language l;
// storage is a class containing several persistent information, like
// the language selected by the user to be used
// the Local attribute states if the language is actually present on
// the current user's system
if(Storage.GetCurrentLanguage().Local == true)
{
// language is present locally, so the user wants to use that one for
// the interface
ci = new CultureInfo(Storage.GetCurrentLanguage().Code);
AppResources.Culture = ci;
CultureInfo.CurrentCulture = ci;
CultureInfo.CurrentUICulture = ci;
CultureInfo.DefaultThreadCurrentCulture = ci;
CultureInfo.DefaultThreadCurrentUICulture = ci;
DependencyService.Get<ILocalize>().SetLocale(ci); // set the Thread for locale-aware methods
}
else
{
// no preferences available yet, use the system's current ci
if (Device.RuntimePlatform != Device.UWP)
ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
else
ci = CultureInfo.CurrentCulture;
l = new Language{
Name = ci.EnglishName,
Code = ci.TwoLetterISOLanguageName
};
Storage.SetCurrentLanguage(l);
CultureInfo.CurrentCulture = ci;
CultureInfo.CurrentUICulture = ci;
AppResources.Culture = ci; // set the RESX for resource localization
DependencyService.Get<ILocalize>().SetLocale(ci); // set the Thread for locale-aware methods
}
}
I'm currently testing with a language set, and that language is English.
And here is the dependency service implementation for the UWP sub-project:
public class Localize : stereopoly.ILocalize
{
public void SetLocale (CultureInfo ci)
{
//Windows.Globalization.ApplicationSettings.PrimaryLanguageOverride = ci.Name;
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "EN-US";
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
}
public CultureInfo GetCurrentCultureInfo ()
{
return null;
}
}
As you can see, I also tried to set the language to EN-US by force, which doesn't work either. I'm calling the UpdateAppLanguage() method even before the initial Application.InitializeComponent() method runs, I also tried calling it within the OnStart() event method, neither works.
I'd expect the language change getting applied since its executed even before the actual Application starts, but I can switch the several pages of my app as often as I want, the language will always be german, no matter what I do.
I found several answers to this question for plain UWP apps, but not for Xamarin.Forms implementations of UWP projects and that seems to be the problem here, because no other hint regarding pure UWP apps seem to work.
Do you have any idea what might help me?
Thanks.
Make sure you are targeting at least UWP 16299 (FCU), because before that version UWP had issues properly switching languages in debug mode. If you run in Release mode however, it should work normally.
In addition the UWP app needs to know it supports a given language, because this is generated at compile time (using <Resource Language="x-generate"/> in Package.appxmanifest)
You can do this by adding a Strings folder in your UWP project and then adding multiple subfolders - one for each supported language. Finally in each of them add a Resources.resw file (right-click folder, Add > New item..., Resources file (RESW)). The result will look like this.
Then inside each RESW file add some resource. I usually put in AppName, as I often localize it as well:
After this, the app should pick up on the fact that you support the given language and display localized.
I finally found the answer to my problem, it was just as simple as it usually is when it comes to such errors.
It turns out that all bootstrap projects like the UWP, iOS and Android sub-projects also inherit the Assembly Neutral Language from the parent project, no matter what configuration is defined in the specific sub-project (at least thats how it works for UWP). I just noticed that I can set an Assembly Neutral Language within the settings of my .Net main project, and as soon as I did that, all the warnings disappeared and my UWP app ended up showing english text instead of the system default german one. I can also switch back to german now, even though I still have to restart the app to get all frames translated, but thats not that big of a problem, I can work on fixing that up later on. Here's the link that finally got me covered:
Xamarin.Forms: Localization of the UWP app
Thanks for your amazing help anyway :).

C# Localized Resources.resx doesn't allow for other languages

Good evening,
I happen to have an issue with Winforms and Resources.resx.
The app I'm working on is built via 'Winforms App' template selectable via Visual Studio.
The issue I'm having is kind of outside of winforms localization - which I think is important to mention.
Here's my issue:
- I've created a 'HistoryManager' class, which has only one method and one action to perform - add a history to the SQL database.
- I've created Resource.resx file, entered a format string into it under "MsgTaskAdded" which is equal to "Task {0} has been added to {1}".
- The said string adds to the database flawlessly.
Resources.resx works well - if I change MsgTaskAdded resource string, it changes what will be added to database .
Now, the issue I'm having is.
- I've created a Resources.de-DE.resx file, copied strings from Resources.resx and translated to german.
- Changed CurrentThread.CurrentCulture and CurrentThread.CurrentUICulture to 'de-DE'.
As a result, the text added to database is STILL in english, as if the file wasn't found and it fell back into using the default Resources.resx.
Make certain that your Resources.de-DE.resx file is contained within the Properties folder of your project, and that it has a Build Action of Embedded Resource, so that it gets properly associated to your default Resources.resx during compile. The culture settings on CurrentThread also need to happen before the call to the database, ideally somewhere in your static void Main() function before the Application.Run(…) call.
This should produce a culture-specific folder in your bin\<build_configuration> folder that contains a file named <your_app>.resources.dll. If needed, you can crack this open with a tool like ILSpy or Reflector to verify that the translated resources exist in the expected place within the assembly.
Maybe the reason in that how you're changing the thread culture. I did exectly what you did and its worked. That is how I've changed the culture
static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("de-DE");
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("de-DE");
Console.WriteLine(Resources.Hello);
}
it prints "Hallo"
I found a solution.
If you guys ever have issue with the Resources.resx, make sure the localized file isn't: Resources.de-DE.resx or Resources.pl-PL.resx, instead - use only the first bit (Resources.de.resx) and make sure to open the file and set accessors to 'Internal' so it generates you a Designer file with proper code.

Creating localizatin .resx files makes empty .Designer.cs files

I'm trying to add localization to my .NET MVC project. As far as I've seen (here, here, and here), I should simply be able to create a total of three files (if I have two languages).
Resources.resx
Resources.en-us.resx
Resources.da-dk.resx
When I open the .resx files, I can add entries to them. Once I've done that (and set "Access Modifier" to either Internal or Public), it generates a Resources.*.Designer.cs file (as it should). However, for en-us and da-dk they are empty. No errors or anything.
As far as I could read (here, here, and here), I cannot have a dot between the file name and the .resx extension. And to my surprise, it's true. If I rename any of those en-us/da-dk files to Whatever.resx the Whatever.Designer.cs file will be created.
I've read a lot of answers, tried my way with T4 templates, and a bunch of other things, but I simply cannot get it to create a working Designer.cs file.
Am I doing it wrong? I feel like I've tried everything now. I just want to be able to do Resources.TestText and have my application do the translation depending on the culture.
It is by design.
The Resources.EN-US.resx file types, doesn't have a designer because the actual designer is in it's "parent" file, Resources.EN-US.resx. The en-us file only holds the key/value XML.
If you are calling your Resource, you probably use it like:
var someVar = Resources.SomeLocalizedString;
You don't have to differentiate between the EN-US types.
If you look at the designer's code, you can see whats happening (hold on, I'll fetch an example)
So, you don't need those designers, and it should work out of the box if you set the culture info of the UI thread.
Thread.CurrentThread.CurrentUICulture = new CultureInfo("EN-US");

Localizing Winforms using the form designer with state changes

I am having an issue where when using the localizable property in the windows forms designer. I have a label that has its Text property set by a resource file, and I want that text to change to another string in the resource file when a button is clicked. There is no issue adding the new string to the resource files or getting the strings with a resource manager. The problem is that every time I open the form designer, the resource generator wipes out that new string that was manually added.
Q: Is there a way,using best practices, to have generated localization resources from the designer and manually created ones live happily together?
I was under the impression that the Microsoft documentation states not to mix project and form resource files for localization, which is why I'm not taking that approach. Though I may have misunderstood the rational as indicated in this document.
EDIT: Reproducible steps
1. Create a windows form (Form1) with a button (button1) and a label (label1)
2. set label1.Text = "Hello";
3. set the localizable property of Form1 in the designer to true
4. In the Form1.resx file that is generated, add a string resource named "strWorld" with a value of "world". When you start typing, click okay on the message box that appears; agreeing that you are foolish enough to modify the resource file that is part of the form.
Steps 5 and 6 optional
5. Add the following eventHandler
private void button1_Click(object sender, EventArgs e)
{
ResourceManager resources = new ComponentResourceManager(typeof(Form1));
label1.Text = resources.GetString("strWorld");
}
6. Build and start the application to verify that the button functions
7. return to the designer and nudge the button by a pixel or two (or change anything else)
8. return to Form1.resx to find strWorld gone.
I am trying to figure out how one can visually align elements in different languages, taking advantage of the form designer, have controls that change properties of elements from said resource files and stay within recommended practices. Does one have to roll their own code around this or use a 3rd party solution or is there just something that I'm missing? Surely this is a common enough issue.
I think Microsoft expect you to do define texts
in the designer or
in the source code
If you enable localization, texts you specify in the designer will be stored in the local resx files associated with the form or the user control.
For each property in the designer, you can specify one text only.
If you want to change the text at runtime, you should define the text in the source code, and update it from your code.
Microsoft would expect you localize this text using named resources, which would be defined in the Resources.resx file at project level. The localized versions would be in localized versions of Resources.resx.
(If you define additional resources of your own in the "local" resource file associated with a form, the designer will probably discard them.)
I don't know if that is "best practice", but I think that is how Microsoft expect you to work.

Localizing of C# Win Forms

I am developing a WinForm application which require localization.
If I try to set the Localizable property of the form to True and set the text for all the languages then every thing works fine.
What I want is to maintain all languages resource files in a separate folder (one file for each form).
-Project
-Resources
-Language
frmFirstForm.en-US.resx
frmFirstForm.en-GB.resx
frmSecondForm.en-US.resx
frmSecondForm.en-GB.resx
frmFirst.cs
frmSecond.cs
In my resource file I have defined all strings as follows:
**Key Value**
lblName Name
lblAddress Address
.....
The key is my control names, I will also keep form specific strings in the resource files. Now the issue is when I compile the solution, it do generate the language files but while running the application it just displays the default values. I don't even know whether the localized resource file is loaded or not. Also, though I have specified two separate form files but while compiling the system is generating only one single resource file per language for a project (means no separate resource file for FirstForm and SecondForm).
Is there any way where the form controls are changed as per the specified localized thread?
I have already added the following line in my main application Program.cs file:
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-GB");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
Please suggest me how to proceed with this..
#Ashish : this is what you want exactly!!!!

Categories