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.
Related
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.
I have an application that I am developing that is made with Window Forms. For localizing all my Labels, ToolStripMenuItems, Buttons, etc I use resx resource files. Specifically to localize my application for German, I open my Main.en-CA.resx file in winres. I then go through all the terms found in the form and change them to their German translation. I then save the file to Main.de-DE.resx. I now have a Main.en-CA.resx file and a Main.de-DE.resx file. In my code I then only have to change the current culture to whatever language I want and apply the change to all my Labels, Controls, Buttons, etc. For example something like this:
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language);
// Must re-apply resources after changing the culture
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main));
resources.ApplyResources(this, "$this");
foreach (Control c in this.Controls)
{
resources.ApplyResources(c, c.Name);
}
This seems to work great for all Labels etc that do not change. I do however have entries that are changed. For example I might have a dropdown ComboBox that is filled with the entries: "Apple", "Banana", "Orange". Or I might have some error messages: "Missing Input", "Cannot find xml file" that are only sometimes displayed. Now I suppose maybe for the error messages I could just have Labels and selectively change their visibility depending on whether they need to be shown, however for the dropdown ComboBox these entries might change depending on say which file the user loads.
I am wondering then, is there a way to store these entries in the resx files and then access them from my code. I tried opening the resx files and adding them manually (i.e. without using winres) but attempting to do this resulted in the warning:
You are trying to edit a resource file that is a part of another project item (such as a form or control). Editing this item could corrupt the project item, and you will have to recover it by hand. In addition, changes made to this resource file may be lost if further changes are made to the project item.
Do you really want to edit this file?
This sounded like a bad idea so I didn't try that any further. Additionally I am not sure on how I would access the terms in the file manually. I am very new to windows forms and resource files (this is my first time using them) so I realize this might be a simple question but I have had trouble finding information on how exactly to do this.
Ok as it turns out I have uncovered how I can achieve what I am looking for. Ok from the SO post I can access any strings stored in the files Resource.resx by the code:
myLabel.Text = Properties.Resources.MissingController;
where MissingController is a key (i.e. Name) in the file Resources.resx.
Therefore all I need to do is add additional resource files such as Resource.de-DE.resx in the case of German and fill in the translations (i.e. the values in the resource file) corresponding to the same keys (i.e. the names in the resource file).
The Resources.resx file looks like:
and the Resources.de-DE.resx looks like:
As mentioned in the question I had already created some resource files for translating my forms but I had used winres. Whereas they had been located under my Main.cs [Design] file, the Resources.resx and Resources.de-de.resx are located under Properties. Because I had used winres to make my resx files I think that meant I was not supposed to manually edit them hence the warning it gave?? I'm still not 100% sure about this.
Regardless I can now just manually add terms to my Resource.resx file as well as create different versions of this file for different languages and the localization will work. When right clicking on Properties and going Add->New Item and then selecting Resource, if you do not see the Resource file type as an option (as happened to me) then that might mean you need to add the development tools that did not get installed with your version of visual studio. You can achieve this by just running the visual studio installer again and clicking modify and adding the .NET development tools.
I have a localized WinForms application. To avoid a large number of iterations in the translation procedure, I have given our translators software to allow them to edit the .resx files directly.
This has worked great for the resource files that are not tied to UI components (Forms/Controls), but for forms and Controls the resources don't seem to be getting updated. What I mean by this, is that at design-time all resource strings are correct (Text/ToolTips et al.) and I can see the correct translations - when I run the application (debug or any other release) the translations are not being updated, why?
Thanks for your time.
Edit1. The plot thickens further. There are two buttons that are not being updated at all when I change their components (button text, tooltip or any thing governed by the underlying resource file). Lets say I change the button text from 'Lock Workbook' to 'Lock Workbook GG', then the new text shows in the designer and the .resx files (both in the .resx designer and the code behind) but when I run the code (in debug or release mode) the button text is not updated!?
If I update the button next to the button I updated above, this does change the text in the running application?? This is baking my noodle as I fail to see where the old text is being stored and why for a sub-set of buttons their component text is not getting updated!?
Any ideas are warmly welcomed!
Edit2. I have tried to delete the .suo and clean and recompile. I have also removed the troublesome form from the solution and re added it.
So that you can see this strange behavior, here is one of the problematic buttons ('Lock Workbook GG') and a normal one ('Set as Default Workbook GG').
Now at run-time I see
Maybe your build settings are wrong?
This is what I have for my dll.
I have given our translators software to allow them to edit the .resx files directly
That certainly was not a good idea. Any professional translator will know how to tackle .NET resx files. Even if they don't have any of the tooling that's traditionally used by translators, like SDL Passolo, then they would still fall back to the standard Winres.exe utility included with the SDK.
Whatever you wrote probably has a bug. Quite hard to reverse-engineer from the question what that bug might be. Other than that the .resx file for a Winforms form is quite different from the one you get from Resource File project template or the resource designer. There are lots of resource naming tricks to avoid ambiguity between the form's properties and the properties of its controls. Get a name wrong and it won't work right.
Don't write your own, at least ask them to use Winres.exe if necessary. It is free.
The bindings to the button are made in the Designer File of the related form, have you checked whether there are some issues? Try removing the code that sets the ressource and re-add it via the designer.
Probably this has something to do with the CopyLocal property. Please check if these are TRUE for these resource files. If not, set them to true, otherwise, after succesfull compilation, they are not being copied to the output directory.
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!!!!
This problem has left me scratching my head! I'll try to be as concise as possible.
On a high level:
The problem is that although the project works fine and the code looks good to me. Whenever I edit and build certain forms, Visual Studio re-writes the *.Designer.cs files in a way that is very undesirable.
I quite confident that these *.Designer.cs files have not been edited (especially the auto-generated portion) in the past.
In more detail:
Our project uses custom controls, some which inherit from PictureBox. On the forms where these controls are present, if I view the *.Designer.cs file, I either see that the Image property is not set, or the Image property refers to an image stored in the project's resx file like below, which is all well and good.
this.customButton.Image = global::MyProject.Properties.Resources.buttonImage;
However, if I simply modify this form by adding another control (drag another button onto the form) and build the project, Visual Studio extensively edits the MyForm.Designer.cs and MyForm.resx files, even for the existing controls on the form that were not touched. It seems that it embeds all the images needed by the controls in the MyForm.resx file and then refers to them in the MyForm.Designer.cs as follows:
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MyForm));
this.customButton.Image = ((System.Drawing.Image)(resources.GetObject("customButton.Image")));
This is obviously not what I want. Why does Visual Studio want the form to use a local resource now, instead of the one embedded in the project's Resources.resx file as it was happy to do before the form was modified? If I go to the designer, view the properties of the customButton, and try to set the Image property to the image in the project resource file, it allows it, but on the next click, it will immediately revert back to the local reference embedded in MyForm.resx.
Any ideas why this is happening?
I figured this out with the help of another question
Basically, even though I've seen several recommendations to centralize your application's resources in a single assembly, this appears to be a bad choice. The VS Designer just doesn't like having to access resources external to the current assembly and while it can do so, it will also change your code to bring those resources in the current assembly by embedding them, thwarting your efforts to keep the resources in a single assembly.
I basically had to go back to keeping resources in the assembly the uses them.