Namespace conflit while using global resource file for multiple languages - c#

I have created two resources files with names:
ManageUserResources.resx
ManageUserResources.zn-CN.resx
Now respective namespaces in designer.cs are:
Resources
Resources.ManageUserResources
//Error: The namespace resources already contains definition for ManageUserResources
Is this conflict between namespace and class(having same names)?
Any solution for this problem?

While creating resource files for name spaces for multiple languages, always make sure you check the correct culture code. In your case the for ManageUserResources.zn-CN.resx. Considering you wanted to select China, it should have been ManageUserResources.zh-CN.resx The code for china is zh-CN and this should not be replaced.
Coming to your problem:
Specifically the error occurs in the Resources.Designer.cs You could just delete the file and let Visual studio regenerate it.
I've had this problem, too, and it was because I created a new namespace, but the parent namespace contained a class with the same name.
To find this, I used the object browser and searched for the name of the item that was already defined.
If it won't let you do this while you still have the error, then temporarily change the name of the item it is complaining about and then find the offending item.
Hope this helps.

Related

How to use windows forms resource files for localizing dynamic data

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.

Embedded Resource Name Loses Extension When File is Nested

I have some scripts stored in files that I've marked as Embedded Resource. I nest each of these files under their associated .cs file. Unfortunately, for some reason, when you nest a file this way, the embedded resource name loses the file extension. This means that at runtime I have no way to identify which embedded resources are or aren't scripts. What can I do about this?
One thing I tried that did not work: getting the ManifestResourceInfo object, which has a FileName property. Unfortunately this property is null.
Another thing I tried was doubling up the extension. (like: filename.ext.ext). This didn't work, and everything after the first . is still missing.
I tried naming the resource with something very different, and noticed that the resource name didn't even change. It seems that it is generating the resource name for a nested embedded resource file based off of the "dependent upon" file, which in this case is just a regular .cs file. I tried doubling the extension of the .cs file to filename.extrastuff.cs but the resource name still doesn't change. It insists on clipping everything after the first ..
No, ok, I see now that it is actually naming the resource after the type defined in the .cs file, not the filename of either file. This is why the extension makes no difference. This means there is nothing I can do to either filename to help find the resource.
I discovered that the reason the file loses its extension is because for some reason when the file is nested, VS is naming the resource after the type instead of after the file.
The only thing I've found to allow me to still have an extension when nesting is to manually edit the .csproj file and add a LogicalName tag, which allows you to override the resource name.
<EmbeddedResource Include="Path\To\NestedFile.ext">
<LogicalName>NestedFile.ext</LogicalName>
<DependentUpon>ParentFile.cs</DependentUpon>
</EmbeddedResource>
Unfortunately, there is no IDE support for this, and the FileNesting extension I'm using doesn't support writing this tag either.
It's too cumbersome to have to do this for every file, so instead of relying on the file extension, I would have to do something like add an identifier inside my script files that identifies them as scripts.
Ultimately I realized that since in my case I'm validating script files from unit tests, I can simply scan the file system instead of the resource manifest and avoid this problem altogether.

Can we skip ResourceManager?

I've working on a project where I'm using ResourceManager extensively and this question just crossed my mind.
Can we read from .resx files without using ResourceManager? I mean, is there another way?
ResourceManager is a convenience class, it works very well with the way the build system supports .resx files. No, it is not a strict necessity.
A .NET assembly has the generic capability of embedding arbitrary data into the manifest of the assembly. Just a blob of bytes, it can be anything you want. Directly supported by the build system as well, just add a file to your project and set its Build Action to "Embedded Resource". At runtime, you retrieve the data in that file with Assembly.GetManifestResourceStream().
You can stop right there, but that's just a single file, it doesn't scale very well if you have many small resources you want to embed. Which is where a .resx file starts, it is an XML file that contains resources in a friendly format. One that gives you a fighting chance to recover the source again when the original got lost.
But an XML format is not a very good format for resource data, it is bulky and it is expensive to find data back. So .NET has resgen.exe, a build tool that turns the XML file into a binary file, a .resources file. Compact and easy to find stuff back. And fit to be embedded directly as a single manifest resource.
What you don't want to do is having to read the .resources data yourself. You'll want to use a helper class that can find specific resources back from the blob of bytes. You want use the ResourceReader class, its GetResourceData() lets you specify the resource name and it will spit the resource type and data back out.
You can stop right there, but an app often has a need for different sets of resources. A very common localization need. Which is what satellite assemblies are all about, different assemblies that contain nothing but resources, each for a specific culture. They are separate so you don't pay for the virtual memory that's required to store all the localized resources when you need only one set of them. What's needed here is a helper class that automatically locates and loads the correct satellite assembly and retrieves the resource for you, based on the current culture.
That helper class is ResourceManager.
If you choose to skip the use of the ResourceManager you can let Visual Studio handle code generation for you. Ultimately the generated code uses a ResourceManager, but you're no longer writing that code manually. Additionally, you get compile-time checking since you're referencing a generated static class.
If you add a resource file to your project and double click it from the Solution Explorer, Visual Studio presents you with a dialog where you can enter a name for a resource, and its value. The dialog presents you with options to add resources as strings, images, audio, etc. (look at the dropdowns at the top of the dialog). Next, to get the code generation bit, you need to set the Access Modifier to either "Public" or "Internal". The third option is "No code generation."
For example, add a resource file called "MyResources", then add a string resource with the name Greeting and a value of Hello! With one of the former two options selected for code generation (start off with public to test it, restrict the access as needed), you should now be able to reference the resources from your code via MyResources.Greeting. If you don't see it right away, make sure you've saved the file and try compiling.
string greeting = MyResources.Greeting; // "Hello!"
If you add other resource types (image, audio, etc.) then the return types will differ, of course.
At this point you could inspect the generated .cs file and see that the generated code is using a ResourceManager. The other use for resource files is localization. Let's say you wanted a Spanish version of MyResources. You would add a new file called MyResources.es.resx, where es corresponds to the language code desired (Spanish in this case). Now add the same resource name of Greeting with a Spanish value of Hola!.
If you change the thread culture to Spanish, referencing the resource will now return the Spanish version:
string defaultGreeting = MyResources.Greeting; // "Hello!"
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("es");
string spanishGreeting = MyResources.Greeting; // "Hola!"
Note that you only really need to set the access modifier to one of the code generation options for your default resource file (i.e., MyResources.resx), not for all the other localized versions you add. There's no harm in doing so, but in my opinion it's cleaner to have the main file generated while the others just have the resource values desired without code generation.
Well, Resources are compiled into the assembly. You could try to read the assembly by reading the bytes (or the IL), and extract the resources from there.
ResourceManager does this all for you, so I could not think of any reason you want to do this... Maybe one, if you don't want to load the assembly in memory, you could do it without ResourceManager.
Ref Microsoft: Represents a resource manager that provides convenient access to culture-specific resources at run time.
I expect, I'd you use multi Lang, you will get a more consistent result and better compatibility.
IMHO

Visual Studio : When and why a class file name change will automatically update references to that class

Sometimes when I'm using Visual Studio and I alter the name of the file containing a code element (i.e. a class, interface) I get a very helpful prompt that offers to automatically update all references/uses of that code element to the new file name.
And other times I don't.
In all cases I'm referring to when the code element file name matches the code elements type name.
Why does this sometimes occur and sometimes not?
I gather it has something to do with either a predefined link or VS's ability to real time resolve dependencies.
I have played around with this however and while in all cases VS can helpfully find all dependencies/uses of/to a code element using the context menu options, it doesn't always offer the prompt if I change the file name. So whats the secret?
It works this way (at least from my experience):
the refactor is activated only when the file contains exactly one single class with the same file as the file. I.e. it doesn't work if there are more classes in the file, or even when there is an enum, or a struct.

Find a specific class in a file using reflection?

I googled and someone found the answer and linked but it was dead. How can i find a specific class in a specific file? The poster i found ask that question and found how to do it in a namespace but i would like to find one specific to a file. This question is to answer my other question but now that i thought of this i would like to know the answer.
Something like this?
string path = "INSERT PATH HERE";
var assembly = Assembly.LoadFile(path);
foreach (var type in assembly.GetTypes())
{
Debug.WriteLine(type.Name);
// do check for type here, depending on how you wish to query
}
I am not sure how the file name shall be stored as part of compiled assembly. Other option is that you can use the PDB file generated by the VS IDE to get the source file at some extension.
Here is some internals of pdb file.
http://www.informit.com/articles/article.aspx?p=22685
Once you can parse the file, you can use the symbol and look at the source definition.
I am glad to know other ways as well.
If you want to find the source code for a class, use the Go To Definition option in Visual Studio.
Once the code is compiled, it's not arranged in files, it's arranged in name spaces and assemblies. If it's at all possible to find out from which source file a class originated, you would have to loop through all classes and look for it.

Categories